TL;DR: The “MCP vs A2A” framing is a category error. They sit on different axes of an agent system: MCP is the vertical protocol connecting one agent down to its tools and data, while A2A is the horizontal protocol connecting agents across each other [4]. An implementation-grounded study from the University of York (arXiv 2607.23884, July 2026) built the same four-agent coordination loop twice — once on MCP, once on A2A — and found MCP delivers a lighter coordination model (1,255 vs 1,898 lines of code, 4 vs 10 coordination primitives, 2 vs 6 coordination stages per interaction) while A2A’s long-lived Task abstraction buys native multi-turn, stateful coordination at the cost of substantially more machinery [1]. The emerging production answer is not either/or: MCP inside each agent, A2A between agents [4].


The one-axis model: capabilities below, collaborators beside

Every operational difference between the two protocols traces back to a single assumption about the other side of the connection. MCP assumes the other end is a capability the agent controls — a database, an API, a deterministic service. A2A assumes the other end is a peer that reasons independently, refuses requests, and asks clarifying questions [4]. MCP describes capabilities; A2A describes collaborators [4].

MCP’s architecture is strictly client–server: a host (the LLM application) instantiates one client per server, and servers expose three first-class primitives — resources (data), tools (executable functions), and prompts (templates) — negotiated over JSON-RPC 2.0 [3]. A2A is peer-oriented: a client agent submits work to a remote agent that hosts its own reasoning, state, and opaque internals [1][2].

flowchart TB
    User((User)) --> AgentA[Orchestrator agent]

    AgentA -->|"A2A · tasks/send"| AgentB[Peer agent B]
    AgentA -->|"A2A · tasks/send"| AgentC[Peer agent C]
    AgentB -->|"A2A · tasks/send"| AgentC

    AgentA -->|"MCP · tools/call"| T1[Tool: SQL database]
    AgentA -->|"MCP · tools/call"| T2[Tool: external API]
    AgentB -->|"MCP · tools/call"| T3[Tool: code sandbox]

    style AgentA fill:#0f766e,stroke:#2dd4bf,color:#fff
    style AgentB fill:#0f766e,stroke:#2dd4bf,color:#fff
    style AgentC fill:#0f766e,stroke:#2dd4bf,color:#fff
    style T1 fill:#1e293b,stroke:#334155,color:#cbd5e1
    style T2 fill:#1e293b,stroke:#334155,color:#cbd5e1
    style T3 fill:#1e293b,stroke:#334155,color:#cbd5e1

The A2A protocol itself is explicit about the division: “MCP is for agent-to-tool communication… A2A is for agent-to-agent communication” — and “not a replacement for MCP” [2]. The protocol docs’ own canonical build recipe is: build with any framework, equip with MCP (or any tool layer), communicate with A2A [2].

Wire-level transports: one RPC dialect, different binding strategies

Both protocols speak JSON-RPC 2.0 at the application layer, but they bind to the wire differently.

MCP defines two standard transports — stdio for local subprocesses and Streamable HTTP for remote servers [4]. Since the 2026-07-28 revision, Streamable HTTP is deliberately stateless: a single POST-only endpoint, no protocol-level sessions, no Mcp-Session-Id header, no initialize handshake [4]. Every request is self-describing — version and capabilities ride in _meta, and routing metadata is mirrored into MCP-Protocol-Version, Mcp-Method, and Mcp-Name headers so intermediaries can inspect traffic without parsing bodies [4]. A conforming tools/call is a plain, cacheable-looking POST [3][4]:

POST /mcp HTTP/1.1
Host: mcp.example.com
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: get_weather

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_weather",
    "arguments": { "city": "London" }
  }
}

A2A takes the opposite approach to binding: the application protocol is defined transport-agnostically (protobuf is the source of truth), with three normative bindings — JSON-RPC 2.0 over HTTP, gRPC over HTTP/2, and HTTP+JSON/REST — and updates delivered by polling, SSE, or webhooks [4][6]. A task submission over the JSON-RPC binding looks like [1][6]:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tasks/send",
  "params": {
    "id": "task-7f3a",
    "contextId": "thread-42",
    "message": {
      "role": "user",
      "parts": [
        { "kind": "text", "text": "Generate a domain model for a library system" }
      ]
    }
  }
}

The binding multiplicity is a real operational cost. Polling, SSE, and webhooks are all valid per spec, so you must verify which update-delivery mechanism a given remote agent actually implements before building against it [4]. MCP’s single-POST statelessness, by contrast, means load balancers, CDNs, and gateways can treat agent traffic like ordinary HTTP — the very property that motivated the rewrite [4].

State: the Task is the atom of A2A; statelessness is the point of MCP

