100,000 Storefronts, One Switch: How WebMCP Makes a Shop Agent-Readable

·11 min read·Evergreen Tools Team

For two years, making a website "AI-friendly" mostly meant guessing: ship structured data, hope the model parses your HTML, and leave polite notes in robots.txt and llms.txt. WebMCP takes a different route. Instead of making agents guess, hand them tools. It is a proposed browser standard from Google that lets a page expose capabilities like search_products as structured tools, so an agent calls the exact tool it needs rather than hunting for dropdowns, getting blocked by cookie banners, or tripping over bot challenges. Cloudflare shipped an edge implementation in beta in August: turn it on and the edge injects a small script, with site owners writing no code at all. Commerce.com runs close to 100,000 domains, and when the preview landed their question was practical: can we turn this on for every store at once? Here is how that worked, and how the one-switch-versus-100,000-merchants conflict got resolved.

Online storefront on a phone

An agent should call a tool called search_products, not guess at dropdowns

1. What WebMCP Actually Solves

Start with its status, because it is easy to over-read: WebMCP is an experimental proposed browser standard in early preview, available behind experimental Chrome flags (chrome://flags/#enable-webmcp-testing), in Chrome Origin Trials, in some agentic browsers, and in developer environments such as Cloudflare Kitesurf. Its value is turning agent shopping from visual guesswork into interface calls. Without WebMCP, an agent simulates human clicks and gets blocked by cookie banners, misreads variant dropdowns, or trips over the challenges that try to separate automated traffic from real customers. With WebMCP, the agent detects the store's tools on document.modelContext and makes two clean calls. For a merchant the point is that the store shows up in the answer, the customer stays on the merchant's site, and the merchant keeps control of checkout.

<!-- What the browser injects at the edge. Site owners write nothing. -->
<script type="module"
    src="/.webmcp/bridge.js"
    data-packs="c2pa,mcp-server-client"
    data-mcp-url="/api/mcp"></script>

<!-- data-mcp-url matters more than it looks. The bridge originally
     assumed every site served MCP at /mcp. Commerce.com's server lives
     at /api/mcp, so the path is now a zone-level setting. -->

2. Why Commerce.com Wanted It

Kristina Pototska, Product Management Director at Commerce.com, puts it plainly: merchants keep asking how to keep up with agentic shopping, and when a shopper asks an agent to find something, they want their store in the answer while keeping the customer, keeping control of checkout, and without rebuilding their site. WebMCP addresses all three, because the agent gets real tools to search products, check details, build a cart and get a checkout link instead of guessing its way around the page. One design point is easy to miss: this runs alongside server-side MCP rather than replacing it. Server-side MCP serves agents that connect to a store directly, like an assistant helping someone shop across several sites; WebMCP serves agents working inside the shopper's browser. Both expose the same set of shopping tools, so merchants do not have to choose or maintain two separate setups.

// What an agent sees on the page: structured tools on document.modelContext.
const ctx = document.modelContext;
if (ctx) {
  const tools = await ctx.getTools();
  console.log(tools.map((t) => t.name));
  // ["search_products", "get_product_details", "build_cart", "get_checkout_link"]
} else {
  // No WebMCP support: fall back to normal navigation. Never block the page.
  console.log("WebMCP not available, continuing as a normal storefront");
}

3. Edge Injection: No Code From Site Owners

Two principles hold it together. First, WebMCP tools execute inside the shopper's active browser session on the storefront's own domain, so the agent sees the same prices and cart as the shopper, no credentials go to a third party, and the visit still happens on the merchant's site. Second, Cloudflare acts as the edge delivery layer for Commerce.com's backend MCP server, proxying tool definitions and actions unchanged so merchants keep full control of tool logic. In practice that is a single injected script, and it came with a detail nobody had planned for: the bridge originally expected every site's MCP server at /mcp, while Commerce.com's lives at /api/mcp. The MCP path is now a zone-level setting passed into the injected script tag. That looks trivial and is actually the most common friction point between a generic edge capability and a real customer deployment.

// Per-merchant opt-out, evaluated at the edge. No allowlist, no lookup.
{
  "action": "set_config",
  "expression": "cf.hostname.metadata.webmcp_opt_out eq \"true\"",
  "action_parameters": {
    "webmcp_enabled": false
  }
}

// Commerce.com enables WebMCP on the main zone, then this rule checks
// merchant metadata. A merchant flipping "opt out" in the dashboard
// produces: no injected script, no extra latency, no remote call.

4. The Real Conflict: One Switch, 100,000 Merchants

Commerce.com uses Cloudflare for SaaS to host thousands of merchant vanity domains on shared zones, and WebMCP was originally designed as a single on-or-off switch for an entire zone. Rather than build a complex custom allowlist, they hooked WebMCP into two existing Cloudflare concepts: Configuration Rules and custom hostname metadata. Commerce.com turns WebMCP on for the main zone, then adds a rule at the edge that checks merchant metadata. If a merchant flips the opt-out switch in their own dashboard, Cloudflare bypasses WebMCP for that storefront automatically. Because rules are evaluated at the edge before the page is served, an opted-out store gets zero extra latency, no remote lookups and no injected scripts. The pattern is worth remembering: default-on with a fine-grained opt-out lands at platform scale far more easily than default-off with an allowlist, and the opt-out costs almost nothing.

# Verify what a storefront actually serves before and after the switch.

check() {
  host=$1
  echo "== $host"
  # is the bridge script present?
  curl -sS "https://$host/" | grep -o 'src="/\.webmcp/bridge.js"' || echo "bridge: absent"
  # does the MCP endpoint answer?
  curl -sS -o /dev/null -w 'mcp_status=%{http_code}\n' "https://$host/api/mcp"
}

check shop-one.example.com
check shop-two.example.com   # this merchant opted out -> expect absent

# Guard the failure mode that matters: an opted-out store must look
# byte-identical to how it looked before WebMCP existed.

5. Design the Failure Path First

Every preview feature meets a few details it did not account for, and this one was no exception. Beyond the custom MCP path, the important one is seamless fallback. If a store's MCP server is offline, or the shopper's browser does not support WebMCP, the script simply exits: the storefront loads normally and human shoppers are unaffected. The last snippet is that contract written down: a 1.5 second timeout, an error on any non-200, and a catch block that logs one debug line and never paints a red error on the page. The discipline generalises to anyone injecting capability into a production page: the injected script is an enhancement, not a dependency, and when the enhancement fails the page must behave as though it never existed. Note also that checkout stays human on purpose, with payment details never passing through the agent. That is a deliberate boundary, not a missing feature.

# The safe-fallback contract, in code.
try {
  const res = await fetch(MCP_URL, { signal: AbortSignal.timeout(1500) });
  if (!res.ok) throw new Error(`mcp ${res.status}`);
  const tools = await res.json();
  window.modelContext?.provideTools?.(tools);
} catch (err) {
  // Server offline, wrong path, browser without support, slow network:
  // exit quietly. Human shoppers must never see an error because of this.
  console.debug("webmcp bridge skipped:", err.message);
}

6. If You Want Your Site to Be Agent-Readable

Four things to check. First, decide which tools you are exposing and design them like a public API: specific names (search_products beats do_search), validatable parameters, stable responses. An agent does not understand your internal vocabulary, only your schema. Second, confirm your MCP endpoint path matches what your edge injection assumes, and pass it through configuration rather than hardcoding when it differs. Third, write the fallback for all three failure modes: timeout, non-200, and an unsupporting browser must each exit silently, because a real shopper should never see an error caused by an agent feature. Fourth, make the opt-out a self-service switch evaluated at the edge, so a platform-wide rollout does not stall on one merchant who does not want it. Cloudflare says it will keep investing in the standard, starting with helping agents find a site's tools more easily. If you run commerce or a SaaS platform, one measurement you can take today: can each of your core actions, search, detail, add to cart, checkout, be described as a tool in one sentence? The ones you cannot describe are usually the flows that are not structured enough yet.

Shopping cart and checkout flow

The shopper still clicks checkout. That part stays human on purpose

📌 Frequently Asked Questions

Is WebMCP a finished standard?

No. Cloudflare describes it as an experimental proposed browser standard in early preview, currently available behind experimental Chrome flags (chrome://flags/#enable-webmcp-testing), in Chrome Origin Trials, in some agentic browsers and in developer environments such as Kitesurf. Any production use has to be designed around preview-grade fallbacks.

How does WebMCP relate to MCP?

They coexist. Server-side MCP serves agents that connect to a store directly, such as an assistant helping someone shop across multiple sites. WebMCP serves agents working inside the shopper's browser. Commerce.com says both expose the same set of shopping tools, so merchants do not have to pick one or maintain them separately.

Why not build an allowlist per merchant?

Because Commerce.com hosts close to 100,000 domains on shared zones through Cloudflare for SaaS, so a custom allowlist would be complex and hard to maintain. They used Configuration Rules plus custom hostname metadata instead: the main zone is on by default, and when a merchant flips their opt-out switch, an edge rule bypasses WebMCP for that storefront with no extra latency, no remote lookups and no injected scripts.

Does enabling it slow the storefront down?

Per Cloudflare, rules are evaluated at the edge before the page is served, so opted-out stores get no extra latency, no remote lookups and no injected scripts. For enabled stores, the bridge script exits when the MCP server is offline or the browser does not support WebMCP, and the storefront loads normally with human shoppers unaffected.

Does the agent get access to payments or credentials?

No. WebMCP tools execute inside the shopper's active browser session on the store's domain, so prices and cart match what the shopper sees and no credentials go to a third party. Checkout is still clicked by the shopper, and payment details never pass through the agent.