Zuplo
MCP

MCP, A2A, and Where ACP Went

Martyn DaviesMartyn Davies
July 3, 2026
10 min read

MCP connects an agent to tools, A2A connects agents to each other, and ACP folded into A2A in 2025. Here is the agent protocol stack in 2026, spec-level, and how a gateway governs both.

Two protocols now define how an AI agent reaches the outside world. The Model Context Protocol (MCP) connects an agent to tools: a database, a Stripe account, an internal API. Agent2Agent (A2A) connects agents to each other, so a planning agent can hand a task to a billing agent without either one exposing its internal state. They solve different problems and are stewarded by different standards bodies.

You may also have heard about a third contender, the Agent Communication Protocol (ACP). Good news: it is no longer a separate thing to track.

If you are deciding what to support, what to secure, and where the gateway sits, the mid-2026 landscape is more settled than the hype implies. Here is the stack at spec level, and where the controls go.

Use this approach if you're:
  • Building or exposing agents that call tools (MCP) or other agents (A2A)
  • Deciding which protocols to support and how to secure them
  • After the spec-level detail, not another "what is an agent" explainer

MCP talks to tools, A2A talks to agents

MCP is agent-to-tool. A client (Claude Desktop, Cursor, your own agent) connects to an MCP server that exposes tools, resources, and prompts. The server is a capability provider; the agent is the caller. Our what is an MCP server walkthrough covers the model.

A2A is agent-to-agent. Both ends are autonomous agents. One discovers another, delegates a task, and the two coordinate over a long-running exchange, streaming partial results as they go. Neither side hands over its tools or its memory. Our A2A protocol guide for API teams covers the higher-level model; this post goes a layer deeper into the wire format.

In a real system you use both: an orchestrator uses A2A to delegate to specialist agents, and each specialist uses MCP to reach the tools it needs.

Where ACP went

For most of 2025 there were three protocols in the conversation, not two. ACP, the Agent Communication Protocol, came out of IBM Research in March 2025 to power its BeeAI platform. It overlapped heavily with A2A: both described how autonomous agents discover and talk to each other.

That overlap resolved. In August 2025, LF AI & Data announced that ACP was joining A2A under the Linux Foundation umbrella. “Merger” undersells it: the ACP team wound down active development and began contributing its technology directly to A2A.

So in 2026 there is one agent-to-agent standard worth building against: A2A.

A2A itself moved to neutral governance first. Google donated the protocol, its SDKs, and tooling to the Linux Foundation on June 23, 2025, launching the Agent2Agent Protocol Project with AWS, Cisco, Google, Microsoft, Salesforce, SAP, and ServiceNow as founding members. By the time ACP wound down, it was joining a project that was already vendor-neutral, not handing itself to a competitor.

Inside the AgentCard

A2A discovery starts with a public document called an AgentCard, served at a well-known path. In the v1.0 spec that path is /.well-known/agent-card.json (the older /.well-known/agent.json you may see in v0.x examples is out of date).

The card advertises who the agent is, what it can do, and how to authenticate to it:

JSONjson
{
  "name": "Billing Agent",
  "description": "Issues refunds and answers invoice questions",
  "url": "https://agents.example.com/a2a",
  "provider": { "organization": "Example Corp" },
  "capabilities": {
    "streaming": true,
    "pushNotifications": true
  },
  "securitySchemes": {
    "oauth": {
      "type": "oauth2",
      "flows": {
        "clientCredentials": {
          "tokenUrl": "https://auth.example.com/token",
          "scopes": { "billing:write": "Issue refunds" }
        }
      }
    }
  },
  "security": [{ "oauth": ["billing:write"] }],
  "skills": [
    {
      "id": "refund",
      "name": "Issue a refund",
      "description": "Refunds a charge by transaction ID"
    }
  ]
}

capabilities tells a caller whether the agent supports streaming and push notifications (a callback to a webhook so a long-running task can report back without holding a connection open). securitySchemes and security describe how to authenticate, using the same shape as OpenAPI security schemes. skills is the menu of what the agent will do. A calling agent fetches the card, decides the remote agent is a fit, and starts a task.

The card is a capability grant in document form, which is exactly why it is a security surface we will come back to.

Task lifecycle and transports