This is the deepest divergence. A2A’s core abstraction is the Task — a stateful, long-running unit of work tracked by both sides from submission to a terminal state, grouped into logical threads by contextId, and producing Artifacts that can stream incrementally as work progresses [4]. Messages, by contrast, are the lightweight path for trivial interactions that need no tracking [4]. The task lifecycle is protocol-level, not application-level [1]:

stateDiagram-v2
    [*] --> submitted
    submitted --> working
    working --> input-required
    input-required --> working
    working --> auth-required
    auth-required --> working
    working --> completed
    working --> canceled
    working --> failed
    working --> rejected
    completed --> [*]
    canceled --> [*]
    failed --> [*]
    rejected --> [*]

The paused states are the tell. input-required exists specifically so a remote agent can halt mid-task, ask for clarification, and resume without losing task identity — a negotiation pattern a stateless function call cannot represent [1][4]. The A2A-based implementation in the York study leans on exactly this: a constant task ID and context ID persist across retry cycles, letting artifacts and status events reconstruct the entire interaction history [1].

MCP’s 2026-07-28 rewrite is deliberately the opposite: stateless by design, with any server instance able to serve any request [4]. Task semantics did briefly appear in MCP core (November 2025 revision: tasks/get, tasks/cancel, status notifications) but were moved out of core into an official extension in the July 2026 revision — a signal to pin your spec revision if you build on them [4]. The York paper found the practical consequence: in the MCP-based system, conversational state and task lifecycle must be “implemented explicitly at the application layer,” whereas A2A provides them natively [1].

Discovery: tools/list versus the well-known card

Discovery encodes the trust boundary each protocol assumes [4]:

  • MCP — servers are client-configured (out of band), and capabilities are enumerated per-connection via listing methods like tools/list [3][4]. There is no spec-defined pre-connection discovery document; a “well-known server card” remains an open proposal and the separate MCP Registry is in preview rather than part of the spec [4].
  • A2A — every agent publishes an Agent Card, a JSON document at the well-known URI /.well-known/agent-card.json, advertising name, description, version, service endpoint, supported modalities, authentication requirements, and skills [4]. Signed Agent Cards have been available since v0.3.0 [4].
{
  "name": "Semantic Reviewer",
  "description": "Validates generated models against a requirements description",
  "url": "https://agents.example.com/semantic-reviewer",
  "version": "1.2.0",
  "skills": [
    { "id": "validate-model", "name": "Validate domain model" }
  ],
  "capabilities": { "streaming": true, "pushNotifications": false },
  "security": { "authenticationSchemes": ["bearer"] }
}

Note the asymmetry: A2A’s card solves discovery, not selection. It is registry-light — finding the right remote agent still depends on knowing where to look, and credentials are exchanged out of band, declared but not delivered by the protocol [4].

What the empirical study actually measured

arXiv 2607.23884 (submitted 26 July 2026, University of York) is the first implementation-grounded comparison of MCP and A2A used for inter-agent coordination rather than tool access [1]. The setup: a fixed four-agent collaboration — a collaboration agent orchestrating a solution agent plus syntactic and semantic supervisor agents — solving a software engineering task (generate an Emfatic/EMF domain model from a natural-language prompt), with both implementations sharing the same coordination algorithm and the same LLM (qwen2.5-coder:32b), differing only in protocol [1]. Validation ran on 30 prompts, 10 straightforward and 20 of higher complexity [1]. Real output from the solution agent, validated end-to-end [1]:

class Library {
  attr String name;
  val Book[*] books;
  val Author[*] authors;
}
class Book {
  attr String title;
  attr int pageCount;
  ref Author author;
}

The complexity delta is stark — measured with cloc, excluding config [1]:

Metric MCP A2A Delta
Lines of code 1,255 1,898 +51%
Coordination primitives 4 10 +150%
Coordination stages per interaction 2 6 +200%

A2A’s six stages (agent discovery, task creation, message dispatch, task state progression, artifact propagation, completion handling) versus MCP’s two (transport initialisation, tool invocation) reflect “the richer protocol-level workflow semantics and lifecycle management capabilities provided by A2A” — and correspondingly a larger coordination failure surface [1].

Against the seven requirements derived from prior literature and industry partners (banking, aerospace, immersive tech, IoT), the scores were [1]:

Requirement MCP A2A
R1: Agent discoverability
R2: Multi-part messaging
R3: Multi-turn conversations
R4: Asynchronous and streaming
R5: Agent observability ~ ~
R6: Interoperability
R7: Access control

Two findings deserve emphasis. First, R3 is the only differentiator: A2A natively supports multi-turn clarification via input-required; MCP requires servers to implement their own context tracking [1]. Second, neither protocol solves observability natively — no protocol-level tracing, no super-task IDs to correlate a tree of tasks and sub-tasks; both implementations had to bolt on Langfuse/Phoenix-style OpenTelemetry instrumentation at the application layer [1]. MCP’s 2026-07-28 revision does now document traceparent/tracestate propagation in _meta, which narrows but does not close that gap [4]. The authors are careful to frame the results as “design observations from an empirical experience report rather than general claims of protocol suitability” — the coordination pattern evaluated is deliberately narrow [1].

