a2a-mcp-bridge
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@a2a-mcp-bridgeAsk the A2A agent what its capabilities are."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
a2a-mcp-bridge
Expose any A2A (Agent2Agent) agent to Claude — and any other MCP client — over stdio or HTTP.
Point it at an A2A endpoint and the agent shows up as four callable tools. The bridge handles the parts of A2A that don't map cleanly onto MCP: multi-turn memory for stateless deployments, long-running turns that would otherwise look like a hang, and responses that interleave the agent's internal reasoning with its actual answer.
MCP client ──stdio/HTTP──▶ a2a-mcp-bridge ──JSON-RPC──▶ A2A agentInstall
git clone https://github.com/parampratap-star/a2a-mcp-bridge.git
cd a2a-mcp-bridge
npm installNode 18 or newer.
Related MCP server: ejentum-mcp
Configure
Two variables are required. There is no default endpoint — a baked-in one would point at someone else's agent.
cp .env.example .envA2A_BASE_URL=https://your-a2a-host.example.com
A2A_AGENT_PATH=/api-endpoint/your-agentThe bridge derives three URLs from those:
Derived | Used for |
|
|
| streaming, where the deployment supports it |
| capability discovery |
Start either entrypoint without these and it exits 78 with setup instructions rather than failing at the first request.
See .env.example for the full list, including auth, timeouts, and history limits.
Connect it to Claude
Add to your MCP client config (for Claude Desktop, claude_desktop_config.json):
{
"mcpServers": {
"my-a2a-agent": {
"command": "node",
"args": ["/absolute/path/to/a2a-mcp-bridge/server.js"],
"env": {
"A2A_BASE_URL": "https://your-a2a-host.example.com",
"A2A_AGENT_PATH": "/api-endpoint/your-agent",
"A2A_AGENT_LABEL": "My Agent",
"A2A_AGENT_DESCRIPTION": "Answers questions about our internal platform."
}
}
}
}env is not optional. MCP clients spawn the server with a minimal environment rather than inheriting your shell, so anything the bridge needs has to be declared here.
A2A_AGENT_LABEL and A2A_AGENT_DESCRIPTION are worth setting: they become the tool's title and description, which is what the model reads when deciding whether to reach for it.
Tools
Tool | What it does |
| Send a message, get the reply. Keeps multi-turn context automatically. |
| Full detail of the last turn — every internal tool call, citations, raw parts. |
| The agent's declared capabilities, skills, and security schemes. |
| Clear the stored transcript. |
ask_agent returns structured content alongside the text: answer, tool_calls[], citations, followups, data, partial, context_id, turn, elapsed_ms.
What the bridge actually handles
Three things make A2A awkward to consume directly from MCP, and each is a deliberate piece of this codebase rather than an accident.
Stateless deployments still get multi-turn memory. Some A2A servers echo contextId back but never reload prior turns — every message/send arrives cold. Verified against the reference deployment: seeding a fact and asking for it again with a matching contextId, taskId, or parentMessageId all failed to recall it. So the transcript is kept client-side in conversation.js and replayed as context, bounded by turn count and character budget. Pass include_history: false to send a bare message instead.
Long turns don't look like hangs. A turn that invokes the agent's own tools runs 15–60 seconds. MCP clients reset their request timeout on each progress notification, so the bridge ticks every 5s while a call is in flight — but only for clients that sent a progressToken, per the spec.
Reasoning is separated from the answer. A response is a sequence of parts: internal tool invocations arrive first as THOUGHT parts, then the answer, then data blocks carrying citations. Concatenating them yields a reply that opens with "Getting help from the tool…" and ends in a JSON blob. normalizeResult splits them into a trace, an answer, and citations.
There's a wrinkle worth knowing about: some turns put the real answer inside a part tagged THOUGHT, leaving no answer part at all. The bridge promotes such a part only when it clears two independent guards — it doesn't open in a first-person deliberation register, and it isn't flagged parallelToolCallEnabled. Both must pass, so the failure mode is an empty answer rather than the model's reasoning leaking out as its reply.
HTTP transport
npm run start:httpRoute | Transport |
| Legacy SSE |
| Streamable HTTP |
| Liveness and session counts |
Binds 127.0.0.1:3737 by default (MCP_HOST, MCP_PORT).
Origin checking is on by default. A server bound to loopback is still reachable by any page your browser visits — a hostile site can point a hostname it controls at 127.0.0.1 and become same-origin, then drive every tool here. Requests carrying a non-local Origin get a 403. Browserless clients send no Origin and are unaffected. Set MCP_ALLOWED_ORIGINS to a comma-separated list to permit specific origins, or * to disable the check.
Idle Streamable HTTP sessions are reaped after MCP_SESSION_TTL_MS (default 30 min), since the spec makes the client's DELETE optional. The SSE stream emits a keepalive comment every 20s to stay under undici's ~5-minute body-inactivity timeout, which otherwise kills the stream with Body Timeout Error.
Tests
npm testFully offline — the suite covers the response normaliser, conversation memory, and config validation without needing an endpoint. CI runs it on Node 18, 20, 22, and 24.
The scripts/smoke-* entries hit a real endpoint and need configuration:
npm run smoke:mcp # full stdio handshake against a live agent
npm run smoke:http # both HTTP transportsWorked example
This was built against a UnifyApps A2A deployment. A real configuration looks like:
A2A_BASE_URL=https://<your-org-host>
A2A_AGENT_PATH=/api-endpoint/<your-agent-slug>
A2A_AGENT_LABEL=AI-FDE
A2A_AGENT_DESCRIPTION=Helps build UnifyApps solutions — data objects, automations, workflows, integrations, and connectors.Find your own values in the agent's URL: everything up to the host is A2A_BASE_URL, and the path segment identifying the agent is A2A_AGENT_PATH. Confirm the pair resolves by fetching ${A2A_BASE_URL}${A2A_AGENT_PATH}/.well-known/agent-card.json — if that returns an agent card, the bridge will work.
License
MIT — see LICENSE.
Available Tools
4 toolsask_agentAsk the A2A agentARead-only
Send a message to the A2A agent 'the A2A agent' and get its reply. If the agent calls its own internal tools while answering, those calls are reported alongside the answer. Multi-turn context is preserved automatically across calls; set new_conversation=true to start over. Tool-using turns can take 15-60s. Also returns structured content: answer, tool_calls[{tool,text,parallel,at}], citations, followups, data, partial, context_id, turn, elapsed_ms.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | The message / question to send to the agent. | |
| timeout_ms | No | Override the upstream request timeout (default A2A_TIMEOUT_MS, 180000). | |
| include_history | No | Replay prior turns as context (default true). | |
| new_conversation | No | Discard prior context and start a fresh conversation. | |
| include_followups | No | Append the agent's suggested follow-up questions (default true). | |
| include_tool_calls | No | Append the agent's internal tool-call trace to the reply text (default true). The trace is always available in structured output and via get_last_trace. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly says multi-turn context is preserved automatically across calls and that new_conversation=true discards prior context, implying the tool mutates conversation state. This contradicts the readOnlyHint=true annotation, which declares no side effects. The additional latency and structured-output details are useful, but the contradiction is a serious inconsistency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is five sentences long, purpose-first, and each sentence adds behavior, state, latency, or output details. There is slight redundancy between the tool-call mention and the structured output list, but no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-parameter tool with no output schema, the description covers the operation, state semantics, latency, and return fields. However, the contradiction with readOnlyHint=true leaves the agent with mixed signals about whether the tool has side effects, so it is not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds semantic value by explaining the effect of new_conversation=true and linking the 15-60s tool-using duration to timeout considerations. It does not merely repeat the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific action and resource: 'Send a message to the A2A agent ... and get its reply.' This clearly distinguishes it from siblings like get_last_trace, get_agent_card, and reset_conversation, which are retrieval or reset tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for multi-turn behavior: context is preserved automatically, and new_conversation=true starts over, which tells the agent when to use that parameter. It also warns that tool-using turns can take 15-60s, setting timeout expectations. It does not explicitly route to sibling tools like get_last_trace, but the core usage guidance is present.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_agent_cardGet agent cardARead-only
Fetch the A2A agent card for 'the A2A agent' — its name, version, capabilities, skills, supported input/output modes, and security schemes.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint and openWorldHint annotations already establish that this is a non-mutating read operation. The description adds context by identifying the fixed target agent and the contents of the returned card, but it does not go further into behaviors like error conditions or availability of the document.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that names the action and the resource before listing contents. Every word earns its place, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple, parameterless read tool with annotations clarifying safety and open-world behavior. The description fully conveys what the returned card contains, so an agent has enough context to call it correctly without an output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the input schema contributes nothing. The description compensates by clarifying what the returned artifact is, though there is no parameter information to add.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Fetch') and resource ('the A2A agent card'), and enumerates the contents (name, version, capabilities, skills, I/O modes, security schemes). This clearly distinguishes it from sibling tools like ask_agent or reset_conversation, which address different actions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: whenever an agent needs the A2A agent's metadata or capabilities. However, it does not explicitly state when not to use it or name alternatives such as ask_agent for interactive queries, leaving some routing decisions to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_last_traceInspect the last agent turnARead-only
Return the full detail of the most recent ask_agent turn: every internal tool call the agent made, its citations, structured data blocks, and — with raw=true — the untouched A2A response parts. Use this to see how the agent reached an answer.
| Name | Required | Description | Default |
|---|---|---|---|
| raw | No | Include the untouched A2A JSON result (default false). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey readOnlyHint=true, and the description adds meaningful behavioral detail: it returns the full last-turn trace including internal tool calls and citations, and raw=true exposes untouched A2A response parts. This goes beyond what annotations provide, though it does not cover edge cases like absence of a prior turn.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The primary result is stated first, followed by the specific use case. Every word contributes to understanding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter read-only tool, the description covers what is returned and why an agent would use it. It does not describe what happens if there is no prior ask_agent turn, but given the low complexity and annotations, the definition is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single boolean parameter raw is already described as 'Include the untouched A2A JSON result (default false).' The description mostly restates this with 'raw=true' and 'untouched A2A response parts,' adding little semantic value beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Return'), a specific resource ('most recent ask_agent turn'), and enumerates the content returned (internal tool calls, citations, structured data blocks). This clearly differentiates it from sibling tools like ask_agent and reset_conversation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives an explicit use case: 'Use this to see how the agent reached an answer.' It does not provide exclusion criteria or name alternatives, but the usage context is clear enough for an agent to select it for inspection purposes.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reset_conversationReset conversationA
Clear the stored transcript so the next ask_agent call starts a brand-new conversation.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly says 'Clear the stored transcript,' which is a destructive operation on stored data. However, the annotations declare destructiveHint=false. This is a direct contradiction: clearing/deleting a stored transcript should be marked as destructive. Per the rubric, a description that contradicts annotations receives a score of 1.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence that states the action and its purpose without filler. Every word earns its place, making it an excellent model of concise tool documentation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter tool with no output schema, the description covers the key operational effect: clearing the transcript and resetting the next ask_agent call. It does not mention the return value or failure modes, but the tool is simple enough that this is a minor gap. The contradictory destructiveHint annotation slightly reduces overall confidence.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters to document, so the description does not need to add parameter-level semantics. The baseline of 4 applies because there is nothing for the description to clarify beyond what the empty schema already conveys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Clear'), names the resource ('stored transcript'), and explains the direct consequence for the next ask_agent call. This unambiguously identifies the tool's purpose and distinguishes it from the read-oriented sibling tools like get_last_trace and get_agent_card.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies when to use this tool: when the agent needs a brand-new conversation and should not carry over the previous transcript. It does not explicitly state when not to use it or compare it to alternatives, but the context is unambiguous enough for an agent to select it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v3.0.0- First observed
ask_agent - First observed
get_agent_card - First observed
get_last_trace - First observed
reset_conversation
TDQS
Scored across 4 tools
Each tool serves a clearly distinct purpose: ask_agent for interaction, get_last_trace for inspecting the latest turn, get_agent_card for metadata, and reset_conversation for state management. There is no overlap between them.
All tool names follow the same verb_noun snake_case pattern (ask_agent, get_last_trace, get_agent_card, reset_conversation). The style is uniform and predictable.
Four tools is a well-scoped set for a single-agent bridge. Each tool covers an essential function without redundancy or bloat.
The tool surface covers the full lifecycle of interacting with the A2A agent: sending messages, inspecting agent capabilities, reviewing trace details, and resetting conversation state. No obvious dead ends or missing operations for this narrow domain.
Maintenance
Related MCP Connectors
Discover and call AI agents via MCP. Supports A2A agents and platform agents with async tasks.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
The OpenRouter for tools. One MCP connection gives any AI agent 254 hosted tools, pay per call.
One MCP endpoint for Claude, GPT & Gemini: 100+ tools + no-code connectors + agent workers.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables MCP-compatible clients to interact with deployed Agent5ive agents as tools. Allows users to query agent purposes and send messages to leverage Agent5ive capabilities through natural language.6 npmMIT

ejentum-mcpofficial
AlicenseAqualityDmaintenanceExposes the four Ejentum cognitive harnesses (reasoning, code, anti-deception, memory) as MCP tools any agentic client can call. Drop-in scaffolding that catches LLM failure modes like sycophancy, hallucination, and reasoning shortcuts.440 npm16MIT- AlicenseNot gradedqualityAmaintenanceExposes Agentweaver runs and outcomes as MCP tools for Claude Desktop and compatible clients.1 npm7MIT
- AlicenseAqualityDmaintenanceProvides browser automation, audio transcription, and LLM chat as MCP tools for any agent.7MIT