Skip to main content
Glama
a2a-mcp-connector

a2a-mcp-connector

a2a-mcp-connector

PyPI CI Audit CodeQL License: MIT

A generic MCP server that stream-connects an AI agent to any standard A2A endpoint — plus a built-in A2A Agent Card validator. Install it once in your MCP-capable agent (Claude Code, Codex, Cursor, …) and you can validate and drive any A2A agent over the standard input-required multi-turn protocol, with no manual a2a-sdk install and no per-endpoint code.

It is deliberately provider-agnostic: there is no LLM and no API key inside this server. It is a pure standard-A2A client bridge — your agent is the intelligence; the connector only speaks A2A. (Contrast with LLM-bound bridges that wire in a specific provider such as OpenRouter — this one binds to none.)

Install

# Claude Code
claude mcp add a2a-connector -- uvx a2a-mcp-connector
# Codex
codex mcp add a2a-connector -- uvx a2a-mcp-connector

Any other MCP-aware client (Cursor, Claude Desktop, a hand-edited .mcp.json):

{
  "mcpServers": {
    "a2a-connector": {
      "type": "stdio",
      "command": "uvx",
      "args": ["a2a-mcp-connector"]
    }
  }
}

To run it from a checkout of this repository instead, use uv run a2a-mcp-connector.

Related MCP server: ANP Bridge MCP Server

Tools

Tool

What it does

a2a_validate(agent_card_url, bearer="")

Fetch a remote Agent Card and return a standard-A2A validation report (valid?/checks/warnings) — parses it against the a2a-sdk model and checks the required spec fields + streaming capability. Nothing is connected.

a2a_connect(agent_card_url, bearer="")

Validate the card first (refuses on failure), then start a background streaming session. Returns immediately.

a2a_wait_turn(max_seconds=30)

Wait (bounded) for the next input-required prompt; returns it, "no turn yet", "the session is over.", or an error string.

a2a_send(message)

Submit your reply to the current turn.

a2a_status()

Connected? / turn pending? / done? / error snapshot.

a2a_leave()

Disconnect and close the session cleanly.

bearer is optional — pass it only when the endpoint's card/RPC route requires auth. It is held in memory only and never logged or returned by any tool.

Flow

a2a_validate <card-url>            # optional pre-flight; a2a_connect validates anyway
a2a_connect  <card-url> <bearer?>  # start the session
loop:
  a2a_wait_turn                    # show the prompt to your human, get their reply
  a2a_send    <their reply>        # submit it
a2a_leave                          # when done (or "the session is over.")

The connecting agent should present each turn's prompt to its human and wait for their actual choice — it must not invent a reply.

How it works

