Function-first
Existing function stays callable. await search({query}) and agent search({query}) — same capability.
Wrap a JS/TS function with webmcp(fn). Keep your API — add a WebMCP capability on top. One function. Two interfaces.
import { webmcp } from 'simple-webmcp';
async function searchCustomers({ query, limit = 20 }: { query: string; limit?: number }) {
return customers.filter(c => c.name.includes(query)).slice(0, limit);
}
const search = webmcp(searchCustomers);Human:
await search({ query: 'alice' });Agent (when mounted):
import { useWebMCP } from 'simple-webmcp/react';
function Page() {
const tool = useWebMCP(search, { description: 'Search customers' });
return <UI />;
}Customize only what you need:
const search2 = webmcp(searchCustomers, {
description: 'Search customers by name or email',
fields: { query: { description: 'Name, email, or ID' } }
});Progressive adoption: webmcp(fn) → add description → fields → schema (Zod) → build-time inference. For real cross-browser WebMCP use @mcp-b/webmcp-polyfill; simple-webmcp/dev-polyfill is for tests and dev.
See Getting Started for a 30-second setup, Schema & Inference for typing, and Browser Support for Chrome/Firefox/Safari. Prefer
webmcp(fn)for function-first authoring over rawdocument.modelContext.registerTool.