# Webmcp React

> React hooks for exposing your app's functionality as WebMCP tools - transport-agnostic, SSR-safe, Strict Mode safe, W3C spec-aligned

- **Type:** MCP server
- **Install:** `agentstack add mcp-mcpcat-webmcp-react`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [MCPCat](https://agentstack.voostack.com/s/mcpcat)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [MCPCat](https://github.com/MCPCat)
- **Source:** https://github.com/MCPCat/webmcp-react

## Install

```sh
agentstack add mcp-mcpcat-webmcp-react
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# webmcp-react

React hooks for exposing typed tools on `document.modelContext`, aligned with the current [WebMCP](https://github.com/webmachinelearning/webmcp) spec.

[](https://www.npmjs.com/package/webmcp-react)
[](./LICENSE)
[](https://github.com/MCPCat/webmcp-react/actions/workflows/ci.yml)
[](https://github.com/MCPCat/webmcp-react/pulls)

> 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

```bash
npm install webmcp-react zod
```

## Playground

Try it live: [**WebMCP Wordle Demo**](https://mcpcat.github.io/webmcp-react/playground/)

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 `` and register tools with `useMcpTool`:

```tsx
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 (
    
      
    
  );
}
```

That's it. The tool is registered on `document.modelContext` and can be called by WebMCP-compatible agents.

### Using an AI agent?

This repo ships with [agent skills](./skills) that can set up webmcp-react and scaffold tools for you. Install them with the [skills CLI](https://skills.sh):

```bash
npx skills add mcpcat/webmcp-react
```

Works with Cursor, Claude Code, GitHub Copilot, Cline, and [18+ other agents](https://vercel.com/docs/agent-resources/skills).

## How it works

[WebMCP](https://github.com/webmachinelearning/webmcp) is an emerging web standard that adds `document.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](https://developer.chrome.com/blog/webmcp-epp).

This library provides React bindings for that API. `` 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 `document.modelContext` directly. The [WebMCP Bridge extension](https://chromewebstore.google.com/detail/webmcp-bridge/chgjbookknohehmaocfijekhaocaanaf) connects your registered tools to any MCP client.

1. Install the extension from the [Chrome Web Store](https://chromewebstore.google.com/detail/webmcp-bridge/chgjbookknohehmaocfijekhaocaanaf)
2. Configure your MCP client — see the [extension setup guide](./extension/README.md) for details

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:

```tsx
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 (
    
       execute({ text: "Hello" })} disabled={state.isExecuting}>
        {state.isExecuting ? "Translating..." : "Translate"}
      
      {state.lastResult && {state.lastResult.content[0].text}}
      {state.error && {state.error.message}}
    
  );
}
```

### Title and annotations

Give a tool a human-friendly display `title`, and hint AI agents about its behavior with `annotations`. Per the current WebMCP spec, annotations are limited to `readOnlyHint` and `untrustedContentHint`:

```tsx
useMcpTool({
  name: "search_users",
  title: "Search users",
  description: "Find users by name or email",
  input: z.object({ query: z.string() }),
  annotations: {
    readOnlyHint: true,
  },
  handler: async ({ query }) => { /* ... */ },
});
```

### Dynamic tools

Tools register on mount and unregister on unmount. Conditionally render them like any React component:

```tsx
function App({ user }) {
  return (
    
      
      {user.isAdmin && }
    
  );
}
```

### Callbacks

Run side effects on success or failure:

```tsx
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:

```tsx
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.

## Breaking changes in 0.2.0

0.2.0 realigns the library with the current [WebMCP](https://github.com/webmachinelearning/webmcp) spec. If you're upgrading from 0.1.0:

- **API moved to `document.modelContext`.** Tools register on `document.modelContext` instead of `navigator.modelContext`. (The testing/consumer API stays on `navigator.modelContextTesting`.)
- **`registerTool` returns a `Promise`.** The polyfill's `registerTool(tool, options?)` returns a `Promise` that rejects on invalid input (bad/duplicate/empty name, empty description, non-function execute, non-serializable `inputSchema`, untrustworthy `exposedTo` origin, or an already-aborted signal).
- **Unregistration is AbortSignal-only.** There is no `unregisterTool` — pass `{ signal }` and abort it. `useMcpTool` does this for you on unmount.
- **Handlers take a single argument.** `handler(args)` / `execute(input)` no longer receive a second `client` argument; `ModelContextClient` and `requestUserInteraction` are removed.
- **`annotations` narrowed to `{ readOnlyHint, untrustedContentHint }`.** The classic hints (`destructiveHint`, `idempotentHint`, `openWorldHint`) and `annotations.title` are removed. A new top-level `title?` field replaces `annotations.title`.
- **New `exposedTo?: string[]`** controls cross-frame origin visibility (changing it re-registers the tool).
- **New `toolchange` event.** `document.modelContext` is an `EventTarget` that fires a bare `toolchange` event on tool register/unregister; an `ontoolchange` handler is also supported.

`outputSchema` (Zod `output` / JSON-Schema `outputSchema`) and `structuredContent` on results are retained as documented library extensions.

## API

See the [full API reference](./docs/api.md).

## License

[MIT](./LICENSE)

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [MCPCat](https://github.com/MCPCat)
- **Source:** [MCPCat/webmcp-react](https://github.com/MCPCat/webmcp-react)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-mcpcat-webmcp-react
- Seller: https://agentstack.voostack.com/s/mcpcat
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
