Every payment surface a PSP or card network has actually shipped to AI agents is an MCP server. Stripe, Visa, Mastercard, PayPal and Alipay all expose MCP tools; I could not find a single merchant or PSP running an A2A agent in production. Yet both payment protocols Google has written, AP2 and the a2a-x402 extension, sit on A2A.
That split is the honest answer to "MCP vs A2A", and none of the pages ranking for the query mention it. The three I read (WorkOS, Auth0, Composio) were written in 2025, cite no spec version, and say nothing about payments, retries or failure states. Since then MCP shipped a revision that made the protocol stateless and A2A went to 1.0 with renamed methods and enums. Everything below is checked against the current specs as of 4 November 2026.
What Is the Difference Between MCP and A2A?
MCP (Model Context Protocol) connects one agent to tools and data. A2A (Agent2Agent) connects one agent to another agent. Google's own docs put it as "MCP is vertical, A2A is horizontal", and an A2A agent can expose some of its skills as MCP tools, so the two are designed to stack rather than compete.
Both use JSON-RPC 2.0 over HTTP, which is where the similarity ends.
| MCP | A2A | |
|---|---|---|
| Current version | Revision 2026-07-28 | 1.0 (12 Mar 2026) |
| Governance | Agentic AI Foundation (Linux Foundation), since Dec 2025 | Linux Foundation project, hosted under the same foundation since Aug 2026 |
| Unit of work | A tool call, returns one result | A Task with a lifecycle and artifacts |
| Discovery | tools/list on the server, plus server/discover | /.well-known/agent-card.json, optionally JWS-signed |
| Transports | stdio, Streamable HTTP | JSON-RPC, gRPC, HTTP+JSON |
| Long-running work | Tasks extension (io.modelcontextprotocol/tasks) | Native: TASK_STATE_WORKING, streaming, push webhooks |
| Auth | OAuth 2.1 resource server, token bound to one server | OpenAPI-style securitySchemes declared in the card |
| Idempotency | None at protocol level | messageId "MAY" be used to dedupe |
| Payment bindings | x402 over MCP (@x402/mcp); Stripe, Visa, Mastercard, PayPal, Alipay servers | a2a-x402 extension, AP2 |
Adoption is lopsided. Anthropic reported 97 million monthly SDK downloads in December 2025, and the July 2026 release post put the Tier 1 SDKs at close to half a billion a month. A2A's April 2026 Linux Foundation release counted 150 organisations backing the protocol and 60 payments and financial services firms behind AP2.
MCP 2026-07-28 vs A2A 1.0: What Changed This Year
If you built against either protocol in 2025, the shape of the wire has changed under you.
MCP became stateless. The 2026-07-28 revision removed theinitialize handshake and the Mcp-Session-Id header. Every request now carries its protocol version and client capabilities in _meta. Servers that need state across calls use "explicit, server-minted handles passed as ordinary tool arguments". The spec's own example is a shopping basket: create_basket returns {"basket_id": "bsk_a1b2c3"} and later calls pass it back. Roots, Sampling and Logging are deprecated. Server-initiated requests are gone, replaced by a result with resultType: "input_required" that the client answers by retrying the original request.
A2A renamed almost everything. JSON-RPC methods moved from message/send and tasks/get to PascalCase SendMessage, GetTask, CancelTask, SubscribeToTask. Task states gained a prefix: TASK_STATE_SUBMITTED, TASK_STATE_WORKING, TASK_STATE_INPUT_REQUIRED, TASK_STATE_AUTH_REQUIRED, TASK_STATE_COMPLETED, TASK_STATE_FAILED, TASK_STATE_CANCELED, TASK_STATE_REJECTED. The kind discriminator on Part was removed. Every request must send A2A-Version: 1.0; an empty header is read as 0.3.
The practical consequence: any "MCP vs A2A" guide that shows tasks/send or lists states like "pending, running" is describing a protocol that no longer exists.
How Does a Payment Request Look on MCP vs A2A?
The cleanest way to compare the two is to watch the same payment protocol, x402, ride on each. x402 has an official MCP transport spec and a Google-maintained A2A extension, so the difference is purely in how each host protocol represents "you need to pay before I continue".
On MCP, payment required is an error. The x402 MCP transport returns an ordinary tool result withisError: true and the PaymentRequired object in structuredContent:
{
"jsonrpc": "2.0",
"id": 7,
"result": {
"resultType": "complete",
"isError": true,
"content": [{ "type": "text", "text": "{\"x402Version\":2,\"accepts\":[...]}" }],
"structuredContent": {
"x402Version": 2,
"accepts": [{ "scheme": "exact", "network": "eip155:84532", "maxAmountRequired": "10000", "asset": "0x036C..." }]
}
}
}
The client signs a payment, retries the same tools/call with the payload under params._meta["x402/payment"], and reads settlement from result._meta["x402/payment-response"], which carries success, transaction, network and payer. A failed settlement is another isError: true result.
input-required and attaches metadata to the status message:
{
"task": {
"id": "task-9f1c",
"contextId": "ctx-4a2e",
"status": {
"state": "TASK_STATE_INPUT_REQUIRED",
"message": {
"role": "agent",
"parts": [{ "text": "Payment required to generate the report." }],
"metadata": {
"x402.payment.status": "payment-required",
"x402.payment.required": { "x402Version": 1, "accepts": [...] }
}
}
}
}
}
The client replies on the same taskId with x402.payment.payload, and the status walks through payment-submitted, payment-verified and payment-completed, or stops at payment-rejected or payment-failed, with a receipt under x402.payment.receipts.
The difference matters for the model in the loop. On MCP the LLM sees a failed tool call and has to be prompted into understanding that failure means "pay and try again". On A2A it sees a paused task with a typed reason. MCP's new input_required result type would model this better than an error, but no x402 binding uses it yet. One wrinkle: the a2a-x402 examples still carry x402Version: 1 while the MCP transport is on version 2, so a client talking to both must parse both shapes.
MCP vs A2A Authentication: OAuth 2.1 vs Agent Card Security Schemes
MCP's authorization spec is strict and narrow. A server MUST publish RFC 9728 protected resource metadata, a client MUST send an RFC 8707 resource parameter so the token is bound to that one server, and "MCP servers MUST NOT accept or transit any other tokens". A 401 carries WWW-Authenticate: Bearer resource_metadata=..., and a 403 with error="insufficient_scope" drives step-up. The 2026-07-28 revision also deprecated dynamic client registration in favour of Client ID Metadata Documents.
That "MUST NOT transit" rule is the single most important line for payments. An MCP server cannot forward your token to a downstream service. Every hop needs its own grant. Multi-hop delegation, where a shopping agent hands a merchant agent a credential that the merchant agent hands to a PSP, is forbidden by design.
A2A takes the opposite approach. The Agent Card declares securitySchemes in OpenAPI style, one of APIKeySecurityScheme, HTTPAuthSecurityScheme, OAuth2SecurityScheme, OpenIdConnectSecurityScheme or MutualTlsSecurityScheme, and securityRequirements say which the caller must satisfy. Each skill can override the requirement. Mid-task step-up has its own state, TASK_STATE_AUTH_REQUIRED. The card can be signed with JWS (RFC 7515, payload canonicalised with RFC 8785), with alg, typ and kid required in the protected header.
{
"securitySchemes": {
"psp-oauth": {
"oauth2SecurityScheme": {
"flows": { "clientCredentials": { "tokenUrl": "https://auth.example-psp.com/token", "scopes": { "payments:write": "Initiate payments" } } }
}
}
},
"securityRequirements": [{ "psp-oauth": ["payments:write"] }],
"capabilities": { "streaming": true, "pushNotifications": true, "extendedAgentCard": true }
}
Flexibility cuts both ways. In August 2026 the a2a-java SDK fixed CVE-2026-111763: a malicious agent could set a custom API-key header name in its card, then redirect the client, which obediently sent the credential to the new host. Agent Card poisoning, where the description field carries prompt injection that the client model reads during discovery, was written up in March 2026. The card is the trust anchor in A2A, and when it is not signed it is also the attack surface. MCP's incident list is longer because its install base is larger: CVE-2025-6514 in mcp-remote (CVSS 9.6) let a malicious server's authorization_endpoint value run OS commands on the client, and tool-description poisoning has been documented since April 2025. Both protocols fail at the discovery document, so sign it and verify kid. I went through the request-signing side of agent verification in Web Bot Auth vs Visa TAP.
Does MCP or A2A Handle Idempotency and Retries?
Neither does, and this is the gap that will produce double charges.
MCP removed SSE resumability in 2026-07-28. The spec now says: "A broken response stream loses the in-flight request; clients MUST re-issue it as a new request with a new request ID." If that request was send_money, the server has no protocol-level way to recognise the retry. The only hint is idempotentHint on the tool definition, which defaults to false, and the schema warns that "Clients should never make tool use decisions based on ToolAnnotations received from untrusted servers".
A2A is softer but not safer. The spec says SendMessage operations "MAY be idempotent" and that agents "may utilize the messageId to detect duplicate messages". Task IDs are server-minted; the spec explicitly says client-provided taskId values for new tasks are not supported, so you cannot pre-assign one as a dedupe key. The a2a-x402 extension adds nonce tracking (DUPLICATE_NONCE) on the payment payload, which stops the same signature settling twice but says nothing about a retried SendMessage producing two distinct payloads.
Compare that with a PSP. Stripe, Adyen and every bank API I have integrated expect a client-generated Idempotency-Key and replay the original response for 24 hours or more (patterns in my payment API idempotency keys guide). Neither agent protocol has an equivalent, so you add it yourself:
- On MCP, follow the spec's own basket pattern. Make a money-moving tool take a required
idempotency_keyargument, store the first result keyed on it, and return that stored result on any repeat. SetidempotentHint: trueonce you have done so, and treat it as documentation rather than protection. - On A2A, persist
messageIdserver-side with the resultingtaskIdand payment outcome. A repeatedmessageIdreturns the existing task, never a new one. Treat push webhooks the way you treat PSP webhooks: assume you will see each one more than once.
Which Payment Providers Support MCP vs A2A in 2026?
This is where the theoretical symmetry collapses.
| Provider | MCP | A2A |
|---|---|---|
| Stripe | mcp.stripe.com, Streamable HTTP, OAuth or agent keys; full-access secret keys rejected from 30 Nov 2026 | None |
| Visa | MCP Server and Acceptance Agent Toolkit, in pilot since Sep 2025 | None |
| Mastercard | Agent Toolkit MCP server (Sep 2025); says MCP "compliments" A2A | No shipped agent |
| PayPal | Remote MCP server and Agent Toolkit (Apr 2025) | Demoed with Google Cloud in 2025; nothing in production I could verify |
| Alipay / Antom | Payment MCP server (May 2026), ant-intl-antom-mcp on PyPI | None |
| AP2 and a2a-x402 specs, no named merchant live |
The Stripe server is the most instructive. Its Treasury tools send_money and transfer_money require "human confirmation" via an approval token that expires after 24 hours. That is a PSP saying, in its API design, that an agent may prepare a payment but a person must release it. It fits MCP's single-hop token model and would not survive an A2A delegation chain unchanged. Even Worldline's live agentic payment with ING and Mastercard, announced on 2 June 2026, names no protocol at all. If you are looking for a production A2A payment to copy, there is not one yet.
Where Does AP2 Fit Between MCP and A2A?
AP2 is the protocol that was supposed to make A2A the payments layer, and it has drifted. The September 2025 launch described it as "an extension of A2A and MCP". Version 0.2, released on 28 April 2026 alongside its donation to the FIDO Alliance, dropped the Intent Mandate and collapsed the model to two SD-JWT mandates, a Checkout Mandate (vct: mandate.checkout.open.1) and a Payment Mandate (vct: mandate.payment.1), bound together by a checkout_hash. It added a Human Not Present flow for autonomous purchases.
The v0.2 spec defines no A2A extension URI and no MCP binding; A2A appears only in sample code paths, and the Rust crate a2a-ap2 still implements v0.1. My AP2 vs ACP vs x402 comparison covers who holds the credential, but its wire format is the v0.1 three-mandate shape. So the answer to "which agent protocol carries AP2" is: whichever one you wrap it in. The mandates are transport-independent JWTs, which means an MCP-first team can pass a Payment Mandate as a tool argument without waiting for an A2A stack.
My Take: Build Payment Tools on MCP, Delegation on A2A
This is opinion, one engineer's reading of the specs and the shipping products.
Build the thing that moves money as an MCP tool. Every PSP you will integrate already exposes one, the OAuth model binds the token to a single audience with no transit, and the stateless revision makes the server a plain HTTP resource behind the same gateway as your REST API. The missing idempotency is a known hole with a known patch.
Use A2A for the conversation above the payment: a shopping agent delegating to a merchant agent, a procurement agent waiting on an approval agent, anything where "working" lasts minutes and a human may need to step in. That is what the Task lifecycle, TASK_STATE_AUTH_REQUIRED and push notifications are for; MCP's Tasks extension is a bolt-on by comparison.
My prediction: by the end of 2027 the x402 and AP2 bindings on A2A will matter as the delegation envelope, and the settlement call at the bottom of the chain will be an MCP tool with a human-confirmation gate, Stripe style. The "MUST NOT transit tokens" rule forces that shape. An A2A chain can carry a mandate, but somebody at the end still holds a PSP token, and MCP is where PSPs hand those out.
What This Means for Payment Engineers
- Pin protocol versions in code. Send
A2A-Version: 1.0explicitly, and putio.modelcontextprotocol/protocolVersionin_metaon every MCP request. Both specs reject or downgrade silently otherwise. - Add an idempotency key to every money-moving MCP tool. Make it a required argument, store results against it, and only then set
idempotentHint: true. - Dedupe on
messageIdin A2A servers. Persist it with the resultingtaskIdand never mint a second task for a repeated message. - Do not let an MCP server forward tokens. If your design needs delegation across hops, that is an A2A problem, and each hop needs its own grant.
- Sign Agent Cards and verify
kid. Treat an unsigned card as untrusted input, including itsdescriptionfield. - Handle both x402 shapes:
isError: trueon MCP versusTASK_STATE_INPUT_REQUIREDon A2A as the "pay me" signal. - On Stripe's MCP server, migrate off full-access secret keys before 30 November 2026 and build the approval-token step for Treasury tools into your UI.
- Carry AP2 mandates as opaque JWTs in whichever protocol you already run; do not wait for an official binding.
Key Takeaways
MCP is where payment tools ship: every PSP and network surface in production is an MCP server with per-server OAuth and human-confirmation gates. A2A is where delegation lives, and it models a paused payment far better than an isError result, but no merchant or PSP runs it in production yet. Neither gives you idempotency, so a retried request can charge twice unless you add a key yourself. Both changed shape in 2026, and most comparison pages have not caught up.
Written by Tom Wang, a payments engineer building agent-facing payment infrastructure in the UK.