---
slug: reference/react
description: "React bindings for WebMCP tools."
---

# `@webmcp-agents/react`

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.

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

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

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

```tsx title="components/clear-cart.tsx"
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](/docs/reference/polyfill), which `<WebAgentsProvider>` loads by itself where the browser has none. In development the provider also installs the [devtools](/docs/reference/devtools) panel: `@webmcp-agents/devtools` is a dependency of this package, so there is nothing else to install.

## APIs

| API | Description |
|---|---|
| [`WebAgentsProvider`](/docs/reference/react/web-agents-provider) | 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`](/docs/reference/react/use-web-tool) | Write a tool in a component: the definition, `execute`, an optional `target`. Returns `{ invoke, registered, supported }`. Includes `UseWebToolOptions`, `WebToolState`. |
| [`useWebAgents`](/docs/reference/react/use-web-agents) | The nearest provider's registry, cursor controls and pathname. Includes `useOptionalWebAgents`, `WebAgentsContextValue`, `WebAgentsVisuals`. |
| [`useEnabledTools`](/docs/reference/react/use-enabled-tools) | The catalog tool ids registered right now. |
| [`useAgentEvents`](/docs/reference/react/use-agent-events) | Every agent event while mounted. |
| [`usePathname`](/docs/reference/react/use-pathname) | The browser's pathname, followed without any router wiring. |
| [`useEnableTools`](/docs/reference/react/use-enable-tools) | Earlier form: enable catalog tools while a component is mounted. Includes the `EnableTools` component. |
| [`useToolAnswer`](/docs/reference/react/use-tool-answer) | 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](/docs/reference/react/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:

- [`defineWebTool`](/docs/reference/core/define-web-tool), with the types `WebTool`, `WebToolConfig`, `WebToolContext`, `WebToolCatalog`, `AvailableTools`, `ToolLocator`, `FieldTarget`, `Register`
- [`waitingForUser`](/docs/reference/core/waiting-for-user)
- [`WebToolError`](/docs/reference/core/web-tool-error)
- [`ToolErrorCode`](/docs/reference/core/tool-error) (type)

## 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

- [Installation](</docs/installation>) and [Define a tool](/docs/build/define-a-tool), the path that teaches these APIs
- [`@webmcp-agents/core`](/docs/reference/core)
- [The polyfill](/docs/reference/polyfill)
- [`@webmcp-agents/tools`](/docs/reference/tools) (common tools for the catalog)
- Example apps: `examples/playground`, `examples/ecommerce`, `examples/flights`, `examples/nextjs`
