The protocol layer of agentic AI is being built right now — here’s what every developer needs to understand
Beneath the visible surface of the AI agent boom, a quieter infrastructure story is being written. MCP from Anthropic and UCP from a Google-Shopify partnership are independently solving different layers of the same problem: how does an AI agent interact reliably and safely with external systems? And more specifically, how does it spend money?
Model Context Protocol gives any language model a standardized handshake with any external tool. Universal Commerce Protocol gives any AI agent a standardized way to browse, negotiate, and purchase across any merchant without a human at the keyboard. They sound similar at first glance. They solve structurally different problems. Most engineers building agents today have not yet internalized why both will be required.
This article presents a technical examination of both protocols. I define each one precisely, compare them across eleven architectural dimensions including session model, payment semantics, identity trust, and multi-agent coordination describe their integration pathway, and derive concrete engineering guidance for developers building commerce-capable agents. I also argue that these protocols represent the first two domain layers of a broader stratified agentic infrastructure pattern that will recur across healthcare, travel, legal, and financial services.
The Problem Both Protocols Are Solving
Before either protocol existed, building an AI agent that could do anything useful required writing a custom integration for every external system. Want your agent to check GitHub issues and query a database and post to Slack? Three separate integrations. Want it to shop at Amazon and Shopify and Wayfair? Three more. The M×N problem — M models times N services became untenable fast.
MCP and UCP both attack this problem, but at different layers of the stack.

2. Model Context Protocol (MCP)
2.1 Design Goals and Architecture
MCP was introduced by Anthropic as an open standard to solve a specific integration problem: every new tool an LLM application wanted to use required a custom integration. This M×N problem, M models times N services, became untenable as both the number of capable models and the number of useful external services grew. MCP provides a single protocol interface that any model can speak and any service can implement.
The protocol is structured around three core abstractions:
- Tool: A stateless callable function. The client sends typed input parameters; the server executes and returns a typed result. Tools are the primary mechanism by which models take actions in the world.
- Resource: Read-only context that the model can retrieve, file contents, database rows, API responses. Resources provide situational awareness without mutation capability.
- Prompt: Templated instruction sets exposed by the server. Prompts allow tool providers to shape model behavior within their domain.

The data flow is straightforward. An LLM application acting as the MCP Host instantiates an MCP Client, which connects to one or more MCP Servers over stdio, HTTP/SSE, or JSON-RPC. Each server publishes a manifest of its capabilities. The host queries the manifest, and the model can then issue tool calls against any discovered capability:
LLM Application (MCP Host)
└── MCP Client
├── MCP Server: GitHub → { tools: [create_issue, list_prs, ...] }
├── MCP Server: Postgres → { tools: [query, insert, ...] }
└── MCP Server: Slack → { tools: [post_message, list_channels, ...] }
2.2 Session Model: Stateless by Design
MCP operates on a request–response model in which every tool call stands alone. The model fires a call, the server responds, and neither side retains memory of the exchange. If an application requires continuity across calls let’s say, maintaining a shopping cart or tracking a multi-step workflow that state must be managed entirely at the application layer, above the protocol. MCP has no opinion on persistence.
This design choice is a strength for general-purpose tool connectivity. Statelessness keeps the protocol simple, makes servers easy to implement, and enables horizontal scaling. It becomes a limitation only when the domain inherently requires persistent transactional state which commerce does.
The protocol achieved something rare in tech standards: broad pre-launch buy-in from merchants, payment processors, and credential providers simultaneously. Walmart, Target, Etsy, Wayfair, Stripe, Mastercard, Visa, and Adyen all signed on. That cross-layer alignment wasn’t accidental it reflects the fact that you can’t standardize commerce without standardizing the payment layer too. A shopping protocol without payment semantics is just a catalog browser.
2.3 Identity and Trust
MCP delegates identity to OAuth 2.0 at the host level. The MCP Host is responsible for authenticating to each server; individual tool calls inherit that credential context. This is appropriate for general tool use but was not designed to accommodate merchant accountability, buyer identity verification, or payment authorization chains.
2.4 Production Status
As of 2025–2026, MCP is in production. Claude natively supports MCP server connections. Cursor and Zed have shipped MCP client implementations. A growing ecosystem of MCP servers exists for GitHub, Postgres, Slack, filesystem access, web search, and dozens of other integrations. The standard is stable and actively maintained by Anthropic as an open specification.
3. Universal Commerce Protocol (UCP)
3.1 Origins and Governance
UCP was co-developed by Google and Shopify as a response to a specific problem in agentic commerce: every merchant-agent integration required custom implementation. A shopping agent working with Amazon had to speak Amazon’s API. The same agent working with a Shopify merchant spoke a completely different protocol. The goal of UCP is to standardize the entire shopping journey from discovery to post-purchase across any merchant.
The protocol has received endorsement from Walmart, Target, Etsy, Wayfair, Stripe, Mastercard, Visa, Adyen, and more than twenty additional global partners at the time of its initial rollout announcement. This breadth of endorsement reflects deliberate stakeholder alignment across the merchant, payment processor, and credential provider layers simultaneously.
3.2 Layered Architecture
UCP borrows the layered thinking of TCP/IP. Rather than a monolithic specification, it is composed of independently versioned layers that can evolve at different rates:
- Shopping Service layer: Core transaction primitives sessions, line items, totals, and inter-party messaging. This is the invariant base of the protocol.
- Capability modules: Independently versioned modules covering Checkout, Orders, and Catalog. A merchant can implement Catalog without Checkout if they support browsing but delegate purchasing elsewhere.
- Extension schemas: Domain-specific compositions for fulfillment, subscriptions, returns, loyalty, and other verticals. Extensions are additive and do not break core compatibility.

