WebMCP in Chrome: what works today and how to build for it
A clear, current guide to WebMCP in Chrome: what works today, how to register tools with feature detection, which agents and frameworks call them, and how to test safely.

You probably searched for “webmcp chrome” to find out how to enable and use WebMCP in Chrome. Short answer: Chrome has WebMCP in an origin trial, some agents in Chrome don’t call page tools yet, and a few do. By the end of this guide, you’ll have a working code snippet that registers tools correctly in Chrome, plus practical ways to test with agents and frameworks that already support WebMCP.
TL;DR
- Chrome status: origin trial. Some agents in Chrome ignore tools; check the live ecosystem tracker.
- Implement now with feature detection: use
document.modelContext ?? navigator.modelContextand register tools with clear JSON Schema and side effects. - Works today for testing: ChatGPT desktop site tools, Stagehand, Vercel agent-browser, Browser Use; Puppeteer requires a flag in recent Chrome builds.
- Don’t pass secrets in tool params; add an in-page confirmation step for sensitive actions (payments, account updates, deletion).
- Use health checks and analytics (or Agent Layer) to catch UI drift, see which agents call your tools, and version configs safely.
The state of WebMCP in Chrome
WebMCP exposes page-native tools to agents so they can call functions instead of scraping your DOM. In Chrome, it’s in an origin trial aiming for Chrome 157. That means you can expect APIs to stabilize, but real-world agent support varies. Today:
- Chrome, Edge: origin trial. Brave: behind a flag. Firefox, Safari: no support. Full details on the ecosystem page.
- Many consumer agents running inside Chrome still read the page but do not call tools. Exceptions exist outside the regular Chrome browsing path (e.g., desktop apps, hosted frameworks) that do call tools.
If you want a deeper background on the standard, see WebMCP Explained: The Native Standard Turning Websites into AI APIs. If you’re shipping a site today, you can still implement tools and test in environments that already call them.
What you can do today in Chrome-based workflows
You can build and publish WebMCP tools right now. They run in-page with your user’s session, no extra backend. Agents or frameworks that support page tools will call them; others will fall back to text or DOM reading.
Practical options that work today:
- ChatGPT desktop app: supports page tools (native “site tools”), on by default. Good for manual testing with a human in the loop.
- Stagehand (framework): launches a browser it controls and calls page tools.
- Vercel agent-browser (framework): on by default, calls tools in a Chrome it launches.
- Browser Use (hosted agents): announced support; calls page tools.
- Puppeteer with recent Chrome: behind a flag; usable if you control the runner.
Evolving or not usable yet:
- Gemini in Chrome: not usable yet.
- Claude for Chrome: reads the page, not its tools.
- Brave Leo: behind a flag in Nightly.
Keep the ecosystem tracker open while you build; it’s verified by hand and updated as implementations land.
Minimal, production-safe WebMCP setup
Two rules keep you out of trouble:
- Feature-detect both
document.modelContextand the oldernavigator.modelContext. - Treat tools like public interfaces. Clear schema, small JSON return, and guardrails for anything sensitive.
Here’s a concise, runnable example that registers two tools on any page type: a non-sensitive “add_to_cart” (idempotent, stateful but reversible) and a sensitive “update_account_email” that requires explicit on-page confirmation.
// Feature-detect both the current and older address
const mc: any = (document as any).modelContext ?? (navigator as any).modelContext;
if (mc && typeof mc.registerTool === 'function') {
// Non-sensitive: add an item to cart
mc.registerTool({
name: 'add_to_cart',
description: [
'Adds a product to the user\'s cart.',
'Use only when the user has selected a valid product and quantity.',
'Side effects: updates cart state in this session and returns a summary.'
].join(' '),
inputSchema: {
type: 'object',
properties: {
product_id: { type: 'string', description: 'Internal product identifier' },
quantity: { type: 'integer', minimum: 1, default: 1 }
},
required: ['product_id'],
additionalProperties: false
},
execute: async (params: any) => {
const { product_id, quantity = 1 } = params;
// Example: call your existing in-page add-to-cart function or click handler
// Never include secrets in params; use session state already in the page
const success = await window.app?.cart?.add(product_id, quantity);
return success
? { status: 'ok', added: { product_id, quantity }, cart_count: window.app?.cart?.count() }
: { status: 'error', message: 'Add to cart failed' };
}
});
// Sensitive: requires explicit user confirmation in-page
mc.registerTool({
name: 'update_account_email',
description: [
'Updates the signed-in user\'s account email.',
'Use only after the user explicitly confirms this change on the page.',
'Side effects: modifies account data; triggers verification email.'
].join(' '),
inputSchema: {
type: 'object',
properties: { new_email: { type: 'string', format: 'email' } },
required: ['new_email'],
additionalProperties: false
},
execute: async (params: any) => {
const { new_email } = params;
// Guardrail: require a visible, user-clicked confirmation
const confirmBtn = document.getElementById('confirm-email-change');
if (!confirmBtn) {
return { status: 'blocked', reason: 'Missing confirmation control' };
}
// Wait for a human click before proceeding
const confirmed = await new Promise<boolean>((resolve) => {
const handler = () => { confirmBtn.removeEventListener('click', handler); resolve(true); };
confirmBtn.addEventListener('click', handler, { once: true });
// Optionally, surface a banner explaining the change
const banner = document.getElementById('confirm-banner');
if (banner) banner.textContent = `Confirm email change to ${new_email}`;
});
if (!confirmed) {
return { status: 'blocked', reason: 'Not confirmed' };
}
const ok = await window.app?.account?.updateEmail(new_email);
return ok ? { status: 'ok', new_email } : { status: 'error', message: 'Update failed' };
}
});
}
Notes:
- Use clear descriptions that state preconditions and side effects. Agents choose tools based on text, not names.
- Keep results small and JSON-serializable.
- Sensitive actions must require explicit user confirmation in the page. Never send secrets through params.
For a longer list of high-value tools by page type, see Essential WebMCP Tools for AI‑Ready Websites.
Testing paths that work now
You don’t have to wait for every Chrome agent to support tools. Use environments that already do.
-
ChatGPT desktop app
- Open your site in the desktop app. Describe the task. When it picks a tool, you’ll see it call your in-page function.
- This is the fastest manual sanity check.
-
Stagehand (TypeScript)
- Launches a controlled browser and calls tools found on the page. Good for automated scenarios and CI.
-
Vercel agent-browser
- Calls tools in a Chrome it launches. Useful for server-side automation that still executes client-side code.
-
Browser Use
- Hosted environment that calls tools. Handy for verifying public pages without local setup.
-
Puppeteer
- Recent Chrome builds can expose the API behind a flag. If you control the runner, you can flip it and test calls end-to-end.
If you’re building for a specific production agent, check its current status on the ecosystem tracker and plan a fallback when tools are not available.
Agent flow at a glance
This diagram shows a typical flow when an agent that supports WebMCP lands on your page and calls a tool.
Chrome specifics: what to expect
- Address: Tools should be available at
document.modelContext. Some early implementations exposednavigator.modelContext. Keep both for now. - Lifetime: Tools live in the page context, tied to the tab and session. They share the user’s cookies, storage and JS state.
- No extra backend: The agent does not need your secret keys; it uses the logged-in browser session.
- Origin trial means change: Expect edge cases and occasional breakage as Chrome lands changes. Feature-detect and keep return values small and stable.
Adding tools to real pages
Templates tend to repeat. Product pages, carts, search, checkout, account. Attach tools to the template lifecycle and bind to existing UI code. A few patterns that work:
- Product page:
get_price,get_stock,add_to_cart,get_shipping_options. - Cart:
apply_coupon,remove_from_cart,get_cart_total. - Search/results:
run_search,filter_results. - Account:
get_orders,start_return,update_account_email(with confirmation).
See WebMCP example: concrete uses that work today for battle-tested combos.
Example: search with filters
const mc: any = (document as any).modelContext ?? (navigator as any).modelContext;
if (mc) {
mc.registerTool({
name: 'run_search',
description: 'Runs on-site search. Use when the user asks to find products or content by keyword. Returns top hits.',
inputSchema: {
type: 'object',
properties: {
query: { type: 'string' },
limit: { type: 'integer', minimum: 1, maximum: 20, default: 5 }
},
required: ['query'],
additionalProperties: false
},
execute: async ({ query, limit = 5 }: any) => {
const hits = await window.app?.search?.run(query);
const top = (hits || []).slice(0, limit).map((h: any) => ({ id: h.id, title: h.title, price: h.price }));
return { status: 'ok', count: top.length, results: top };
}
});
}
Provide strong descriptions
The selection step is language-driven. State:
- When to use it: “Use when the user asks to…”
- Preconditions: “Only if the user is signed in”, “Only on product pages with a selected variant”.
- Side effects: “Modifies cart”, “Sends an email”, “Starts a refund”.
Observability and keeping tools working
In production, two things cause pain: UI drift and blind spots. A selector changes, or an agent stops calling your tools and you don’t notice.
What you can do manually:
- Log calls to your internal analytics when
executeruns. - Add unit tests around the UI functions your tools call.
- Keep descriptions aligned with visible UI so agents pick the right tool.
Where Agent Layer helps with less toil:
- Health checks: detect when a UI change breaks a tool and suggest the updated selector.
- Versioned configs: define tools per template, publish, and roll back if needed.
- Analytics: see which agent called which tool, success or error, and duration.
- Test scenarios: write intents and the tool you expect; run them as checks.
- Guardrails: built-in patterns for sensitive actions like payment.
If you want a concrete, step-by-step enablement walkthrough beyond Chrome, read How to Enable WebMCP on Your Website: A Practical Guide.
Handling fallbacks when tools aren’t available
Some agents won’t see your tools yet. Plan for:
- Readable UI: Semantic HTML, labelled buttons, real form labels, server-rendered essentials. This keeps traditional agents on track.
- Minimal friction: Avoid hard CAPTCHAs and popups that block automation paths.
- JSON-LD: Helps agents and crawlers understand entities. The free audit below flags gaps.
This isn’t about “SEO for AI.” It’s basic hygiene so both tool-aware and tool-agnostic agents can complete tasks.
What breaks in production
-
Only using
document.modelContextor onlynavigator.modelContext.- Fix: feature-detect both until the old address disappears in practice.
-
Vague tool descriptions.
- Symptom: agent picks the wrong tool or ignores yours.
- Fix: write preconditions and side effects in plain language.
-
Large return payloads.
- Symptom: timeouts or agent truncation.
- Fix: return a compact summary; link or reference IDs for details.
-
Secrets in params.
- Symptom: accidental logging or exfiltration.
- Fix: never pass secrets; execute with session state already in the page.
-
No guardrails on sensitive actions.
- Symptom: unintended account changes, refunds, or deletions.
- Fix: require explicit user confirmation via visible UI controls.
-
UI drift.
- Symptom:
executefails after a CSS or DOM refactor. - Fix: centralize bindings; add smoke tests; consider Agent Layer health checks.
- Symptom:
-
Assuming all Chrome agents call tools.
- Symptom: works in your test rig, fails for users.
- Fix: consult the ecosystem tracker and test with at least one environment that calls tools and one that doesn’t.
Comparison: testing options
| Environment | Calls page tools today | Notes |
|---|---|---|
| ChatGPT desktop app | Yes | Fastest manual test of site tools |
| Stagehand | Yes | TypeScript, launches a browser and calls tools |
| Vercel agent-browser | Yes | On by default in the browser it launches |
| Browser Use | Yes | Hosted agents with tool support |
| Puppeteer | Behind flag | Recent Chrome builds only |
| Claude for Chrome | No | Reads page, not tools |
| Gemini in Chrome | Not usable | Nothing shipped in writing |
Refer back to the ecosystem page for up-to-date verification.
Architecture options
Two ways to wire tools into your app lifecycle:
- Template hook: initialize tools on each page type (product, cart) with the bindings that page needs.
- Global bootstrap: register a base set everywhere (e.g.,
run_search,get_user_status), then layer template-specific tools.
Shipping checklist for Chrome-compatible WebMCP
- Feature-detect
document.modelContext ?? navigator.modelContext. - Descriptions include when to use, preconditions, side effects.
- JSON Schema: strict types, required fields, no additional properties.
- Small, serializable results with status and summary fields.
- Explicit confirmation for sensitive actions; no secrets in params.
- Test in at least one environment that calls tools (e.g., ChatGPT desktop, Stagehand) and one that doesn’t.
- Monitor calls and errors; plan for UI drift.
When Agent Layer is worth it
You can ship plain WebMCP without us. Where teams pull in Agent Layer is when:
- Tools drift after UI changes and someone has to patch selectors under pressure.
- You want guardrails for sensitive actions and a clear audit trail of who called what.
- Product managers want to see which agents actually use the tools, and where they fail.
- You need versioned configs per template, with rollbacks and health checks.
- You want to test “user intents” against expected tools before a release.
Add one script tag, define tools per template, publish versioned configs, and keep the support tracker handy as Chrome and agents evolve.
Try it
Start with the free agent-readiness audit at agentlayer.tech. You’ll get a /100 score with fixes for missing tools, JSON-LD issues, unlabeled fields, and more, plus suggested tools per page. Want hands-on context on standards and differences? See What is the Difference Between MCP and WebMCP? and the practical setup guide How to Enable WebMCP on Your Website.