Work in A2A is modeled as a Task. A caller sends a Message (made up of Parts: text, files, structured data), and the remote agent does the work and streams back Messages and Artifacts. The task moves through a defined set of states:

State Meaning
submitted The task has been accepted but not started
working The agent is actively processing
input-required The agent is blocked waiting on the caller
auth-required The agent needs additional authentication
completed The task finished successfully
failed The task errored
canceled The caller or agent stopped the task
rejected The agent declined the task

The input-required and auth-required states are what make A2A a coordination protocol rather than a request/response API: a task can pause mid-flight, ask the caller for more, and resume.

A2A v1.0 defines three transport bindings: JSON-RPC 2.0 over HTTP, gRPC, and HTTP+JSON/REST. Streaming updates ride Server-Sent Events. Over the JSON-RPC binding, delegating a task is a single POST to the agent’s URL:

http
POST /a2a HTTP/1.1
Host: agents.example.com
Authorization: Bearer <token>
Content-Type: application/json

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "message/send",
  "params": {
    "message": {
      "role": "user",
      "parts": [{ "kind": "text", "text": "Refund charge ch_3Nk for $40" }]
    }
  }
}

The agent replies with a Task object carrying an id and a status.state of submitted or working, then streams updates over SSE as that state advances. For a gateway operator this is the headline: A2A traffic is HTTP plus JSON plus SSE, with no exotic transport to learn. Zuplo’s runtime is web-standard down to streams, so the SSE leg rides the same engine that handles your other streaming responses.

How A2A authenticates

A2A does not invent an auth scheme. The securitySchemes field on the AgentCard reuses the OpenAPI vocabulary, so an agent can declare API keys (APIKeySecurityScheme), HTTP auth, OAuth 2 (OAuth2SecurityScheme), OpenID Connect, or mutual TLS.

A calling agent reads the scheme, obtains a matching credential (usually authenticating as itself with a machine identity, though a scheme can carry a user’s delegated token), and presents it on every task request.

Because the AgentCard is a public document that drives trust decisions, the spec also defines signed agent cards so a caller can verify the card has not been tampered with before acting on it. If you can poison an agent’s card, you can redirect or escalate everything that trusts it.

That puts A2A on familiar ground for anyone who runs API infrastructure: HTTP with OAuth-style auth and a discovery document. The controls you already apply to APIs (token validation, rate limiting, observability) apply directly, which is why a standard gateway can govern A2A without a dedicated handler.

Threats when agents call agents

Adding agents to the call graph adds attack surface that traditional API security models do not fully cover, and the threats are increasingly catalogued.

  • Tool poisoning. A malicious or compromised tool returns content crafted to manipulate the calling model. It is item #3 in the OWASP MCP Top 10, currently an incubator project, alongside rug pulls and tool shadowing.
  • Prompt injection. Untrusted content reaches the model as instructions. This is LLM01 in the OWASP Top 10 for LLM Applications. It flows backwards through tool and agent responses, so the boundary has to inspect what comes back, not only what goes out.
  • Excessive agency. An agent is granted more capability than the task needs and acts on it. That is LLM06 in the same OWASP list, the failure mode that makes least-privilege grants non-negotiable.
  • Agent-card and confused-deputy attacks. A poisoned AgentCard or a token replayed at the wrong server lets a compromised component act with another’s authority. (A confused deputy is a privileged component tricked into misusing its authority on an attacker’s behalf.) The MCP authorization spec names the confused-deputy attack explicitly in its security considerations.

OWASP now ships a dedicated Top 10 for Agentic Applications for 2026, the list to design against if your system has agents calling agents. The common thread: the model layer cannot be the sole enforcement point. Model-side guardrails help, but they are probabilistic and never catch everything, so a deterministic boundary has to sit between the agent and whatever it is reaching.

MCP in 2026

MCP grew up over the last year. In December 2025 Anthropic donated MCP to the Agentic AI Foundation, a Linux Foundation directed fund it co-founded with Block and OpenAI, so it is no longer an Anthropic project the rest of the industry consumes; it is community-governed, with working groups and a formal proposal process. Both protocols in this post now sit under the Linux Foundation, the clearest signal yet that the agent stack is standardizing rather than fragmenting.

