MCP (the Model Context Protocol) connects an AI agent to tools and data: it sees each tool's schema, decides to call one, and gets a result back. A2A (the Agent2Agent protocol) connects an agent to another agent it can't see inside. It hands over a goal, and the other side plans the work, may come back with questions, and reports progress on a task until it finishes. They aren't rivals. A common design uses A2A between agents and MCP inside each one, and since August 2026 both protocols sit in the same foundation.
Most "A2A vs MCP" pages were written against A2A 0.3 and the 2025 versions of MCP, and both protocols have changed since. This comparison is checked against A2A 1.0 (1.0.1 patch, May 2026) and the MCP 2026-07-28 revision as of October 28, 2026. We also run an MCP server whose tool is, underneath, an agent, so we have a concrete view on where the line sits.
A2A vs MCP at a glance
| MCP | A2A | |
|---|---|---|
| What's on the other end | A tool, resource or prompt with a declared schema | An independent agent that plans and executes on its own |
| What you send | A tool name plus arguments that match its input schema | A message made of parts (text, files, structured data) |
| What comes back | A tool result, often structured, with isError for failures the model should read | A direct message, or a task with a status and artifacts |
| Who plans | The calling model picks which tool to call and when | The remote agent decides how to do the job |
| Long-running work | The optional tasks extension (poll with tasks/get), or a handle the server returns and you poll yourself | Built into the core: blocking by default, plus polling, SSE streaming and webhook push notifications |
| Mid-job questions | Elicitation requests ride back inside tool results; tasks take input through tasks/update | TASK_STATE_INPUT_REQUIRED and TASK_STATE_AUTH_REQUIRED, answered with a follow-up message |
| Discovery | You configure a server URL; the client lists tools with tools/list and can call server/discover for versions and capabilities; public catalogs via the MCP Registry | An Agent Card at /.well-known/agent-card.json, a registry, or direct configuration |
| Wire format | JSON-RPC 2.0 over Streamable HTTP or stdio | Three bindings: JSON-RPC 2.0, gRPC, and HTTP+JSON/REST |
| Typical client | An AI app such as Claude, ChatGPT, Cursor or VS Code | Another agent, an orchestrator, or an agent platform |
| Origin and home | Anthropic, November 2024; donated to the Agentic AI Foundation in December 2025 | Google, April 2025; Linux Foundation project since June 2025, in the Agentic AI Foundation since August 2026 |
What is A2A?
A2A is an open protocol that lets agents built by different teams, on different frameworks, find each other and hand off work without sharing their internals. Google announced it on April 9, 2025 and donated it to the Linux Foundation on June 23, 2025. Version 1.0, the first release the project calls stable, shipped on March 12, 2026. The v1.0 announcement lists a technical steering committee drawn from AWS, Cisco, Google, IBM Research, Microsoft, Salesforce, SAP and ServiceNow. In August 2026 the project said it had been accepted as a Growth Stage project at the Agentic AI Foundation, next to MCP, goose and AGENTS.md.
Two of the spec's guiding principles are "Async First" and "Opaque Execution": agents collaborate "without needing to share their internal thoughts, plans, or tool implementations." A handful of objects carry most of the protocol:
- Agent Card: a JSON document describing the agent's name, skills, endpoints, supported bindings and auth requirements.
- Message: one turn from the user side or the agent side, made of Parts (text, a file reference, or structured data).
- Task: the unit of work, with an ID and a lifecycle. A request can also get a plain message back if the job is quick.
- Artifact: an output the agent produced, such as a document or a JSON result.
- Context: an optional ID that groups related tasks into one conversation.
A task moves through eight states. Submitted and working are in progress. Completed, failed, canceled and rejected are terminal; "rejected" means the agent decided not to do the job. The other two, input required and auth required, are interruptions where the agent is waiting on the caller. That last pair is the clearest sign of what A2A is for: the thing on the other end can push back.
Here is a trimmed Agent Card, shaped like the spec's sample (the security scheme is left as a placeholder):
{
"name": "Clinic Scheduling Agent",
"description": "Books, moves and cancels appointments at Example Dental.",
"version": "1.2.0",
"supportedInterfaces": [
{ "url": "https://agent.example.com/a2a/v1",
"protocolBinding": "JSONRPC", "protocolVersion": "1.0" }
],
"capabilities": { "streaming": true, "pushNotifications": true },
"securitySchemes": { "...": "OAuth 2.0 or OpenID Connect details" },
"defaultInputModes": ["text/plain"],
"defaultOutputModes": ["application/json"],
"skills": [
{ "id": "reschedule", "name": "Reschedule an appointment",
"description": "Moves an existing booking to a new slot.",
"tags": ["scheduling", "dental"],
"examples": ["Move my cleaning to next week, mornings only."] }
]
}
Version 1.0 added version negotiation through an A2A-Version header, multi-tenancy, and PascalCase method names such as SendMessage and GetTask. Cards can also carry a JWS signature, so a client can check who published one; signatures arrived in 0.3 and are part of what the 1.0 release pitched for enterprise use. If a tutorial shows message/send or a card at agent.json, it predates 1.0.
What MCP does, in one paragraph
An AI app (the host) runs an MCP client for each server it connects to. The server exposes tools the model can call, resources the app can read, and prompts the user can pick. We cover the roles in MCP client vs server and the tool contract in MCP tools explained, so here is only what changed recently. The 2026-07-28 revision made MCP stateless. There is no initialize handshake any more: every request carries its own version and capabilities, and servers never send requests to the client. It also moved long-running tasks out of the core spec into an official, opt-in extension. MCP is no longer a strictly call-and-wait protocol, but its unit is still the tool call.
The real difference: what you know about the other side
The usual way to put it is "MCP is agent-to-tool, A2A is agent-to-agent." That's right, but it leaves the question of what counts as a tool. A better test is what the caller knows and controls.
With an MCP tool, the caller sees the input schema, chooses the arguments and reads a result it can predict the shape of. The model doing the calling holds the plan. If step two depends on step one, the model decides that. The MCP spec even says there "SHOULD always be a human in the loop with the ability to deny tool invocations," because the calling side is the one making decisions.
With an A2A agent, the caller sends a goal in words and maybe some data. The remote agent picks its own steps and its own tools, may ask for more information, may need the user to authorize something, and may refuse. The caller doesn't see the plan, only the task state and whatever artifacts come out. That suits work that crosses a trust boundary: another team's agent, a vendor's agent, a partner's system you will never get source access to.
So the question isn't whether there is a language model behind the endpoint. It's whether you want the job to look like a function or like a colleague.
The same job over each protocol
Take a real errand: "Call my dentist and move Thursday's cleaning to next week, mornings only." This is exactly what our server does, so here is how it looks today over MCP, and how it would look as an A2A agent.
As an MCP tool call
The user's AI app sees a place_call tool and fills in its arguments. Trimmed from the request the client sends:
{
"jsonrpc": "2.0", "id": 7, "method": "tools/call",
"params": {
"name": "place_call",
"arguments": {
"to": "+14155550123",
"callee_name": "Example Dental",
"objective": "Move Thursday's cleaning to a weekday morning next week.",
"context": "Patient: Dana Lee. Mornings before 11am only."
}
}
}
The server returns a call_id straight away, and the client polls get_call until the call ends. The result is a structured outcome: whether the objective was achieved, a summary, commitments made, follow-ups, and key facts such as the new time. The full contract is on the tools reference.
As an A2A task
If the same capability were an A2A agent, the caller would send a message instead of arguments:
{
"jsonrpc": "2.0", "id": 7, "method": "SendMessage",
"params": {
"message": {
"role": "ROLE_USER", "messageId": "msg-1",
"parts": [{ "text": "Call Example Dental at +1 415 555 0123 and move Dana Lee's Thursday cleaning to a weekday morning next week." }]
},
"configuration": { "returnImmediately": true }
}
}
The response would be a task in the working state. Partway through the call the agent could switch the task to input required ("They offer Tuesday 9:00 or Wednesday 10:30. Which one?"), the caller would answer with a follow-up message carrying the task ID, and the task would finish with an artifact holding the outcome.
Why ours is an MCP server anyway
Behind place_call there is a voice agent with its own model and its own small toolset: it can wait on hold, press keys through a phone menu, and hang up. By the spec's own definitions that's an agent. We still expose it as a tool, for three reasons:
- The callers are MCP hosts. People use DialMCP from Claude, ChatGPT, Cursor, Codex and VS Code, and those apps connect to MCP servers, not to A2A agents. See the client setup guides.
- The contract is narrow. An objective goes in and a structured outcome comes out. The calling model doesn't need to steer the conversation, and we don't want it to: disclosure, calling hours and opt-outs are enforced on our side (see how calls stay safe), not negotiated per task.
- Questions come before the call, not during it. The
contextfield carries preferences up front, and whatever is still open after the call comes back infollow_upsfor the user to act on. That covers most errands without a mid-call round trip.
To be honest about where we stand: DialMCP runs on the TypeScript SDK's 1.x line and speaks the 2025-06-18 MCP revision. It doesn't implement the tasks extension yet. The call_id plus get_call loop is the hand-rolled version of the same idea. The mid-call question is where A2A's model fits better than ours. If users needed the calling model to choose between offered slots while the callee waits on the line, an interrupted A2A task (or MCP's newer tasks extension, which also takes input mid-task) would be the right shape.
Long-running work in each protocol
This is where older comparisons go stale fastest. In A2A, SendMessage blocks by default until the task finishes or is interrupted. Set returnImmediately and you get the task back at once, then choose how to follow it: poll GetTask, open a stream with SubscribeToTask, or register a webhook and let the agent POST updates to you. For jobs that take hours, or that wait on a human, push notifications mean nobody holds a connection open.
MCP's answer is newer and optional. Under the tasks extension, a server can answer a tool call with a durable task handle instead of a result. The client polls tasks/get, sends input with tasks/update, and can cancel. The server decides per request whether to create a task, and both sides have to opt in to the extension. Because of that, a server can't assume a given client supports it, which is why some remote servers, ours included, return their own job ID and expose a status tool. If your workload is mostly long jobs with a lot of back-and-forth, A2A's task model is more mature. If it's mostly quick calls with the occasional slow one, MCP is enough.
Discovery and trust
A2A agents advertise themselves. A public agent serves its card at https://{domain}/.well-known/agent-card.json. A private one can serve a basic public card and a fuller "extended" card only to authenticated clients. Signed cards let a client check the publisher before sending anything. The spec allows curated registries but, in its own words, "does not prescribe a standard API" for them yet.
MCP discovery usually starts with a person: someone pastes a server URL into a client, signs in, and the client lists the tools. Public catalogs exist, including the official MCP Registry, but they are directories you search, not addresses agents resolve on their own. On the auth side, MCP's authorization spec for remote servers is built on OAuth 2.1, with tokens issued to the signed-in user, which we cover in MCP authorization. A2A declares its schemes in the card (OAuth 2.0, OpenID Connect, API keys, HTTP auth or mutual TLS) and adds the auth-required task state for credentials needed partway through a job.
The practical difference is who you trust. MCP assumes the user chose the server. A2A assumes agents may meet for the first time and need to prove who they are.
When you need MCP, A2A, or both
MCP alone covers most products today:
- You want an AI app like Claude or ChatGPT to use your service. Those apps speak MCP.
- The capability has a clear input and output, even if a lot happens behind it.
- Your rules (limits, permissions, safety checks) should be enforced in your server, the same for every caller.
A2A alone fits when:
- You're exposing an agent to other organizations' agents, and you won't show them its tools or prompts.
- The work is open-ended, can run for hours, or regularly needs clarification mid-way.
- Your buyers' platforms already support A2A. The project names Google Cloud, Amazon Bedrock AgentCore and Azure AI Foundry, though those are its own claims.
Both is the usual shape for a multi-agent system that crosses team or vendor lines. An orchestrator delegates to specialist agents over A2A, and each specialist uses MCP servers for its own tools. The A2A docs give the same picture: A2A "connects the agents to each other," MCP "connects each agent to its own tools."
One caution: plenty of multi-agent setups don't need A2A at all. Subagents running inside one framework, in one process, owned by one team, can call each other directly. A2A earns its keep at the boundary where you can't share code, memory or credentials.
Bridging the two
Because each protocol has a clear job, gateways and adapters that translate between them are common. The A2A docs note that an agent can expose some skills to MCP clients (they say "MCP-compatible resources") when those skills are "well-defined and can be called in a tool-like, stateless way." The reverse also works: an A2A agent can call any MCP server as a client, so a scheduling agent could place its phone calls through an MCP server like ours. If you are putting many servers or agents behind one entry point, our MCP gateway guide covers the trade-offs.
What doesn't translate cleanly is the interruption. An A2A task waiting on input has no direct equivalent in a basic MCP tool call. A bridge either has to collect everything up front, as we do, or depend on the tasks extension on both sides.
Three things that are no longer true
- "A2A is Google's answer to MCP." Google's April 2025 launch post called A2A "an open protocol that complements Anthropic's Model Context Protocol," and both protocols now sit in the same Linux Foundation fund.
- "MCP can't handle long-running work." It can, through the tasks extension. Both sides have to opt in, but the spec covers it.
- "A2A is JSON-RPC only." gRPC and HTTP+JSON/REST bindings have existed alongside JSON-RPC since the 0.2 releases, 1.0 formalized all three, and an agent can offer several at once in its card.
For how MCP compares with a plain REST API, as opposed to another protocol, see MCP vs API.
Try a task-shaped MCP server. DialMCP lets Claude, ChatGPT, Codex, Cursor or VS Code place real phone calls from your own verified number and hand back a transcript and a structured outcome. Add https://mcp.dialmcp.com/mcp as a connector and sign in. US and Canada, free during launch.
FAQ
What is the difference between A2A and MCP?
MCP connects an AI agent to tools and data: the agent sees each tool's schema, chooses arguments and gets a result. A2A connects an agent to another, independent agent: it sends a goal as a message, and the remote agent plans the work, may ask for more input, and reports progress on a task. Many systems use A2A between agents and MCP inside each agent.
What is A2A?
A2A, the Agent2Agent protocol, is an open standard for agents built on different frameworks or by different organizations to discover each other and delegate work. Google announced it in April 2025 and donated it to the Linux Foundation that June. Version 1.0 shipped in March 2026, and in August 2026 the project joined the Agentic AI Foundation, which also hosts MCP.
Is A2A a replacement for MCP?
No. Google's launch post described A2A as complementing MCP, and the A2A documentation recommends using both: A2A for collaboration between agents, MCP for each agent's tools. An A2A agent can itself be an MCP client.
Do I need A2A to build a multi-agent system?
Not always. Subagents that run inside one framework and are owned by one team can call each other directly. A2A pays off when agents cross a boundary where you can't share code, memory or credentials, such as another team's or another company's agent.
Can MCP handle long-running tasks like A2A?
Partly. Since the 2026-07-28 revision, MCP has an official tasks extension: a server can return a task handle, and the client polls it, sends input and can cancel. Both sides must opt in, so some remote servers return their own job ID and a status tool instead. A2A has tasks, streaming and webhook push notifications in its core.