Skip to content
Back to blog
developer-guide14 min

Building Agentic Commerce #5: UCP — Shopify's Universal Commerce Protocol in Practice

How UCP (Universal Commerce Protocol) enables AI agents to discover stores, create checkouts, link shopper identity, and fetch real-time catalog data — with production code examples.

Executive summary

Part 5 of 'Building Agentic Commerce' explains UCP — Google and Shopify's Universal Commerce Protocol. Covers protocol detection (3 confidence levels), discovery via /.well-known/ucp, 6-state checkout lifecycle, SCP identity linking with loyalty tiers, real-time catalog capability, AP2 mandate delegation, 5 MCP tools, and 215 tests.

Published

2026-04-06

14 min

Author

AgenticMCPStores Engineering

Core Protocol Team

Category

developer-guide

UCPUniversal Commerce ProtocolShopifyGoogleagentic commerceMCPcheckoutidentitycatalogSCP

In Parts 1, 2, 3, and 4 we covered multi-protocol checkout, agent discovery, trust scores, and x402 stablecoin payments. Now we tackle the protocol backed by Google and Shopify with 30+ partners: UCP — the Universal Commerce Protocol.

What is UCP?

UCP is an open protocol designed by Google and Shopify to standardize how AI agents interact with commerce platforms. Unlike ACP (which is Stripe-centric) or x402 (which is wallet-based), UCP is platform-agnostic with a rich capability system. Stores declare what they support — checkout, cart, real-time catalog, identity linking — and agents discover these capabilities via a standard endpoint.
Key differences from other protocols: UCP has a 6-state checkout lifecycle (vs ACP's 4), a capability extension namespace (dev.ucp.*), native SCP identity linking for shopper loyalty data, and built-in AP2 mandate delegation for recurring payments.

Discovery: /.well-known/ucp

Agents discover UCP-enabled stores via the /.well-known/ucp endpoint. Platform-level discovery returns all capabilities; merchant-level discovery returns store-specific profiles:
// Platform discovery
GET /.well-known/ucp

// Merchant-specific discovery
GET /.well-known/ucp?store=my-store-slug

// Response (merchant profile)
{
  "specVersion": "2026-01-23",
  "status": "active",
  "capabilities": [
    "dev.ucp.shopping.checkout",
    "dev.ucp.shopping.cart",
    "dev.ucp.catalog.realtime",
    "dev.ucp.identity.loyalty"
  ],
  "extensions": ["dev.ucp.shopping.ap2_mandate"],
  "services": {
    "rest": "/api/v1/ucp",
    "mcp": "/my-store-slug/mcp",
    "a2a": "/my-store-slug/a2a",
    "ag_ui": "/my-store-slug/ag-ui"
  },
  "paymentHandlers": ["stripe", "usdc_x402"],
  "tools": [
    "ucp_create_checkout",
    "ucp_get_checkout",
    "ucp_update_checkout",
    "ucp_complete_checkout",
    "ucp_cancel_checkout"
  ]
}
Discovery profiles are cached for 60 seconds with automatic invalidation when merchant configuration changes. Phase B capabilities (dev.ucp.catalog.realtime, dev.ucp.identity.loyalty) appear only when the merchant has enabled them.

Protocol Detection

The UCP inbound adapter uses three confidence levels to identify UCP requests:

  • 1
    UCP-Agent header present → confidence 1.0 (explicit declaration)
  • 2
    Body contains capabilities array → confidence 0.9
  • 3
    Body matches UcpCheckout Zod schema → confidence 0.85 (shape detection)

UCP is registered 4th in the protocol plugin registry (after ACP, AP2, x402). When multiple protocols match, the highest-confidence adapter wins. If no protocol is detected, ACP is used as the default fallback at confidence 0.5.

The 6-State Checkout Lifecycle

UCP defines a richer checkout lifecycle than ACP. The 6 states map to both internal intent statuses and HTTP responses:
UCP Status            → Intent Status        → HTTP
─────────────────────────────────────────────────────
incomplete            → CREATED              → 200
requires_escalation   → BLOCKED              → 422
ready_for_complete    → POLICY_EVALUATED     → 200
complete_in_progress  → DISPATCHED           → 200
completed             → COMPLETED            → 200
canceled              → FAILED               → 409
The requires_escalation state is unique to UCP — it signals that a KYAI policy rule has blocked the checkout and the agent needs to escalate to the user for review. This is more expressive than ACP's binary success/failure model.

Normalization: UcpCheckout → AgentPaymentIntent

When a UCP request arrives, the inbound adapter normalizes it to the shared AgentPaymentIntent format used by all protocols. The checkout mapper is a pure function with bidirectional mapping:
// UcpCheckout input from agent
{
  "id": "ckout-ucp-001",
  "status": "incomplete",
  "currency": "USD",
  "line_items": [
    {
      "product_id": "prod-aaa",
      "title": "Widget",
      "quantity": 2,
      "price": { "amount": 1500, "currency": "USD" }
    }
  ],
  "totals": [{ "label": "Subtotal", "amount": 3000, "currency": "USD" }],
  "idempotency_key": "idempotent-123"
}

// Normalized to AgentPaymentIntent
{
  id: "ckout-ucp-001",
  status: "CREATED",
  source: { sourceProtocol: "UCP", sourceVersion: "1.0" },
  transaction: {
    currency: "USD",
    totalAmount: 3000,
    items: [{ productId: "prod-aaa", title: "Widget", quantity: 2, unitPrice: 1500 }]
  }
}
All mappers use immutable spread syntax — no object mutations. The same mapper works in reverse: intentToUcpCheckout() translates back for outbound responses.

SCP Identity Linking

UCP natively integrates with SCP (Shopper Context Protocol) for identity verification and loyalty data. The flow uses OAuth 2.0:

// Step 1: Agent requests authorization
GET /ucp/identity/authorize?scope=loyalty:read,identity:link
→ Returns authorization code

// Step 2: Agent exchanges code for token
POST /ucp/identity/token
{ "code": "auth-code-123", "grant_type": "authorization_code" }
→ Returns { "access_token": "tok-xxx", "expires_in": 3600 }

// Step 3: Agent calls checkout with token
POST /api/v1/ucp/checkout
Authorization: Bearer tok-xxx
→ UCP Identity Service fetches real loyalty data
Supported scopes: loyalty:read (access tier + discount eligibility), identity:link (link shopper identity), checkout:discount (apply loyalty discounts). The identity service fetches real data from the platform:
  • 1
    Shopify: Reads customer metafields (namespace loyalty) via Storefront GraphQL. Maps tier to discount: gold = 10%, silver = 5%, bronze = 0%.
  • 2
    WooCommerce: Fetches points balance via /wp-json/wc/v1/customers/{id}/points. Returns loyaltyPoints count. Graceful fallback if loyalty plugin not installed.

Real-Time Catalog (Phase B)

When a merchant enables dev.ucp.catalog.realtime, agents can fetch live prices and inventory without a full catalog sync:
GET /{slug}/ucp/catalog?product_ids=prod1,prod2&limit=20

{
  "products": [
    {
      "id": "prod-aaa",
      "title": "Widget A",
      "price": { "amount": 1500, "currency": "USD" },
      "availability": "IN_STOCK",
      "inventory_count": 42
    }
  ],
  "freshness_ms": 2500
}
The freshness_ms field tells the agent how stale the data is. Results are cached for 30 seconds (near-realtime). The catalog service fetches from Shopify Storefront GraphQL or WooCommerce REST API depending on the platform.

AP2 Mandate Delegation

UCP supports AP2 (Authorization Protocol v2) mandates as a native extension. When a merchant enables dev.ucp.shopping.ap2_mandate, agents can embed recurring payment mandates directly in UCP checkout requests. The ucp-ap2-delegate.ts adapter extracts the mandate from the UCP extensions field and delegates to the existing AP2 parser — no new mandate verification code was written.

Error Handling: Severity-Based Model

UCP uses a severity-based error model that maps to HTTP status codes:
Severity               → HTTP  → Meaning
──────────────────────────────────────────────────
recoverable            → 400   → Client can retry with different input
requires_buyer_input   → 303   → Redirect agent to collect user input
requires_buyer_review  → 422   → Policy rule needs user confirmation
unrecoverable          → 409   → Checkout already completed or canceled
This is more expressive than ACP's generic error responses. The requires_buyer_input severity (303) is particularly useful — it tells the agent to use MCP elicitation or AG-UI to collect missing information (e.g., shipping address) rather than failing the checkout.

UCP vs ACP: When to Use Which

AspectUCPACP
Backed byGoogle + Shopify (30+ partners)Stripe + OpenAI
Discovery/.well-known/ucp (dynamic, per-merchant)/.well-known/acp.json (static)
Checkout states6 states (with escalation)4 states
Cart supportYes (dev.ucp.shopping.cart)No (checkout only)
Real-time catalogYes (dev.ucp.catalog.realtime)No
Identity linkingSCP standard (OAuth 2.0)Custom headers
TransportsREST, MCP, A2A, AG-UI, EmbeddedREST, MCP
ExtensibilityExtension namespace (dev.ucp.*)Headers + body metadata
Error model4 severity levelsHTTP status + body

Both protocols normalize to the same AgentPaymentIntent internal format and share the same KYAI policy engine. From the platform's perspective, UCP and ACP are just different protocol adapters — the checkout logic is identical.

Essential insight

MCP Tools for UCP

  • 1
    ucp_create_checkout — Create a UCP checkout session from line items
  • 2
    ucp_get_checkout — Fetch checkout details by ID
  • 3
    ucp_update_checkout — Modify items or totals
  • 4
    ucp_complete_checkout — Finalize and trigger payment
  • 5
    ucp_cancel_checkout — Cancel an active session
All 5 tools return structuredContent (compatible with Claude SDK 1.27.x) alongside formatted text summaries. Idempotency is supported via idempotency_key — the same checkout ID + key returns the same response without re-processing.

Merchant Configuration

Merchants enable UCP via the protocol configuration API:
POST /api/v1/stores/{storeId}/protocols
{
  "protocol": "UCP",
  "enabled": true,
  "config": {
    "capabilities": [
      "dev.ucp.shopping.checkout",
      "dev.ucp.shopping.cart"
    ],
    "specVersion": "2026-01-23",
    "enableMcpBinding": true,
    "enableRestBinding": true,
    "enableAp2Extension": false
  }
}
Once enabled, the UCP adapter is registered in the plugin registry, /.well-known/ucp?store=slug becomes available, and the 5 MCP tools are activated. KYAI policy rules apply immediately — no separate configuration needed.

Test Coverage

The UCP implementation is backed by 215 tests across 22 test files. Coverage includes: inbound detection (25 tests), outbound translation (20 tests), checkout mapping (18 tests), error mapping (12 tests), AP2 delegation (20 tests), discovery profiles (25 tests), configuration validation (10 tests), integration end-to-end (30 tests), catalog service (40+ tests), identity service (35+ tests), and MCP tools (10 tests). All tests use pure function patterns with immutable data.

What's Next

In Part 6, we'll explore A2A — Google's Agent-to-Agent Protocol and how it enables agents to collaborate on multi-step commerce workflows. Stay tuned.

Frequently asked questions

What is UCP and who created it?

UCP (Universal Commerce Protocol) is an open protocol designed by Google and Shopify with 30+ partners. It standardizes how AI agents interact with commerce platforms — from product discovery to checkout to identity linking.

How is UCP different from ACP?

UCP has a 6-state checkout lifecycle (vs ACP's 4), a capability extension namespace (dev.ucp.*), native SCP identity linking for loyalty data, real-time catalog access, and supports 5 transport bindings (REST, MCP, A2A, AG-UI, Embedded). ACP is Stripe-centric with simpler checkout flows.

Can UCP and ACP coexist on the same store?

Yes. Both protocols normalize to the same AgentPaymentIntent format and share the KYAI policy engine. The protocol detector routes each request to the correct adapter based on confidence scoring. A store can have both UCP and ACP enabled simultaneously.

What is SCP identity linking in UCP?

SCP (Shopper Context Protocol) enables agents to link shopper identity and access loyalty data via OAuth 2.0. Agents can read loyalty tiers (gold/silver/bronze), fetch points balances, and apply loyalty discounts at checkout.

How does UCP real-time catalog work?

When a merchant enables dev.ucp.catalog.realtime, agents can fetch live prices and inventory via GET /{slug}/ucp/catalog. Data is cached for 30 seconds with a freshness_ms field showing staleness. The service fetches from Shopify Storefront GraphQL or WooCommerce REST API.

Sources and references

Related articles

UCP Universal Commerce Protocol for AI Agents | Building Agentic Commerce #5 | AgenticMCPStores