Summary: WebMCP lets sites declare callable tools instead of forcing agents to infer forms from the DOM, but Chrome’s documentation says agents cannot currently call those tools from a headless browser. Native support is expected with Chrome 157, roughly November 2026. Firecrawl Interact bridges the gap by running a real cloud browser and proxying discovery and execution to headless harnesses.
An agent still meets a web built for people. Booking a restaurant table means scraping the form’s HTML, working out which fields hold the name, phone, date, and party size, filling each one, then confirming the outcome through screenshots or DOM inspection. Every run rebuilds its picture of the page from nothing, token cost climbs with the field count, and a redesign usually breaks the scraper that worked before.
The Firecrawl WebMCP demo turns that around: rather than teaching agents to handle human interfaces better, let each site declare the tools an agent may use. What follows walks the WebMCP tool model, the hard line Chrome draws around headless execution, and how Firecrawl fills the gap with a real browser in the cloud.
WebMCP: Sites Declare Their Own Agent Tools
WebMCP is a web platform proposal from engineers at Google and Microsoft. Developers register tools on the page in JavaScript (HTML-based declarations are planned for later), and every tool carries a name, a description, an inputSchema in JSON Schema form, and the execute logic that does the work — the same shape as an ordinary MCP tool. Registration runs through document.modelContext.registerTool, and required fields are spelled out in the schema, so an agent never has to scrape the DOM and guess at the form’s structure.
In the demo’s restaurant booking, filling a form field by field collapses into one book_table_le_petit_bistro tool call. The execute function takes validated arguments, writes them into the form fields, and calls the page’s existing validateForm(). A failed check returns isError: true together with the error message; a passing one shows a confirmation modal and sends back the reservation result. On the discovery side, document.modelContext.getTools() enumerates the page’s registered tools (name, description, inputSchema), and document.modelContext.executeTool() invokes one by name with JSON arguments.
The Hard Limit Chrome Draws: No Headless Calls
The spec looks complete enough; the difficulty sits in the runtime. Chrome’s WebMCP documentation, as the article relays it, states plainly that agents cannot currently call these tools from a headless browser. An agent has to drive a live browser itself, and the browser must onboard that agent. A terminal harness such as Claude Code holds no real tab to operate, which leaves it unable to see what a site has registered at all.
The schedule makes that position more awkward still. WebMCP is expected to ship natively with Chrome 157 (roughly November 2026 for stable, per the article), yet stable stood at version 150 when the piece was written; the feature opens in stages behind a flag and through origin trials, and today’s demo leans on @mcp-b/webmcp-polyfill. Put another way: even once native support arrives, Claude Code stays locked out for as long as the headless restriction holds.
The Local Route: agent-browser and What It Costs
Vercel Labs’ agent-browser takes the local approach. It runs a browser on your own machine that code can drive, and agent-browser eval executes JavaScript inside the page — the same effect as calling getTools() and executeTool() from the console.
The cost shows up in deployment: the machine needs a real browser on it, and the first run downloads Chrome for Testing. On a CI pipeline, a locked-down workstation, or a cloud runtime, installing and maintaining a browser is rarely realistic.
Firecrawl Interact: A Real Browser, Moved to the Cloud
Firecrawl’s job is to fill this slot. The interact endpoint runs a real browser in Firecrawl’s cloud, so a headless harness gets a live tab without carrying a browser of its own. There are two ways to steer it — describe the intent in a prompt, or run code directly — and since the browser lives in Firecrawl’s cloud sandbox, nothing is installed locally.
The sequence goes scrape first, interact second. Call scrape with maxAge: 0 to force a genuine browser load and get back a scrapeId — when a cache hit answers, there is no live session behind that scrapeId — then issue interact against the same scrapeId, and close out with stopInteraction. The interact code runs inside the cloud browser, where page is the Playwright Page of a connected session; Node Playwright is the default code mode, with Python Playwright and the bash agent-browser command also available.
// 1. discover — list tools registered by the page
const tools = await page.evaluate(() => document.modelContext.getTools());
// 2. execute — arguments travel base64-encoded, decoded in-page
const result = await page.evaluate(async (b64) => {
const tool = (await document.modelContext.getTools())
.find((t) => t.name === "book_table_le_petit_bistro");
return document.modelContext.executeTool(tool, atob(b64));
}, argsB64);
Arguments reach the tool base64-encoded (as argsB64) and are decoded in-page with atob, which keeps quoting dependable across Firecrawl’s transport. From the agent’s side, the whole thing is one tool call proxied through a headless-friendly API. It works for one plain reason: the cloud side is a real browser, where WebMCP already functions, so Firecrawl needs no special integration of its own.
The Booking Demo: One Tool Call, Start to Finish
The demo site is adapted from Google’s French Bistro demo. As a before baseline, the author first removed the tools the site already had, leaving the agent only the slow path — scrape every input, fill each field one by one, verify with screenshots — then restored the tool on a stage-1 branch. A small runner wraps the two calls, discovery and execution, into a single entry point, and Claude Code is pointed at that runner. Asked to book a table for two next Thursday, the agent finds the tool and works out the missing fields (time, phone) — which, the source warns, it may ask the user for or simply make up — fills them in, and finishes the reservation in one call, entirely on the local machine, with no browser, no scraping, and no screenshots.
A Spec Still in Motion, and Two Engineering Red Lines
Every step of this approach rests on a floor that keeps moving. The API namespace has already shifted from navigator.modelContext to document.modelContext, and plain HTML tag declarations are promised for the future, at which point discovery scripts like the one above will need rewriting. Two engineering red lines belong in your defaults: a scrape-interact pair always requires a live session, so maxAge: 0 is not optional; and base64-encoded arguments, reliable as they are, add an encoding layer to remember when debugging.
Builder Guidance
Three judgments worth taking away. First, site owners can register tools with the polyfill today — a tool interface outlives page structure, so the investment carries straight over when native support lands. Second, agent builders should expose interact as a single governed tool: a fixed allowlist of sites, validated input schemas, restricted actions, and an operation log — headless describes where execution happens, and governance must not go headless with it. Third, keep watching Chrome 157 and the spec’s motion: until an official headless answer appears, a real browser in the cloud remains the most practical bridge for any environment that cannot ship a local browser, and a way to put WebMCP to work today.
