Build an AI Shopping Agent
Step-by-step guide to building your first shopping agent on UCP, using the tool names and request shapes from the spec (v2026-08-25). Copy-paste code, real test targets from 19,337+ verified stores, and error patterns from production. Get to a working agent in under 30 minutes. Want the shortcut? Connect the UCP Checker MCP server and skip to shopping — see the API & MCP docs.
Thousands of real agent sessions have run on this stack
LLM-driven agent sessions run through UCP Playground against real verified stores, across several model providers and store platforms. As of September 2026.
What you're actually building
A UCP shopping agent is four things glued together: a profile fetcher, an MCP client, a tool-call dispatcher, and (optionally) an LLM to pick which tools to call. That's it. Every step below is one of those layers.
/.well-known/ucp.
This tells you which protocol versions and capabilities the store supports, and where its endpoints are.
capabilities (e.g. dev.ucp.shopping.catalog.search, dev.ucp.shopping.checkout) and the services entry for dev.ucp.shopping. Decide whether this store supports the flow you want to run.
mcp transport. List the tools, then call them — every call carries meta["ucp-agent"], the URL of your platform's own UCP profile.
search_catalog → get_product → create_cart → create_checkout → complete_checkout. Optionally wire an LLM to pick steps automatically.
What you need
- A language runtime with an MCP client library. Official MCP SDKs exist for Python, TypeScript and several other languages. Any language works — MCP is JSON-RPC, ~100 lines to roll your own.
- An HTTP client (curl, requests, fetch, whatever). You'll use it to fetch the store's profile before MCP takes over.
-
A platform profile URL. UCP requires every request to name your platform's profile (a JSON document you host, same shape as a store's
/.well-known/ucp). The store fetches it to agree a protocol version and capabilities with you. See Platform Profile in the spec. - A test store from the UCP directory. We list 6 ready-to-use targets below — all verified, all with deep capability declarations, across platforms.
- Optional: any LLM with tool calling if you want the agent to pick which tools to call. You can also hard-code the flow for deterministic testing.
Pick a target store
Start with a store that already has deep UCP coverage so your agent has real tools to call. The 6 stores below are top of the directory by capability depth — pick any one as your first target.
Tip: Start with a store whose profile declares dev.ucp.shopping.catalog.search and an mcp transport — catalog reads are the easiest first call. Open a store's status page to see exactly what it declares, or browse the full directory to pick your own target.
Fetch the store's profile
Every UCP store publishes a JSON profile at /.well-known/ucp. Fetch it first — it tells you which protocol versions and capabilities the store supports and which transports you can use.
# curl
curl https://store.example/.well-known/ucp | jq .ucp.services
# Python
import httpx
STORE = "https://store.example" # any store from the directory
profile = httpx.get(f"{STORE}/.well-known/ucp").json()
print(profile["ucp"]["version"])
print("capabilities:", list(profile["ucp"].get("capabilities", {}).keys()))
// TypeScript
const STORE = "https://store.example"; // any store from the directory
const profile = await (await fetch(`${STORE}/.well-known/ucp`)).json();
console.log(profile.ucp.version);
console.log("capabilities:", Object.keys(profile.ucp.capabilities ?? {}));
You want two things from the profile: the services map (to find the MCP endpoint URL) and the capabilities map (to know what you can call, keyed by names like dev.ucp.shopping.catalog.search). See the full field reference on the /.well-known/ucp developer guide.
Find the MCP endpoint
The spec is exact about this: the MCP endpoint is services["dev.ucp.shopping"] → the entry whose transport is mcp → its endpoint. Stores can also declare rest, a2a and embedded transports for the same service.
# Python — find the MCP endpoint from a parsed profile
def find_mcp_endpoint(profile):
for entry in profile["ucp"].get("services", {}).get("dev.ucp.shopping", []):
if entry.get("transport") == "mcp":
return entry["endpoint"]
raise ValueError("No MCP transport declared for dev.ucp.shopping")
endpoint = find_mcp_endpoint(profile)
print(f"MCP endpoint: {endpoint}")
Heads up: use the endpoint the profile declares — the spec says the endpoint MUST come from the store's profile, not from a guessed path. If a store declares no mcp transport, check its REST entry or pick another store.
Connect an MCP client and list tools
MCP is JSON-RPC over HTTP. You can use an official MCP SDK or hand-roll the calls you need: initialize, tools/list and tools/call.
Or let UCP Checker do steps 1–4: connect https://ucpchecker.com/mcp to your client and call list-stores, search-catalog and check-domain to resolve a verified store — then transact against that store's own endpoint. Parameters and limits in the docs.
# Python — minimal MCP client, no SDK
import httpx
def mcp_call(endpoint, method, params=None):
res = httpx.post(endpoint, json={
"jsonrpc": "2.0",
"id": 1,
"method": method,
"params": params or {},
}, headers={
"Content-Type": "application/json",
"Accept": "application/json, text/event-stream",
})
return res.json()
mcp_call(endpoint, "initialize", {
"protocolVersion": "2025-06-18",
"capabilities": {},
"clientInfo": {"name": "my-agent", "version": "0.1"},
})
tools = mcp_call(endpoint, "tools/list")["result"]["tools"]
for tool in tools:
print(f"- {tool['name']}: {tool['description'][:80]}")
The UCP tool names are fixed by the spec: search_catalog, lookup_catalog and get_product for catalog; create_cart, get_cart, update_cart, cancel_cart for cart; create_checkout, get_checkout, update_checkout, complete_checkout, cancel_checkout for checkout; and get_order. A store exposes the ones for the capabilities it declares. If tools/list returns an empty array or an error, the store declares MCP but hasn't wired it up — validate the store to confirm.
Execute your first tool call
Call search_catalog with a query and a buyer context. Two argument blocks: meta (required on every UCP call — it names your platform profile) and catalog (the search itself). Context values are hints for relevance and localisation, not binding data.
# Python — search the catalog
PLATFORM_PROFILE = "https://agent.example/.well-known/ucp" # your platform profile
result = mcp_call(endpoint, "tools/call", {
"name": "search_catalog",
"arguments": {
"meta": {
"ucp-agent": {"profile": PLATFORM_PROFILE},
},
"catalog": {
"query": "running shoes",
"context": {
"address_country": "US",
"currency": "USD",
"language": "en",
},
"pagination": {"limit": 10},
},
},
})
# UCP payloads come back in result.structuredContent
for p in result["result"]["structuredContent"].get("products", []):
print(p["id"], p["title"], p.get("price_range", {}).get("min"))
If you get real product results back — titles, prices (in minor units, e.g. 12000 = $120.00), variant IDs — you have a working UCP shopping agent. Everything past this point (create_cart, create_checkout, complete_checkout) is the same tool-call pattern with the same meta block. Full request and response shapes are in the spec's Catalog MCP binding.
Handle the common failure modes
Real stores fail in predictable ways. Here's the taxonomy and how to recover.
/.well-known/ucp-32001: invalid_profile_url, profile_unreachable, profile_malformed or version_unsupportedmeta["ucp-agent"].profile is present, publicly reachable and valid, and that it declares a protocol version the store supports (compare with the store's ucp.version). The error's data.continue_url, when present, is where to hand the buyer off instead.ucp.status: "error" and capabilities_incompatibledev.ucp.shopping.catalog.search) in your platform profile.-32000 (HTTP 401 / 403)dev.ucp.common.identity_linking) — check whether the store declares it.-32000 (HTTP 429)Retry-After when the store sends it and back off — don't retry in a tight loop.-32602inputSchema each tool returns from tools/list against your arguments — UCP puts operation fields under a named block (catalog, cart, checkout) next to meta.tools arrayproducts or missing itemsmessages explaining why. Try a broader query, drop filters, and follow pagination rather than assuming one call returns everything.Where to go next
Watch your agent run against real stores, and let UCP Checker find the stores for you.
UCP Playground
Run an agent against a verified store and watch every search_catalog → create_cart → create_checkout step with full tool-call visibility. Replay any session and compare models on the same store.
UCP Checker MCP
Connect https://ucpchecker.com/mcp to your client and resolve verified stores by what they declare — then transact against each store's own endpoint. Every store's profile is checked daily.
Frequently Asked Questions
What language should I build my agent in?
Do I need an API key to call a UCP store?
meta["ucp-agent"] with your platform profile URL. Many stores serve catalog reads (search_catalog, lookup_catalog, get_product) without further credentials; carts, checkout and orders may require authentication, and buyer-account flows use Identity Linking. The store's profile at /.well-known/ucp is always public.How do I test without making real purchases?
complete_checkout. That is the call that places the order; search, cart and checkout creation before it do not.Which AI models can call UCP tools?
What's the minimum viable agent?
/.well-known/ucp profile, read the MCP endpoint from services["dev.ucp.shopping"], call tools/list, then call search_catalog with a query and your meta["ucp-agent"] profile. That's roughly 50 lines of Python. Cart and checkout use the same tool-call pattern — they need the store to declare those capabilities and (often) authentication.How do I handle stores that reject my agent?
-32001 means negotiation failed — your meta["ucp-agent"] profile is missing, unreachable, malformed or on a version the store doesn't support. -32000 means authentication, permission or rate limiting. A normal result with ucp.status: "error" is a business outcome such as capabilities_incompatible; read its messages. When in doubt, run a live check on the store to see what it declares.Get the agentic commerce digest every Monday
Real adoption data, ecosystem trends, new spec versions, and the stores that broke or recovered this week. Read by founders and engineers building the next generation of commerce.
