{"_id":"use-webmcp-tool","_rev":"4-8d61591e705799926df9ef5f1da0675d","name":"use-webmcp-tool","dist-tags":{"latest":"0.3.0"},"versions":{"0.0.1":{"name":"use-webmcp-tool","version":"0.0.1","keywords":["webmcp","mcp","react","hooks","model-context"],"author":{"name":"Sarah Drasner"},"license":"Apache-2.0","_id":"use-webmcp-tool@0.0.1","maintainers":[{"name":"sdras","email":"sarah.drasner@gmail.com"}],"dist":{"shasum":"ba7b96c8761e251a06922f18b9b060da52d15479","tarball":"https://registry.npmjs.org/use-webmcp-tool/-/use-webmcp-tool-0.0.1.tgz","fileCount":2,"integrity":"sha512-g+bYNyKTwt3Yiu1nVOxGTQOOLaJv9mfxZ2YBLZZmCCeY5/oLDCi3KyE/oZ5j98tIZ7onPylhM5zwCMYvrfS5fg==","signatures":[{"sig":"MEUCIQD/MndhsFrJUBXHW58qanX1OvRPO1wgTLYAF2eyQA84awIgMC3/qzouM+WEtbHoj4pIVCir3Fc+B7odbx6s4UL7IzQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":707},"_npmUser":{"name":"sdras","email":"sarah.drasner@gmail.com"},"_npmVersion":"11.7.0","description":"Placeholder for useWebMCP — a React hook for registering WebMCP tools (document.modelContext). Official release coming soon under the use-webmcp package.","directories":{},"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/use-webmcp-tool_0.0.1_1784486752168_0.042475044164497655","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"use-webmcp-tool","version":"0.1.0","keywords":["webmcp","mcp","react","react-hook","hooks","model-context","modelcontext","ai","agent"],"author":{"name":"Sarah Drasner"},"license":"Apache-2.0","_id":"use-webmcp-tool@0.1.0","maintainers":[{"name":"sdras","email":"sarah.drasner@gmail.com"}],"homepage":"https://github.com/GoogleChromeLabs/use-webmcp-tool#readme","bugs":{"url":"https://github.com/GoogleChromeLabs/use-webmcp-tool/issues"},"dist":{"shasum":"3592927756027320dbc6d198eb3a72476b5a9dc8","tarball":"https://registry.npmjs.org/use-webmcp-tool/-/use-webmcp-tool-0.1.0.tgz","fileCount":5,"integrity":"sha512-Hrd18h3v3rntF/dHeSpNeRjW9VGdx9v5zHc0DiMd6OAdJokDADhjobxEbgVgvADspB2OZ4rTo+8O3xwCINb86g==","signatures":[{"sig":"MEUCICW6oaM/3hd8U02Q4sNQorh/4m2BlgNG4f1RyCzmOOiIAiEA5HVzQhmlDPechvkA6urTkTrbsqAcM6o8LcEWDxmsb3w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23565},"main":"./useWebMCP.js","type":"module","types":"./useWebMCP.d.ts","module":"./useWebMCP.js","exports":{".":{"types":"./useWebMCP.d.ts","default":"./useWebMCP.js"}},"gitHead":"6daf3f8e448c0158832fd77399d069bd98cd0f20","scripts":{"test":"vitest run"},"_npmUser":{"name":"sdras","email":"sarah.drasner@gmail.com"},"repository":{"url":"git+https://github.com/GoogleChromeLabs/use-webmcp-tool.git","type":"git"},"_npmVersion":"11.7.0","description":"React hook for registering WebMCP tools (document.modelContext) with lifecycle-managed registration and MCP result normalization.","directories":{},"sideEffects":false,"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0","react":"^19.1.0","vitest":"^3.2.4","react-dom":"^19.1.0","@testing-library/react":"^16.3.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/use-webmcp-tool_0.1.0_1784681784032_0.6987380530930198","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"use-webmcp-tool","version":"0.2.0","keywords":["webmcp","mcp","react","react-hook","hooks","model-context","modelcontext","ai","agent"],"author":{"name":"Sarah Drasner"},"license":"Apache-2.0","_id":"use-webmcp-tool@0.2.0","maintainers":[{"name":"sdras","email":"sarah.drasner@gmail.com"}],"homepage":"https://github.com/GoogleChromeLabs/use-webmcp-tool#readme","bugs":{"url":"https://github.com/GoogleChromeLabs/use-webmcp-tool/issues"},"dist":{"shasum":"7154e4b5230128d24efc5f9aab4393b864969304","tarball":"https://registry.npmjs.org/use-webmcp-tool/-/use-webmcp-tool-0.2.0.tgz","fileCount":5,"integrity":"sha512-kYUpV1xFmX3Wnq68KOM1MbedpRc6mbgWEcVFtWpFPBTGEcuc7Sva4bHjRxM3k8mkGshkwxnLKn9/I4/NP2bTBw==","signatures":[{"sig":"MEUCIDrqcxAsY9Zyx/vDreYnMN1P+XF9KS9fCnWlMPUK9MDVAiEAk2dSldPkRcVXTGcSVx5RP51SeNip+oRC02BWtxblWpI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25183},"main":"./useWebMCP.js","type":"module","types":"./useWebMCP.d.ts","module":"./useWebMCP.js","exports":{".":{"types":"./useWebMCP.d.ts","default":"./useWebMCP.js"}},"gitHead":"25f120ac4c6ae77bcd000c733d6ff0ba8b0fd502","scripts":{"test":"vitest run"},"_npmUser":{"name":"sdras","email":"sarah.drasner@gmail.com"},"repository":{"url":"git+https://github.com/GoogleChromeLabs/use-webmcp-tool.git","type":"git"},"_npmVersion":"11.7.0","description":"React hook for registering WebMCP tools (document.modelContext) with lifecycle-managed registration and MCP result normalization.","directories":{},"sideEffects":false,"_nodeVersion":"22.11.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0","react":"^19.1.0","vitest":"^3.2.4","react-dom":"^19.1.0","@testing-library/react":"^16.3.0"},"peerDependencies":{"react":">=18"},"_npmOperationalInternal":{"tmp":"tmp/use-webmcp-tool_0.2.0_1785419810629_0.12321309244243839","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"use-webmcp-tool","version":"0.3.0","description":"React hook for registering WebMCP tools (document.modelContext) with lifecycle-managed registration and MCP result normalization.","type":"module","main":"./useWebMCP.js","module":"./useWebMCP.js","types":"./useWebMCP.d.ts","exports":{".":{"types":"./useWebMCP.d.ts","default":"./useWebMCP.js"}},"sideEffects":false,"scripts":{"test":"vitest run"},"repository":{"type":"git","url":"git+https://github.com/GoogleChromeLabs/use-webmcp-tool.git"},"homepage":"https://github.com/GoogleChromeLabs/use-webmcp-tool#readme","bugs":{"url":"https://github.com/GoogleChromeLabs/use-webmcp-tool/issues"},"keywords":["webmcp","mcp","react","react-hook","hooks","model-context","modelcontext","ai","agent"],"author":{"name":"Sarah Drasner"},"license":"Apache-2.0","peerDependencies":{"react":">=18"},"devDependencies":{"@testing-library/react":"^16.3.0","jsdom":"^26.1.0","react":"^19.1.0","react-dom":"^19.1.0","vitest":"^5.0.0"},"dependencies":{"webmcp-types":"^0.1.7"},"gitHead":"9f0dc6eddf88cff65ebe877f199d4547e74ab31e","_id":"use-webmcp-tool@0.3.0","_nodeVersion":"22.11.0","_npmVersion":"11.7.0","dist":{"integrity":"sha512-iwO5KbSdDzcV33PSCZw4baclCD3tEU4drdXAeeKfTCM/+F5t+LAug14UXbYKD3K3tWxBiYCuDuWXmm/q1ZSDjw==","shasum":"70048d862d2d8c537701f6068d4b4c595fb95528","tarball":"https://registry.npmjs.org/use-webmcp-tool/-/use-webmcp-tool-0.3.0.tgz","fileCount":5,"unpackedSize":25725,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDG8+mGbavDQTI71IoY4oibJ2wQzFWpQ4Rb0IGRbimCzgIgdYORu4rZSvYnlM2u8sJk9/0Qufn0ZkC1Chd06zlOMmg="}]},"_npmUser":{"name":"sdras","email":"sarah.drasner@gmail.com"},"directories":{},"maintainers":[{"name":"sdras","email":"sarah.drasner@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/use-webmcp-tool_0.3.0_1789095597276_0.06789615744359279"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-19T18:45:52.117Z","modified":"2026-09-11T02:59:57.596Z","0.0.1":"2026-07-19T18:45:52.298Z","0.1.0":"2026-07-22T00:56:24.183Z","0.2.0":"2026-07-30T13:56:50.764Z","0.3.0":"2026-09-11T02:59:57.419Z"},"bugs":{"url":"https://github.com/GoogleChromeLabs/use-webmcp-tool/issues"},"author":{"name":"Sarah Drasner"},"license":"Apache-2.0","homepage":"https://github.com/GoogleChromeLabs/use-webmcp-tool#readme","keywords":["webmcp","mcp","react","react-hook","hooks","model-context","modelcontext","ai","agent"],"repository":{"type":"git","url":"git+https://github.com/GoogleChromeLabs/use-webmcp-tool.git"},"description":"React hook for registering WebMCP tools (document.modelContext) with lifecycle-managed registration and MCP result normalization.","maintainers":[{"name":"sdras","email":"sarah.drasner@gmail.com"}],"readme":"# Use-Webmcp-Tool\n\nA hook that registers a [WebMCP](https://github.com/webmachinelearning/webmcp) tool with the browser and ties its lifecycle to a React component.\n\n> This is maintained by Chrome, and will be updated with any spec changes. The spec is `🧪` experimental, so the hook feature-detects and degrades to a no-op everywhere the API is absent.\n\n**Status / accuracy note (2026-06-05):** Built against the current WebMCP spec, which exposes the imperative API on **`document.modelContext`** (`registerTool` + an `AbortSignal` for unregistration).\n\n---\n\n## Install\n\n```bash\nnpm install use-webmcp-tool\n```\n\nRequires React 18+ as a peer dependency. Ships as ESM with TypeScript types included — no runtime dependencies.\n\n---\n\n## What it does\n\nWebMCP lets a page expose JavaScript functions as \"tools\" that an AI agent (browser-built-in, iframe-hosted, or extension) can discover and call. The site author can expose functionality, and the agent uses this instead of scraping the DOM, a11y tree, or using screenshots.\n\nThe raw imperative API looks like this:\n\n```js\nconst controller = new AbortController();\n\ndocument.modelContext.registerTool({\n  name: \"add-todo\",\n  description: \"Add a new item to the user's active todo list\",\n  inputSchema: {\n    type: \"object\",\n    properties: {\n      text: { type: \"string\", description: \"The text content of the todo item\" },\n    },\n    required: [\"text\"],\n  },\n  async execute({ text }) {\n    await addTodoItemToCollection(text);\n    return { content: [{ type: \"text\", text: `Added todo item: \"${text}\" successfully.` }] };\n  },\n}, { signal: controller.signal });\n\n// Unregister later:\ncontroller.abort();\n```\n\n`useWebMCP` wraps that imperative, lifecycle-bound API in the declarative, lifecycle-managed model React developers already use for everything else:\n\n```jsx\nimport { useWebMCP } from \"use-webmcp-tool\";\n\nfunction TodoTools({ addTodo }) {\n  const { supported, registered } = useWebMCP({\n    name: \"add-todo\",\n    description: \"Add a new item to the user's active todo list\",\n    inputSchema: {\n      type: \"object\",\n      properties: {\n        text: { type: \"string\", description: \"The text content of the todo item\" },\n      },\n      required: [\"text\"],\n    },\n    async execute({ text }) {\n      addTodo(text);\n      return `Added todo item: \"${text}\" successfully.`;\n    },\n  });\n\n  if (!supported) return null;\n  return <p>{registered ? \"🤖 Agent tools ready\" : \"…\"}</p>;\n}\n```\n\nThe tool is registered when the component mounts and **unregistered automatically when it unmounts**. This is designed so that the set of tools an agent sees stays in lockstep with what is actually on screen.\n\n---\n\n## API\n\n```ts\nconst { supported, registered, error } = useWebMCP({\n  name,           // string — tool identifier (required)\n  description,    // string — natural-language description for the agent (required)\n  inputSchema,    // JSON Schema object describing args (optional)\n  annotations,    // WebMCP.ToolAnnotations object with readOnlyHint/untrustedContentHint/consequentialHint (optional)\n  execute,        // (args, { signal }) => result | Promise<result> (required)\n  enabled = true, // boolean — register only while true\n  formatOutput,   // (result, args) => any — optional shaper before MCP normalization\n  onError,        // (error) => void — optional side-effect when execute throws\n});\n```\n\n**Returns**\n\n| field        | type             | meaning                                                              |\n| ------------ | ---------------- | -------------------------------------------------------------------- |\n| `supported`  | `boolean`        | `document.modelContext` exists in this environment.                  |\n| `registered` | `boolean`        | The tool is currently registered with the browser.                   |\n| `error`      | `Error \\| null`  | Registration error, e.g. `NotAllowedError` from a `tools` permissions policy. |\n\n**`execute` parameters & return values**:\n\n`execute` receives `(args, { signal })`, where `signal` is an [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) provided by the browser/agent to handle cancellation if the call is aborted or timed out.\n\nReturn values are normalized:\n\n- a **string** → `{ content: [{ type: \"text\", text }] }`\n- **`undefined`/`null`** (no return) → `{ content: [] }` (success, no payload)\n- a value that is **already** `{ content: [...] }` → passed through untouched\n- a **thrown value** — Error or not (`throw \"not signed in\"`, `throw { code: 403 }` both count) → `{ content: [{ type: \"text\", text }], isError: true }`, after `onError`. A failure must never read as success to the agent.\n- a **returned `Error`** → treated exactly like a throw: `onError` fires, then an `isError` result\n- anything else (object/array/number) → JSON-serialized into a text block\n\n---\n\n## Tests\n\n[`useWebMCP.test.jsx`](./useWebMCP.test.jsx) (vitest + jsdom + `@testing-library/react`, 29 tests) covers the registration lifecycle (mount/unmount, StrictMode, `enabled`, late injection, registration errors), re-registration identity (execute changes don't churn, content-equal schemas don't churn, name changes do), options and cancellation signals (`execute(args, { signal })`), and the full result/error normalization matrix including thrown non-Errors and returned `Error`s. \n\nRun with `npm install && npm test`.","readmeFilename":"README.md"}