Skip to content

reference: A2A transport alongside MCP on reference agents #69

@bokelley

Description

@bokelley

Why

AdCP defines MCP and A2A as first-class transports. adcp-go is currently MCP-only — no /.well-known/agent-card.json, no message/send / tasks/get handlers. That leaves half the protocol undemonstrated and gives Go buyers nothing to hit when we ship an A2A client (companion to adcontextprotocol/adcp-client-python#251).

What

Add A2A transport to at least one reference agent (start with reference/seller-agent), sharing tool-handler logic with the existing MCP surface so both transports produce identical output.

Endpoints

  • GET /.well-known/agent-card.json — advertise skills, transports, auth
  • POST /a2a (JSON-RPC 2.0):
    • message/send
    • tasks/get
    • tasks/cancel

Envelope contract (server-side of the PR 251 story)

  • Always return contextId on every response.
  • Echo caller-provided contextId when present; mint when absent. Default to pass-through (no ADK-style rewriting) unless we have a reason otherwise — document the choice.
  • Preserve taskId across responses while status is non-terminal (submitted, working, input-required, auth-required).
  • Terminal-state semantics for taskId (completed, failed, canceled, rejected) documented on the response type.
  • Error responses still carry contextId/taskId when they belong to a task.

Shared handler plumbing

Refactor adcp.Register() so the tool handler closure is transport-agnostic — both mcp.CallToolRequest and an A2A message/send payload dispatch into the same typed (ctx, input) -> (output, error) function. No duplicated business logic per transport.

Schema nit (opportunistic)

CreateMediaBuySubmitted is missing ContextID while MCPWebhookPayload has it. Both are async-shaped envelopes; align them.

Tests

  • HTTP-level E2E: A2A buyer against the agent, assert contextId persists across two sends.
  • HITL test: tool returns input-required; follow-up message/send with same contextId + taskId resumes the same server task.
  • Cross-transport conformance: same scenario over MCP and A2A produces identical payloads modulo envelope fields.

Scope

  • Sync message/send only. Streaming (SSE) and push-notification config are out of scope for v1.
  • Reference agent(s) only — production agents opt in later.
  • No breaking changes to existing MCP surface.

Non-goals

  • Extensions API, batch, or any A2A feature not required for AdCP tool flows.
  • New auth mechanism — inherit existing AdCP signing.

Sequence

  1. Transport-agnostic handler refactor (adcp/seller.go, adcp/addtool.go).
  2. A2A server package (adcp/a2a).
  3. Wire into reference/seller-agent.
  4. Companion: Go A2A client (tracked separately).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions