{"id":18941,"plugin_id":"plugins_6a8ebee3dc2c819198e336f2a2ead981","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:15:04.203Z","digest":"ceec1e2557a45b5144450a1844b05f8b53f202edaf378c00a55209682f6bec80","against":null,"payload":{"description":"Make a website usable by in-browser AI agents with WebMCP. Plan which paths to expose, then ship them as declarative form annotations, dedicated imperative tools, or a bridge to an existing MCP server. Use when the user mentions WebMCP, document.modelContext, navigator.modelContext, registerTool, webmcp-proxy, or browser agents.","included_files":[{"relative_path":"references/declarative-forms.md","size_in_bytes":3216},{"relative_path":"references/frameworks.md","size_in_bytes":2918},{"relative_path":"references/proxy-existing-mcp.md","size_in_bytes":3122},{"relative_path":"references/runtime.md","size_in_bytes":1948},{"relative_path":"references/security.md","size_in_bytes":1599},{"relative_path":"references/strategies.md","size_in_bytes":3570},{"relative_path":"references/tool-design.md","size_in_bytes":3438},{"relative_path":"references/verify.md","size_in_bytes":2131}],"name":"webmcp","skill_md_contents":"---\nname: webmcp\ndescription: >-\n  Make a website usable by in-browser AI agents with WebMCP. Plan which paths\n  to expose, then ship them as declarative form annotations, dedicated\n  imperative tools, or a bridge to an existing MCP server. Use when the user\n  mentions WebMCP, document.modelContext, navigator.modelContext, registerTool,\n  webmcp-proxy, or browser agents.\n---\n\n# WebMCP — make a website agent-compatible\n\nWebMCP lets a **page** register tools that in-browser AI agents can call. It is\n**not** a remote MCP server and **not** an MCP App / ChatGPT widget.\n\nCanonical surface: `document.modelContext.registerTool(...)`.\nFallback (deprecated): `navigator.modelContext`.\nDeclarative surface: HTML `<form>` attributes (`toolname`, `tooldescription`).\n\n## When this skill applies\n\n- User asks to make a site / app **WebMCP compatible**\n- Mentions `document.modelContext`, `navigator.modelContext`, `registerTool`,\n  `webmcp-proxy`, or declarative form tools\n- Wants browser agents to use page actions without DOM scraping\n\n**Do not use this skill** for building remote MCP servers, ChatGPT/Claude MCP\nApps, or Skybridge UIs.\n\n## Workflow (follow in order)\n\nCopy and track:\n\n```\nWebMCP Progress:\n- [ ] 1. Design: inventory + strategy + paths (stop for user agreement)\n- [ ] 2. Wire runtime (native / polyfill) if the chosen strategy needs JS\n- [ ] 3. Implement the agreed strategy (Declarative / Imperative / Bridge)\n- [ ] 4. Dogfood with Chrome DevTools MCP\n- [ ] 5. Harden (security, lifecycle, errors)\n```\n\n**Do not implement until step 1 is agreed.** Path choice is a product decision.\n\n### 1. Design — UX paths worth exposing\n\nRead [references/strategies.md](references/strategies.md) first.\n\nTalk to the user. Propose; do not assume. Goal: a **short list of paths** and\n**which strategy** ships each one.\n\n1. Find the browser entry (HTML shell, `main.tsx`, router root) and stack\n   (vanilla / React-Next / Vue / other). If several apps exist, ask which one\n   first.\n2. Inventory, then **ask**:\n   - What jobs should a browsing agent complete on this site?\n   - Are there existing HTML `<form>`s that should become tools as-is?\n   - Is there already a remote MCP server with the right tools/paths?\n   - Which human tunnels (checkout, onboarding, booking) should collapse into\n     one agent tool instead of step-by-step forms?\n3. Present **Declarative vs Imperative vs Bridge** (mix OK; first ship should\n   stay small). Use the user’s domain in the examples.\n\n**Declarative — expose existing forms as tools.** Add missing WebMCP meta on\nexisting form DOM (`toolname`, `tooldescription`, `toolparamdescription`,\noptional `toolautosubmit`) so each form is a declarative tool. Fast, visual\n(browser fills the form). See [references/declarative-forms.md](references/declarative-forms.md).\n\n**Imperative — craft dedicated paths.** Unlike Declarative tools (via form),\n`registerTool` packages a real agent path. Example: a 4-step checkout tunnel as\n**one** tool from step 1 that fills everything and redirects to the last step.\nPlan with the user: which scenarios, what **input**, what **UI/state outcome**.\nSee [references/tool-design.md](references/tool-design.md).\n\n**Bridge — expose an existing MCP server.** Reuse the tools and paths already\ndesigned for a shipped MCP server. `webmcp-proxy` is a fast first patch that\nregisters those tools on WebMCP for any AI browsing agent. It **lacks visual\nfeedback** in the browser. It **can leverage existing webapp credentials** if\nthe MCP server uses the **same OAuth client**. See\n[references/proxy-existing-mcp.md](references/proxy-existing-mcp.md).\n\n4. Write back a proposal and wait for a yes / edits:\n\n```\nProposed WebMCP paths:\n- [strategy] path — input → UI/state outcome\n- …\nOut of scope this round: …\n```\n\n5. Only then implement. If the user is unsure, recommend: **Bridge** if an MCP\n   server already exists; **Declarative** if the site is form-heavy;\n   **Imperative** for the one high-value tunnel they care about.\n\n### 2. Wire the runtime\n\nSkip a polyfill for **Declarative only** if you are not registering JS tools.\nImperative and Bridge need `document.modelContext` (native or polyfill).\n\n```js\nfunction getModelContext() {\n  return document.modelContext ?? navigator.modelContext ?? null;\n}\n```\n\n| Situation | What to do |\n| --- | --- |\n| Target browsers with native WebMCP | Feature-detect; graceful no-op if missing |\n| Need tools without native support | `@mcp-b/webmcp-polyfill` (or `@mcp-b/global`) **before** register/proxy |\n| Bridge (existing MCP HTTP/SSE) | `webmcp-proxy` — do not reimplement each tool |\n\nSecure context (HTTPS or localhost) is required.\nDetails: [references/runtime.md](references/runtime.md).\n\n### 3. Implement the agreed strategy\n\n#### Declarative\n\nPatch templates/components: attributes only, plus optional `respondWith` if the\nagent should get a structured result. Do not rewrite forms into JS tools unless\nthe user switched to Imperative.\n\n#### Imperative\n\nDefault = **imperative API**. Snippets:\n[references/frameworks.md](references/frameworks.md).\n\n```js\nconst mc = document.modelContext ?? navigator.modelContext;\nif (!mc?.registerTool) {\n  // Browser has no WebMCP — leave human UI working; skip registration.\n} else {\n  const controller = new AbortController();\n\n  await mc.registerTool(\n    {\n      name: \"search_docs\",\n      title: \"Search docs\",\n      description:\n        \"Search published documentation by keyword and return up to five matches.\",\n      inputSchema: {\n        type: \"object\",\n        properties: {\n          query: {\n            type: \"string\",\n            description: \"Topic or phrase to search for.\",\n          },\n        },\n        required: [\"query\"],\n      },\n      annotations: {\n        readOnlyHint: true,\n        untrustedContentHint: false,\n      },\n      async execute({ query }, { signal }) {\n        const res = await fetch(\n          `/api/search?q=${encodeURIComponent(query)}`,\n          { signal },\n        );\n        if (!res.ok) {\n          throw new Error(`Search failed (${res.status}). Retry with a shorter query.`);\n        }\n        const hits = await res.json();\n        return { matches: hits.slice(0, 5) };\n      },\n    },\n    { signal: controller.signal },\n  );\n}\n```\n\nHard requirements for imperative tools:\n\n1. Feature-detect before `registerTool`\n2. Pass `{ signal }` on registration for cleanup\n3. Honor `execute`’s `{ signal }` for fetch / long work\n4. Set `annotations.readOnlyHint` accurately\n5. Set `untrustedContentHint: true` when return data comes from users / third parties\n6. Never embed agent instructions in `description` or return payloads\n7. Names: ASCII `[a-zA-Z0-9_.-]`, length 1–128; one tool = one agreed path\n\n#### Bridge\n\nInstall `webmcp-proxy`, point it at the MCP URL, confirm CORS and OAuth. Do not\nhand-wrap each remote tool.\nSee [references/proxy-existing-mcp.md](references/proxy-existing-mcp.md).\n\n### 4. Dogfood (mandatory)\n\nDo **not** call the work done until tools are exercised as an agent would.\n\nWith **Chrome DevTools MCP** (Chrome Dev 145+ / Canary preferred):\n\n1. Open the page (`navigate_page` / existing tab)\n2. `list_webmcp_tools` — confirm names match the agreed proposal\n3. `execute_webmcp_tool` with `toolName` + JSON `input` string for each tool\n4. Declarative: confirm fields fill and UI highlight. Bridge: confirm MCP\n   result (no DOM fill expected). Imperative: confirm UI/state outcome from\n   the proposal.\n5. Fix and re-run\n\nIf DevTools MCP isn’t available, use page console:\n\n```js\nconst tools = await document.modelContext.getTools();\nconsole.table(tools.map(t => ({ name: t.name, description: t.description })));\n```\n\nChecklist: [references/verify.md](references/verify.md).\n\n### 5. Harden\n\n- Destructive tools: confirm in UI or require explicit params\n- Auth: tools inherit the user’s cookies/session — scope to what the signed-in\n  user may do (Bridge: same OAuth client as the webapp when applicable)\n- Cross-origin iframes: parent needs `allow=\"tools\"`; child tools use\n  `exposedTo: ['https://parent.origin']` when sharing\n- Avoid returning secrets, raw PII dumps, or HTML that could prompt-inject\n\nMore: [references/security.md](references/security.md).\n\n## Decision tree\n\n```\nNeed WebMCP on this site?\n│\n├─ Ping-pong paths with the user first (never skip)\n│\n├─ Existing HTML forms that should stay forms?\n│    → Declarative: toolname / tooldescription\n│\n├─ Packaged agent scenario (tunnels, store updates, redirects)?\n│    → Imperative: registerTool\n│\n└─ Existing remote MCP tools to reuse on the page?\n     → Bridge: webmcp-proxy\n```\n\n## Sources of truth\n\n- Spec: https://webmachinelearning.github.io/webmcp/\n- Chrome imperative API: https://developer.chrome.com/docs/ai/webmcp/imperative-api\n- Chrome declarative API: https://developer.chrome.com/docs/ai/webmcp/declarative-api\n- Chrome best practices: https://developer.chrome.com/docs/ai/webmcp/best-practices\n- webmcp-proxy: https://www.npmjs.com/package/webmcp-proxy\n\n## Anti-patterns\n\n- Implementing before the user agrees on strategy and paths\n- Building a **server** MCP transport when the user asked for **page** tools\n- Reimplementing an existing MCP server in page JS instead of `webmcp-proxy`\n- Registering overlapping tools for the same job across Declarative / Imperative / Bridge\n- Using `navigator.modelContext` alone with no `document.modelContext` prefer\n- Calling `unregisterTool()` (removed) instead of aborting the registration signal\n- Returning DOM nodes / functions / circular structures from `execute`\n- Skipping DevTools dogfood because “it compiles”\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}