simple-webmcp — Full Store Demo

Six existing functions — no rewrite — made agent-ready with webmcp(fn). Try as a human, then as an agent via Inspect or Chrome WebMCP Inspector. Same functions, two interfaces.

WebMCP status 0 tools checking…
Chrome canary: native document.modelContext.registerTool + getTools/executeTool. Other browsers: simple-webmcp/dev-polyfill shim. For production cross-browser use @mcp-b/webmcp-polyfill.

Search products searchProducts tool

Agent: searchProducts({query: "key"}) → same searchProducts function. Try empty {} in Inspect → fails (query required).

Products — real catalog addToCart, getProduct tools

Add calls addToCart; Details calls getProduct — both are WebMCP tools.

Cart getCart, updateCart, removeFromCart, checkout tools

0 items — £0
Cart is empty — add a product or ask the agent “Add a keyboard and show my cart”.

Raw WebMCP vs simple-webmcp — same capability

Left: manual registerTool (schema + wrapper + AbortSignal). Right: webmcp (keeps function callable). Both register add_to_cart with productId: string enum + quantity: integer 1–10.

Raw WebMCP — 22 lines manual

document.modelContext.registerTool({
  name: 'add_to_cart',
  description: 'Add product to cart',
  inputSchema: {
    type: 'object',
    properties: {
      productId: {
        type: 'string',
        enum: ['macbook','keyboard','mouse','monitor'],
        description: 'Product ID'
      },
      quantity: {
        type: 'integer',
        minimum: 1, maximum: 10,
        default: 1
      }
    },
    required: ['productId','quantity']
  },
  execute: ({productId, quantity}) =>
    addToCart({productId, quantity})
}, { signal });
Maintain inputSchema + wrapper + AbortSignal. Not callable as tool. 22 lines, all manual.

simple-webmcp — 9 lines (1 line minimal) function-first

import { webmcp } from 'simple-webmcp';
const addToCartTool = webmcp(addToCart, {
  description: 'Add product to cart',
  fields: {
    productId: {
      type: 'string',
      enum: ['macbook','keyboard','mouse','monitor'],
      description: 'Product ID'
    },
    quantity: { type: 'integer', minimum: 1, maximum: 10 }
  }
});
 // still callable:
await addToCartTool({productId:'keyboard', quantity:1});
// React: const t = useWebMCP(addToCart, {description})
9 lines with fields vs 22 raw for production types; 1 line minimal webmcp(addToCart) for prototype. fields patches inferred schema — no silent defaults for required fields.
checking… Live: registering… — 6 tools: searchProducts, getProduct, getCart, addToCart, updateCart, checkout

🔍 Inspect — 6 tools on this page (simple-webmcp/inspect)

Lists registry.list() + document.modelContext.getTools() and lets you invoke — same path agents use. Try {} on addToCartisError (missing productId).
API: import { listTools, invokeTool } from 'simple-webmcp/inspect' · React: Inspector from simple-webmcp/devtools

Log