The spec hardened alongside that governance shift. The current stable revision is dated 2025-11-25, with the next version (2026-07-28) in release candidate as of this writing. The authorization model got strict: MCP servers MUST implement OAuth 2.0 Protected Resource Metadata (RFC 9728) and MCP clients MUST implement Resource Indicators (RFC 8707), binding every token to the specific server it was issued for. Dynamic client registration, once the expected path, is now optional.

Common mistake:

If you implemented MCP auth in early 2025, do not assume it still conforms. The token-binding and Resource Indicator requirements became MUST since, and dynamic client registration is no longer the expected path. Re-read the current spec before you ship against it.

After a long stretch of people wondering whether MCP would stick, it has settled into something normal. As teams landed on their preferred AI setups, adoption turned routine rather than experimental. That maturity is not the same as a free pass. A critical command-injection vulnerability disclosed in April 2026 (CVE-2026-30623) let LiteLLM’s MCP server-creation feature run config commands without validation. The lesson is boring, but very real: a maturing protocol needs a governed path, not blind trust in every server you connect to. Ungoverned servers are exactly the shadow MCP problem.

One gateway for both

Both protocols ride HTTP, both use OAuth-style auth, and both put untrusted content in front of a model. That is why the same gateway can govern both, with one asymmetry in how much it does for each:

Concern MCP A2A
Gateway’s job Issues tokens (full OAuth 2.1 auth server) Validates tokens (each agent brings its own)
Dedicated handler Yes, the MCP Gateway No, front it like any HTTP API
Transport HTTP, JSON-RPC, SSE, stdio HTTP, JSON-RPC, SSE
Extra controls Capability filtering, no token passthrough Per-agent rate limiting, request logging

The split: MCP needs the gateway to mint and bind credentials, while A2A only needs it to validate the credentials agents already carry.

For MCP, Zuplo ships a dedicated MCP Gateway: a full OAuth 2.1 authorization server in front of your MCP servers, implementing the authorization-server metadata (RFC 8414), protected-resource metadata (RFC 9728), and dynamic client registration (RFC 7591) surfaces.

Each upstream you front is published as a virtual server, its own gateway route with its own OAuth resource. With PKCE and a required resource parameter (RFC 8707), a token issued for one virtual server is rejected at another, closing the confused-deputy gap: a token minted for /mcp/linear-v1 cannot be replayed against /mcp/stripe-v1.

Two more controls matter:

  • No token passthrough. Passthrough is forbidden by the MCP spec, and the gateway enforces it. Inbound auth headers never leak to the upstream; the gateway resolves the user’s credential server-side and attaches it, storing upstream tokens encrypted at rest. The reasoning behind binding a token to one server is in bind MCP tokens to one server.
  • Capability filtering. A policy filters the upstream’s tools/list, prompts/list, and resources/list responses and blocks calls to anything hidden, returning MethodNotFound even to an agent that already knows or guesses the tool name. You publish a read-only or hand-picked subset of a server’s tools rather than handing the agent everything.

For A2A there is no dedicated handler, and there does not need to be. Each agent presents its own credential, so the gateway validates rather than issues tokens, the lighter job. A2A is HTTP plus JSON-RPC plus SSE, so you front it the way you front any API: JWT or OpenID Connect validation, per-agent rate limiting, and full request logging. Same boundary, applied to agent-to-agent traffic. Our AI gateway comparison for MCP, A2A, and agent governance lays out where each vendor sits on native A2A support today.

An AgentCard describes one agent, but a caller still has to discover which servers and agents an organization publishes in the first place. Because the gateway already sits in front of all of them, it is the natural place to publish that catalog, kept in sync with what is actually deployed rather than a manifest that drifts on its own. We cover the mechanics in serving an agentic resource discovery manifest from the gateway.

MCP Gateway Quickstart

Build a virtual MCP server in the browser: pick an upstream, wire up OAuth, curate the tools, and point an agent at it.

In not much more than a year, the agent protocol stack has grown clear and settled. MCP for tools, A2A for agents, both under the Linux Foundation, both spec-hardened on auth. The work now is not picking a protocol but putting a governed boundary in front of the ones you already have, so the next disclosed vulnerability is something your gateway absorbs instead of something your agents inherit.