Skip to main content
@mcp-b/webmcp-polyfill installs the core WebMCP producer API when the browser does not provide it. It does not add MCP prompts, resources, transport, or an MCP server; use @mcp-b/global for that bridge.

Package entries

The IIFE reads window.__webMCPPolyfillOptions before initialization and exposes the package exports on window.WebMCPPolyfill.

initializeWebMCPPolyfill(options?)

The ESM entry does not initialize as an import side effect. The function returns without changing anything outside a secure browser context or when document.modelContext already exists. When only the deprecated navigator.modelContext exists, initialization exposes that same context on document.modelContext. It does not install a testing shim in this adoption path.

Options

The polyfill never replaces an existing testing implementation.

cleanupWebMCPPolyfill()

Removes polyfill registrations, detaches their abort listeners, and restores the previous descriptors for window.ModelContext, document.modelContext, navigator.modelContext, and navigator.modelContextTesting.

Installed core surface

registerTool(tool, options?)

options.signal owns the registration. Aborting it removes the tool and emits a toolchange event. unregisterTool() is not exposed. options.exposedTo is validated, but a non-empty array rejects with NotSupportedError because a local polyfill cannot securely expose tools across document origins.

getTools(options?)

Returns a sorted Promise<RegisteredTool[]>. Each record contains name, title, description, window, origin, and an optional inputSchema JSON Schema object and annotations. An empty fromOrigins array discovers the current document’s tools. A non-empty array rejects with NotSupportedError; native WebMCP is required for cross-document discovery.

ontoolchange

ModelContext is an EventTarget. Use addEventListener('toolchange', ...) or assign document.modelContext.ontoolchange.

executeTool(tool, inputJson, options?)

The polyfill implements the serialized-JSON execution signature used by current Chrome builds. The live proposal includes executeTool() with a different draft signature. Feature-detect the package method through ChromeModelContext:
Invalid JSON, unknown tools, detached documents, disallowed Permissions Policy, and aborted calls reject instead of invoking the handler.

Declarative forms

When this package creates document.modelContext, it observes the current document and its open shadow roots for forms with toolname and tooldescription. It registers each form as a tool and derives its input schema from native named controls. Changes that affect the generated tool update the registration. tooltitle supplies an optional display title. toolparamdescription overrides the description derived from a control’s label or aria-description.
Invocations fill controls and dispatch input and change events. Without toolautosubmit, the polyfill focuses the first enabled submit button and waits for the user to submit. With toolautosubmit, it applies native constraint validation and calls requestSubmit(). Agent-triggered submit events expose SubmitEvent.agentInvoked and SubmitEvent.respondWith(); toolactivated fires on window after the controls are filled. Removing a declarative form unregisters its tool. Changes to its registration attributes or generated schema replace the registration. Resetting, removing, or replacing a registration cancels a pending invocation. Tool names must be unique; duplicate names expose one form. Chrome’s declarative API documentation defines the current compatibility target. This package covers the tested subset described above. CI runs the upstream declarative Web Platform Tests against the standalone polyfill. The Community Group draft’s declarative section is still incomplete.

Compatibility surfaces

document.modelContext is canonical. The polyfill also installs the repository’s deprecated navigator.modelContext alias and logs once when it is read. When installTestingShim is true, navigator.modelContextTesting provides: This surface exists for older browser tests. Native coverage should prefer getTools() and feature-detected executeTool(). Follow the Chrome imperative API for the current browser signature.

Schema entry

normalizeInputSchema() on @mcp-b/webmcp-polyfill/schema converts plain JSON Schema and Standard Schema v1 implementations that expose ~standard.jsonSchema.input(). MCP-B runtimes use the converted JSON Schema for browser metadata and preserve ~standard.validate() for the MCP SDK when it is available. The public schema entry exports these low-level adapter groups: The document.modelContext.registerTool() boundary does not perform this conversion or validate invocation arguments. It follows WebMCP and serializes the registered JSON Schema metadata.

Runtime limits

  • Cross-document exposure and discovery require native WebMCP.
  • Declarative forms run only when this package installs the context. An existing native context keeps ownership of its declarative behavior.
  • The polyfill does not emulate the native :tool-form-active or :tool-submit-active CSS pseudo-classes, the toolcancel event, or cross-navigation response extraction.
  • Closed shadow roots cannot be inspected.
  • File inputs and custom form-associated elements are omitted from synthesized declarative schemas.
  • The polyfill enforces the tools Permissions Policy where the browser exposes that feature. Cross-origin frames fail closed when it does not.
  • navigator.modelContextTesting is opt-in and testing-only.
  • provideContext(), clearContext(), and unregisterTool() are absent.

WebMCP draft

Read the current community group report.