3.3 The Checkout Session as a First-Class Object
This is the architectural difference that matters most in practice. In UCP, a checkout session is not something you construct above the protocol, it is a first-class object that the protocol itself manages, held in synchrony across the merchant, the payment service provider, and the credential provider simultaneously.
When an agent adds a line item, applies a discount code, and authorizes payment, those are three operations on the same persistent session object. All parties maintain a consistent view of that session state. This is not a design preference; it is a technical requirement. Commerce without persistent state is not commerce, it is a form that keeps resetting.
Consumer Agent
└── UCP Protocol
├── discover_capabilities() → Merchant Profile
├── search_catalog() → Structured product data
├── create_checkout_session() → Session ID: sess_abc123
├── add_line_item(sess_abc123) → Cart state updated
├── apply_discount(sess_abc123) → Totals recalculated
└── authorize_payment(sess_abc123) → AP2 → PSP → Cryptographic receipt
3.4 Agent Payments Protocol (AP2)
Every UCP payment flows through the Agent Payments Protocol. The core idea is straightforward but its security implications are significant: AP2 issues a scoped, single-use token per transaction, not a standing API credential. The agent requests authorization for a specific purchase amount to a specific merchant. The user (or a pre-configured policy) approves that specific scope. The token is created, consumed in the transaction, and expires.
The practical consequence: a compromised agent cannot silently drain a payment method. Every purchase leaves an explicit authorization chain that can be audited after the fact. For enterprise deployments, this distinction between “standing credential” and “per-transaction consent” is the difference between an acceptable security posture and a liability.

3.5 Multi-Agent Support via A2A
UCP has native support for multi-agent delegation through A2A, Google’s Agent-to-Agent Protocol. A2A governs how one AI agent delegates a sub-task, including a purchase, to another agent, with appropriate handoff of credentials, session state, and authorization scope. This is architecturally distinct from MCP, which has no native concept of agent-to-agent delegation and relies on application-layer orchestration to coordinate multiple agents.

3.6 Capability Declaration
Merchants participating in UCP publish a structured Merchant Profile that declares which capabilities they support. An agent can query this profile before interacting with a merchant and route behavior accordingly; for example, checking whether a merchant supports the Catalog capability before attempting a product search, or confirming Orders capability before attempting order tracking.
This capability-first design allows agents to interact generically with any UCP-compliant merchant without hardcoded merchant-specific logic.
4. Architectural Comparison

5. UCP-over-MCP: The Transport Pattern
A key architectural feature of UCP is that it explicitly supports MCP as a transport mechanism. A merchant can expose their UCP-compatible commerce capabilities as an MCP server. An AI agent using any MCP-compatible framework such as Claude, Cursor, or a custom LangGraph pipeline can then issue UCP-defined tool calls through the standard MCP client interface.
From the model’s perspective, this is just a tool call. From the commerce infrastructure’s perspective, it is a fully stateful, auditable, cryptographically secured transaction. The seam is invisible to the model.
Claude (MCP Host)
└── MCP Client
└── UCP-over-MCP Server → Merchant Backend
├── discover_capabilities() → Merchant Profile
├── search_catalog(query) → Structured product results
├── create_checkout_session() → sess_abc123
├── add_line_item(sess, item_id) → Cart updated
└── authorize_payment(sess) → AP2 → PSP → Cryptographic receipt

