Agent commerce with mock.shop

mock.shop supports Universal Commerce Protocol (UCP) version 2026-08-25 for catalog search and mock carts. Each store has its own catalog and carts, selected by the request hostname. The apex mock.shop serves the default demo store.

Discover a store

Read https://mock.shop/llms.txt to choose a store. For example:

curl https://pets.mock.shop/.well-known/ucp
curl https://pets.mock.shop/api/ucp/mcp \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

The discovery document advertises dev.ucp.shopping.catalog.search and dev.ucp.shopping.cart, plus the MCP endpoint on that same host. The endpoint is anonymous, accepts one JSON-RPC request per POST, and uses the MCP SDK's standard initialize, ping, tools/list, and tools/call methods. It does not need a session ID or a persistent event stream.

Publish your agent profile

UCP tool calls require a profile describing your agent's supported protocol version and capabilities. Host this JSON on a public HTTPS URL, such as https://your-agent.example/ucp-profile.json, with Content-Type: application/json and Cache-Control: public, max-age=60:

{
  "ucp": {
    "version": "2026-08-25",
    "services": {},
    "capabilities": {
      "dev.ucp.shopping.catalog.search": [{
        "version": "2026-08-25",
        "spec": "https://ucp.dev/2026-08-25/specification/shopping/catalog/search",
        "schema": "https://ucp.dev/2026-08-25/schemas/shopping/catalog_search.json"
      }],
      "dev.ucp.shopping.cart": [{
        "version": "2026-08-25",
        "spec": "https://ucp.dev/2026-08-25/specification/shopping/cart",
        "schema": "https://ucp.dev/2026-08-25/schemas/shopping/cart.json"
      }]
    },
    "payment_handlers": {}
  },
  "keys": []
}

initialize and tools/list can run without a profile. Every tools/call request includes its URL at params.arguments.meta["ucp-agent"].profile. Only capabilities present in both the store's and your agent's profile can run. Profiles are cached for one minute, must use HTTPS on port 443, and cannot redirect or resolve to private addresses.

You can run mock.shop locally and call its MCP endpoint using the configured development shop host. The public-address restriction applies to the agent profile that mock.shop fetches, not to the incoming MCP request. Use a public HTTPS profile for local integration testing; profiles hosted on localhost or private networks are rejected. Unit tests use a stubbed profile fetch.

Search the catalog

Send this JSON body to the store's /api/ucp/mcp endpoint, replacing the profile URL with your own:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "search_catalog",
    "arguments": {
      "meta": {"ucp-agent": {"profile": "https://your-agent.example/ucp-profile.json"}},
      "catalog": {"query": "dog", "pagination": {"limit": 10}}
    }
  }
}

Results appear in result.structuredContent, with a JSON text copy in result.content for MCP clients that use text. Product variants have IDs that can be used as cart item IDs. Search uses mock.shop's existing text matching; an empty catalog object browses the store.

Supported filters are catalog.filters.categories (Shopify taxonomy IDs returned in product categories) and catalog.filters.price.min / max. Prices and cart totals are integers in ISO 4217 minor units: USD 18.00 is 1800; JPY 1800 is 1800. The store's currency is fixed. If supplied, context.currency must match it. Other context hints do not change mock prices or localization. Search and cart requests accept optional attribution and signals objects; carts also accept buyer. They are validated but are not saved to the cart or used for personalization, tracking, or checkout. These objects are filtered from request parameter logs.

Search returns up to 25 products per page and up to 100 variants per product. Use the returned pagination.cursor with the same query and filters for the next page. JSON key order, empty options, and nonbinding context hints do not affect pagination. Cursors expire after one hour. The Storefront GraphQL API remains available for larger variant lists and other catalog operations.

Build and manage a cart

Copy a variant's id from search into item.id:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "create_cart",
    "arguments": {
      "meta": {
        "ucp-agent": {"profile": "https://your-agent.example/ucp-profile.json"},
        "idempotency-key": "550e8400-e29b-41d4-a716-446655440000"
      },
      "cart": {
        "line_items": [{"item": {"id": "VARIANT_ID_FROM_SEARCH"}, "quantity": 2}]
      }
    }
  }
}
Tool Arguments besides meta Behavior
create_cart cart.line_items Creates a mock cart.
get_cart id Reads the cart and estimated totals.
update_cart id, cart.line_items Replaces the entire item list. An empty list clears it.
cancel_cart id Removes the cart. Further reads return not_found.

Cart writes require a random meta["idempotency-key"] with at least 128 bits of entropy, such as UUIDv4 (22–255 characters). Retry with the identical JSON request bytes, including the JSON-RPC id, metadata, whitespace, and key order. Use a new key whenever the body changes. A reused key with a different body returns JSON-RPC error -32000 with data.code: idempotency_conflict. Successful write responses are retained for 24 hours, scoped to the store, agent profile URL, and operation. Storage failures return HTTP 503 without committing cart changes; retry the identical request.

Profile discovery or version failures return JSON-RPC error -32001. An incompatible capability returns a UCP tool result with isError: true and capabilities_incompatible. Optional metadata and nonbinding context hints are accepted; only context.currency affects validation. Other context fields do not change mock prices, language, availability, or checkout.

Carts use the existing mock.shop storage, IDs, 10-day renewable expiry, validation, and limits. Up to 250 lines can be supplied in one request. Updates are atomic: invalid items leave the previous cart intact. A cart or variant from another store cannot be used here. The same cart IDs work with the store's Storefront GraphQL API.

Quantities count whole items. An optional item.quantity_unit can explicitly assert unit: "C62", with scale omitted or set to 0, and a display_text string. Its display text and optional increment do not change mock quantities. Other sale units are rejected with a recoverable invalid_input result. Line id and parent_id strings are accepted on updates, but the mock rebuilds flat cart lines and does not retain those identifiers or nested relationships.

Existing mock checkout

Checkout stays mocked: no payment is taken, nothing ships, and no real order is placed. The existing storefront checkout uses the browser's cart cookie; these UCP tools do not set that cookie or transfer an API cart into the browser. Use the storefront normally to walk through its mock checkout.

There are no UCP create_checkout, update_checkout, complete_checkout, payment, fulfillment, or order tools. The discovery profile does not advertise those capabilities or payment handlers.