Chapter 5: Agent Interoperability — MCP, A2A, and the Protocol Landscape
Introduction: Two Protocols and a Blurry Line
Every agent eventually has to reach something outside itself. Sometimes that something is a tool or a data source — a database, a file system, an API, an enterprise application. Sometimes it’s another agent — a specialist you hand a subtask to and wait for a result. Either way you hit the same wall: the systems an agent needs to talk to were not built for agents. They were built for humans and for services that communicate over well-defined contracts. Getting an agent across that gap, cleanly and safely, is one of the messier unsolved problems in practical AI deployment.
The naive approach is to hand-write a connector for every target. Need to query a database? Write a function that opens a connection, runs a query, and formats the result. Need to call another team’s agent? Write an HTTP client for its bespoke API. This works until it doesn’t: the number of integrations grows roughly quadratically with the number of agents and targets, each connector bakes in its own assumptions about auth and error handling, and the result is a tangle that is expensive to maintain and nearly impossible to audit. Standards exist to collapse that quadratic into something linear — write to the protocol once, interoperate with everything that speaks it.
Two such standards have emerged, and this chapter is about both. The Model Context Protocol (MCP) — Anthropic’s open standard, launched in late 2024 — connects an agent to tools, data, and services. The Agent2Agent Protocol (A2A) — created by Google in April 2025 and donated to the Linux Foundation two months later — connects an agent to other agents. Their creators are careful to position them as complementary rather than competing; the official one-liner, which both camps endorse, is: MCP connects agents to tools and context; A2A connects agents to other agents.
That line is useful, and this chapter uses it — but a practitioner should know up front that it is cleaner in a slide than in production. The boundary is real, but it describes topology and intent, not a wall between what each protocol is capable of. In particular, and worth stating plainly because the marketing tends to blur it: people use MCP for agent-to-agent communication all the time, and it is not a misuse.
The overlap is genuine, for concrete reasons. Wrapping an agent as an MCP server is a perfectly ordinary pattern — the host calls a “tool,” and behind that tool sits a full agent with its own model, memory, and tools. A large share of production multi-agent systems today are built exactly this way: one orchestrator delegating to a set of subordinate specialist agents, all wired together over MCP. And MCP has been drifting toward the agentic use case, not away from it. Elicitation lets a server pause and ask for input mid-task, inverting the usual control flow. The (experimental) Tasks primitive exists precisely to carry long-running, asynchronous work that looks nothing like a stateless function call. If your architecture is one coordinator delegating to sub-agents you build and control, MCP is very likely all you need — reaching for a second protocol would be premature.
So what does A2A actually add, once you set the co-marketing aside? Not “agent-to-agent messaging” — MCP can do that. Its contribution is a specific shape MCP’s tool-centric model doesn’t give you naturally: symmetric peer discovery (an agent advertising itself at a well-known URL to callers it was never wired to, rather than MCP’s hub-and-spoke where the host is always the orchestrator), a trust model built for calling agents across organizational and framework boundaries, and treating the remote as an opaque, autonomous peer with its own state rather than a transparent function. A memorable way to hold the distinction: MCP is the agent’s hands — it reaches out and works a tool itself; A2A is the agent’s phone — it calls a peer and hands off a job.
In practice, then, the choice is driven as much by topology and ecosystem maturity as by any hard rule. MCP is far more widely adopted, with a large server ecosystem and native support across every major AI platform; A2A is newer and aimed squarely at the cross-vendor, peer-to-peer case. The rule of thumb that holds up: if your agents live inside one application and you control them, an orchestrator-over-MCP design is the well-trodden path; A2A earns its keep when agents are autonomous peers, span organizational or framework boundaries, and need to discover each other dynamically. Between those poles is a wide grey band where either works — and there the honest answer is “whichever fits your topology and the ecosystem you’re already in.”
The distinction at a glance:
| MCP tool/server | A2A remote agent | |
|---|---|---|
| Mental model | A capability you use | A peer you partner with |
| Transparency | Transparent — schema fully describes it | Opaque — internals hidden by design |
| Statefulness | Often stateless, discrete calls | Stateful across a multi-turn task |
| Autonomy | None — executes exactly what’s called | Reasons, plans, uses its own tools |
| Interaction | Request → response | Delegate a task with a lifecycle; may stream, pause, ask back |
| Discovery / topology | Hub-and-spoke — servers pre-wired into the host | Peer-to-peer — agents advertise via a well-known Agent Card |
| Typical examples | Calculator, DB query, weather lookup, file read | Research agent, booking agent, fraud-check agent |
| Auth model | Prescriptive: OAuth 2.1 Resource Server, PKCE, audience binding | Delegative: OAuth 2.0 / OIDC over HTTP, declared in the Agent Card |
When you’re genuinely on the fence, one question settles most cases: does the thing on the other end have agency — does it decide how to accomplish a goal, or does it just execute what it’s told? Agency points to A2A; mechanism points to MCP. But treat that as a design heuristic, not a law: because the two overlap, you can wrap an A2A agent behind an MCP tool or expose a simple MCP server where an agent might have done, and sometimes the right call is just “whatever the rest of my stack already speaks.”
MCP and A2A are the two protocols this chapter treats in depth, but they are not the whole story of agent interoperability — they are the two that won. §1 examines MCP — its architecture, how the spec has evolved through several fast releases, the security model it imposes, and the authorization details where the costly mistakes are made. §2 examines A2A — its opaque-agent model, the Agent Card discovery mechanism, its object model and transports, and how its security posture differs from MCP’s. §3 steps back to the wider landscape: the other protocols that briefly contended (ACP, ANP, AGNTCY, NLWeb), why the field is consolidating around MCP-plus-A2A, and the harder problem all of them still leave open — the gap between agents that can exchange messages and agents that actually understand each other. §4 turns to building: how MCP and A2A compose in a real system, and the implementation and security discipline each one demands.
1. MCP: Connecting Agents to Tools and Data
1.1 Architecture: A Two-Layer Design
MCP follows a two-layer design that separates what is communicated from how it is communicated. Understanding this separation is essential to understanding every other aspect of the protocol.
The data layer defines the protocol itself: the types of primitives available, the message formats, and the lifecycle of a connection. MCP uses JSON-RPC 2.0 as its message format — a lightweight, well-understood standard for remote procedure calls over JSON. The data layer defines three core primitives: Resources (data that an AI application can read — files, database records, API responses), Tools (functions that an AI application can call — search engines, code executors, external services), and Prompts (reusable prompt templates and workflows that servers expose to clients). Note that Anthropic’s marketing materials sometimes use the term “workflows” for this third primitive; the spec calls them Prompts.
The transport layer defines how messages move between participants. This is where authentication lives. The separation is intentional: by placing auth in the transport layer rather than the data layer, MCP ensures that the data protocol itself is auth-agnostic. Different transports can implement different auth mechanisms without changing the protocol semantics. A server that exposes the same tools over both stdio (for local use) and Streamable HTTP (for remote use) uses completely different auth mechanisms at each transport, but the tool calls look identical from the data layer’s perspective.
Three distinct entities participate in every MCP deployment:
| Entity | Role |
|---|---|
| MCP Host | The AI application — Claude Desktop, a custom agent framework, VS Code Copilot |
| MCP Client | A component within the host that manages the connection to a specific MCP server |
| MCP Server | A process that exposes tools, resources, or prompts to clients |
The host-client-server terminology trips people up initially because it suggests a clean one-to-one hierarchy. In practice the relationship is more flexible: a single host may manage connections to many MCP servers, and the granularity of what constitutes a “server” is left to the implementer. A server might expose a single tool or hundreds.
1.2 Transport Mechanisms
MCP defines exactly two standard transports, and the choice between them has significant implications for both capability and security.
stdio
stdio (standard input/output) is used for local process communication. The MCP server runs as a subprocess of the client. Messages flow over standard input and standard output streams — an approach that requires no network stack, no port binding, and no firewall exceptions.
For local tool integration — running a code interpreter, accessing the local file system, querying a local database — stdio is the right choice. The client starts the server process, communicates over pipes, and can kill it when the session ends. The attack surface is minimal: the server process inherits the permissions of the client, runs on the same machine, and is not reachable from the network.
Authentication for stdio transports does not use the OAuth flows described later in this chapter. Credentials are retrieved from the environment: environment variables, configuration files, OS credential stores. This is both simpler and appropriate for the local context — the assumption is that if a process is running on the user’s machine with the user’s credentials, it is operating in a trusted environment.
Streamable HTTP
Streamable HTTP handles remote communication — scenarios where the MCP server runs on a different machine, in a cloud environment, or as a shared service. The transport uses HTTP POST for client-to-server messages and optional Server-Sent Events (SSE) for server-to-client streaming. The use of SSE for streaming rather than WebSockets is a deliberate choice: SSE works over standard HTTP/1.1 without a protocol upgrade, which is more compatible with existing proxy infrastructure and corporate firewalls.
Streamable HTTP replaced an older transport called HTTP+SSE in the 2025-03-26 specification. The older transport predates the current design and should be considered deprecated. For backward compatibility, servers can maintain both the new Streamable HTTP endpoint and legacy SSE/POST endpoints simultaneously, but new implementations should use Streamable HTTP exclusively.
Streamable HTTP carries mandatory security requirements that are normative in the spec — meaning they use MUST language and implementers are not allowed to skip them:
MUST: Validate the Origin header on all incoming connections
→ Return HTTP 403 Forbidden if Origin is present but unexpected
→ This prevents DNS rebinding attacks (see §1.6)
SHOULD: Bind to 127.0.0.1 rather than 0.0.0.0 for locally-running servers
→ Prevents remote access to local MCP servers
SHOULD: Session IDs must be globally unique and cryptographically secure
→ UUID v4, JWT, or cryptographic hash — not sequential integers
MUST: Clients must handle session IDs securely against hijacking
→ TLS required for all Streamable HTTP connections in production
The Origin header validation requirement exists because browsers send requests with Origin headers, and a malicious web page could attempt to reach a locally-running MCP server by making requests from a browser context. Validating Origin and rejecting unexpected values closes this vector. The localhost binding requirement is a defense-in-depth measure: a server that binds to 0.0.0.0 is reachable from any network interface, including external ones, even when running on a developer’s laptop.
1.3 Specification Evolution: Four Releases in Eighteen Months
MCP has evolved faster than almost any comparable open protocol. The original spec shipped in late 2024. Three stable revisions followed in 2025, with a fourth in release candidate status as of mid-2026. Understanding the changes across these versions is important both for correctly implementing current MCP and for understanding the security implications of running older server or client code.
The 2025-03-26 Release: Transport and Annotations
The March 2025 release made two significant changes. The first was the replacement of HTTP+SSE with Streamable HTTP as the standard HTTP-based transport, as described above. The second was the introduction of tool annotations — metadata that lets servers communicate behavioral properties of their tools to clients.
Tool annotations address a practical problem: without metadata, a client cannot distinguish between a tool that reads data (safe to call automatically) and a tool that sends an email or deletes a record (dangerous to call without user confirmation). The annotations added in this release allow tools to declare whether they are read-only or destructive, whether they are idempotent, and whether they interact with external systems. This gives host applications the information they need to implement appropriate confirmation flows before calling potentially dangerous tools.
The annotation system does not enforce safety — a malicious server could lie about its annotations, and the client has no way to verify the claim. What annotations do is establish a convention and put the responsibility where it belongs: the server declares its intent, the client decides how much to trust that declaration.
The 2025-06-18 Release: Security Hardening
The June 2025 release was the most consequential security update in MCP’s history. Four changes landed simultaneously, and taken together they represent a fundamental hardening of the protocol’s authorization model.
Structured tool output was added first. Prior to this release, tools returned free-form content — text, images, or unstructured JSON. The June release introduced outputSchema and structuredContent fields, allowing tools to declare a JSON Schema for their return value and return validated structured data against that schema. This is primarily a usability improvement for clients consuming tool results, but it also makes output validation more tractable and provides one more mechanism for detecting when tool outputs have been tampered with.
JSON-RPC batching was removed. The March 2025 release had added support for batching multiple JSON-RPC calls into a single request. The June release removed it. The decision reflects a security vs. complexity tradeoff: batching creates subtle authorization and ordering ambiguities when individual calls in a batch have different permission requirements. Removing it simplifies the security model at the cost of a minor efficiency feature.
MCP servers were reclassified as OAuth Resource Servers. This is the most architecturally significant change in the June release. In earlier versions of the spec, an MCP server could act as its own OAuth Authorization Server — the server that issues tokens and the server that validates them were the same entity. The June release split these roles permanently. Going forward, an MCP server is a Resource Server in OAuth terms: it accepts and validates tokens, but it does not issue them. Token issuance is delegated to a separate Authorization Server that is discovered via RFC 9728 Protected Resource Metadata.
The practical implication is that deploying a production MCP server now requires either pairing it with a dedicated authorization server (an IdP like Okta, Auth0, or Azure AD, or a self-hosted OAuth server) or relying on one provided by the platform. This adds deployment complexity but eliminates an entire class of security mistakes that arise from servers implementing their own OAuth incorrectly.
The Elicitation primitive was added. Elicitation allows MCP servers to request additional information from users mid-interaction via the elicitation/create method. A server handling a multi-step workflow might need clarification from the user — a filename, a confirmation, a preference — without having to embed that interaction into the tool’s initial call. The user can accept, decline, or cancel an elicitation request; the client must declare support for elicitation in its capability negotiation before a server will send elicitation requests.
Elicitation is architecturally interesting because it inverts the typical control flow. In the standard model, the client calls tools on the server. Elicitation allows the server to call back to the client — specifically to the human behind the client — during a tool execution. This enables more natural multi-turn interactions but also creates a new attack surface: a malicious server could use elicitation to phish users by presenting misleading prompts that appear to come from a trusted application.
The 2025-11-25 Release: PKCE as a Hard Gate
The November 2025 release is the current stable spec. Its headline change is a tightening of the PKCE requirement from a strong recommendation to a hard gate.
PKCE (Proof Key for Code Exchange, pronounced “pixie”) is a security extension to the OAuth 2.0 authorization code flow that prevents authorization code interception attacks. Before examining the spec change, it is worth explaining why PKCE matters for MCP specifically.
In the standard OAuth authorization code flow, after a user approves access, the authorization server sends an authorization code to the client via a redirect URI. The client then exchanges that code for an access token. The vulnerability is the exchange step: if a malicious application on the same device can intercept the authorization code before the legitimate client exchanges it, the attacker can obtain a valid access token. On mobile devices and desktop applications — exactly the environments where MCP clients run — redirect URIs are delivered through OS-level URI scheme handling, which can be registered by any app. Traditional OAuth clients use a client secret to authenticate the code exchange, but a secret embedded in a desktop app or local process is not actually secret: it can be extracted from the binary.
PKCE solves this without requiring a stored secret. Before initiating the authorization flow, the client generates a random value called the code_verifier. It hashes this value using SHA-256 to produce the code_challenge, which it sends to the authorization server with the initial authorization request. The user approves the request, the authorization server issues a code, and when the client presents that code for exchange, it also sends the original code_verifier. The authorization server hashes the verifier and checks that it matches the challenge it stored. Only the client that generated the original verifier can produce a matching one — a stolen code is useless without it.
The evolution of PKCE requirements across MCP spec versions tells a story about the protocol’s security posture maturing under real-world scrutiny:
| Spec Version | PKCE Requirement |
|---|---|
2025-03-26 | “PKCE is REQUIRED for all clients” |
2025-11-25 | Clients MUST implement PKCE (S256 method) AND MUST refuse to authorize if code_challenge_methods_supported is absent from the Authorization Server’s metadata |
The November 2025 change turns PKCE into a hard gate. If the Authorization Server does not advertise support for PKCE in its metadata, the MCP client must refuse to proceed with authorization — not fall back to the code flow without PKCE, not warn the user, but refuse. This prevents silent downgrade attacks in which a network attacker strips PKCE support from the AS metadata and causes clients to authenticate without it.
The 2026-07-28 Release Candidate
A release candidate for the next MCP revision, dated 2026-07-28, was published in draft form in May 2026. It is pre-release and not yet normative, but it signals where the protocol is heading.
The most significant change in the RC is architectural: the experimental Tasks primitive, which was added in 2025-11-25, is being moved out of the core specification into an official extension (io.modelcontextprotocol/tasks). This suggests the protocol maintainers are adopting an extensibility model — a stable core with optional extensions — that allows the spec to evolve specific capabilities independently of the base protocol.
1.4 Key Capabilities: Tools, Resources, Prompts, and Tasks
Before turning to security in depth, it is worth surveying the four core capability primitives that MCP exposes — both because they shape how agents actually use MCP and because each has distinct security implications.
Tools are the most commonly used primitive. They are functions that the AI application can call via the MCP server. A tool might search the web, query a database, execute a shell command, or call an external API. Tools are synchronous by default: the client sends a tools/call request, the server executes the function, and returns the result. Tool annotations (added in the March 2025 release) allow servers to declare whether tools are read-only, destructive, or idempotent. Structured tool output (added in the June 2025 release) allows tools to return validated JSON against a declared schema.
Resources are data that the server exposes for the client to read. Unlike tools, resources are not functions — they are named data items identified by URIs. A resource might be a file, a database record, a configuration object, or a live data feed. The client can list available resources, read specific resources, and in some cases subscribe to resource updates. Resources are designed to be read-only from the client’s perspective; mutation happens through tools.
Prompts are reusable prompt templates that servers expose. A server might offer a standard prompt for code review, a template for generating structured reports, or a multi-step workflow that combines several tool calls into a coherent interaction pattern. Clients can list available prompts and instantiate them with parameters. This primitive is the one most often confused with “workflows” in marketing materials — the spec calls them Prompts because they are, technically, templates for model interactions.
Tasks (experimental, added in 2025-11-25) address a gap that the synchronous tool call model cannot handle: long-running operations where the result is not available immediately. Tasks are durable state machines. When a client initiates a task, the server returns a task ID immediately — not the operation result. The client can poll for status, and the server delivers the actual result when the operation completes. This two-phase response pattern is essential for operations like “run this data pipeline” or “process this batch of documents” that may take minutes or hours. Because Tasks are experimental, their API should be treated as unstable; the 2026-07-28 RC already indicates they will be restructured as an extension. (Note that A2A, in §2, makes a durable Task the center of its model rather than a late add-on — a revealing difference in what each protocol is optimized for.)
1.5 Authorization: OAuth 2.1 in Depth
The authorization model for Streamable HTTP transports is where MCP’s security design is most sophisticated and where the most costly implementation mistakes are made. This section covers the complete authorization framework.
Roles and Flows
As of the June 2025 specification, MCP maps onto OAuth 2.1 as follows:
| OAuth Role | MCP Entity |
|---|---|
| Resource Server | MCP Server |
| Authorization Server | Separately discovered via RFC 9728 |
| Client | MCP Client (the host application) |
| Resource Owner | The end user |
The authorization flow for a new MCP client connecting to a Streamable HTTP server follows these steps: the client first uses RFC 9728 Protected Resource Metadata to discover which Authorization Server governs the MCP server. It fetches the AS’s metadata, initiates the PKCE-protected authorization code flow, the user authenticates and grants consent, the client exchanges the authorization code for an access token, and subsequent requests to the MCP server carry that token in the Authorization header.
This flow happens at the transport layer. The MCP data layer — tool calls, resource reads, prompt requests — never sees token material. This is the clean separation the two-layer architecture is designed to enforce.
Resource Indicators and Token Scoping
As of June 2025, MCP clients are required to implement RFC 8707 Resource Indicators. In every authorization and token request, the client includes a resource parameter containing the canonical URI of the MCP server it is authorizing for.
The purpose is audience binding: the token issued by the Authorization Server is scoped to a specific resource (the MCP server), and the MCP server validates that the token was issued for it specifically. Without audience binding, a token issued to access MCP Server A could be presented to MCP Server B — the servers would have no protocol-level basis for rejecting it.
There is an important caveat that the spec does not obscure: RFC 8707 audience binding only provides security benefit when the Authorization Server actually enforces it. An AS that ignores the resource parameter and issues tokens without audience constraints provides no real scoping, regardless of whether the client sends the parameter. The spec requires clients to always include the resource parameter — which future-proofs deployments as AS implementations improve — but practitioners should audit their chosen Authorization Server’s actual behavior rather than assuming RFC 8707 compliance.
Token Passthrough: The Prohibition
One of the most important rules in the MCP spec is also one of the most frequently violated in early implementations. The spec states in normative MUST language:
“MCP servers MUST only accept tokens specifically intended for themselves and MUST reject tokens that do not include them in the audience claim or otherwise verify that they are the intended recipient of the token.”
“The MCP server MUST NOT pass through the token it received from the MCP client.”
What does this mean in practice? When an MCP server needs to call a downstream API — say, a GitHub API to fulfill a code search request — it cannot simply forward the token it received from the MCP client to GitHub. The token was issued for the MCP server as the audience; GitHub should reject it (and if GitHub doesn’t reject it, the token was probably scoped too broadly). The MCP server must obtain a fresh token for the downstream API through a separate authorization exchange.
The mechanism for doing this in enterprise environments is typically the On-Behalf-Of (OBO) flow: the MCP server presents its incoming token to the Authorization Server and requests a new token for the downstream resource, scoped with the user’s delegated permissions. The Authorization Server validates the incoming token, verifies that the MCP server is authorized to perform OBO exchanges, and issues a new token for the downstream API. The new token carries the user’s identity but is issued for the correct audience.
The token passthrough prohibition is the confused deputy mitigation. Without it, an MCP server that proxies multiple downstream services becomes a single-point capability amplifier: compromise the MCP server’s token validation, and you get access to every downstream system it can reach. By requiring fresh tokens for each downstream call, the spec ensures that a token’s blast radius is limited to the specific resource it was issued for.
1.6 Security Attack Classes
MCP’s security model addresses several distinct attack classes. Understanding them is essential for both implementing servers correctly and evaluating the security posture of third-party MCP servers you are integrating.
DNS Rebinding
DNS rebinding attacks target locally-running MCP servers that bind to network interfaces. The attack scenario: an attacker hosts a malicious web page. The page’s DNS record initially resolves to the attacker’s server. After the browser loads the page, the attacker changes the DNS record to resolve to 127.0.0.1 (or another local address). Because the browser’s same-origin policy is based on hostname, not IP address, subsequent requests from the page are treated as same-origin with the attacker’s server — but they actually reach the local MCP server.
The mitigations are both specified in the MCP transport requirements: validate the Origin header and reject connections with unexpected origins (browsers always send Origin headers for cross-origin requests), and bind to 127.0.0.1 rather than 0.0.0.0 (which makes the server unreachable from network interfaces other than loopback). The first mitigation is MUST-level; the second is SHOULD-level. Both are cheap to implement.
Tool Poisoning and Prompt Injection
Tool poisoning is an attack in which a malicious MCP server embeds adversarial instructions in its tool descriptions or tool results with the goal of hijacking the AI model’s behavior. Because AI models process tool descriptions and results as input, a crafted description can effectively inject instructions into the model’s context — instructions that may override system prompts, cause the model to exfiltrate data through other tool calls, or manipulate the model into taking actions the user did not request.
The attack surface is larger than it might appear. Tool descriptions, resource content, prompt templates, and structured tool outputs are all paths through which a server can inject content into the model’s context. Invisible Unicode characters, markdown formatting that renders differently than it appears in the raw text, and base64-encoded content are among the obfuscation techniques documented in security research on this class of vulnerability.
The MCP security best practices page addresses this attack class, but the mitigations are guidance rather than normative requirements — there are no MUST-level controls in the spec. The practical defense is to treat all MCP tool outputs as untrusted external input. Models should not execute tool results as instructions; host applications should not pass raw tool content into the model context without inspection; and organizations operating sensitive agentic systems should consider sandboxing the tool execution environment and filtering tool outputs before they reach the model.
The Confused Deputy
The confused deputy vulnerability arises specifically in MCP servers that act as proxies to third-party authorization servers. The scenario:
- An MCP proxy server uses a static OAuth client ID to authorize against a third-party service (GitHub, Salesforce, etc.)
- User A goes through the OAuth flow and grants consent; a cookie is stored
- An attacker steals User A’s authorization code from the redirect
- The attacker replays the code against the proxy’s static client ID
- Because the client ID matches and a consent cookie exists, the authorization server issues a token — without User A’s active consent to this exchange
The spec’s mitigation is procedural: MCP proxy servers using static client IDs must obtain explicit per-client user consent before forwarding authorization to third-party servers. Each dynamically registered client requires its own consent flow. This prevents the consent-cookie replay scenario but requires careful implementation in multi-user proxy deployments.
Session Hijacking
If session identifiers are predictable — sequential integers, timestamps, or short random values — an attacker who can observe one valid session ID can enumerate adjacent values and attempt to take over another user’s session. The mitigation is straightforward: use cryptographically secure session ID generation (UUID v4 as a minimum, JWT preferred) and always carry session tokens over TLS.
1.7 The Enterprise Identity Gap
The MCP spec’s OAuth 2.1 framework is well-designed for straightforward single-tenant scenarios. It is less complete for the multi-tenant, multi-downstream-service deployments common in enterprise environments. Understanding this gap is important for architects building MCP into enterprise agentic systems.
The core problem is delegation chaining. When an enterprise MCP server acts as an orchestrator for multiple downstream APIs — an email service, a CRM, a data warehouse — each downstream call requires a token scoped for that service with the user’s delegated permissions. The MCP spec governs the token exchange between MCP client and MCP server. It does not specify what the MCP server should do with downstream APIs.
The pattern the enterprise market has converged on is the OBO (On-Behalf-Of) flow as implemented by major identity platforms. For Microsoft environments, this means the MCP server presents its incoming access token to Azure AD and requests a new token for the downstream resource (Microsoft Graph, Dynamics, SharePoint). Azure AD validates the incoming token, checks that the calling service is authorized for OBO, and issues a scoped token for the downstream API. The sequence enforces that no token escapes its intended audience, which satisfies the MCP token passthrough prohibition.
For multi-tenant MCP deployments — one MCP server serving users from multiple organizations — the complexity multiplies:
| Challenge | Implication |
|---|---|
| Token audience isolation | A token issued for Tenant A’s MCP instance must not be accepted for Tenant B’s |
| Per-tenant AS discovery | Each tenant may have its own Authorization Server; RFC 9728 discovery must resolve per-tenant |
| Dynamic client registration | Each tenant or user may require its own OAuth client registration to satisfy per-client consent requirements |
| Consent management | The confused deputy mitigation requires per-client consent flows, multiplied across all tenants |
None of these challenges are impossible to address, but the MCP spec does not define a multi-tenant enrollment model. Implementers must build their own. An IETF draft — draft-ietf-oauth-identity-chaining — is working toward a standardized mechanism for identity propagation across service chains, which would eventually provide a protocol basis for multi-hop MCP authorization. It is not yet an RFC and is not referenced in the MCP spec, but it represents the likely direction.
1.8 Ecosystem and Adoption
MCP’s adoption trajectory since its late 2024 release is notable for a protocol that requires coordinated changes from both client and server implementations. By June 2026, the modelcontextprotocol/servers GitHub repository has accumulated 87,493 stars and 11,043 forks. An official MCP Registry is live at registry.modelcontextprotocol.io — a discovery platform for published MCP servers that functions as an app store for the ecosystem, separate from the reference implementations in the servers repository. The registry entered preview in September 2025 and froze its API at v0.1 in October 2025.
On the client side, adoption has been driven by major AI platform integrations. Claude Desktop and the Claude API support MCP natively. OpenAI integrated MCP support, bringing ChatGPT into the client ecosystem. Microsoft added MCP support to Copilot Studio. Visual Studio Code’s Copilot agent mode supports MCP servers directly. Cursor — the AI-first code editor — treats MCP as a first-class integration mechanism. This cross-vendor adoption is significant: it means MCP servers written for one client will work with others, which creates the positive-sum dynamic that makes a protocol standard worth implementing.
The combination of client-side adoption and a growing server registry is beginning to produce the network effect that makes integration standards self-reinforcing. Teams building new agentic applications no longer need to evaluate whether MCP is worth implementing — the question is how to implement it correctly.
2. A2A: Connecting Agents to Other Agents
MCP solves the tool problem: it gives one agent a clean, auditable way to reach data and functions. But it says nothing about how two agents talk to each other. If a coordinator agent needs to hand a subtask to a specialized research agent running in a different company’s cloud, MCP is the wrong shape — it models the research agent as a tool, flattening away everything that makes it an agent. The Agent2Agent Protocol (A2A) exists to fill exactly this gap.
2.1 The Agent-to-Agent Problem
The obvious workaround — expose the other agent as an MCP tool — breaks down as soon as the peer is genuinely agentic. A tool is a function: predictable inputs, predictable outputs, stateless, and fully described by its schema. A real collaborator agent is none of those things. It reasons and plans. It may take minutes or hours. It maintains state across a multi-turn dialogue. It may come back and ask you a clarifying question mid-task. And critically, you usually neither control nor want to see its internals — it might be a third party’s agent, built on a different framework, with its own model, memory, and tools.
A2A’s premise is that a peer agent should be treated as an agent, not as a tool. That single design decision drives everything else: how agents find each other, how work is delegated, and how much they reveal to one another.
2.2 Design Principle: Opaque Agents
The defining principle of A2A is opacity. From the client’s perspective, a remote agent is a black box. Its internal workings — its memory, its tools, its plans, its chain of thought — are not exposed. The spec’s guiding principles put it directly: “Agents collaborate based on declared capabilities and exchanged information, without needing to share their internal thoughts, plans, or tool implementations.”
This is the axis that separates an A2A agent from an MCP tool. An MCP tool is transparent by design: you call it, and the schema tells you exactly what it does. An A2A agent is deliberately not transparent: you see only what it chooses to advertise (its capabilities) and what it chooses to return (its results). Google’s framing is that this “enables agents to collaborate naturally without requiring shared memory, tools, or context” — true multi-agent collaboration rather than one agent puppeteering another’s tools.
Opacity is a double-edged sword, and it is worth being honest about the trade. It is what makes cross-organization, cross-framework collaboration possible — you can delegate to an agent you didn’t build and don’t operate. But it also makes trust harder: if you can’t see inside a remote agent, verifying that it is trustworthy, or debugging why it produced a wrong answer, is genuinely difficult. Security researchers have flagged this as A2A’s central tension (§2.7).
2.3 Architecture and Object Model
A2A has two roles. An A2A Client is the agent delegating work. An A2A Server (also called the remote agent) is the agent doing the work. Any agent can be both — a client to the agents it delegates to, and a server to the agents that delegate to it. The protocol is built entirely on existing standards; its guiding principle is to “reuse existing, well-understood standards (HTTP, JSON-RPC 2.0, Server-Sent Events).”
The object model is small and worth memorizing, because it is the vocabulary of every A2A interaction:
| Object | What it is |
|---|---|
| Agent Card | A JSON metadata document describing the agent’s identity, capabilities, skills, service endpoint, and authentication requirements. The “digital business card” — and the discovery mechanism. |
| Task | The unit of work, defined by the protocol, with a lifecycle. This is the center of A2A, not an afterthought. |
| Message | A single turn of communication — a role (user or agent) plus content. |
| Part | A typed content segment inside a message or artifact: text, a file (bytes or URI), or arbitrary structured JSON. Parts let the two agents negotiate format and even UI capabilities. |
| Artifact | The output of a task, composed of one or more Parts. |
A Task moves through a defined lifecycle, which is what lets A2A handle long-running, interruptible work cleanly. The states (spec v1.0.0) are:
submitted— accepted, not yet startedworking— in progressinput-required— the remote agent needs something from the client to continue (interrupted, not terminal)auth-required— the remote agent needs authorization to continue (interrupted, not terminal)completed— finished successfully (terminal)failed— errored (terminal)canceled— stopped by request (terminal)rejected— refused by the remote agent (terminal)
The two “interrupted” states are what make this an agent protocol rather than a request/response API. A task can pause, come back to the caller for a missing input or an authorization step, and then resume — modeling the multi-turn, occasionally-blocking nature of real delegation.
A versioning note for implementers: spec v1.0.0 renders these states as gRPC-style constants (
TASK_STATE_SUBMITTED,TASK_STATE_INPUT_REQUIRED, and so on), while the earlier 0.x specs used the lowercase strings shown above. If you are reading older SDK code, expect the lowercase form.
2.4 Discovery: The Agent Card
Before one agent can delegate to another, it has to find it and learn what it can do. A2A handles this with the Agent Card — a JSON document an agent publishes to advertise itself. It declares the agent’s identity, its service endpoint, its authentication requirements, and a list of skills, where each skill can carry examples of what it does (in Google’s purchasing-concierge tutorial, a seller agent advertises a create_burger_order skill with example invocations).
By convention the card lives at a well-known URI: https://{domain}/.well-known/agent-card.json, following the RFC 8615 well-known-URI pattern, and a client fetches it with a plain HTTP GET.
There is a version trap worth flagging, because it will bite anyone reading older tutorials. The discovery path changed in spec v0.3.0 (July 2025): it was renamed from the original /.well-known/agent.json to /.well-known/agent-card.json. A lot of code and blog posts written in the first half of 2025 hardcode the legacy agent.json path. Don’t — resolve the current path, and treat any hardcoded agent.json as a smell.
Capability negotiation flows from the card: the client reads the advertised skills and the declared transport/streaming capabilities, then interacts within those bounds. An agent that supports streaming says so in its card; a client that wants a UI-rich response can negotiate content types through Parts.
2.5 Transport and Interaction
A common mistake — including in a lot of early writing about A2A — is to describe it as “JSON-RPC over HTTP” and stop there. That was roughly true of the earliest 0.x drafts, but the current spec is broader. As of v1.0.0 there are three formal transport bindings:
- JSON-RPC 2.0 over HTTP(S) — the baseline binding
- gRPC — for lower-overhead, strongly-typed service-to-service calls
- HTTP+JSON / REST — for teams that prefer plain REST semantics
(The spec also documents guidelines for custom bindings.) An agent declares which bindings it supports in its Agent Card. So the accurate statement for a practitioner is: A2A’s baseline is JSON-RPC 2.0 over HTTP, but it is a multi-transport protocol, and you should not assume a given peer speaks JSON-RPC.
On top of whatever binding is chosen, A2A defines three interaction patterns, matched to how long the work takes:
- Request/Response (polling) — synchronous; fine for fast tasks.
- Streaming (SSE) — the remote agent streams incremental updates as it works, over Server-Sent Events. Good for progress and partial results.
- Push notifications (webhooks) — for genuinely long-running tasks, the remote agent POSTs updates to a client-registered webhook when the task changes state, so neither side has to hold a connection open for minutes or hours.
The push-notification pattern is the one that matters most for real deployments. It is A2A’s answer to the same problem MCP addresses with its experimental Tasks primitive — but where MCP bolted async on late, A2A designed the durable, interruptible Task in from the start.
2.6 Authentication and Authorization
A2A’s auth model is deliberately thinner than MCP’s, and the contrast is instructive.
A2A does not define a bespoke authentication scheme. Per its enterprise-ready guidance, it “delegates authentication to standard web mechanisms,” relying primarily on HTTP headers and established standards like OAuth 2.0 and OpenID Connect. Authentication is a transport-level concern, and an agent declares its requirements in the Agent Card. An extended (authenticated) Agent Card can reveal additional detail to clients that have already authenticated — so a public card advertises the basics, and an authenticated fetch unlocks the rest.
Compare this to MCP (§1.5). MCP is prescriptive: it formally classifies the server as an OAuth 2.1 Resource Server, mandates PKCE as a hard gate, requires RFC 8707 audience binding, and forbids token passthrough — normative MUST-level rules baked into the spec. A2A is delegative: it says “use OAuth 2.0 / OIDC over standard HTTP auth” and leaves the enforcement model largely to the deployment. As of v1.0, A2A’s authorization story is comparatively underspecified — which is why Auth0 (Okta) and Google Cloud publicly partnered to define A2A auth specifications and ship SDKs for authenticating agents remotely. If you are building on A2A in an enterprise setting, expect to bring your own identity rigor rather than inherit it from the spec.
2.7 Security: The Opaque-Agent Attack Surface
A2A launched alongside a body of security research — much of it published in April–May 2025, essentially concurrent with the protocol itself. The central academic analysis, “Building A Secure Agentic AI Application Leveraging A2A Protocol” (Habler et al., 2025), applies the MAESTRO threat-modeling framework and concentrates on three areas: Agent Card management, task execution integrity, and authentication. A separate analysis of A2A handling highly sensitive data (payment credentials, identity documents) flagged four gaps: insufficient token lifetime control, lack of strong customer authentication, overbroad access scopes, and missing consent flows.
The attack classes worth naming, framed for a practitioner:
- Agent Card spoofing / tampering — a forged or modified card that misadvertises capabilities, points to a malicious endpoint, or lies about auth requirements. Because discovery hinges entirely on the card, its integrity is load-bearing.
- Agent impersonation — a malicious agent posing as a trusted peer.
- Task replay — resubmitting a captured task to trigger a duplicate effect.
- Cross-agent prompt injection — adversarial content passed between opaque agents, where the receiving agent treats delegated content as instructions. This is the tool-poisoning problem from §1.6, reappearing one layer up: the same discipline (treat everything a peer sends as untrusted input) applies.
The through-line is that opacity, A2A’s greatest strength, is also its central security challenge: you are delegating work to something you can’t inspect. Treat this section as a map of documented concerns rather than settled requirements — much of it is early research, and A2A’s normative security controls are still maturing.
2.8 Governance, Timeline, and Ecosystem
A2A’s short history is unusually well-documented, because it happened in public:
- April 9, 2025 — Google announces A2A “with support and contributions from more than 50 technology partners,” including Atlassian, Box, Cohere, Intuit, LangChain, MongoDB, PayPal, Salesforce, SAP, and ServiceNow.
- June 23, 2025 — the Linux Foundation launches the A2A Protocol Project at Open Source Summit North America, with more than 100 supporting companies and an Apache 2.0 license. Named founding contributors include AWS, Cisco, Google Cloud, Microsoft, Salesforce, SAP, and ServiceNow. Donating the protocol to a neutral foundation was the move that turned A2A from “Google’s protocol” into a genuinely vendor-neutral standard.
The spec matured quickly: 0.1.0 → 0.2.x → 0.3.0 → 1.0.0, with v1.0.0 landing in March 2026 as the first stable, production-ready release (a v1.0.1 patch followed). The two changes most likely to trip up someone reading older material both happened in 0.2.x/0.3.0: the addition of gRPC and REST bindings (v0.2.2), and the agent.json → agent-card.json discovery rename (v0.3.0). Official SDKs exist for Python, JavaScript/TypeScript, Go, Java, .NET, and Rust.
A necessary caveat on all of this: adoption evidence is drawn from launch announcements, foundation press releases, and vendor commitments. Those establish serious intent and cross-industry backing — but they are not the same as measured production usage. Treat A2A’s adoption as “broadly committed and rapidly standardizing,” not “everywhere in production.” A2A did not emerge into an empty field, though — it won one. The next part explains what it beat, and why.
3. The Wider Landscape
MCP and A2A can look, from inside this chapter, like the natural and inevitable pair. They are not. Through 2025 the agent-interoperability space briefly looked like it might fragment the way messaging or identity standards have before — several serious protocols, backed by serious companies, all launched within months of each other. What happened next is the more interesting story, and it is why a practitioner today can safely bet on two protocols instead of hedging across five.
3.1 The Protocols That Contended
Four names beyond MCP and A2A are worth knowing, if only so you recognize them and know why you can mostly set them aside.
ACP (Agent Communication Protocol) — IBM Research’s agent-to-agent protocol, launched March 2025 to power its open-source BeeAI platform and donated to the Linux Foundation the same month. For a few months ACP and A2A were direct alternatives, both solving agent-to-agent communication under the same foundation. That ended cleanly: in August 2025, ACP formally merged into A2A. IBM’s Kate Blair put it plainly — “by bringing the assets and expertise behind ACP into A2A, we can build a single, more powerful standard for how AI agents communicate.” The ACP team is winding down active development, migration adapters shipped (BeeAI agents now expose themselves over A2A), the ACP repository was archived, and Blair joined the A2A Technical Steering Committee. This is the single clearest consolidation event in the space, and it matters because it happened by agreement, not by one protocol quietly dying — the same eight-vendor coalition (Google, Microsoft, AWS, Cisco, Salesforce, ServiceNow, SAP, and now IBM) now sits on the A2A steering committee.
ANP (Agent Network Protocol) is the one genuine philosophical alternative still standing, and it’s worth understanding precisely because it is not trying to be A2A. Where A2A is enterprise-shaped — agents inside and between companies, discovered through Agent Cards — ANP is decentralized and open-web-shaped. It builds identity on W3C Decentralized Identifiers (a did:wba, “web-based agent,” method), reuses existing web infrastructure (HTTP, DNS, TLS, CAs) rather than inventing a new stack, and describes agent capabilities with semantic-web standards (RDF, JSON-LD, schema.org). Its stated ambition is to be “the HTTP of the Agentic Web era” — a shift “from platform-centric closed ecosystems to protocol-centric open ecosystems” for billions of agents. That is aspiration, not adoption; ANP today is an open-source project and a W3C community-group draft, not a production standard with a vendor coalition behind it. But it is the clearest articulation of the road not taken: a decentralized agent web rather than a federation of enterprise agents. If A2A is the agent equivalent of enterprise SSO, ANP is the agent equivalent of the open web.
AGNTCY (the “Internet of Agents”) is the one most often miscategorized as a competing protocol. It isn’t. Launched by Cisco’s Outshift group with LangChain and Galileo in early 2025 and donated to the Linux Foundation in July 2025, AGNTCY is infrastructure around the protocols, not a wire protocol itself — a decentralized agent directory for discovery, an identity layer, observability, a many-to-many messaging substrate (SLIM), and a capability-schema framework (OASF). It’s best understood as complementary plumbing that can sit beneath A2A and MCP rather than a third thing you’d choose instead of them. (A naming trap to note: AGNTCY has a component also abbreviated “ACP” — “Agent Connect Protocol” — which is unrelated to IBM’s now-merged “Agent Communication Protocol.” Two different “ACP”s; use the full names.)
NLWeb, Microsoft’s Build 2025 project, is the last one to place — and it reinforces the pattern rather than complicating it. NLWeb turns an ordinary website into something agents can query in natural language, reusing existing structured web data (Schema.org, RSS). The revealing detail: every NLWeb endpoint is itself an MCP server. Microsoft’s play to make the web agent-legible is built on MCP, not as a rival to it. When the company with its own cloud, model, and agent platform reaches for a way to expose the web to agents and chooses to ride MCP, that tells you which way the standard is settling.
3.2 Why It Consolidated — and Where It Didn’t
Step back and the shape is clear. The field is converging on MCP for tools and A2A for agents, with the Linux Foundation as neutral host and a striking amount of vendor overlap between the two — the same companies contribute to both. The consolidation is real: ACP folded into A2A by agreement, AGNTCY positioned itself as complementary infrastructure, and even Microsoft’s web-to-agent effort rides MCP. For a team choosing what to build on, that convergence is the practical gift — you are not betting on one of five uncertain contenders; you are adopting the pair the industry has already agreed on.
But “consolidating” is not “monolithic,” and it’s worth being precise about what has not happened. MCP and A2A remain two separate protocols — complementary, not merged into one grand unified standard. ANP persists as a decentralized alternative with a genuinely different worldview, and if the future tilts toward an open agent web rather than federated enterprise agents, it (or something like it) could matter more than it does today. And every bit of this rests on announcements, foundation donations, and steering-committee seats — governance facts and stated intent, not measured production usage. The coalition is real; the at-scale deployment is still mostly ahead of us.
3.3 The Deeper Gap: Talking vs. Understanding
There is a harder problem underneath all of these protocols, and it is the one most likely to bite you in practice — because none of them fully solve it.
Every protocol in this chapter standardizes the envelope: how a message is framed, how it’s transported, how a task moves through its lifecycle. That is transport (or syntactic) interoperability, and it is largely a solved problem — MCP and A2A do it well. What they do not standardize is the meaning. There is no shared ontology for what a capability actually does. Two agents can speak A2A flawlessly, exchange perfectly-formed messages, and still misunderstand each other, because one agent’s advertised refund skill and another’s assumption about what “refund” entails were never reconciled by the protocol. A JSON Schema guarantees the shape of a message, not a shared understanding of its intent.
A 2026 survey of eighteen agent protocols put it directly: most protocols “prioritize establishing communication channels and defining syntactic standards while providing limited explicit support for semantic alignment,” so “contemporary agents can reliably transmit and parse messages, yet they lack built-in mechanisms for clarification, confirmation, and repair.” MCP in particular “remains weak at the semantic layer” — it offers no protocol-level mechanism for clarifying intent or verifying that two parties mean the same thing.
The practical consequence for a builder is concrete: when the protocol doesn’t carry meaning, you have to reintroduce it — through prompt engineering, orchestration logic, wrapper code, and task-specific adapters that translate one agent’s notion of a capability into another’s. That’s the hidden cost that wire-level compatibility papers over. It’s why “we both support A2A” is necessary but not sufficient for two agents built by different teams to actually work together.
A few protocols try to attack this at the protocol level — ANP leans on semantic-web standards (JSON-LD, schema.org) precisely to make capability descriptions machine-understandable, and AGNTCY’s OASF is an attempt at a shared capability schema — but these are partial and early. Semantic interoperability, a shared and machine-readable notion of what agents can actually do, is the genuinely open frontier. Wire-level interop was the first hard problem, and the industry largely solved it in eighteen months. Meaning is the next one, and it is nowhere near solved.
4. Building With Both
The introduction and §3 drew the line between the two protocols — MCP for the tools an agent uses, A2A for the agents it partners with, with a wide grey band in between. This part assumes that choice is made and turns to the practical question: how do you actually build with them? The short answer is that in most real systems you use both, and the interesting engineering is in how they stack and in the security discipline each one demands.
4.1 How They Compose
The two protocols stack cleanly because they operate at different layers: A2A between agents, MCP within an agent.
Consider Google’s purchasing-concierge reference architecture. A top-level concierge agent uses A2A to delegate to independent remote “seller” agents — each an opaque peer it discovered via an Agent Card. Each seller agent, internally, uses its own MCP servers to do its job: query inventory, check pricing, place an order. The concierge never sees the seller’s tools; it only sees the seller’s advertised skills and returned artifacts. The seller never exposes its MCP layer across the A2A boundary. Each protocol operates in its own layer, and the opacity that A2A enforces is exactly what keeps the seller’s MCP tools private.
That layering is the real payoff of having two protocols instead of forcing everything through one. MCP gives each agent a clean, auditable, well-secured way to reach its own tools. A2A gives a network of agents a vendor-neutral way to reach each other without leaking those tools. Build a single agent and you may only need MCP; even a small orchestrator-plus-sub-agents system can stay entirely on MCP, as the introduction noted. It’s when the agents become autonomous peers that must collaborate across teams or organizations that you add A2A on top — and the composition above is what that looks like in practice.
4.2 Practical Guidance for Implementers
Both specs, the security literature around them, and hard-won practitioner experience point to a short list of things that actually matter when you build. The checklists below synthesize them.
Building an MCP Server
The most important principle for server implementers is to never trust a token without validating its audience. Every access token presented to your server must be checked to confirm it was issued for your server’s URI. Tokens without an aud claim, or with an aud claim that does not match your server, must be rejected — not logged, not downgraded, rejected.
Never forward the token you received from an MCP client to an upstream API. Obtain a fresh token through OBO or a similar delegation mechanism. This is the single most common mistake in early MCP server implementations and the one with the largest potential blast radius.
Implement RFC 9728 Protected Resource Metadata so clients can discover your Authorization Server. Without this, clients must be configured with your AS information out-of-band, which creates deployment friction and is easy to get wrong.
The complete server-side checklist:
- Validate the
audclaim on every access token — reject tokens not issued for your server’s URI - Never forward received tokens to upstream APIs — exchange via OBO or equivalent
- Validate the
Originheader on all Streamable HTTP connections — return 403 for unexpected origins - Bind to 127.0.0.1, not 0.0.0.0, for locally-running servers
- Use RFC 9728 Protected Resource Metadata for AS discovery
- Generate cryptographically secure session IDs (UUID v4 minimum; JWT preferred)
- Implement per-client consent flows if acting as a proxy to third-party authorization servers
- Treat all tool output content as potentially adversarial — sanitize before returning
Building an MCP Client
The most important principle for client implementers is to refuse authorization when security requirements are not met. This sounds obvious but requires active checks. If the Authorization Server’s metadata does not include code_challenge_methods_supported, the client must not proceed with the authorization flow — not warn, not offer to continue, refuse. The spec requires this as a hard gate against PKCE downgrade attacks.
Include the RFC 8707 resource parameter in every authorization and token request. This may feel like a formality when your AS doesn’t enforce it, but it makes your implementation correct for AS implementations that do and future-proofs your code as the ecosystem matures.
The complete client-side checklist:
- Implement PKCE with S256 — refuse authorization if AS metadata lacks
code_challenge_methods_supported - Include the RFC 8707
resourceparameter in all authorization and token requests - Use RFC 9728 to discover the correct Authorization Server from the MCP server’s metadata
- Store tokens securely — OS keychain or equivalent; never localStorage or plaintext files
- Handle session IDs securely over TLS for all Streamable HTTP connections
- Treat all MCP tool outputs as untrusted input — do not execute tool results as instructions
Building on A2A
A2A’s spec leaves more to the implementer, so the discipline is different — less “comply with these MUSTs,” more “add the rigor the spec delegates to you.”
- Resolve the Agent Card at the current well-known path (
/.well-known/agent-card.json); never hardcode the legacyagent.jsonpath - Don’t assume a peer speaks JSON-RPC — read its declared transport bindings from the Agent Card (JSON-RPC 2.0, gRPC, or HTTP+JSON/REST)
- Verify Agent Card integrity and provenance before trusting advertised capabilities or endpoints — card spoofing is a documented attack
- Bring your own auth rigor: enforce short token lifetimes, tight scopes, and explicit consent flows; the spec delegates OAuth 2.0/OIDC but doesn’t mandate the discipline
- Treat everything a remote agent returns as untrusted input — cross-agent prompt injection is tool poisoning one layer up
- Use push notifications (webhooks) for long-running tasks rather than holding connections open; handle the
input-requiredandauth-requiredinterrupt states explicitly - Pin the spec version you build against (1.0.x is the current stable line) — the 0.x-to-1.0 transition introduced breaking changes
Transport Selection (MCP)
| Scenario | Recommended Transport |
|---|---|
| Local tool integration (same machine) | stdio |
| Remote or cloud-hosted MCP server | Streamable HTTP + TLS |
| Backward compatibility with pre-2025 clients | Streamable HTTP + legacy SSE/POST endpoints |
4.3 Open Questions
A few questions are still genuinely unsettled, and they are worth watching as both protocols evolve. The largest of all — semantic interoperability — was covered in §3; the ones here are narrower and per-protocol.
On the MCP side, the enterprise identity gap remains the largest. How MCP authorization integrates with enterprise identity systems — Azure AD, Okta, Salesforce Identity — for OBO flows, delegated permissions, and multi-tenant deployments is not addressed in the current spec. Practitioners are solving this with platform-specific patterns, but the lack of a standardized approach creates interoperability risk. The IETF identity chaining draft points toward a solution, but it is not yet normative. Relatedly, the normative controls against tool poisoning remain advisory rather than mandatory — the security best practices page uses SHOULD rather than MUST, so high-security deployments must define their own requirements rather than relying on spec compliance.
On the A2A side, the authorization model is comparatively underspecified. A2A delegates auth to OAuth 2.0/OIDC over HTTP but does not impose MCP-style normative controls, which is why third parties (Auth0/Google Cloud) are working to define fuller auth specifications. The security controls are still maturing: the attack classes documented in early research (Agent Card spoofing, task replay, cross-agent prompt injection, impersonation) are concerns raised in analysis rather than mitigations mandated in the spec. And the largest open question is empirical: how much of A2A’s adoption is production reality versus announced intent? The partner lists and foundation backing are real, but there is little public data on agents actually collaborating via A2A in production at scale.
Finally, the two protocols’ async models are converging on the same problem from opposite directions — MCP is extracting Tasks into an extension while A2A built durable Tasks into its core — and it remains to be seen whether the ecosystem settles on one pattern for long-running agent work or lives with two.
Summary
Agentic systems have two integration problems, and by mid-2026 the industry has largely settled on one open protocol for each. MCP connects an agent to its tools and data. It is a technically mature protocol whose two-layer architecture separates protocol semantics from transport, letting the same tools be reached locally via stdio and remotely via Streamable HTTP with transport-appropriate security. Its 2025 revisions were a serious security hardening — reclassifying servers as OAuth Resource Servers, requiring audience binding, prohibiting token passthrough, and making PKCE a hard gate — and its ecosystem, with an official registry and native support across every major AI platform, has reached self-reinforcing network effects.
A2A connects an agent to other agents. Its defining choice is to treat a peer as an opaque, autonomous collaborator rather than a transparent tool: agents discover each other through a JSON Agent Card, then delegate durable, interruptible Tasks over JSON-RPC, gRPC, or REST, with streaming and webhook patterns for long-running work. Created by Google in April 2025 and donated to the Linux Foundation two months later, A2A reached a stable v1.0 in early 2026 and has been consolidating the once-fragmented agent-interop space around itself. Its auth and security models are thinner and less mature than MCP’s — a delegative “use OAuth/OIDC” posture rather than MCP’s prescriptive one — which means A2A implementers must supply rigor the spec leaves to them.
The two are complementary, and the decision rule is simple: model a function as an MCP tool; model a collaborator as an A2A agent. In real systems they stack — A2A between agents, MCP within each agent — and that layering is exactly what lets a network of agents collaborate across teams and organizations without leaking the private tools each one depends on. The overlap is real and the boundary is a heuristic, not a law; but for a practitioner starting today, “MCP for tools, A2A for agents” is the framing the whole industry is building toward.
That framing is also the outcome of a real contest, not a foregone conclusion. Through 2025 several protocols vied for the agent-to-agent slot — IBM’s ACP, the decentralized ANP, Cisco’s AGNTCY infrastructure, Microsoft’s NLWeb — and the field consolidated fast: ACP merged into A2A by agreement, AGNTCY repositioned as complementary plumbing, and NLWeb turned out to ride MCP. What’s left is a genuine two-protocol standard under neutral governance, with one honest philosophical alternative (ANP’s decentralized agent web) still in the wings. And the frontier is no longer the wire: the protocols have largely solved how agents exchange messages, but not how they understand each other. Semantic interoperability — a shared, machine-readable notion of what a capability actually means — is the next hard problem, and for now it’s the developer, not the protocol, who fills the gap.
📬 Get the next chapter in your inbox
I'm writing this book in the open. Subscribe and I'll email you when a new chapter goes live — nothing else.