5.2 The Full Protocol Stack
When you step back from the two-protocol view, you start to see the real infrastructure pattern. MCP and UCP aren’t competing standards, they’re two layers in what will become a stratified agentic infrastructure stack. Each layer owns a different concern:

6. Show Me the Code
Enough architecture. Let me show you what this actually looks like in Python. The core pattern is an MCP server that exposes UCP-defined tools, a checkout session object that maintains state across agent turns, and AP2 token lifecycle management for payment authorization.
The architecture has three components:
- server/merchant_server.py — An MCP server exposing 8 UCP tools
- ap2/authorization.py — Mock AP2 token issuance and authorization
- client/commerce_agent.py — Claude driving the full shopping flow
Note: The snippets below are simplified illustrations of each layer. The full production implementation using FastMCP, LangGraph, and a FastAPI streaming layer is at github.com/Sudip-Pandit/ucp_mcp_agent
The MCP Server Exposing UCP Tools
from mcp.server.fastmcp import FastMCP
from dataclasses import dataclass, field
from typing import Optional
import uuid, time
app = FastMCP("ucp-merchant-server")# ─── Session state: the first-class object that makes commerce possible ───
@dataclass
class LineItem:
sku: str
name: str
quantity: int
unit_price: float
@dataclass
class CheckoutSession:
session_id: str
merchant_id: str
status: str = "open" # open | confirmed | paid | cancelled
line_items: list[LineItem] = field(default_factory=list)
discount_code: Optional[str] = None
discount_amount: float = 0.0
shipping_amount: float = 4.99
receipt_id: Optional[str] = None # set after AP2 authorization
@property
def subtotal(self) -> float:
return sum(i.quantity * i.unit_price for i in self.line_items)
@property
def total(self) -> float:
return self.subtotal - self.discount_amount + self.shipping_amount
_sessions: dict[str, CheckoutSession] = {}# ─── UCP tools exposed as MCP tools ─────────────────────────────────────
@app.tool()
def discover_capabilities() -> dict:
"""Returns the merchant's UCP capability profile."""
return {
"merchant_id": "shop_789",
"capabilities": ["Catalog", "Checkout", "Orders"],
"supports_ap2": True,
"currencies": ["USD", "EUR", "CAD"],
}
@app.tool()
def create_checkout_session() -> dict:
"""Creates and returns a new checkout session.
The session_id MUST be passed to every subsequent call."""
sess = CheckoutSession(
session_id=str(uuid.uuid4())[:8],
merchant_id="shop_789"
)
_sessions[sess.session_id] = sess
return {"session_id": sess.session_id, "status": "open"}
@app.tool()
def add_line_item(session_id: str, sku: str, quantity: int = 1) -> dict:
"""Adds a product to the checkout session."""
sess = _sessions.get(session_id)
if not sess:
raise ValueError(f"Session {session_id} not found")
catalog = {"cam_1080": ("1080p Webcam", 89.99), "ssd_1tb": ("1TB SSD", 79.99)}
name, price = catalog[sku]
sess.line_items.append(LineItem(sku=sku, name=name, quantity=quantity, unit_price=price))
return {"session_id": session_id, "subtotal": sess.subtotal, "items_count": len(sess.line_items)}
@app.tool()
def authorize_payment(session_id: str, confirmed: bool = False) -> dict:
"""Executes AP2 payment authorization. Must have explicit confirmation."""
if not confirmed:
raise ValueError("Payment requires confirmed=True - never authorize silently")
sess = _sessions[session_id]
# AP2: request single-use scoped token, then consume it
token = request_ap2_token(sess.merchant_id, session_id, sess.total, "USD")
result = consume_ap2_token(token.token_id) # single-use enforcement
sess.receipt_id = result.receipt_id
sess.status = "paid"
return {"receipt_id": sess.receipt_id, "total_charged": sess.total, "status": "paid"}
Session State: The Checkout Object
The CheckoutSession is the first-class UCP object, it accumulates state across every agent turn and must survive LLM context resets, retries, and agent handoffs:
@dataclass
class CheckoutSession:
session_id: str # Long-lived handle — carry this through every call
merchant_id: str
status: str # "open" | "confirmed" | "paid" | "cancelled"
line_items: list[LineItem]
discount_code: str | None
discount_amount: float
shipping_amount: float
receipt_id: str | None # Set only after AP2 authorization completes
The Claude Agent
The agent is a standard Claude tool-calling loop. The system prompt enforces correct UCP sequencing, protocol discipline lives in the prompt:
SYSTEM_PROMPT = """You are a commerce agent operating over UCP-compliant infrastructure.
Protocol rules:
1. Always call discover_capabilities() first.
2. Always create_checkout_session() before adding any items. Never skip this.
3. Carry the session_id through every subsequent call — it is the transaction state.
4. Before authorize_payment, call review_checkout() and get explicit user confirmation.
5. Never authorize payment silently. Surface errors rather than retrying payment."""
def run_commerce_agent(user_request: str):
messages = [{"role": "user", "content": user_request}]
while True:
response = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
system=SYSTEM_PROMPT,
tools=load_ucp_tools(), # fetched from MCP server manifest
messages=messages
)
if response.stop_reason == "end_turn":
break
tool_results = []
for block in response.content:
if block.type == "tool_use":
result = call_mcp_tool(block.name, block.input)
tool_results.append({
"type": "tool_result",
"tool_use_id": block.id,
"content": json.dumps(result)
})
messages.append({"role": "assistant", "content": response.content})
messages.append({"role": "user", "content": tool_results})Running It
Clone and run the full production implementation:
git clone https://github.com/Sudip-Pandit/ucp_mcp_agent
cd ucp_mcp_agent
pip install -r requirements.txt
cp .env.example .env # add your ANTHROPIC_API_KEY
# Terminal 1 — UCP/MCP server
python mcp_server/server.py
# Terminal 2 — Agent API
uvicorn api.main:app --reload --port 8000
# Send a shopping request
curl -X POST http://localhost:8000/shop \
-H "Content-Type: application/json" \
-d '{"message": "I need a laptop under $2500. Confirm purchase with Google Pay."}'

