Skip to content
WebMCP Agents
Esc
↑↓navigate↵open⌘Jpreview
On this page

@webmcp-agents/react

React bindings for WebMCP tools.

React bindings for WebMCP tools. Write a tool in a component with useWebTool, put the app’s catalog in one provider, and get the agent cursor without any ordering rules. Nothing is added to your JSX for the cursor: it finds controls by role and accessible name.

pnpm add @webmcp-agents/react @webmcp-agents/core

React is a peer dependency (react >= 18).

import { WebAgentsProvider } from "@webmcp-agents/react";
import "@webmcp-agents/core/cursor.css";

// Module level: the catalog of every tool the app has. Each says where it is on with `match`.
<WebAgentsProvider tools={tools}>
  <App />
</WebAgentsProvider>;

A tool that lives in a component is on while the component is mounted:

import { useWebTool } from "@webmcp-agents/react";
import { useState } from "react";

import { Button } from "@/components/ui/button";

export function ClearCart() {
  const [items, setItems] = useState(["Ocean Tee", "Canvas Tote"]);

  const clear = () => {
    setItems([]);
    return "The cart is empty.";
  };

  // An agent calls this.
  useWebTool({
    id: "clear_cart",
    title: "Clear cart",
    description:
      "Empty the cart. Use when the user asks to start over. " +
      "The user confirms on the page.",
    destructive: true,
    requireConfirmation: true,
    execute: clear,
  });

  // A person clicks this.
  return (
    <div className="flex flex-col items-start gap-3">
      <p>
        {items.length > 0 ? items.join(", ") : "The cart is empty."}
      </p>

      <Button variant="destructive" onClick={clear}>
        Clear cart
      </Button>
    </div>
  );
}

The page needs document.modelContext: a browser with WebMCP, or the polyfill, which <WebAgentsProvider> loads by itself where the browser has none. In development the provider also installs the devtools panel: @webmcp-agents/devtools is a dependency of this package, so there is nothing else to install.

APIs

API Description
WebAgentsProvider The tool catalog (tools, availableTools), the agent cursor and, in development, the devtools, on createWebAgents. The earlier global, routes, pathname and context props are documented there too. Includes WebAgentsProviderProps, ProviderDevtoolsOptions.
useWebTool Write a tool in a component: the definition, execute, an optional target. Returns { invoke, registered, supported }. Includes UseWebToolOptions, WebToolState.
useWebAgents The nearest provider’s registry, cursor controls and pathname. Includes useOptionalWebAgents, WebAgentsContextValue, WebAgentsVisuals.
useEnabledTools The catalog tool ids registered right now.
useAgentEvents Every agent event while mounted.
usePathname The browser’s pathname, followed without any router wiring.
useEnableTools Earlier form: enable catalog tools while a component is mounted. Includes the EnableTools component.
useToolAnswer Earlier form, for declarative forms: answer an agent’s submit and keep the form until the agent has its answer. Includes ToolAnswer and the deprecated useAnswerGrace.
JSX attributes Earlier form: types for a declarative form’s toolname, tooldescription, toolautosubmit, toolparamdescription.

Re-exported from core

The package re-exports the common path from @webmcp-agents/core, so one import is enough. They are documented there:

StrictMode, routes and in-flight calls

Chrome cancels a running call when its tool’s definition changes or the tool is unregistered. So nothing here unregisters synchronously: releases wait a macrotask (StrictMode’s mount, unmount, mount, or a route swap that keeps a tool, never touches WebMCP), then until the tool’s calls have settled, plus 500 ms for the answer to reach the agent. A tool that turns itself off still answers. The cursor is kept across StrictMode’s remount the same way.

See also

Was this page helpful?