a2a-mcp-bridge
A minimal MCP server that bridges MCP clients(Claude Desktop, etc.) to A2A agents — built directly ona2a-sdk 0.3.26+, so it speaks the A2Aprotocol version that current agent servers (e.g. Google ADK's to_a2a) actuallyimplement.
Stateless by design: no registry file, no local persistence, nothing written todisk. Each call opens a connection, does the round trip, and returns — so it neverhits the file-permission traps that registry/cache-based bridges run into onlocked-down or sandboxed clients.
Why this exists
The most visible community bridge, PyPI's a2a-mcp-server, does not depend ona2a-sdk at all — it vendors a hand-copied client from the pre-1.0 draft A2Aprotocol. Its hardcoded JSON-RPC methods are tasks/send, tasks/sendSubscribe,tasks/get, tasks/cancel, tasks/pushNotification/{get,set}.
Current a2a-sdk (0.3.26+) servers use a different method set entirely:message/send, message/stream, tasks/get, tasks/cancel,tasks/pushNotificationConfig/{get,set,list,delete}, tasks/resubscribe,agent/getAuthenticatedExtendedCard.
Point the old bridge at a modern A2A server and every call fails with-32601 Method not found — the server has genuinely never heard of tasks/send.This isn't a version skew you can fix by bumping a pin; the dialect changed.a2a-mcp-bridge sidesteps the problem by using a2a-sdk's own client(ClientFactory, send_message), so it always speaks whatever protocol the SDKyou install implements.
Install
Option A — uvx, no clone, no install:
uvx --from git+https://github.com/ytugarev/a2a-mcp-bridge a2a-mcp-bridge
Option B — pip, from source:
git clone https://github.com/ytugarev/a2a-mcp-bridge
cd a2a-mcp-bridge
pip install -e .
Option C — single file, zero install: src/a2a_mcp_bridge/server.py carries aPEP 723 inline metadata header, so you candownload that one file and run it directly with uv — uv resolves and cachesits dependencies on first launch, no pip install and no venv to manage:
uv run --script /absolute/path/to/server.py
Configure
Two environment variables, both optional:
| Variable | Default | Purpose |
|---|---|---|
A2A_AGENT_URL |
http://localhost:8001 |
Default A2A agent endpoint (also overridable per tool call) |
A2A_TIMEOUT_SECONDS |
300 |
HTTP client timeout — raise this for slow/long-running agents |
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"a2a-bridge": {
"command": "a2a-mcp-bridge",
"env": {
"A2A_AGENT_URL": "http://192.168.1.50:8001"
}
}
}
}
Using the single-file uv run --script form instead (Option C above):
{
"mcpServers": {
"a2a-bridge": {
"command": "/absolute/path/to/uv",
"args": ["run", "--script", "/absolute/path/to/server.py"],
"env": {
"A2A_AGENT_URL": "http://192.168.1.50:8001"
}
}
}
}
Both command and every path in args must be absolute. MCP clients launchserver subprocesses with the working directory set to some system default (onWindows, Claude Desktop uses C:\WINDOWS\System32) and often a stripped PATH,so a bare "uv" or a relative "server.py" will silently fail to resolve —this is the single most common setup error with this bridge (and MCP servers ingeneral), not a bug in the bridge itself. On Windows, also double check youractual config path: Store-installed Claude Desktop keeps it underAppData\Local\Packages\<package-id>\LocalCache\Roaming\Claude\, not the%APPDATA%\Claude path most docs assume.
Tools exposed
get_agent_card(agent_url?)— fetches the target agent's name,description, and skills from its/.well-known/agent.jsoncard.send_a2a_message(message, agent_url?)— sends a message to the agentand returns its final text response. Runs non-streaming so the client getsone clean answer per call, even if the underlying agent takes minutes.
Both tools accept an optional agent_url override, so a single bridgeinstance can talk to multiple agents if needed.
Requirements
- Python 3.10+
- An A2A server speaking
a2a-sdk0.3.26+ semantics (e.g. Google ADK'sto_a2a, or anything else built on the same SDK)
Development
pip install -e ".[dev]"
pytest
License
MIT — see LICENSE.