Skip to content

useWebMCP

React adapter for @web-ai-sdk/webmcp. Registers WebMCP tools on mount and unregisters them on unmount via an AbortSignal. For the conceptual overview see WebMCP.

Live demo

Toggle the tools on or off, then click “Run agent”. On browsers with WebMCP enabled the demo asks Chrome’s testing surface (navigator.modelContextTesting.executeTool) to dispatch one of the live tools.

Usage

import { useWebMCP } from "@web-ai-sdk/webmcp/react";
import { useMemo } from "react";
export function AgentTools() {
const tools = useMemo(
() => [
{
name: "add_to_cart",
description: "Add a SKU to the user's cart",
execute: async (input) => ({ ok: true, ...input }),
},
],
[],
);
useWebMCP(tools);
return null; // pure logic; render whatever UI you want elsewhere
}

The hook re-registers whenever the tools array reference changes. Pass a stable reference (memoized or module-level) so the hook doesn’t tear down and rebuild on every render.

State + reactivity

Tool execute closures capture whatever they read at definition time. If your tool needs to read live React state, use a useRef:

const stateRef = useRef(state);
stateRef.current = state;
const tools = useMemo(
() => [
{
name: "open_settings",
description: "...",
execute: async () => ({ pane: stateRef.current.pane }),
},
],
[],
);
useWebMCP(tools);

This is necessary because Chrome’s AbortSignal-driven unregister is asynchronous; a same-tick re-register can be silently skipped on a duplicate-name race, leaving the old closure in place. Reading from a ref guarantees the latest state regardless of which closure Chrome holds.

Cleanup

The hook returns nothing; cleanup is automatic on unmount via useEffect’s return value. If you need imperative cleanup (e.g. log out flow), use the vanilla registerTools(tools) directly and call the returned cleanup.

Errors and unavailability

On browsers without navigator.modelContext, the hook is a no-op. Render whatever fallback UI you want; nothing breaks.

Reference

import type { Tool, ToolAnnotations, DefineToolOptions } from "@web-ai-sdk/webmcp/react";
interface Tool {
name: string;
description: string;
execute: (input: unknown) => Promise<unknown> | unknown;
readOnly?: boolean; // → annotations.readOnlyHint
destructive?: boolean; // → annotations.destructiveHint
annotations?: ToolAnnotations; // raw passthrough; merges on top of shorthand
inputSchema?: object; // JSON Schema or Standard Schema v1
}
interface ToolAnnotations {
readOnlyHint?: boolean;
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
}
declare const useWebMCP: (tools: readonly Tool[]) => void;
// Helper for type-safe tool definitions with a Standard Schema.
declare function defineTool<T extends StandardSchemaV1>(options: DefineToolOptions<T>): Tool;

Source: packages/webmcp/src/react/index.ts.