At a glance
| Protocol | Layer | Status | Pinned revision | Where |
|---|---|---|---|---|
| MCP | transport | Supported | @modelcontextprotocol/[email protected] | /mcp |
| HTTP | transport | Supported | native routes | /api/resources/{id}/invoke |
| A2A | transport | Experimental | v1.0.0, JSON-RPC | /a2a |
| ACP | checkout transport | Experimental | 2026-04-17 | /acp |
| x402 | payment | Supported | v2, exact, EVM | headers or _payment |
| AP2 | authorization | Experimental | v0.2.0, Direct mode | Agent-Authorization or _authorization |
| UCP · MPP | — | Planned | — | no code ships |
How they fit together
Think of the gateway as a shop front with several doors. HTTP, MCP, A2A and ACP are the doors — different ways for an agent to walk in and ask for something. Whichever door it uses, the same cashier handles the sale: x402 is how the agent pays, and AP2, when you ask for it, is the signed note proving a human approved the purchase. Your backend stays behind the counter and never has to learn any of these protocols.
HTTP, MCP, A2A and ACP are protocol adapters: each translates its wire format into one CanonicalRequest and hands it to the ExecutionPipeline, which never knows which adapter called it. x402 is a PaymentProvider that creates the requirement, verifies the proof and settles; AP2 is an AuthorizationProvider that runs between payment verification and settlement. No adapter contains payment logic or calls the backend, so every rule applies identically on every surface. ACP is the exception on payment: its checkout resources are free at the gateway layer, because the purchase is paid through the merchant's own checkout.
MCP HTTP A2A ACP agent transports
│ │ │ │
└──────────┴─────┬─────┴──────────┘
▼
ExecutionPipeline ──────────► your backend API
│ │
▼ ▼
AP2 mandate x402 payment
(who approved) (who paid, how much, to whom)MCP
MCP is the standard way AI assistants find and use tools. The gateway lists each of your endpoints as a tool, with its price written in the description, so the assistant knows what it costs before it asks. When it calls a paid tool, it first gets the bill instead of the result — it pays, then calls the same tool again with the payment attached.
Resources with expose: [mcp] are served as MCP tools over Streamable HTTP at protocols.mcp.mountPath (default /mcp). Tool name = resource id, inputSchema = the canonical input schema; a paid tool gains an optional _payment string and its price in the description. An unpaid tools/call returns isError: true with a PaymentRequiredEnvelope in structuredContent; the client retries with _payment set to the base64 x402 payload. The adapter normalises into a CanonicalRequest and holds no payment logic of its own.
In this gateway
| Endpoint | /mcp |
| Transport | Streamable HTTP |
| Methods | tools/list, tools/call |
| Payment proof | _payment |
| AP2 mandate | _authorization |
| Buyer's receipt | _meta["agent-commerce/delivery"] |
| Concurrency | 8 tool calls + a queue of 64, then GATEWAY_BUSY |
| Needs | @modelcontextprotocol/sdk |
The exchange
curl -s http://localhost:8080/mcp \
-H 'content-type: application/json' \
-H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Not implemented
resourcespromptssamplingcompletionselicitationrootsloggingnotifications/tools/list_changedtasks
Reference: MCP API · Example: Paid MCP tool
HTTP
The most ordinary way in: a normal web request. Anything that can call a URL — a script, a backend, an agent framework — can use your resources without learning an agent protocol. A free resource just answers. A paid one first answers “payment required” with the price, and the caller repeats the same request with the payment in a header.
Every resource exposed with http is invocable at POST /api/resources/{id}/invoke; the JSON body is the input, validated against the resource's closed schema. An unpaid call to a paid resource returns 402 with a PaymentRequiredEnvelope body and the x402 v2 PaymentRequired document base64-encoded in PAYMENT-REQUIRED. The retry carries the proof in PAYMENT-SIGNATURE (and an AP2 envelope in Agent-Authorization where required); the backend's status and body are relayed with a base64 PAYMENT-RESPONSE summary.
In this gateway
| Invoke | POST /api/resources/{id}/invoke |
| Discovery | GET /api/resources, GET /.well-known/agent-commerce |
| Payment proof | PAYMENT-SIGNATURE |
| Settlement result | PAYMENT-RESPONSE |
| AP2 mandate | Agent-Authorization |
| Authentication | none — paid resources are protected by payment |
| Limits | 256 KB request body, 1 MB backend response |
The exchange
POST /api/resources/market_report/invoke HTTP/1.1
content-type: application/json
{}Reference: Invoke a resource
A2A
A2A is how agents work with other agents. The gateway introduces itself with a public business card — the Agent Card — listing what it can do; each of your resources is one “skill” on it. Another agent sends a single message naming the skill and the input, and gets back a finished task: either the result, or a bill to pay first.
The Agent Card at GET /.well-known/agent-card.json lists every expose: [a2a] resource as an AgentSkill (skill id = resource id; paid skills tagged paid). JSON-RPC 2.0 SendMessage is served at protocols.a2a.mountPath (default /a2a) and requires A2A-Version: 1.0. A request carries one message with one data part, { resource, input }, with _payment inside the input. Every outcome is a terminal task — TASK_STATE_COMPLETED with the response as an artifact, or TASK_STATE_FAILED carrying the payment or error envelope. JSON-RPC errors are reserved for requests malformed or unsupported as A2A.
In this gateway
| Agent Card | GET /.well-known/agent-card.json |
| Endpoint | POST /a2a |
| Required header | A2A-Version: 1.0 |
| Invocation | one message, one data part { resource, input } |
| Payment / mandate | input._payment, input._authorization |
| Outcomes | terminal tasks only — no task store |
| Enable | protocols.a2a.enabled: true |
| Needs | nothing installed — the A2A SDK is a test-only dependency |
The exchange
{
"jsonrpc": "2.0",
"id": "1",
"method": "SendMessage",
"params": {
"message": {
"role": "ROLE_USER",
"messageId": "msg-1",
"parts": [
{
"data": {
"resource": "market_report",
"input": { "_payment": "<base64 x402 payload>" }
},
"mediaType": "application/json"
}
]
}
}
}Not implemented
SendStreamingMessageGetTaskListTasksCancelTaskSubscribeToTaskpush notificationsGetExtendedAgentCardHTTP+JSON bindinggRPC bindingtask persistencemulti-turn continuationA2A auth schemes
Reference: A2A API
ACP
ACP is a standard checkout for agents: open a checkout, change it, look at it, complete the purchase or cancel it. The gateway speaks that standard to agents and passes each step to the checkout you already run. The buyer pays through your own checkout — the gateway does not take a second payment for these calls.
Five operations — create, update, get, complete and cancel CheckoutSession — under /acp/checkout_sessions, each mapped in protocols.acp.checkout.operations to one free resource with expose: [acp]. Every checkout route requires Authorization: Bearer and API-Version: 2026-04-17; every POST requires an Idempotency-Key, durable for at least 24 hours and scoped by token digest, path and key. Bodies are validated against the vendored schema in both directions; payment_data reaches the merchant unchanged and is never turned into an x402 payment.
In this gateway
| Discovery | GET /.well-known/acp.json (public) |
| Checkout | /acp/checkout_sessions… |
| Authentication | Authorization: Bearer |
| Version | API-Version: 2026-04-17 |
| Idempotency | stored answer on retry, 409 in flight, 422 on a different body |
| Services | checkout |
| Enable | protocols.acp.enabled: true |
The exchange
curl -s http://localhost:8080/acp/checkout_sessions \
-H "Authorization: Bearer $ACP_BEARER_TOKEN" \
-H "API-Version: 2026-04-17" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"line_items":[{"id":"item_123"}],"currency":"usd","capabilities":{}}'Not implemented
cartsfeedordersdelegate_paymentdelegate_authenticationACP MCP bindingwebhooksclient roleSignature verificationextensionsother API versions
Reference: ACP API · Example: ACP checkout
x402
x402 puts the web's long-unused “402 Payment Required” answer to work. When an agent asks for something paid, the gateway replies with a price tag: how much, in which token, to which wallet. The agent signs a permission slip for exactly that amount to exactly your wallet and sends the request again with the slip attached. The money goes from the buyer straight to you — the gateway can check the slip, but it cannot redirect it.
Scheme exact on EVM via EIP-3009 transferWithAuthorization. The provider builds x402 v2 PaymentRequirements with extra: { name, version, assetTransferMethod } to pin the EIP-712 domain. verify checks scheme, signature, recipient, amount, validity window, balance, network and asset without moving funds; a replayKey derived from (chainId, asset, payer, nonce) is reserved under a UNIQUE constraint before settle; the facilitator broadcasts, and the transaction hash becomes the receipt's settlement reference.
In this gateway
| Networks | eip155:84532 (Base Sepolia, local), eip155:8453 (Base) |
| Asset | USDC, or MockUSDC on the local chain |
| Challenge | 402 + PAYMENT-REQUIRED, or the MCP envelope |
| Proof | PAYMENT-SIGNATURE or _payment |
| Facilitator | local (dev chain only) or remote with none / bearer / cdp auth |
| Custody | none — buyer pays payTo directly |
| Needs | @x402/[email protected] @x402/[email protected] viem |
The exchange
agent gateway facilitator / chain
│ request, no proof │ │
├─────────────────────────►│ price → PaymentRequirements │
│◄─────────────────────────┤ 402 + PAYMENT-REQUIRED │
│ sign EIP-3009: │ │
│ amount → payTo │ │
│ retry + proof │ │
├─────────────────────────►│ verify, reserve replayKey │
│ ├─────────────────────────────────►│ transferWithAuthorization
│ │◄─────────────────────────────────┤ tx hash
│◄─────────────────────────┤ result + PAYMENT-RESPONSE │Not implemented
Solana / SVMdeferred schemeupto schemePermit2multi-asset routingdynamic pricing
Guides: Accept payments · Handle a payment · Networks & facilitators
AP2
AP2 answers a different question: did a person actually approve this purchase? Before the payment goes through, the agent shows a signed note from the buyer's side saying “yes — buy exactly this, at this price, from this shop”. The gateway checks the signature and that the note matches the purchase, and each note works only once. It never pays for anything by itself: the payment still has to happen.
A closed Checkout Mandate (vct: mandate.checkout.1) presented as an SD-JWT, ES256 over P-256, signed by an issuer and key listed statically in authorization.ap2.trust. It binds a merchant-signed checkout JWT whose agent-commerce/ap2/checkout/v1 claims must match the resolved resource, the RFC 8785 input hash, the amount as a string, currency, method, destination, network and asset. It is verified and reserved after payment verification and before settlement, and spendable once — keyed on the issuer-signed token and the checkout jti in its own SQLite store.
In this gateway
| Carrier | Agent-Authorization (HTTP, ≤ 8192 bytes), _authorization (MCP, A2A) |
| Envelope | { "method": "ap2", "payload": "<SD-JWT>" } |
| Trust | static public keys; no JWKS, jku or x5u |
| Require it | authorization: { required: [ap2] } |
| Errors | 403 required / invalid, 409 replayed, 503 provider unavailable |
| Signing helper | createCheckoutJwt (merchant side) |
| Needs | jose @sd-jwt/core canonicalize |
The exchange
{ "method": "ap2", "payload": "<the SD-JWT presentation>" }Not implemented
autonomous modeopen mandatesintent / cart mandatesconstraint evaluationcnf-bound keysJWKS / jku / x5ualgorithms other than ES256mandate issuanceCheckout ReceiptsAP2 over ACP
Guide: AP2 mandates
Planned: UCP · MPP
Both are on the roadmap, and neither ships in this release. “Planned” means exactly that: no partial adapter, no endpoint and no diagnostic pretending otherwise. doctor reports MPP as planned - not implemented in this release, and expose: [ucp] fails config validation.
doctor as not implemented.Status and versions
| Status | Meaning |
|---|---|
| Supported | Ships, is the stable surface of this release, and is covered end to end by the test suite. |
| Experimental | Ships, is tested against the protocol's own official artifacts, serves a narrow named subset — and is off by default. |
| Planned | No code ships. |
Every adapter reports its supportedSpec, capabilities, unsupported list and status at runtime. If this page and the gateway ever disagree, the gateway is the truth.
curl -s http://localhost:8080/.well-known/agent-commerceNext on the roadmap
A doctor GitHub Action · UCP · MPP · autonomous-mode AP2 (open mandates, agent key binding, constraint evaluation) · more of ACP (carts, feed, delegated payment) · Shopify and WooCommerce examples · PostgreSQL · richer observability.