AI & Agentic Commerce

Shopify Checkout WebMCP: Build a Browser Agent That Reaches Checkout

By CartStack Team6 min read

Shopify Checkout WebMCP lets an AI agent running in the buyer’s browser read and update a Shopify checkout, and place the order after the buyer confirms it. This guide covers the four tools, a small helper for calling them, the PUT semantics that catch people out, authentication, and error handling. It ends with our view on where the risk sits. Checked against Shopify’s Checkout WebMCP documentation in October 2026, which follows UCP version 2026-08-25.

Cover graphic for Shopify Checkout WebMCP
The agent prepares the checkout. The buyer stays in control of the order.

Where Shopify Checkout WebMCP Fits

Checkout WebMCP tools run in the buyer’s browser and act on the checkout open in that tab. The buyer sees the same state, handles interactions such as Shop Pay login or payment challenges, and confirms the order before the agent calls complete_checkout. It implements the UCP checkout capability over browser-registered tools instead of server-side JSON-RPC. Use it when your agent runs in the browser. If your agent can run on a server, Shopify points to Checkout MCP instead. For the storefront side, start with Shopify WebMCP Tools, and for the protocol background see Shopify UCP Explained.

The Four Checkout WebMCP Tools

  • get_checkout: reads the current checkout, or the order receipt on the Thank you page. It takes no parameters.
  • update_checkout: changes buyer contact details, fulfillment, discount codes, declared fields and payment, without placing an order. Line items are ignored, because the buyer changes items on the page.
  • complete_checkout: places the order after the buyer confirms it. It takes no parameters.
  • navigate_to_storefront: leaves checkout and returns the tab to the storefront, when the store has an online storefront.

Call a Checkout WebMCP Tool

Checkout registers its tools on the checkout page’s top-level document. Discover them with document.modelContext.getTools() and call them with executeTool(). Shopify’s helper wraps discovery, execution and result parsing.

async function callCheckoutTool(name, args = {}) {
  const tools = await document.modelContext.getTools();
  const tool = tools.find((candidate) =>
    candidate.name === name &&
    candidate.window === window &&
    candidate.origin === location.origin
  );
  if (!tool) {
    throw new Error(`${name} isn't registered on this page.`);
  }
  const result = await document.modelContext.executeTool(
    tool,
    JSON.stringify(args),
  );
  // The page navigated before the result arrived.
  if (result === null) return null;
  return JSON.parse(result);
}

document.modelContext.addEventListener('toolchange', () => {
  // Refresh tools and schemas before the next call.
});

Three details from the documentation matter. Pass arguments as a JSON string, because in Chrome 153 passing an object fails, and Chrome plans to accept objects in Chrome 155. Check ucp.status on every result, since an error replaces the checkout with an error object. And listen for toolchange, because the tool list changes as the buyer moves through checkout.

Update With PUT Semantics

update_checkout replaces the whole desired state. Send every value you want to keep, and build each request from a fresh get_checkout response. Checkout clears most omitted values, with field-specific behavior for payment, declared fields and vaulted contact details. This example sets contact, shipping and a discount code.

const checkout = await callCheckoutTool('update_checkout', {
  checkout: {
    buyer: { email: 'buyer@example.com', phone_number: '' },
    fulfillment: {
      methods: [{
        type: 'shipping',
        destinations: [{
          first_name: 'Maya',
          last_name: 'Chen',
          street_address: '118 Greene St',
          address_locality: 'New York',
          address_region: 'NY',
          postal_code: '10012',
          address_country: 'US',
        }],
        groups: [{ id: 'shipment_1', selected_option_id: 'standard' }],
      }],
    },
    discounts: { codes: ['WELCOME10'] },
    declared_fields: [],
  },
});

Use the destination, group and option IDs from the latest get_checkout. A returned discount code does not mean it applied, so check discounts.applied. Money values are integers in the currency’s minor unit. Payment is limited: Checkout WebMCP does not accept new card details. It takes a saved Shop Pay card by ID, or a billing address for a guest checkout, and the buyer chooses any other method on the page. Some checkouts also ask for extra information such as a tax number, which appears as declared fields you fill by key and value.

Completing the Order

Call complete_checkout only when the status is ready_for_complete and the buyer has confirmed the current order and total. Shopify’s documentation is explicit that Web Bot Auth and a ready status do not grant that permission, and that you should ask again if the total changes. Only status: completed confirms the order. Two paths need care.

  • Review step: if the store configured one, the first call returns requires_escalation with a buyer_review_required message. The buyer reviews on the page, and you call again only after they authorize submission.
  • Buyer action: for a payment challenge or similar, the buyer finishes it in the same tab. Do not call complete_checkout again. Poll get_checkout until the status is completed or the checkout needs your agent.

Authenticate With Web Bot Auth

Sign browser requests with Web Bot Auth, not tool arguments. Shopify uses it to identify your agent, and without it bot detection might deprioritize or block you. Shopify verifies only registered keys, so generate an Ed25519 signing key, host the public key in a key directory, register and publish that directory with Shopify, sign requests with the headers, and keep signature timestamps short-lived.

Handle Errors

A failure returns ucp.status: "error" with a code. Group your handling by what the code asks of you.

  • Fix the request: invalid_request and rejected.
  • Refresh state first: completion_failed, internal_error and update_failed. For completion_failed, do not resubmit while the outcome is unknown.
  • Wait or let the buyer act: buyer_action_required, checkout_busy and completion_in_progress.
  • Navigation: navigation_failed.

After any error, cancellation or timeout, refresh the tool list, call get_checkout, and compare the state with your request before retrying. Updates that run longer than 30 seconds return update_failed and might still apply.

Our Analysis: Where the Risk Sits

The dangerous call is the last one. Everything before complete_checkout can be redone. Placing an order cannot. Build your agent so that call requires an explicit confirmation of the exact total, and so that a changed total resets that confirmation.

Retry logic is different here. This tool does not use an idempotency key. If a completion is running or done, it returns the current checkout or a completion_in_progress error. That is why the guidance is to read state, not to repeat the call. For the keyed approach on the Admin API side, see Shopify Idempotency Keys.

Plan for untrusted text. Shopify warns that merchant and third-party text in tool responses can carry prompt-injection attempts, and tells agents never to work around a tool by operating the page’s controls. Treat those fields as data in your prompts.

Know who this is for. Store owners do not need to build anything. This is for teams building shopping agents, and for merchants who want to understand what an agent can and cannot do at their checkout. Eligible checkouts register the tools, and Shopify documents excluded checkouts, so check your store before assuming coverage.

FAQ about Shopify Checkout WebMCP

Can an agent enter new card details? No. Checkout WebMCP accepts a saved Shop Pay card by ID or a billing address, and the buyer picks any other payment method on the page.

Do I use Checkout WebMCP or Checkout MCP? Use WebMCP when the agent runs in the buyer’s browser, and Checkout MCP when it can run on a server.

How do I know the order went through? Only a checkout status of completed confirms it. Read the order receipt with get_checkout on the Thank you page.