npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

webmcp-gen

v1.2.0

Published

CLI tool that generates WebMCP tool definitions from TypeScript interfaces. Built with AI assistance.

Readme

webmcp-gen

webmcp-gen demo

CLI tool that generates WebMCP tool definitions from TypeScript interfaces.

WebMCP is the browser-native API (navigator.modelContext) that lets web pages expose structured tools to AI agents. It shipped as a Chrome 149 origin trial in June 2026. This tool reads your TypeScript interfaces and produces spec-compliant JSON tool definitions plus ready-to-use handler stubs.

Disclaimer: This project is not affiliated with or endorsed by Google or the W3C.

Built with AI assistance.

Install

npm install -g webmcp-gen

Or use without installing:

npx webmcp-gen --api myapp.ts

Quick start

1. Write your API as TypeScript interfaces:

// api.ts

/** Search products by keyword. */
interface SearchProducts {
  /** The search query string. */
  query: string;
  /** Filter by category. */
  category?: "electronics" | "clothing" | "home";
  /** Max results (1-100). */
  limit?: number;
}

/** Add an item to the shopping cart. */
interface AddToCart {
  /** Product identifier. */
  productId: string;
  /** Quantity to add. */
  quantity: number;
}

2. Generate WebMCP definitions:

webmcp-gen --api api.ts

3. Output (in webmcp-out/):

webmcp-out/
  searchProducts.webmcp.json     # JSON tool definition
  searchProducts.handler.ts      # TypeScript handler stub
  addToCart.webmcp.json
  addToCart.handler.ts

The .webmcp.json files contain the tool definition ready for navigator.modelContext.registerTool(). The .handler.ts files contain the full registration call with a stub execute callback for you to implement.

Usage

Generate from TypeScript

# Default output to ./webmcp-out/
webmcp-gen --api myapp.ts

# Custom output directory
webmcp-gen --api myapp.ts -o generated/

# Single combined file instead of per-tool files
webmcp-gen --api myapp.ts --combined

# Validate only (no files written)
webmcp-gen --api myapp.ts --validate

Example templates

# List available templates
webmcp-gen --list-templates

# Emit a template to the current directory
webmcp-gen --template crud-api

# Then generate from it
webmcp-gen --api crud-api.ts

Available templates:

| Template | Description | |---|---| | crud-api | CRUD operations (create, read, update, delete) | | search | Search/filter with pagination and sorting | | form-handler | Form submissions (contact, booking) | | data-transformer | Data conversion and formatting tools |

How it works

  1. Parse -- Uses ts-morph to read TypeScript interfaces and type aliases from your source file.
  2. Convert -- Maps TypeScript types to JSON Schema: string -> "string", number -> "number", union literals -> enum, arrays -> { type: "array", items: ... }, nested objects -> nested schemas.
  3. Annotate -- Pulls descriptions from JSDoc comments. Detects @readonly tags and sets annotations.readOnlyHint.
  4. Validate -- Checks every generated definition against the WebMCP spec: valid name, non-empty description, valid JSON Schema, no orphaned required entries.
  5. Output -- Writes one .webmcp.json + one .handler.ts per tool (or a combined pair with --combined).

Generated output format

JSON definition (*.webmcp.json)

{
  "name": "searchProducts",
  "description": "Search products by keyword.",
  "inputSchema": {
    "type": "object",
    "properties": {
      "query": {
        "type": "string",
        "description": "The search query string."
      },
      "category": {
        "type": "string",
        "enum": ["electronics", "clothing", "home"]
      },
      "limit": {
        "type": "number"
      }
    },
    "required": ["query"]
  },
  "annotations": {
    "readOnlyHint": true
  }
}

Handler stub (*.handler.ts)

// Chrome 149: navigator.modelContext — Chrome 150+: document.modelContext
const ctx = "modelContext" in document ? document.modelContext : navigator.modelContext;

ctx.registerTool({
  name: "searchProducts",
  description: "Search products by keyword.",
  inputSchema: { /* ... */ },
  annotations: { readOnlyHint: true },
  execute: async (input: SearchProductsInput): Promise<string> => {
    // TODO: Implement searchProducts logic here
    throw new Error("Not implemented: searchProducts");
  },
});

Note: navigator.modelContext is deprecated in Chrome 150. Generated stubs include a compatibility shim that works across Chrome 149–156+.

TypeScript mapping reference

| TypeScript | JSON Schema | |---|---| | string | { "type": "string" } | | number | { "type": "number" } | | boolean | { "type": "boolean" } | | "a" \| "b" \| "c" | { "type": "string", "enum": ["a", "b", "c"] } | | string[] | { "type": "array", "items": { "type": "string" } } | | { nested: string } | { "type": "object", "properties": { "nested": ... } } | | prop?: type | Excluded from required array | | /** JSDoc */ | "description" field | | @readonly tag | annotations.readOnlyHint = true | | @untrusted tag | annotations.untrustedContentHint = true |

Security

WebMCP allows AI agents to execute tools that affect live web applications. Google advises developers to follow these practices — webmcp-gen bakes them into the generated handler stubs automatically:

  • Human-in-the-loop for mutating actions. Tools that aren't marked @readonly get a requestUserInteraction() reminder in their handler stub. Use this to confirm sensitive operations (purchases, deletions, account changes) before executing.
  • Input sanitisation. Tools accepting freeform string inputs get a sanitisation reminder. WebMCP tool data may contain indirect prompt injection from contaminated tool responses or malicious manifests — validate and escape all inputs.
  • Read-only annotations. Mark query/lookup interfaces with @readonly in JSDoc. The generator sets annotations.readOnlyHint = true, signalling to agents that the tool has no side effects.

See Chrome's WebMCP security guidance for full details.

Programmatic API

import { parseTypeScriptFile, generate, validateToolDefinition } from "webmcp-gen";

// Parse a file
const result = parseTypeScriptFile("./api.ts");
console.log(result.tools);

// Full pipeline
const output = generate({
  inputFile: "./api.ts",
  outDir: "./webmcp-out",
});

// Validate a definition
const validation = validateToolDefinition({
  name: "myTool",
  description: "Does something useful.",
  inputSchema: {
    type: "object",
    properties: { id: { type: "string" } },
    required: ["id"],
  },
});

npm package note

The primary package name is webmcp-gen. The fallback name untangled-webmcp is reserved on npm as an alternative if needed.

Development

git clone <repo-url>
cd webmcp-gen
npm install
npm run build
npm test

License

MIT