One A2A task maps to the whole interaction. a2a_client.A2ASession resolves the Agent Card, derives the JSON-RPC URL from the served card path (reverse-proxy safe — it does not trust the card's advertised interface URL), opens or resumes the task, and drives turns with message/send. Because an A2A turn blocks until it is genuinely your turn, the session runs on one background asyncio task and the MCP tools are small, bounded polls over it — so a tool call never hangs.

validator.validate_agent_card fetches the raw card, parses it into the a2a-sdk AgentCard model (the authoritative "can this connector drive it?" check), then runs the standard-A2A structural checks (required fields, tolerant of both the supportedInterfaces and legacy top-level url shapes) and reports the capabilities.streaming capability.

Standalone

This package imports neither a2a_games nor a2a_raid_mcp (its game-specific sibling) — its only dependencies are the public mcp, a2a-sdk (pinned ==1.1.0), and httpx — so it is reusable against any A2A endpoint. It is published to PyPI and developed in the open here.

Development

uv sync --frozen --extra dev
uv run --frozen pytest -q

--frozen is deliberate: it installs exactly what uv.lock pins and fails if the lock has drifted from pyproject.toml. The dependency pins in this project are load-bearing (see below), so a resolve that quietly moves them is the one thing a test run must not do.

Security

Every push and pull request runs the test suite on Python 3.11 and 3.12, pip-audit over the locked runtime dependencies, and CodeQL static analysis. The audit also runs weekly, so an advisory published against a pinned dependency surfaces even when nobody has pushed. Results are in this repository's Actions and Security tabs.

There is no LLM and no API key in this server, and no telemetry. A bearer token is optional; when you supply one it lives only in memory for the life of the session, is sent as an Authorization header to the endpoint you named, and is never written to disk, to a log line, or into any tool's return value. The connector contacts no host other than the one you point it at.

To report a vulnerability, see SECURITY.md - please use a private advisory rather than a public issue.

Two pins that look like neglect and are not

mcp is capped below 2.0 and a2a-sdk is pinned exactly. Both are deliberate, both are explained in pyproject.toml and SECURITY.md, and tests/test_packaging.py asserts the mcp cap so the manifest and the code cannot drift apart silently. Please don't lift either in a drive-by pull request - under mcp 2.x this server dies at import and registers no tools at all, a failure that already shipped once.

License

MIT © 2026 Alvin Tay

Available Tools

6 tools
a2a_connectA

Connect to a standard A2A endpoint and start streaming its turns. Validates the Agent Card first and REFUSES to connect if it isn't usable (returns the validator report). On success, starts a background session and returns immediately — then call a2a_wait_turn for the first prompt. bearer is optional (pass it only if the endpoint requires auth). Neither the card URL's contents nor the bearer are echoed back.

Inputs: agent_card_url (required), bearer. Returns: result

a2a_leaveA

Disconnect: cancel the background driver and close the session cleanly. Safe to call even if not connected.

Inputs: no named parameters. Returns: result

a2a_sendA

Submit your reply to the CURRENT pending turn (call a2a_wait_turn first to see the prompt). Returns immediately; call a2a_wait_turn again for the next turn. Rejected if it isn't your turn yet.

Inputs: message (required). Returns: result

a2a_statusA

A quick snapshot: connected? a turn pending? session over? any error? Useful to re-orient after a gap in the conversation.

Inputs: no named parameters. Returns: result

a2a_validateA

Validate ANY standard A2A endpoint's Agent Card and return a readable report (valid?/checks/warnings). agent_card_url is the full served card URL (e.g. .../.well-known/agent-card.json); bearer is optional (only needed if the card route requires auth). Nothing is connected or sent — this only fetches and inspects the card. The bearer is never echoed back.

Inputs: agent_card_url (required), bearer. Returns: result

a2a_wait_turnA

Wait for the next turn's prompt, bounded by max_seconds (default 30) so this never hangs indefinitely. Returns the prompt text once it's your turn, "the session is over." once the remote agent finishes, an "Error: ..." string if the session broke, or "No turn yet — call a2a_wait_turn again." if the window elapsed first (just call it again). Show whatever this returns to your human and get their actual reply before calling a2a_send.

Inputs: max_seconds. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.5/5.0

    Scored across 6 tools

    Disambiguation5/5

    Each tool has a distinct responsibility: validate checks the Agent Card, connect establishes the session, send/wait_turn handle messaging, status reports state, and leave tears down. No functional overlap or ambiguity exists.

    Naming Consistency4/5

    All tools use the a2a_ prefix and mostly use verb-led names like connect, send, leave, and validate. The sole exception is a2a_status, which is a noun rather than an imperative verb, but it remains clear and aligned with the overall pattern.

    Tool Count5/5

    Six tools is appropriate for a focused A2A connector: validation, connection, turn-based messaging, status polling, and disconnection. The toolset is lean without missing necessary lifecycle operations.

    Completeness5/5

    The toolset covers the full A2A session lifecycle: validate, connect, send, wait for turn, check status, and leave. No essential operation for interacting with a remote agent over this protocol appears to be missing.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers