A2A + MCP Interoperability Gateway: Cross-Framework Agent Communication with Google ADK & LangGraph
Agents speak two protocols: MCP for tools and A2A for agents. This workflow builds a FastAPI interoperability gateway that bridges Google ADK and LangGraph, exposing A2A inbound while multiplexing shared MCP tool servers to both frameworks.
Deepak Bagada
CEO, SaaSNext
- MCP solves agent-to-tool connectivity on A2A solves agent-to-agent collaboration; a gateway, not a single protocol, is needed for heterogeneous fleets.
- Make the gateway an A2A endpoint and an MCP client simultaneously so ADK and LangGraph share one tool registry with zero per-framework glue.
- Use stable task lifecycle states and idempotency keys to make cross-protocol handoffs survive timeouts, retries, and duplicate delegation.
A2A + MCP Interoperability Gateway: Cross-Framework Agent Communication with Google ADK & LangGraph
By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.
The two-protocol reality of 2026 agents
Agentic systems today speak two different languages, and they are not mutually intelligible out of the box. MCP (Model Context Protocol), the Anthropic-originated standard now cared for by the Linux Foundation, is the lingua franca for agents talking to tools and data sources. A2A (Agent2Agent), the protocol Google launched and also donated to the Linux Foundation, is the lingua franca for agents talking to other agents.
The moment you try to build a heterogeneous fleet — a LangGraph agent on the research track, a Google ADK agent on the recommendation track, and a CrewAI agent on the writing track — you discover that MCP answers "where are my tools?" while A2A answers "who can finish this task?" They solve adjacent problems, and production systems need both, bridged by a gateway.
This article designs a production-grade A2A + MCP interoperability gateway that lets an ADK agent and a LangGraph agent discover each other, exchange shared task cards, and route to shared MCP tool servers, without either framework being rewritten.
Understanding the two standards
| Aspect | MCP (Model Context Protocol) | A2A (Agent2Agent) |
|---|---|---|
| Solves | Agent-to-tool connectivity | Agent-to-agent collaboration |
| Core abstraction | Resources, Tools, Prompts | AgentCard, Task, Message, Artifact |
| Transport | stdio, Streamable HTTP, SSE | HTTP + JSON-RPC (streaming SRP) |
| Lifecycle | Client connects to tool server | Agent publishes card; client claims task |
| Use case | Files, DBs, search APIs, cloud services | Handoffs, chained reasoning, delegation |
MCP is a client-server tool brokerage; A2A is a peer-to-peer task handoff protocol. The gateway in this project normalizes both so that an ADK agent can invoke a LangGraph agent through the same task-shaped interface it uses for its own agents, and both can sit in front of the same MCP tool servers.
Interoperability gateway architecture
+--------------------------------------------------------------+
| ADMIN / CLI / WEB U.I |
+------------------+-------------------------------------------+-
|
v
+-------------------------------+
| INTEROP GATEWAY (FastAPI) |
| - A2A server root (/a2a) |
| - A2A client for upstream |
| - MCP client (Streamable HTTP)|
| - Task lifecycle + transport |
+----------+----------+---------+----------+---------------+
| A2A | A2A | MCP client
v v v
+------------------------+ +-------------------+
| ADK AGENT (Google) | | LangGraph agent |
| A2A support built-in | | A2A adapter |
+------------------------+ +-------------------+
| |
v v
+---------------------------------+
| MCP TOOL SERVERS (stdio/HTTP) |
| - Slack MCP - Arxiv MCP |
| - DB MCP - Search MCP |
+---------------------------------+
The gateway is deliberately model- and framework-neutral. It exposes A2A to inbound clients, talks A2A to the ADK agent, translates A2A tasks into execution inside a LangGraph workflow, and is itself an MCP client that hands shared tools to both agents. Every handoff is recorded as a task with a stable lifecycle so any of them can fault, timeout, or be cancelled without corrupting the others.
Project layout
interop/
├── .env
├── gateway/
│ ├── schemas.py
│ ├── mcp_client.py
│ └── a2a_server.py
├── agents/
│ ├── adk_agent.py
│ ├── langgraph_tools.py
│ └── langgraph_graph.py
├── main.py
└── requirements.txt
Environment configuration
# .env
A2A_ENDPOINT=https://api.example.com/a2a
AGENT_SERVICE_URL=https://internal.agents.example.com
MCP_FILE_SERVER=mcp://file-server.internal:9000
MCP_ARXIV_SERVER=http://mcp-arxiv.internal
GOOGLE_API_KEY=AIza...
OPENAI_API_KEY=sk-...
GATEWAY_API_KEY=gw-secret-123
LANGFUSE_HOST=https://cloud.langfuse.com
LOG_LEVEL=INFO
A2A task and message schemas
A2A centers on the Task object: an agent accepts a task, produces messages, and optionally yields artifacts. Validation is strict so the gateway never forwards malformed handoffs.
# gateway/schemas.py
from typing import Optional
from pydantic import BaseModel, Field
from enum import Enum
class TaskState(str, Enum):
SUBMITTED = "submitted"
WORKING = "working"
INPUT_REQUIRED = "input-required"
COMPLETED = "completed"
CANCELED = "canceled"
FAILED = "failed"
class MessageRole(str, Enum):
USER = "user"
AGENT = "agent"
class TaskMessage(BaseModel):
role: TaskRole = TaskRole.AGENT
parts: list[dict] = Field(default_factory=list)
class Task(BaseModel):
id: str
session_id: str
agent_id: str
state: TaskState = TaskState.SUBMITTED
messages: list[TaskMessage] = Field(default_factory=list)
artifacts: list[str] = Field(default_factory=list)
MCP client that both agents share
MCP streamable HTTP keeps a stable session with the tool servers. The gateway owns these sessions and multiplexes them to ADK and LangGraph, so both agents transparently see the same tool universe.
# gateway/mcp.py
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client
async def connect(server_url: str, headers: dict):
async with streamablehttp_client(server_url, headers=headers) as (read, write, get_session_id):
async with ClientSession(read, write, get_session_id, headers=headers) as session:
await session.initialize()
tools = await session.list_tools()
return {t.name: t for t in tools.tools}
mcp list over each configured server URL registers the union of tools. Both the ADK agent and the LangGraph node route to this shared registry, which means tool additions at one MCP server propagate to every framework in the fleet with zero per-framework glue.
Google ADK agent with built-in A2A
Google's Agent Development Kit ships with an A2A server adapter out of the box, which is why ADK is the reference end of this gateway. The agent subscribes to MCP tools through ADK's McpToolset.
# agents/adk_agent.py
from google.adk.agents import LlmAgent
from google.adk.tools import mcp_toolset
from google.adk.sessions import InMemorySessionService
adk_agent = LlmAgent(
name="recommender",
model="gemini-2.5-pro",
instruction="You return ranked finance recommendations. Delegate research via A2A.",
tools=mcp_toolset.McpToolset(
tools=[
mcp_toolset.StreamableHttpMcpTool("TrendRank", "http://mcp-trends:9000"),
]
),
session_service=InMemorySessionService(),
)
The A2A server adapter in ADK publishes an AgentCard so the gateway and the LangGraph agent can discover recommender as a capable peer. No custom A2A JSON-RPC boilerplate is required on the ADK side; the SDK handles the transport.
The gateway receives a task and fans out
# agents/langgraph.py
from langgraph.graph import StateGraph, START, END
from langgraph.checkpoint.memory import MemorySaver
def build_langgraph(state):
g = StateGraph(dict)
g.add_node("research", research_node)
g.add_node("recommend", recommend_node)
g.add_node("synthesize", synthesize_node)
g.add_edge(START, "research")
g.add_edge("research", "recommend")
g.add_edge("recommend", "synthesize")
g.add_edge("synthesize", END)
return g.compile(checkpointer=MemorySaver())
The gateway maps an A2A Task onto the graph: it invokes graph.ainvoke(state, config={"thread_id": task.id}), streams astream_events back as A2A TaskMessages, and closes the task as COMPLETED when the final update lands. A2A is transport, LangGraph is execution — the gateway is the translator that keeps them decoupled.
Retry rules and error handling
Cross-protocol failures have a third class beyond typical service faults: translation failures, where an A2A artifact cannot be mapped to a LangGraph state field, or an MCP tool result cannot be encoded back into an A2A artifact.
# gateway/a2a_server.py
import asyncio
from typing import Optional
async def run_task_with_retry(task: Task, executor, max_attempts: int = 4) -> Task:
for attempt in range(max_attempts):
state_ = task.state.value
if state_ in (TaskState.COMPLETED.value, TaskState.CANCELED.value):
return task
if state_ == TaskState.FAILED.value and attempt == max_attempts - 1:
raise task.latest_exception
try:
result = await asyncio.wait_for(executor(task), timeout=90)
task.state = TaskState.COMPLETED
return task
except asyncio.TimeoutError:
task.state = TaskState.SUBMITTED
except TranslationError:
task.state = TaskState.INPUT_REQUIRED
except ModelError as exc:
task.state = TaskState.FAILED
task.latest_exception = exc
return task
| Failure | A2A state | Strategy |
|---|---|---|
| Tool timeout (>90s) | resubmit | Retry with+1 attempt on a fresh thread |
| Artifact/state mismatch | INPUT_REQUIRED | Ask the source agent for a structured artifact |
| MCP server down | FAILED | Circuit-breaker 30s, then fail the peer task |
| Duplicate delegation | dedup by task id | Idempotency keys on the gateway |
Everything is idempotent: tasks carry stable IDs, and the gateway holds a task ledger so replays do not double-execute side effects such as writes or notifications.
A2A vs MCP: which to add first
| Need | Protocol | When to adopt |
|---|---|---|
| Call a database, API, or file server | MCP | Immediately |
| Chain two LLM agents built in different frameworks | A2A | As soon as you have 2+ agents |
| Let a third-party agent call our tools | MCP server | Turnkey integrations |
| Let a third-party agent delegate work to us | A2A server | Open a fleet |
From gateway to durable execution
Now that the A2A/MCP gateway gives you clean cross-framework transport, the last missing capability is durability. Continue this journey in event-sourced durable agent execution with checkpointing to make every handoff resumable across crashes. You can also audit the growing MCP server directory to find the tool servers worth wiring into the gateway, and keep an eye on the latest agent protocol news for A2A and MCP spec releases.
Key takeaways
A gateway researched around A2A for task handoff and MCP for tool access decouples your fleet from any one framework. ADK and LangGraph remain first-class citizens; the gateway is the only component that knows both protocols, which keeps the rest of your stack simple and portable.
- Adopt MCP for tools, A2A for agents, and a gateway for translation — do not try to force one protocol to do the other's job.
- Pipe every task through a stable lifecycle (submitted -> working -> completed | failed | canceled) so timeouts and retries are deterministic.
- Make the gateway an MCP client and an A2A endpoint at the same time, so both ADK and LangGraph share one tool registry.
By Deepak Bagada, CEO at SaaSNext & Principal AI Architect.
Enjoyed this breakdown? Get our morning dispatch in your inbox.
Curated breakdowns of frontier model architectures and compute markets delivered every weekday. Zero fluff.
Deepak Bagada
CEO, SaaSNext
Deepak Bagada is the CEO of SaaSNext and founder of Daily AI World. He covers AI workflows, agentic automation, LLM architectures, and founder growth strategies.
Cursor 2026 Agent Mode & Google Workspace Plugins: Multi-File Automated Code Execution Architecture
Next Story →Google ADK in 2026: Enterprise Multi-Agent Systems with Native A2A Protocol & Multimodal Agents
Related Intelligence Analysis
The Step-by-Step Guide to Automating Meeting Tasks with Whisper
You're spending 45 minutes after every client meeting typing up notes and manually assigning tasks in Jira. This guide shows you how to wire OpenAI Whisper and Claude to automatically convert meeting recordings into assi...
Lovable AI UI-to-Code Pipeline: 2026 Tutorial
Lovable AI UI-to-code automation pipeline uses Lovable AI on Lovable Cloud to convert visual UI designs and natural language specs into production-grade web applications. UI/UX designers and frontend developers bridging...
Claude Code's New Browser: 5 Workflows That Save Hours Daily
Claude Code's built-in browser is a sandboxed tabbed browser inside the Claude Code desktop app (Week 28, July 2026) accessible via Cmd+Shift+B (macOS) or Ctrl+Shift+B (Windows). It lets Claude open websites, read docume...