The production pattern: both protocols, one architecture

Every row of the comparison traces back to the same design decision, and so does the architecture that is emerging in production: MCP manages each agent’s access to tools and data; A2A coordinates between agents [4]. The A2A project itself ships this as the reference mental model — “MCP is for agent-to-tool communication… A2A is for agent-to-agent communication” — and the majority of application-oriented work combining both protocols follows exactly this layered structure [1][2].

flowchart LR
    subgraph OrgA[Organization A]
        direction TB
        CA[Client agent] -->|"MCP tools/call"| M1[MCP server: internal DB]
        CA -->|"MCP tools/call"| M2[MCP server: analytics API]
    end
    subgraph OrgB[Organization B]
        direction TB
        RA[Remote agent] -->|"MCP tools/call"| M3[MCP server: proprietary service]
    end
    CA <-->|"A2A tasks/send · Agent Card discovery"| RA

    style CA fill:#0f766e,stroke:#2dd4bf,color:#fff
    style RA fill:#0f766e,stroke:#2dd4bf,color:#fff
    style M1 fill:#1e293b,stroke:#334155,color:#cbd5e1
    style M2 fill:#1e293b,stroke:#334155,color:#cbd5e1
    style M3 fill:#1e293b,stroke:#334155,color:#cbd5e1

That architecture obliges you to operate: durable HTTPS endpoints (A2A’s long-lived endpoint per remote agent, not short-lived functions), published Agent Cards, out-of-band credential infrastructure, task lifecycle state, one MCP server per tool or data source, and correlated logging across every A2A message and MCP call [4]. Treat those as first-class infrastructure, not afterthoughts [4].

Decision rules that fall out of the protocol analysis and the empirical results:

  1. Everything in one codebase, one team — skip both protocols. Framework-native subagents or plain function calls add less serialization and no interoperability tax [4].
  2. The remote side is deterministic (same input → same output) — expose it as an MCP tool. Keep reasoning in the calling agent [4].
  3. The remote side reasons autonomously, runs long, needs back-and-forth, or crosses an organizational boundary — that is a peer, not a tool; use A2A [4].
  4. You need cross-boundary delegation and tool access — run both: A2A between agents, MCP inside each [4].
  5. Coordination is constrained and in-process — the York results show MCP can carry it with ~51% fewer lines of code and a far smaller coordination surface, at the price of hand-rolled conversation state and lifecycle handling [1].
  6. Multi-turn negotiation is the core interaction — reach for A2A’s Task lifecycle; MCP will make you rebuild input-required at the application layer [1].

Governance: two foundations, one trajectory

Both protocols now live under neutral open governance. Anthropic donated MCP to the Linux Foundation on 9 December 2025 as a founding project of the new Agentic AI Foundation (AAIF), alongside Block’s goose and OpenAI’s AGENTS.md, with platinum members including AWS, Anthropic, Bloomberg, Cloudflare, Google, Microsoft, and OpenAI — MCP alone counted more than 10,000 published servers at the time [5]. A2A, originally developed by Google and donated to the Linux Foundation, is Apache-2.0 licensed, maintained by a technical steering committee with seats at AWS, Cisco, Google, IBM Research, Microsoft, Salesforce, SAP, and ServiceNow, and reached 1.0 stable in March 2026 with public support from 150+ organizations [2][4][6]. IBM Research’s ACP (Agent Communication Protocol) merged into A2A under LF AI & Data in August 2025, consolidating the agent-to-agent layer further [4]. Maturity-wise: A2A 1.0 adds multi-tenancy and a web-aligned architecture built for the load balancers and gateways teams already run [4]; MCP’s surface is stable but its task semantics are settling inside an official extension, its registry is in preview, and it still has no memory primitive — plan around those gaps [4].

Bottom line

MCP and A2A are not competing standards; they are two orthogonal layers of the same stack, and the empirical record now backs that up [1][2][4]. MCP wins where the other side is a deterministic capability and the priority is a small coordination surface; A2A wins where the other side is an autonomous peer and the priority is stateful, multi-turn negotiation [1][4]. The protocol-level question to ask before reaching for either is the one Vercel’s guide leads with: what does your architecture assume about the other side of the connection? [4]

Sources:

  • Hermes Tutorials — Hermes Agent setup, configuration, and advanced workflows
  • ToolBrain — tool reviews, LLM comparisons, and AI workflow guides
  • NoCode Insider — AI workflow automation with no-code tools, agents, and APIs

Cross-links automatically generated from NiteAgent.

← Back to all posts