> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mcp-b.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# @mcp-b/webmcp-polyfill reference

> API reference for the upstream WebMCP polyfill bundled by @mcp-b/webmcp-polyfill.

`@mcp-b/webmcp-polyfill` bundles the upstream
[webmachinelearning/webmcp-polyfill](https://github.com/webmachinelearning/webmcp-polyfill)
at revision `439c6c341f1c632c63498ba206e2bd8471cb8efb`. It installs the
standard `document.modelContext` runtime when the browser does not provide one.
The [WebMCP draft](https://webmachinelearning.github.io/webmcp/) and upstream
package define the core API.

This package temporarily adds [declarative tools](#declarative-tools) and their
`SubmitEvent` extensions until upstream supports them. Use
[`@mcp-b/global`](/packages/global/reference) for transports, prompts, resources,
and MCP `outputSchema` support.

## Package entries

| Import | Purpose |
| - | - |
| `@mcp-b/webmcp-polyfill` | ESM installer for the bundled upstream runtime |
| `@mcp-b/webmcp-polyfill/iife` | Script bundle that installs the runtime when loaded |

The standalone bundle installs `document.modelContext` automatically:

```html "Load the polyfill" theme={null}
<script src="https://unpkg.com/@mcp-b/webmcp-polyfill@6/dist/index.iife.js"></script>
```

## Minimal example

```ts "Install and register a tool" theme={null}
import { installWebMCP } from '@mcp-b/webmcp-polyfill';

installWebMCP();

const context = document.modelContext;
if (!context) throw new Error('WebMCP is unavailable');

await context.registerTool({
  name: 'get_page_title',
  description: 'Get the current page title',
  inputSchema: { type: 'object', properties: {} },
  execute() {
    return { title: document.title };
  },
});
```

## `installWebMCP()`

Call the installer before registering tools. Installation is idempotent and
preserves an existing native context. It does nothing when the browser document
is unavailable, on an insecure page, or below the
[browser baseline](#browser-baseline). Importing the ESM entry does not install
the runtime as a side effect. The script bundle exposes the installer as
`WebMCPPolyfill.installWebMCP`.

## Core runtime

The installed `document.modelContext` implementation comes from the pinned
upstream package. Use the upstream
[API reference](https://webmachinelearning.github.io/webmcp/) for method
signatures and behavior. The polyfill follows the current object-input
`executeTool()` shape and supports registration cancellation through
`AbortSignal`.

The package does not provide:

* `cleanupWebMCPPolyfill()` or another uninstall operation.
* A `navigator.modelContext` alias or `navigator.modelContextTesting` shim.
* MCP `outputSchema` metadata.
* MCP prompts, resources, or transports.

For MCP features, use [`@mcp-b/global`](/packages/global/reference).
The upstream context and the declarative layer remain installed for the lifetime
of the document.

MCP-B schema conversion and response helpers are exported by the
[`@mcp-b/webmcp-ts-sdk/schema` adapter](/packages/webmcp-ts-sdk/reference#schema-boundary).
The polyfill's `document.modelContext.registerTool()` follows WebMCP and does
not validate invocation arguments.

## Declarative tools

The declarative layer registers a tool for each form with `toolname` and
`tooldescription` in the document and its open shadow roots. `tooltitle` sets
the tool title. The input schema comes from the form's named controls;
`toolparamdescription` on a control or its fieldset describes the parameter.

```html "Declarative form" theme={null}
<form toolname="search_catalog" tooldescription="Search the product catalog" toolautosubmit>
  <input name="query" required toolparamdescription="Words to match" />
  <button type="submit">Search</button>
</form>

<script>
  document.querySelector('form').addEventListener('submit', (event) => {
    if (!event.agentInvoked) return;

    event.preventDefault();
    event.respondWith(Promise.resolve({ matches: [] }));
  });
</script>
```

An invocation fills the controls and dispatches `input` and `change` events.
Without `toolautosubmit`, it focuses the first enabled submit button and waits
for the user to submit; a form with no submit button rejects. With
`toolautosubmit`, it runs constraint validation and calls `requestSubmit()`
before `toolactivated` fires.

| Behavior | Description |
| - | - |
| Submit hooks | The agent-invoked submit event reports `agentInvoked` as `true`. Call `preventDefault()` and `respondWith(promise)` to answer; `respondWith()` throws `InvalidStateError` outside an agent-invoked submit or without `preventDefault()`. |
| Results | JSON strings like every `executeTool()` result. `respondWith(Promise.resolve('sent'))` resolves as `"sent"`; a submission without `respondWith()` resolves as `null`. |
| Events | `document.modelContext` fires `toolactivated` once the form is filled and `toolcancel` when the `executeTool()` signal aborts. Both are plain `Event` instances with a `toolName` property. |
| Cancellation | Aborting the signal rejects with the abort reason and clears the agent attribution, so a later user submission reports `agentInvoked` as `false`. Reset, registration changes, removal, and a new invocation also reject a pending call. |
| Failures | Validation, unknown or invalid parameters, a missing submit button, and a rejected response reject with the generic `UnknownError: Tool execution failed`. Resolve `respondWith()` with an error description when agents need details. |
| Native context | When the browser provides `document.modelContext` without `SubmitEvent.agentInvoked` and `respondWith`, the layer installs the hooks and registers tools on that context. A native context that already has them keeps declarative tools. |

The layer does not emulate the `:tool-form-active` and `:tool-submit-active`
pseudo-classes and skips closed shadow roots, file inputs, and form-associated
custom elements. The [declarative API page](/reference/webmcp/declarative-api)
links the proposal and Chrome sources.

## Browser baseline

`installWebMCP()` installs only when the engine provides every API the vendored
core calls. Otherwise it returns without defining `document.modelContext`, so
`if (!document.modelContext)` remains a valid feature check.

| API | Chrome | Firefox | Safari |
| - | - | - | - |
| `String.prototype.toWellFormed` | 111 | 119 | 16.4 |
| `AbortSignal.any()` | 116 | 124 | 17.4 |
| `Promise.withResolvers()` | 119 | 121 | 17.4 |
| `URL.parse()` | 126 | 126 | 18 |

The resulting floor is Chrome 126, Firefox 126, and Safari 18.

<Card title="WebMCP draft" icon="book" href="https://webmachinelearning.github.io/webmcp/">
  Read the current Community Group report.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.