MCP and A2A

MCP and A2A are general-purpose agent transports with no advertising semantics: AdCP requires a sales agent to support at least one, AAMP adds REST over OpenDirect 2.1, and neither protocol requires an agent to declare which transport it speaks.

MCP and A2A are general-purpose agent transports. MCP, the Model Context Protocol, is Anthropic’s specification for how a model calls an external tool. A2A, Agent2Agent, covers how autonomous agents send each other messages and run long tasks; Google donated it to the Linux Foundation, and a technical steering committee governs it now.

Both define message framing and task lifecycle only. Operations, field names and obligations come from AdCP and AAMP. Supporting MCP or A2A does not by itself imply support for any AdCP operation, because neither transport specification defines advertising operations.

Neither stack requires an agent to say which of the two it speaks: AdCP has no general field for it, and AAMP has an unconstrained one. AdCP and AAMP also target different major versions of A2A, so a buying client reaching both parses both agent card shapes.

With no declaration to read, the transport has to be probed. /.well-known/agent.json first: a card that parses means A2A, and the card’s shape says which A2A, root url for v0.3 or supportedInterfaces[] for 1.0. No card, and an MCP session carries protocolVersion on initialize. get_adcp_capabilities over whichever one answered confirms the domains and says nothing about the transport underneath. Neither specification defines this sequence.

Transport requirements in each stack

AdCP requires a sales agent to support MCP or A2A; which one is the implementer’s choice. Its required-tasks page reads: “Sales agents MUST also support at least one transport (MCP or A2A) and declare media_buy in supported_protocols.” supported_protocols lists AdCP domains (media_buy, signals, governance, sponsored_intelligence, creative, brand, measurement), and a transport never appears in it.

MCPA2A
FramingJSON-RPC 2.0 over Streamable HTTP, responses as SSEmessage/send carrying a DataPart of { skill, input }
Discoverytools/listAgent card
Typed response sits atTool result / structuredContenttask.artifacts[0].parts[0].data
Conversation contextManual, the client passes context_idProtocol-managed
Webhookspush_notification_config in the tool argumentsNative PushNotificationConfig
Version handshakeMCP protocolVersion on initializeNone

AdCP’s protocol-comparison page states that the two “provide identical AdCP capabilities using the same unified status system. They differ only in transport format and async handling”. The difference lands in the code the implementer owns: under MCP the client threads context_id through every call by hand, and under A2A the protocol carries it.

MCP’s protocolVersion versions the MCP wire and says nothing about the AdCP payload riding inside it, and A2A offers no initialize to hang a handshake on, so adcp_version travels in the payload instead. No conformance rule sets an MCP version floor, though structuredContent needs MCP 2025-03-26 or later, a requirement recorded in AdCP’s operating guidance rather than in its conformance rules.

AdCP’s MCP servers publish tools with empty inputSchema objects, so a client takes its request shapes from the published schema files under dist/schemas/3.1.13/ rather than from tools/list. The calling-an-agent page says those servers no longer publish per-tool parameter schemas, so every tool comes back as {type: 'object', properties: {}}; the known-limitations page defers a runtime get_schema tool on the grounds that the decision “depends on MCP tools/list continuing to carry inputSchema” and warns that stripping it “would create the exact wire-surface gap get_schema was meant to close.”

Trusted Match is a serving-path surface rather than a buying transport, and it runs over “JSON over HTTP/2 POST. All implementations MUST use this transport”.

AAMP’s three transport paths

AAMP has three paths, and the rule for picking between them sits in a reference implementation’s docs rather than in a specification. buyer-agent’s protocols document, which governs that framework’s own tool calls, makes MCP “the default for all CrewAI tool operations”, reaches for A2A on “exploratory discovery and complex negotiations where natural language interpretation adds value”, and leaves REST over OpenDirect 2.1 to operator dashboards and legacy integrations.

agentic-direct hardcodes protocolVersion: '0.3.0' in server/src/a2a/agent-card.ts. ARTF, the Agentic Real Time Framework, appears only in the RTB path and leads with gRPC: one service, RTBExtensionPoint.GetMutations, on port 50051, plus an MCP tool extend_rtb on 50052 as the standalone secondary. The AAMP hub README does not mention MCP, A2A or transport.

Which transport an agent speaks

get_adcp_capabilities is the first call made against any AdCP agent. Its response schema requires exactly two things, adcp and supported_protocols, and supported_protocols is the domain list. The only place the transport vocabulary is constrained is the Sponsored Intelligence surface, inside an optional block. A sales agent must support MCP or A2A, but unless it also offers Sponsored Intelligence there is no field in which to say which one it chose.

AAMP defines capabilities.protocols but constrains nothing in it: iab-agentic-primitives/spec/jsonschema/Agent.json declares the field as {"items": {"type": "string"}, "type": "array"} — no enum, nothing pinning those strings to MCP or A2A or to anything. capabilities is absent from Agent.required, so a card with no declared transport validates clean.

AdCP 3.1.13AAMP
Transport required?Yes, MCP or A2ANot required
Field that declares itsponsored_intelligence.endpoint.transports[]Agent.capabilities.protocols
Constrained?enum: ["mcp", "a2a"], minItems: 1Bare array of string
Required?Only if the agent declares Sponsored IntelligenceNo, capabilities is absent from Agent.required
What the API bindsEndpoints are deployment-specificPOST /a2a/jsonrpc, GET /.well-known/agent.json, no /mcp path, from the shared OpenAPI rather than from a specification obligation

AAMP’s artifacts point three ways: the shared OpenAPI binds A2A and REST across 13 operations with no MCP path in it, all four golden vectors declare ["a2a"], and the reference agents’ docs call MCP the default.

A2A version targets

AdCP targets A2A 1.0, with v0.3 supported “through the compatibility period”. 1.0 replaces the root url and protocolVersion with a supportedInterfaces[] array carrying per-interface url, protocolBinding and protocolVersion, and drops the kind discriminator that v0.3 puts on every Part.

agentic-direct hardcodes 0.3.0, the tier AdCP files under compatibility. Neither AdCP’s docs nor the A2A project’s own site gives that compatibility period an end date, so a client reaching both stacks parses both card shapes. Backward compatibility is “not enabled by default”, and a v0.3 client hitting a 1.0-only server fails unless that server opted in.

AdCP’s protocol-comparison page shows A2A examples carrying "kind": "text" and "kind": "data", the v0.3 form, and names no A2A version. Its industry overview credits A2A to Google as maintainer.

Common confusions

An A2A Task.status.state of completed describes the call, not the buy. A completed A2A task can come back carrying a rejected artifact, with a reason and suggestions[]. A client that reads the task state as the commercial outcome records media buys the seller never agreed to.

AdCP’s polling surface reuses the tasks/* names from MCP and A2A, and the wire shapes differ, so the shared names do not indicate a shared message format.