What This Means for Developers
If you’re building on Claude or any MCP-compatible framework today, you can implement UCP semantics by exposing a UCP-compatible tool set as an MCP server. You don’t need to wait for broad platform adoption. The transport layer is ready.
Design your agents for stateful sessions. The session ID must survive LLM context windows, retries, and agent handoffs. Don’t flatten the shopping flow into a single tool call. Each phase such as discovery, selection, confirmation, payment, post-purchase maps to a distinct protocol operation.
Implement AP2 properly. Per-transaction OAuth delegation is more complex than API key authentication. Handle token expiry, implement explicit user consent prompts, and never substitute a standing credential for a scoped per-transaction token. This isn’t just a security best practice in a UCP-compliant system, it’s a protocol requirement.
Multi-merchant orchestration is still unsolved. UCP handles single-merchant interoperability. The genuinely hard problem comparing inventory across ten merchants, splitting a purchase across PSPs, maintaining a coherent user-facing cart lives at the orchestration layer above UCP. That’s where multi-agent frameworks earn their complexity.
The Bigger Pattern
Commerce was the first domain to get this two-layer treatment. But the pattern will recur. Healthcare, travel, legal services, financial services each regulated domain will eventually see a domain-specific protocol (analogous to UCP) sitting above MCP’s general tool connectivity layer. Commerce had the necessary infrastructure already: OAuth, PSPs, structured product data.
The engineers building these systems now are writing the infrastructure assumptions that the next generation of agents will inherit. Understanding why both layers exist and how they compose is the foundation for building anything durable in this space.
The code is open source. Run it, break it, extend it. The UCP merchant onboarding is underway through 2025–2026. The transport layer is already here.
References & Resources
- UCP Official Specification: https://ucp.dev
- Google Developer Documentation — UCP: https://developers.google.com/merchant/ucp
- MCP Official Documentation: https://modelcontextprotocol.io
- Agent Payments Protocol (AP2): https://ucp.dev (AP2 specification section)
- A2A Protocol (Agent-to-Agent): https://google.github.io/A2A
- Anthropic MCP Announcement: https://www.anthropic.com/news/model-context-protocol
- Full working implementation: https://github.com/Sudip-Pandit/ucp_mcp_agent
If you’ve stayed with me to the end, thank you! your curiosity and attention mean more than you know. I share thoughtful updates on the fast‑moving world of AI, so if you’d like to keep exploring with me, feel free to 🔔 follow clap👏👏👏 subscribe 📩 and I’ll keep the good stuff coming 🙌❤️.
How AI Agents Shop, Work, and Transact: The MCP–UCP Architecture Breakdown was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.