MCP & agents
Stores for shopping agents
How an AI agent shopping for a person (Claude, ChatGPT, Gemini) finds the products of a Recaudo store and builds their cart.
Turning it on
The business turns on “Open my store to AI agents” in Online store → Settings. While it is off, the store MCP and catalog return 404. The product page markup is always published.
Store MCP (Claude and other MCP clients)
Every store has its own public MCP server. It needs no account or token because it is for the shopper's agent; /mcp is a different server, for the business's team.
https://recaudo.app/store/{slug}/mcp
Tools
search_productsSearches the catalog by text or category. Returns in-stock products with tax-included price, link and image.get_productProduct detail: description, images and presentations with their price.create_cart_linkBuilds a link that opens the store cart with those products. The agent gives it to the person, who reviews and pays.
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "search_products",
"arguments": {
"query": "café",
"limit": 5
}
}
}
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "create_cart_link",
"arguments": {
"items": [
{
"product_id": "…",
"quantity": 2,
"tier_label": "Caja de 6"
}
]
}
}
}
Note
Catalog in ChatGPT format
The full catalog as JSON Lines, with the fields of the ChatGPT product feed (Agentic Commerce Protocol). To show up in ChatGPT Shopping, OpenAI has to onboard the store; this file is what you hand them. Only active products with a photo and price are included.
https://recaudo.app/store/{slug}/agent-feed.jsonl
Markup on every product page
Every product page carries a schema.org Product block in JSON-LD: name, images, tax-included price, currency, availability and seller. Browsing agents (Claude, Gemini, Perplexity) read it, and so does Google.
Tip
Checkout from the chat (Agentic Commerce Protocol)
So ChatGPT or another platform can buy without sending the shopper to the store. The platform opens a session with catalog ids (SKU or product id), Recaudo sets prices, taxes and shipping from the store, and on completion creates the order and charges the single-use payment token.
POST /checkout_sessionsOpens the session (201).POST /checkout_sessions/{id}Changes items, buyer or address.GET /checkout_sessions/{id}Reads the session.POST /checkout_sessions/{id}/completeCreates the order and charges.POST /checkout_sessions/{id}/cancelCancels; a completed session answers 405.
https://recaudo.app/acp/{slug}/checkout_sessions
{
"items": [
{
"id": "SKU-123",
"quantity": 2
}
],
"buyer": {
"first_name": "Ana",
"last_name": "López",
"email": "ana@example.com"
},
"fulfillment_address": {
"name": "Ana López",
"line_one": "Av. Reforma 1",
"city": "CDMX",
"state": "CDMX",
"country": "MX",
"postal_code": "06600"
}
}
{
"payment_data": {
"token": "spt_…",
"provider": "stripe"
}
}
Authenticate with Authorization: Bearer and the key the business generates in Online store → Settings (shown once). Every POST carries Idempotency-Key: the same body returns the same response; a different body with the same key answers 422 idempotency_conflict and a request still running, 409 idempotency_in_flight.
Amounts are integers in cents and currency is lowercase. Both items [{id, quantity}] and line_items [{item: {id, quantity}}] are accepted. The session is ready_for_payment once there is a buyer email, an address (if the store asks for one) and everything is available; otherwise not_ready_for_payment with per-field messages. Payment is a Stripe Shared Payment Token (spt_…) charged with the business's Stripe account; if declined it answers 402 payment_declined, the order is canceled, stock returns and the session takes another token.
Note
If the business saves the notification URL and secret the platform gives it, Recaudo sends order_created on completion and order_updated on every order change, with the Merchant-Signature header (hex HMAC-SHA256 of the body) and Timestamp. Statuses: created, confirmed, shipped, fulfilled, canceled. With checkout on and terms and privacy policy set, the catalog flags is_eligible_checkout.
AP2 mandates (v0.2)
For agents using AP2 (FIDO Alliance): the person signs which cart they authorize and the store verifies it before charging. It is optional; without a mandate the checkout works the same.
- When the session is ready_for_payment, the response carries ap2.checkout_jwt: the cart (items, quantities, currency and total) signed by the store with ES256, and ap2.jwks_uri with its public key.
- The agent builds the checkout mandate (SD-JWT mandate.checkout.1) with that checkout_jwt, its checkout_hash (base64url SHA-256) and the person's key in the jwk header and cnf.jwk, plus a KB-JWT with sd_hash and aud equal to the complete URL.
- It sends it in ap2.checkout_mandate when completing. Recaudo checks signatures, disclosures, hash, dates and that the cart is unchanged. If anything is off it answers 400 invalid_mandate and does not charge.
- On charge, the response carries ap2.checkout_receipt: a JWT signed by the store with status Success, reference (the checkout_hash) and order_id. If the charge is declined, the receipt says Error.
https://recaudo.app/store/{slug}/jwks.json
{
"payment_data": {
"token": "spt_…",
"provider": "stripe"
},
"ap2": {
"checkout_mandate": "<issuer-jwt>~<disclosure>~…~<kb-jwt>"
}
}
Note