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.
v0.1 is validated â webmcp(), useWebMCP(), Scope, polyfill, 42 tests. unplugin (0.2) and webmcp.server() for Next.js (0.3) are deferred behind spike.