@mcp-b/react-webmcp

August 31, 2026 ยท View on GitHub

React hooks for Model Context Protocol (MCP) - Let AI agents like Claude, ChatGPT, Cursor, and Copilot control your React components

npm version npm downloads License: MIT TypeScript React

Reference | React Tutorial | Framework Guides

@mcp-b/react-webmcp provides React hooks that expose your components as AI-callable tools via the Model Context Protocol. Build AI-powered React applications where Claude, ChatGPT, Gemini, Cursor, and Copilot can interact with your app's functionality.

Why Use @mcp-b/react-webmcp?

FeatureBenefit
React-First DesignHooks follow React patterns with automatic cleanup and StrictMode support
Type-Safe SchemasJSON Schema and Standard JSON Schema input typing, plus JSON Schema output typing
Two-Way IntegrationBoth expose tools TO AI agents AND consume tools FROM MCP servers
Execution State TrackingBuilt-in loading, success, and error states for UI feedback
Works with Any AICompatible with Claude, ChatGPT, Gemini, Cursor, Copilot, and any MCP client

Installation

pnpm add @mcp-b/global @mcp-b/react-webmcp

You can omit @mcp-b/global when you only consume an MCP server as a client, or when a native WebMCP implementation supplies document.modelContext and you only use the core useWebMCP tool hook. Prompt and resource hooks require the MCP-B extensions installed by @mcp-b/global. If you only want strict core WebMCP hooks, install usewebmcp directly.

For client functionality, you'll also need:

pnpm add @mcp-b/transports @modelcontextprotocol/client

Prerequisites: Provider hooks require document.modelContext. Install @mcp-b/global, or use a native WebMCP implementation for the core useWebMCP tool hook.

Provider hooks register tools with document.modelContext.registerTool(tool, { signal }) and abort the controller on unmount. The hooks retain a navigator.modelContext fallback for older preview runtimes, but document.modelContext is the canonical surface. Install @mcp-b/global when you need a portable runtime with spec-aligned cleanup behavior.

outputSchema is MCP-B helper metadata for output typing and structured MCP responses. Native Chrome WebMCP does not currently define or enforce it.

Quick Start - Provider (Registering Tools)

import '@mcp-b/global';
import { useWebMCP } from '@mcp-b/react-webmcp';

function PostsPage() {
  const likeTool = useWebMCP({
    name: 'posts_like',
    description: 'Like a post by ID. Increments the like count.',
    inputSchema: {
      type: 'object',
      properties: {
        postId: { type: 'string', description: 'The post ID to like' },
      },
      required: ['postId'],
    } as const,
    outputSchema: {
      type: 'object',
      properties: {
        success: { type: 'boolean' },
        postId: { type: 'string' },
      },
      required: ['success', 'postId'],
    } as const,
    annotations: {
      title: 'Like Post',
      readOnlyHint: false,
      idempotentHint: true,
    },
    execute: async (input) => {
      await api.posts.like(input.postId);
      return { success: true, postId: input.postId };
    },
  });

  return (
    <div>
      {likeTool.state.isExecuting && <Spinner />}
      {likeTool.state.error && <ErrorAlert error={likeTool.state.error} />}
    </div>
  );
}

Quick Start - Client (Consuming Tools)

import { McpClientProvider, useMcpClient } from '@mcp-b/react-webmcp';
import { TabClientTransport } from '@mcp-b/transports';
import { Client } from '@modelcontextprotocol/client';

const client = new Client(
  { name: 'MyApp', version: '1.0.0' },
  { versionNegotiation: { mode: 'auto' } }
);
const transport = new TabClientTransport({
  channelId: 'mcp',
  targetOrigin: window.location.origin,
});

function App() {
  return (
    <McpClientProvider client={client} transport={transport}>
      <ToolConsumer />
    </McpClientProvider>
  );
}

function ToolConsumer() {
  const { client, tools, isConnected } = useMcpClient();

  const handleCallTool = async () => {
    const result = await client.callTool({ name: 'posts_like', arguments: { postId: '123' } });
    console.log('Result:', result.content[0].text);
  };

  return (
    <div>
      <p>Connected: {isConnected ? 'Yes' : 'No'}</p>
      <p>Available Tools: {tools.length}</p>
      <button onClick={handleCallTool} disabled={!isConnected}>
        Call Tool
      </button>
    </div>
  );
}

useMcpClient().reconnect() retries tool and resource discovery while the client remains connected. If a one-shot transport closes, construct a new transport and pass it to reconnect(newTransport); closed transport instances are not generally reusable.

API Overview

Provider Hooks

HookDescription
useWebMCP(config, deps?)Register a tool with full control over behavior and state
useWebMCPContext(name, description, getValue, options?)Simplified hook for read-only context exposure
useWebMCPPrompt(config)Register a reusable MCP prompt
useWebMCPResource(config)Register an MCP resource

All registration hooks support enabled, defaulting to true. Pass it in the config for tools, prompts, and resources, or as the fourth argument ({ enabled: false }) to useWebMCPContext. Disabling unregisters the item; re-enabling registers the latest committed configuration. Keep the hook call unconditional.

Disabled prompt and resource hooks report isRegistered: false. Tool and context hooks retain their execution state and local execute/reset controls. Disabling does not cancel the handler's work, though the runtime may reject an in-flight MCP request when its registration is removed.

Client Hooks

Hook / ComponentDescription
McpClientProviderProvider component managing an MCP client connection
useMcpClient()Access client, tools, connection status, and capabilities

Schema Compatibility

Inputs accept JSON Schema or Standard JSON Schema v1 implementations such as Zod 4.2+. Outputs use JSON Schema for typed structuredContent.

Resources

License

MIT - see LICENSE for details