Skip to main content
@mcp-b/webmcp-extension installs WebMCP from a Chromium extension and connects an isolated content script to the page’s imperative and declarative tools. It returns the official MCP Client; websites continue to use document.modelContext and annotated HTML forms.
Package metadata

Installation

Install packages

Extension layout

The template declares two static document_start content scripts. Chrome 111 or newer is required for world: "MAIN".
manifest.json
The template omits all_frames, extension API permissions, a background worker, and web_accessible_resources. It targets matching top-level pages.

MAIN-world entry

The MAIN-world bundle only installs the runtime:
src/main-world.ts
Website code uses the native-shaped page API directly:
Page code
See the WebMCP standard API for a page-facing quick reference and a link to the authoritative Community Group draft.

Declarative form tools

The MAIN-world runtime also discovers annotated forms:
Page form
@mcp-b/global adopts native declarative behavior when available and installs the polyfilled form runtime otherwise. Form tools and JavaScript registrations both appear in the isolated client’s listTools() result and run through callTool(). listChanged.tools reports form additions, definition changes, and removals. The extension package adds no separate DOM scanner or declarative client API. See the declarative API reference for the upstream behavior and the polyfill’s documented compatibility boundary.

Document-tree scope

The template injects its MAIN-world runtime and isolated client into top-level pages only. Native Chrome’s getTools() still includes tools owned by same-origin active documents in the same frame tree. The extension client can therefore list and call both JavaScript and declarative form tools from same-origin child documents without child-frame injection. The polyfilled path discovers only the top document. Cross-origin imperative tools require allow="tools", child registration with exposedTo, and a caller-supplied fromOrigins list. The extension client does not supply that list. Declarative forms currently have no equivalent cross-origin exposure attribute. See the WebMCP standard API and Chrome’s cross-origin iframe guidance. MCP tool names are global within one client connection. Use unique names across the frame tree. Chrome resolves executeTool() with null when a tool triggers navigation. The extension client reports that call as interrupted. It does not preserve the call across document navigation or read JSON-LD from the destination document. For a declarative tool that must return a result without navigation, cancel the submission and use SubmitEvent.respondWith(). The upstream declarative explainer tracks the unresolved cross-document response design.

Isolated content-script entry

src/content-script.ts
client is the official Client from @modelcontextprotocol/client, not a package-specific wrapper.

connectWebMCPClient()

Signature
The helper:
  1. Creates the official MCP Client with automatic protocol version negotiation.
  2. Applies the supplied ClientOptions.
  3. Connects a TabClientTransport with targetOrigin set to window.location.origin.
  4. Resolves with the connected client.
Use the returned client’s listTools(), callTool(), and close() methods. The second argument also accepts official client features such as listChanged.tools; the template uses it to follow tools registered after page hydration.

Template build

The published package includes a copyable template directory. Its build requires Node 22.12 or newer.
Build the template
Load the generated dist/ directory as an unpacked extension. The Vite+ config bundles both entries as self-contained, minified IIFEs targeting Chrome 111 and copies manifest.json into dist/. Content scripts cannot load bare npm imports at runtime.

Security and scope

MAIN-world code shares the website’s JavaScript environment. Keep secrets, credentials, and privileged Chrome API calls out of the MAIN-world bundle. The client pins messages to window.location.origin, but this routing check is not authentication. Same-page code can observe or forge the channel. Treat page tool metadata, arguments, and results as untrusted. Authorize privileged actions from trusted extension state, never from page-provided values alone.
  • Narrow the manifest match patterns before publishing.
  • The template injects into top-level pages only. Native Chrome can still discover same-origin child-document tools.
  • Add icons and Chrome Web Store listing metadata before publishing.
For the broader threat model, see Security and human control.