Feature · WebMCP
WebMCP, both sides.
WebMCP is the W3C standard for how a page exposes tools to AI agents. Every other player sits on one side of it. Dornick sits on both — it calls your page's tools as a client, publishes its own as a provider, and ships the polyfill so both work today.
WebMCP is the W3C draft for how a web page exposes
typed, callable tools to AI agents, through
document.modelContext. Dornick is the only runtime that
sits on both sides of it: it calls the page's tools as a client, and
publishes its own as a provider — generated from configuration you
already wrote.
Everyone else is on one side
| Who | Their side | What they can't do |
|---|---|---|
Shopify, Cloudflare, any site adding <form toolname> | provider | nothing calls those tools from inside the page |
| Chrome's built-in agent | consumer | you can't build on it, or ship it |
MCP-B (@mcp-b/*) | provider plumbing | it has no agent of its own |
| CopilotKit, Stagehand, Vercel AI SDK | neither | not on the standard at all |
Consuming: the page's tools become the agent's tools
On by default. Every tool registered on document.modelContext
is adopted into Dornick's tool registry under a webmcp__
prefix and re-synced whenever the page fires toolchange.
The agent calls them directly — no DOM scraping, no selector guessing.
// The page registered "add_to_cart" — however it was built.
// Dornick's agent now has a real tool called webmcp__add_to_cart.
const dornick = new Dornick({ config, transport }); // webmcp defaults to on
dornick.attach(form); Adopted tools are always treated as untrusted, whatever the page claims about itself. Their output is fenced and screened for prompt injection before it reaches the model, and side-effecting tools are denied unless you supply a confirmation handler.
Publishing: your config is already the tool schema
This is the part that costs you nothing. Dornick already knows your data points, so it generates the provider surface from them.
new Dornick({ config, transport, webmcp: { publish: true } });
// Registers onto document.modelContext:
// dornick_tree · dornick_read · dornick_ls · dornick_grep — read-only workspace verbs
// dornick_set_email, dornick_set_plan, … — one per configured dataPoint
// dornick_ask — talk to the running agent
Each setter's JSON Schema comes from the type,
pattern, and allowedValues you already wrote in
your config. Writes route through the virtual filesystem, so your
beforeFieldFill hooks and ACLs still apply — nothing
touches the DOM directly. Read-only by default; you widen it explicitly.
Declarative tools, from HTML attributes
WebMCP also has an attribute form, and Dornick's polyfill implements it —
including SubmitEvent.agentInvoked and
respondWith(). It works against a native implementation
with no polyfill loaded at all.
<form toolname="search-cars"
tooldescription="Search the inventory by make and model"
toolautosubmit>
<input name="make" toolparamdescription="e.g. BMW, Ford" required>
<button type="submit">Search</button>
</form>
Field types map to JSON Schema the way you'd expect —
type=number with min/max/step
becomes minimum/maximum/multipleOf,
a <select> becomes an enum, required
populates required[]. Password and file inputs are left out:
the first for safety, the second because it can't be set programmatically.
Native vs polyfilled — the part we won't overstate
@dornick/webmcp is zero-dependency and never clobbers: it
stands down for a native implementation and for another vendor's
polyfill. But a polyfill is page JavaScript, and native
document.modelContext is a browser IPC surface.
| Environment | Who can see your tools |
|---|---|
Chrome 149+ with the origin trial or chrome://flags/#enable-webmcp-testing | the browser's own agent, extensions, DevTools, page script |
| Anything else (polyfilled) | extensions, CDP/Playwright drivers, the MCP relay, page script — not a browser-native agent |
The polyfill buys you one authoring API that works everywhere today, and extension reach. It does not buy browser-agent reach, and no polyfill can. Check which you have:
dornick.capabilities.current.apis.webmcp.implementation
// "native" | "polyfill" | "none" Going native
- Production: register for the WebMCP origin trial
(Chrome 149–156) and add the token to your page as
<meta http-equiv="origin-trial" content="…">. - Local development: enable
chrome://flags/#enable-webmcp-testing. - Debugging: Chrome 149+ ships a WebMCP panel in DevTools → Application. It lists registered tools, shows their schemas, and lets you invoke one by hand — the fastest way to check your schema is what you think it is.
Make your page agent-ready this afternoon.
Drop in Dornick, set publish: true, and your existing config becomes a tool surface any agent can call.