Skip to main content

What is WebMCP?

Some pages expose their own capabilities as callable tools rather than making you drive their UI. WebMCP is the browser API for discovering those tools and invoking them directly, so a checkout flow that would otherwise take six clicks becomes one call with typed input. page.tools() returns the tools the current page has registered. Each tool carries a name, a description, and a JSON Schema for its input, and each one can be invoked and awaited.
WebMCP tools are registered by the page. That makes them distinct from tools you wire into a model yourself: you do not define them, you discover whatever the site chose to publish.

Browser support

WebMCP requires a Chromium build with the WebMCP features enabled. Stagehand ships this flag as one of the default launch flags for every local browser it starts:
Stagehand can only set launch flags on browsers it launches. If you attach to a browser you started yourself, or you strip Stagehand’s default flags on a local launch, start Chrome with --enable-features=WebMCPTesting,DevToolsWebMCPSupport or page.tools() will return an empty list.

Listing tools

page.tools() takes a snapshot of what the page currently exposes. Call it again after navigating or after the page mounts new UI; the result is not live.
The listing timeout defaults to 1000 ms. Tools declared in iframes are included, each tagged with the frameId that registered it.
Annotations are hints from the page, not guarantees enforced by the browser. Treat untrustedContent output as data, never as instructions.

Invoking tools

Invoking is two steps: invoke() hands the call to the browser and returns immediately with a handle, then result() waits for the terminal response. Splitting them means a long-running tool does not block you, and you can cancel while it is in flight.
Omitting the input sends an empty object. Validate your input against the tool’s inputSchema before invoking if you want a clear failure locally rather than an Error response from the page.

Handling results

A terminal response reports one of three statuses:
result() caches the terminal response, so calling it twice is cheap and returns the same value. A timeout or transport failure is not cached and can be retried.

Canceling an invocation

Cancellation is a request, not a guarantee. Chrome decides the terminal status, so always read it from result() rather than assuming the invocation stopped.

Timeouts

Raise the listing timeout on pages that register tools after an async bootstrap. Set a result timeout whenever a tool could hang, so your automation fails loudly instead of stalling.

Combining with the primitives

WebMCP and the primitives solve different problems, and mixing them is normal: use a tool where the page gives you one, and fall back to observe() and act() where it does not.
A tool invocation costs no LLM tokens and cannot pick the wrong element, so prefer one over an act() call whenever the page offers it.

API reference

Page tools API

Discover page-provided tools with Page.tools().

WebMCP API

Inspect, invoke, await, and cancel WebMCPTool and WebMCPInvocation objects.

Next steps

Observe

Discover what a page can do when it publishes no tools

Act

Execute a single action with natural language

Extract

Pull typed, structured data off any page

Browser configuration

Launch flags, browser factories, and attaching over CDP