# UCP Integration Guide
## Overview
The Universal Commerce Protocol (UCP) is a discovery and capability negotiation standard for agentic commerce. It allows AI agents to programmatically discover what a merchant supports, negotiate terms, and interact through a standardized API surface.
This gateway implements UCP version `2026-01-11`.
---
## Profile Discovery
### How It Works
When an AI agent encounters a merchant, the first step is **profile discovery**. The agent fetches `/.well-known/ucp` from the merchant's domain to receive a machine-readable manifest of the merchant's services, transports, capabilities, and payment methods.
```
Agent Gateway
| |
|-- GET /.well-known/ucp ------------->|
| |
|<--- 200 OK (UCPProfile JSON) --------|
| |
| [Agent parses profile, extracts |
| capabilities, selects transport] |
| |
|-- Connect via selected transport --->|
```
### Profile Endpoint
**Request:**
```http
GET /.well-known/ucp HTTP/1.1
Host: gw.example.com
Accept: application/json
```
**Response:**
```json
{
"version": "2026-01-11",
"services": [
{
"type": "dev.ucp.shopping",
"transports": [
{ "type": "rest", "endpoint": "https://gw.example.com/api/v1" },
{ "type": "mcp", "endpoint": "https://gw.example.com/mcp" },
{ "type": "a2a", "endpoint": "https://gw.example.com/a2a" },
{ "type": "embedded", "endpoint": "https://gw.example.com/embedded" }
],
"capabilities": [
{ "name": "dev.ucp.shopping.checkout", "version": "2026-01-11" },
{ "name": "dev.ucp.shopping.catalog", "version": "2026-01-11" },
{ "name": "dev.ucp.shopping.order", "version": "2026-01-11" },
{ "name": "dev.ucp.shopping.fulfillment", "version": "2026-01-11" }
],
"payment_handlers": [
{ "id": "shopify_payments", "type": "processor_tokenizer" },
{ "id": "ap2_mandate", "type": "mandate" }
],
"signing_keys": {
"jwk": "https://gw.example.com/.well-known/jwks.json"
}
}
]
}
```
### Profile Generation
The profile is generated dynamically from `GatewayConfig` at runtime:
```typescript
// src/ucp/profile.ts
export function generateProfile(config: GatewayConfig): UCPProfile {
const baseUrl = config.gateway.baseUrl;
return {
version: '2026-01-11',
services: [{
type: 'dev.ucp.shopping',
transports: buildTransports(baseUrl),
capabilities: DEFAULT_CAPABILITIES,
payment_handlers: DEFAULT_PAYMENT_HANDLERS,
signing_keys: { jwk: `${baseUrl}/.well-known/jwks.json` },
}],
};
}
```
The `GATEWAY_BASE_URL` environment variable determines the public URL embedded in all transport endpoints and JWKS references.
---
## Capability Negotiation
### Algorithm
Before transacting, the agent and merchant must agree on a shared set of capabilities. The negotiation algorithm works as follows:
```
Step 1: INTERSECTION
Server capabilities: [checkout, catalog, order, fulfillment]
Agent capabilities: [checkout, catalog, checkout.loyalty]
----------------------------------------
Intersection: [checkout, catalog, checkout.loyalty]
Step 2: EXTENSION PRUNING
For each extension capability (contains "."):
Check if its parent base capability is in the intersection.
"checkout.loyalty" -> parent "checkout" IS in intersection -> KEEP
----------------------------------------
Active capabilities: [checkout, catalog, checkout.loyalty]
Step 3: RESULT ASSEMBLY
Return:
- active_capabilities: [checkout, catalog, checkout.loyalty]
- available_discounts: [AGENT10 - 10% off]
- shipping_options: [Standard $5.99, Express $14.99, Overnight $29.99]
- payment_handlers: [shopify_payments, ap2_mandate]
```
### Extension Pruning Rules
Extensions are capability names that extend a base capability with a dot-separated suffix:
| Capability Name | Type | Parent |
|----------------|------|--------|
| `dev.ucp.shopping.checkout` | Base | -- |
| `dev.ucp.shopping.checkout.loyalty` | Extension | `dev.ucp.shopping.checkout` |
| `dev.ucp.shopping.checkout.subscriptions` | Extension | `dev.ucp.shopping.checkout` |
| `dev.ucp.shopping.catalog` | Base | -- |
An extension is only included in the active set if its parent base capability is also present in the intersection. This prevents orphaned extensions that would lack the required base functionality.
### Negotiation via MCP Tool
The `negotiate_terms` tool triggers the full negotiation flow:
```
Agent Gateway Agent Profile URL
| | |
|-- negotiate_terms( | |
| cart_id, | |
| agent_profile_url | |
| ) ----------------------->| |
| | |
| |-- GET agent_profile_url -------->|
| |<---- UCPProfile JSON ------------|
| | |
| | [Extract agent capabilities] |
| | [Generate server capabilities] |
| | [Run intersection algorithm] |
| | [Create checkout session] |
| | |
|<--- NegotiateResult ---------| |
| { | |
| negotiation: { | |
| active_capabilities, | |
| available_discounts, | |
| shipping_options, | |
| payment_handlers | |
| }, | |
| checkout_session: {...}, | |
| discount_applied: bool | |
| } | |
```
---
## Checkout State Machine
### States
The checkout session follows a three-state machine with auto-detection:
```
+---------------------------+
| |
v |
+------------+ |
+------->| incomplete |----+ |
| +------------+ | |
| | | |
| [escalation [all fields |
| signal] present] |
| | | |
| v v |
| +-------------------+ +-----------------------+
+---| requires_ | | ready_for_ |
| escalation | | complete |
+-------------------+ +-----------------------+
|
| execute_checkout
v
+----------+
| Order |
| Created |
+----------+
```
### State Definitions
| State | Meaning | Trigger |
|-------|---------|---------|
| `incomplete` | Checkout is missing required information | Default state; one or more of: line items, buyer email, shipping address, payment instrument is missing |
| `requires_escalation` | Checkout needs human buyer input | A `CheckoutMessage` with severity `requires_buyer_input` exists (e.g., 3-D Secure challenge, address verification) |
| `ready_for_complete` | All requirements met, ready to execute | All required fields are present and no escalation signals exist |
### Valid Transitions
| From | To | Condition |
|------|----|-----------|
| `incomplete` | `requires_escalation` | Escalation signal detected |
| `incomplete` | `ready_for_complete` | All fields populated |
| `requires_escalation` | `incomplete` | Escalation resolved, back to building |
| `requires_escalation` | `ready_for_complete` | Escalation resolved and all fields present |
| `ready_for_complete` | (none) | Terminal pre-completion state |
### Auto-Detection
The `CheckoutSessionManager.update()` method automatically determines the correct status after every update:
```typescript
function determineStatus(session: CheckoutSession): CheckoutStatus {
// Escalation signals take priority
if (session.messages.some(m => m.severity === 'requires_buyer_input')) {
return 'requires_escalation';
}
// All required fields present
if (hasLineItems && hasBuyerEmail && hasShippingAddress && hasPayment) {
return 'ready_for_complete';
}
return 'incomplete';
}
```
### Required Fields for Completion
| Field | Type | Purpose |
|-------|------|---------|
| `line_items` | `LineItem[]` (non-empty) | At least one item in the cart |
| `buyer.email` | `string` | Buyer's email for order confirmation |
| `shipping_address` | `Address` | Delivery address |
| `payment_instruments` | `PaymentInstrument[]` (non-empty) | At least one payment method |
### Totals Recalculation
Every time line items change, totals are automatically recalculated:
```
subtotal = sum of product/service line items
tax = subtotal * 8% (configurable)
shipping = determined by selected shipping option
discount = sum of discount line items (absolute value)
fee = subtotal * 0.5% (configurable)
total = subtotal + tax + shipping - discount + fee
```
All amounts are in **minor units** (cents for USD).
---
## UCP Schema Reference
### UCPProfile
```typescript
interface UCPProfile {
version: string; // "2026-01-11"
services: UCPService[];
}
```
### UCPService
```typescript
interface UCPService {
type: string; // "dev.ucp.shopping"
transports: UCPTransport[];
capabilities: UCPCapability[];
payment_handlers: UCPPaymentHandler[];
signing_keys: { jwk: string }; // URL to JWKS endpoint
}
```
### UCPTransport
```typescript
interface UCPTransport {
type: "rest" | "mcp" | "a2a" | "embedded";
endpoint: string; // Full URL
}
```
### UCPCapability
```typescript
interface UCPCapability {
name: string; // "dev.ucp.shopping.checkout"
version: string; // "2026-01-11"
}
```
### UCPPaymentHandler
```typescript
interface UCPPaymentHandler {
id: string;
type: "processor_tokenizer" | "platform_tokenizer" | "mandate";
}
```
### CheckoutSession
```typescript
interface CheckoutSession {
id: string;
status: "incomplete" | "requires_escalation" | "ready_for_complete";
currency: string;
line_items: LineItem[];
totals: CheckoutTotals;
buyer?: BuyerInfo;
shipping_address?: Address;
billing_address?: Address;
payment_instruments: PaymentInstrument[];
messages: CheckoutMessage[];
continue_url?: string;
created_at: string;
updated_at: string;
}
```
### CheckoutTotals
```typescript
interface CheckoutTotals {
subtotal: number; // minor units
tax: number;
shipping: number;
discount: number;
fee: number;
total: number;
currency: string; // ISO 4217
}
```