Webmcp React
React hooks for exposing your app's functionality as WebMCP tools - transport-agnostic, SSR-safe, Strict Mode safe, W3C spec-aligned
Ask AI about Webmcp React
Powered by Claude · Grounded in docs
I know everything about Webmcp React. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
webmcp-react
React hooks for exposing typed tools on navigator.modelContext.
Experimental. WebMCP is still evolving, so small API and behavior changes should be expected.
- Zod-first. Define inputs with Zod and get full type inference in handlers
- JSON Schema fallback. Pass raw JSON Schema when you don't want Zod
- Built-in polyfill. Uses a lightweight polyfill when native WebMCP is unavailable
- SSR-safe. Works with Next.js, Remix, and other server-rendering frameworks
- StrictMode safe. Avoids duplicate registrations and orphaned tools
Install
npm install webmcp-react zod
Playground
Try it live: WebMCP Wordle Demo
A fully playable Wordle clone that showcases webmcp-react hooks. Tools dynamically register and unregister as the game moves through phases (idle, playing, won/lost), and guesses can be made via keyboard or through a connected MCP agent. Includes a DevPanel for inspecting tool state and an easy-mode toggle that enables a hint tool. Install the Chrome extension to bridge tools to AI clients like Claude and Cursor.
Quick start
Wrap your app in <WebMCPProvider> and register tools with useMcpTool:
import { WebMCPProvider, useMcpTool } from "webmcp-react";
import { z } from "zod";
function SearchTool() {
useMcpTool({
name: "search",
description: "Search the catalog",
input: z.object({ query: z.string() }),
handler: async ({ query }) => ({
content: [{ type: "text", text: `Results for: ${query}` }],
}),
});
return null;
}
export default function App() {
return (
<WebMCPProvider name="my-app" version="1.0">
<SearchTool />
</WebMCPProvider>
);
}
That's it. The tool is registered on navigator.modelContext and can be called by WebMCP-compatible agents.
Using an AI agent?
This repo ships with agent skills that can set up webmcp-react and scaffold tools for you. Install them with the skills CLI:
npx skills add mcpcat/webmcp-react
Works with Cursor, Claude Code, GitHub Copilot, Cline, and 18+ other agents.
How it works
WebMCP is an emerging web standard that adds navigator.modelContext to the browser, an API that lets any page expose typed, callable tools to AI agents. Native browser support is still experimental and may evolve quickly. Chrome recently released it in Early Preview.
This library provides React bindings for that API. <WebMCPProvider> installs a polyfill (skipped when native support exists), and each useMcpTool call registers a tool that agents can discover and execute.
Connect to AI clients
Desktop MCP clients like Claude Code and Cursor can't access navigator.modelContext directly. This repo includes a Chrome extension that connects your registered tools to any MCP client.
See the extension setup guide for build, install, and configuration instructions.
Once Chrome supports this bridging natively, I'll deprecate the extension.
Recipes
Execution state
useMcpTool returns reactive state you can use to build UI around tool execution:
function TranslateTool() {
const { state, execute } = useMcpTool({
name: "translate",
description: "Translate text to Spanish",
input: z.object({ text: z.string() }),
handler: async ({ text }) => {
const result = await translate(text, "es");
return { content: [{ type: "text", text: result }] };
},
});
return (
<div>
<button onClick={() => execute({ text: "Hello" })} disabled={state.isExecuting}>
{state.isExecuting ? "Translating..." : "Translate"}
</button>
{state.lastResult && <p>{state.lastResult.content[0].text}</p>}
{state.error && <p className="error">{state.error.message}</p>}
</div>
);
}
Tool annotations
Hint AI agents about tool behavior with annotations (supports the full MCP annotation set):
useMcpTool({
name: "delete_user",
description: "Permanently delete a user account",
input: z.object({ userId: z.string() }),
annotations: {
destructiveHint: true,
idempotentHint: true,
},
handler: async ({ userId }) => { /* ... */ },
});
Dynamic tools
Tools register on mount and unregister on unmount. Conditionally render them like any React component:
function App({ user }) {
return (
<WebMCPProvider name="app" version="1.0">
<PublicTools />
{user.isAdmin && <AdminTools />}
</WebMCPProvider>
);
}
Callbacks
Run side effects on success or failure:
useMcpTool({
name: "checkout",
description: "Complete a purchase",
input: z.object({ cartId: z.string() }),
handler: async ({ cartId }) => { /* ... */ },
onSuccess: (result) => analytics.track("checkout_complete"),
onError: (error) => toast.error(error.message),
});
JSON Schema
Don't want Zod? Pass inputSchema directly:
useMcpTool({
name: "calculate",
description: "Basic arithmetic",
inputSchema: {
type: "object",
properties: {
a: { type: "number" },
b: { type: "number" },
op: { type: "string", enum: ["add", "subtract", "multiply", "divide"] },
},
required: ["a", "b", "op"],
},
handler: async (args) => {
const { a, b, op } = args as { a: number; b: number; op: string };
const result = { add: a + b, subtract: a - b, multiply: a * b, divide: a / b }[op];
return { content: [{ type: "text", text: String(result) }] };
},
});
SSR
Works with Next.js, Remix, and any server-rendering framework out of the box. The build includes a "use client" banner, so no extra configuration is needed.
API
See the full API reference.
