Interoperability of Coding Tools with MCP and A2A

Última actualización: 05/11/2026
  • MCP standardizes how AI agents discover and invoke tools, resources and prompts, decoupling agents from concrete APIs.
  • A2A defines how independent agents discover each other, exchange tasks and share artifacts over HTTP and JSON-RPC.
  • Combining MCP for tool access and A2A for agent collaboration enables scalable multi-agent architectures across teams and vendors.
  • Real-world adoption raises new challenges in prompt design, security, identity federation and governance that frameworks and gateways must address.

Interoperability between coding tools and AI protocols

AI agents are no longer just fancy chatbots that answer questions in a single window. They are turning into distributed systems that can read and write code, call APIs, coordinate with other services and even negotiate with other agents to get work done. As soon as you go from “one smart assistant” to “a network of agents”, a brutal problem appears: how do all these pieces talk to each other without descending into chaos?

That is exactly the gap that MCP (Model Context Protocol) and A2A (Agent-to-Agent Protocol) are trying to fill. MCP focuses on how an agent connects to tools, data and context, while A2A focuses on how agents communicate and collaborate with each other. They overlap in spirit but operate at different layers. In this article we will go deep into what each one does, how they complement each other, how they are already used in real systems, and what this means for the future of coding tools and multi‑agent architectures.

What MCP really is in practice

At its core, MCP is a standard way to expose tools, resources and prompts to an AI agent so that the agent can call them safely and consistently. Instead of wiring every tool directly into every agent with custom glue code, you expose those tools behind an MCP server, and let MCP clients (the agents) discover and invoke them through a unified protocol.

MCP follows a clear client-server architecture: a host application (like an editor, CLI or agent runtime) embeds an MCP client, and that client opens one‑to‑one connections to one or more MCP servers. Each server is just a lightweight process that exposes a bundle of capabilities – typically tools, read‑only resources and reusable prompts.

The inspiration is very close to Language Server Protocol (LSP). LSP abstracted the problem “editor ↔ language features” so we didn’t have to write custom integrations between every editor and every programming language. If you implement a language server once, any LSP‑compatible editor can talk to it. MCP takes the same idea and applies it to tools and context for LLMs: implement a tool once as an MCP server, and every MCP‑aware agent can use it.

From a transport point of view, MCP is flexible but opinionated enough to be practical. It uses JSON‑RPC 2.0 as the message format and supports multiple transports: stdio for local processes (great for desktop apps and local dev) and HTTP or SSE for remote servers (perfect for Cloud Run or containerized deployments). The protocol also defines how a client discovers capabilities and how tools are described using JSON Schema so that an LLM can decide when and how to call them.

Crucially, MCP does not try to orchestrate your agent’s reasoning. It does not decide when a tool should be invoked, or how tools should be chained. MCP is the wiring layer: it makes tools, resources and prompts available in a structured, discoverable way, leaving the decision‑making to your agent framework, planner or prompt engineering.

Core MCP building blocks: tools, resources and prompts

MCP servers revolve around three main primitives: tools, resources and prompts. These three concepts are enough to cover most real‑world agent needs without turning the protocol into a full orchestration framework.

Tools are discrete actions that an agent can trigger. Think “get_weather”, “search_inventory”, “book_flight”, “run_sql_query” or “get_exchange_rate”. Each tool is declared with a name, a human‑readable description and an input schema. That schema is what lets the LLM understand what parameters it should pass, and it also protects your backend by validating arguments before execution.

Resources represent read‑only data that a server can serve on demand. Files, logs, database rows, documentation snippets, config files – any piece of information that is better modeled as “fetch this thing” than “run this function”. Resources can be large, so MCP defines ways to page and stream them, which is critical when feeding context into a model with a limited window.

Prompts are reusable templates that servers can surface to clients. Instead of hard‑coding long, fragile prompt strings inside your agent, you can centralize them as MCP prompts. The server exposes them with names, descriptions and parameter slots, and the client fills those slots at runtime. This is surprisingly powerful when multiple agents need to share the same patterns for how to talk to a specific tool or follow company‑wide safety and compliance rules.

When a client connects to a server, it performs a capability discovery step. The server responds with a catalog of tools, resources and prompts, each with detailed metadata. That catalog is then fed into the LLM (usually in summarized form) so the model can reason: “I can use get_exchange_rate to answer this question about currency conversion, and I should not attempt to invent the answer.”

Because all of this is declarative, new capabilities can be added or removed without touching the agent’s core logic. Add a new tool to the server, redeploy, and every MCP client that connects will see it at the next capability negotiation. This is the “plug one more USB device” moment for AI tooling.

A concrete MCP example: a currency conversion tool

The currency‑agent demo from Google’s Agent Development Kit (ADK) is a perfect illustration of MCP in action. It starts by building a tiny MCP server that exposes a single tool, get_exchange_rate, backed by the public Frankfurter API. On disk it’s just a small Python script using fastmcp.

The server defines the tool with typed arguments for currency_from, currency_to and currency_date, plus robust logging and error handling. When the agent calls it, the server hits Frankfurter over HTTP, validates the response and returns a JSON payload with the exchange rate or an error object. Nothing about this is AI‑specific; MCP just standardizes how this functionality is described and invoked.

Locally, you run the server with a simple command and it listens on http://localhost:8080. A separate test client, also using MCP, connects, discovers get_exchange_rate and triggers a call for USD → EUR. The log shows the tool invocation, the outgoing HTTP request, the successful response and the returned JSON. From the point of view of your agent, it just asked “what tools do I have?” and then “please call this one”.

Deploying the same server to Cloud Run barely changes the story. You containerize the MCP server, deploy with --no-allow-unauthenticated so it requires IAM‑backed authentication, and then open a secure tunnel from your local machine using the Cloud Run proxy command. Locally, your MCP client still thinks it’s talking to http://127.0.0.1:8080; the proxy handles auth and network hops transparently.

This pattern is powerful in teams: you can run a centralized MCP server for shared tools like currency rates, internal APIs or proprietary databases. Every developer agent in the organization can plug into that server over a secure transport instead of shipping its own slightly different, half‑maintained wrapper around the same API.

Building agents on top of MCP: from single tools to full workflows

MCP becomes really interesting when you embed it into an agent framework like Google’s ADK. In the currency‑agent example, the ADK is used to create a specialized LLM agent whose only job is to answer questions about exchange rates using the MCP tool. The agent’s system instruction literally tells it: “your sole purpose is to use the get_exchange_rate tool”.

The ADK wires this instruction, the chosen model (for example gemini-2.5-flash) and an MCPToolset instance that points to the MCP server URL. From then on, when a user asks “How much is 250 CAD in USD?”, the agent reasons about whether it needs a tool call, fills in the tool parameters, sends the request through MCP and then writes a user‑friendly response using the returned JSON.

The same pattern scales to far more complex agents. Instead of a single currency API you can wire in multiple servers: one for internal databases, another for third‑party SaaS, another for document search, plus a server that exposes reusable prompts or RAG pipelines. MCP doesn’t care whether those servers run locally, on Cloud Run, in Kubernetes or behind a VPN, as long as the transport is supported and authentication is correctly configured.

The ADK also adds an agent‑first perspective that MCP deliberately avoids. It treats agents as composable software components: you can define LLM‑based agents, tool‑heavy agents, evaluation agents and orchestrators, all of them capable of speaking MCP out of the box. The result is that “build an agent” starts looking a lot more like “build a microservice” and a lot less like “tweak an endless prompt in a notebook”.

What A2A is – and why MCP alone is not enough

If MCP is about wiring agents to tools, A2A is about wiring agents to other agents. As soon as you have multiple agents that each know how to do something well, you need a way for them to find each other, exchange tasks and stay in sync while work is in flight. That is the problem space A2A is designed for.

A2A, initiated by Google Cloud and now under the Linux Foundation, is an open standard for agent‑to‑agent interoperability. It uses familiar technologies (HTTP(S), JSON‑RPC 2.0, and SSE for streaming) but wraps them in a domain model that understands agents, skills, tasks, artifacts and capabilities. Instead of “tool calls”, you get a higher‑level language of collaboration.

The two core ideas in A2A are Agent Cards and Tasks. An Agent Card is a JSON document – usually discoverable at /.well-known/agent.json – that describes what an agent can do, how to reach it, what authentication it expects and what input/output modes it supports. Tasks are the units of work that one agent can send to another, with a well‑defined lifecycle and structured results.

In an A2A interaction, one agent takes the role of “client agent” and another acts as the “remote agent”. The client discovers the remote agent’s card, decides whether this is the right partner for the job, and then creates a task request. The remote agent receives the task, uses its own LLM and internal tools (often via MCP) to execute it, and then streams back progress updates and final artifacts.

This design makes A2A natively point‑to‑point, asynchronous and network‑friendly. Under the hood, Python implementations build on ASGI frameworks like Starlette (via A2AStarletteApplication) and uvicorn, with artifacts and task updates flowing over JSON‑RPC and SSE. That means tasks can run for seconds or hours without blocking a single HTTP request, which is essential for real‑world multi‑agent workflows.

An A2A example: exposing a “Hello” agent and beyond

The canonical A2A “HelloWorldAgent” shows the mechanics in a stripped‑down form. You define an AgentExecutor subclass that implements an execute method. Inside, you enqueue a single text message – “Hello from A2A!” – onto the event queue as the outcome of the task. Cancellation becomes a no‑op for this simple case, but the hook exists for real workloads.

Next you create an AgentSkill describing what this agent can do. In the example, the skill hello carries a name, description, a set of tags and representative user queries. That skill then gets bundled into an AgentCard along with the agent’s name, version, URL, capabilities and supported input/output modes.

Finally, you wire everything into an A2AStarletteApplication with a DefaultRequestHandler and run it under uvicorn. As far as the outside world is concerned, you now have a fully fledged A2A agent listening on http://localhost:9000. Any client that supports A2A can fetch /.well-known/agent.json, understand what this agent offers, and send it tasks.

In more realistic deployments, the same pattern scales out to orchestration scenarios like travel booking, onboarding or support automation. A “Travel Agent” might discover and talk to a “Flights Agent”, “Hotels Agent” and “Car Rentals Agent”, each running behind its own A2A endpoint and hiding its internal tooling and vendor‑specific API contracts. The Travel Agent just sees tasks, skills and artifacts.

This is where A2A’s separation of concerns shines. Every downstream agent can choose its own models, frameworks and tools – a hotel agent built with ADK and MCP, an airline agent built with another stack, a car rental agent sitting in a partner’s infrastructure – and all still collaborate cleanly through the A2A surface.

Bringing MCP and A2A together in one architecture

On paper the split sounds neat – MCP for tools, A2A for agents – but in practice the boundaries blur fast. Real systems often want to hide A2A behind MCP, layer MCP inside A2A, or mix both in the same process. The official A2A samples even wrap A2A communication as MCP tools exposed from a single server, so that an LLM sees “one MCP toolset” instead of two parallel protocol stacks.

One common pattern is to treat MCP as the internal wiring of each agent and A2A as the external network between agents. Inside an agent, your LLM calls MCP tools to hit databases, APIs or document stores. Outside, your orchestrator talks to that agent via A2A, handing off tasks and reading artifacts back. From the orchestrator’s perspective, the agent is a black box service with a clean, typed interface.

The reverse pattern – surfacing A2A as MCP tools – is attractive from an integration point of view. Many LLM providers already have polished tooling around MCP: devtools, UI demos, SDKs and security guides. By exposing “contact remote agent X” as a single MCP tool, you let the LLM trigger an A2A interaction with minimal setup. You only register one MCP server, but under the hood, that server can be brokering tasks across a whole A2A network.

This is exactly what some example repos demonstrate: instead of wiring every remote A2A agent directly into the model, an MCP server offers a compact set of tools that themselves talk A2A. That breaks the naive mental model (“MCP and A2A must be totally separate”) but massively simplifies practical integration and keeps your LLM interface surface small and well‑curated.

There is also nothing stopping you from using MCP and A2A in isolation where it makes sense. Plenty of projects will only ever need MCP to connect a single agent to a handful of tools. Others, especially when stitching together vendors or internal teams, will lean heavily on A2A for cross‑organizational coordination while using their own internal wiring instead of MCP. The important point is that the protocols don’t compete – they compose.

Interoperability, frameworks and the missing “big structure”

Protocols alone don’t guarantee interoperability if everyone embeds them into wildly different higher‑level architectures. You can speak perfect MCP and A2A and still end up with a zoo of mutually incompatible agent patterns that each reinvent planning, memory, error handling and governance.

The likely next step in the ecosystem is a layer of frameworks built on top of MCP and A2A that standardize not just the wires, but the larger structure. Think of how web frameworks emerged on top of HTTP or how ORMs built on top of SQL. We are starting to see this with ADK, LangGraph‑like orchestrators, managed platforms such as Vertex AI Agent Engine and AI gateways that understand both protocols.

Once the industry converges on a handful of pragmatic patterns – “this is how you structure a multi‑agent workflow over A2A and MCP”, “this is how you expose teams’ tooling behind MCP” – the hand‑wringing about whether something “should be behind MCP or A2A” will start to fade away. Most builders will just pick a framework, plug in a server or two, and get sane defaults.

The trickier, slower problem is prompt engineering and prompt interoperability. Even with perfect protocols, when you connect systems via MCP and A2A you are effectively allowing arbitrary prompts – system instructions, tool descriptions, safety rails – to leak and interact across boundaries. If those prompts are misaligned, redundant or flat‑out contradictory, your performance suffers long before security concerns arise.

In practice, badly designed prompts and instructions across an MCP + A2A stack can produce massive latency, hallucination and instability. Each agent may be locally “well‑prompted”, but when you layer them, flows can become brittle: tools are mis‑prioritized, context windows are wasted and user‑level expectations are broken. A2A can coordinate tasks, MCP can expose tools, but neither forces you to keep prompts coherent.

This is why teams that have actually shipped LLM products at scale tend to treat prompt engineering as a first‑class engineering concern, not a last‑minute tweak. Business stakeholders often see prompts as a magical way to fix everything; engineers sometimes dismiss prompts as a secondary detail compared to code. Reality sits in the middle: prompts won’t make a bad system good, but sloppy prompts can absolutely tank an otherwise solid architecture.

Security, identity and governance across MCP and A2A

Once you start letting agents act on behalf of humans across MCP and A2A boundaries, identity and authorization quickly become central problems. A single request might traverse several layers of delegation: a user talks to an orchestrator agent, which calls a tool over MCP, which internally invokes other MCP servers or A2A agents that require separate credentials.

Concrete scenarios pop up everywhere: a SaaS app exposes an MCP server that needs OAuth tokens; an internal HR agent behind A2A consumes corporate LDAP identities; a third‑party analytics tool uses its own SSO. The user expects “log in once and get things done”, but behind the scenes multiple identity systems must be federated.

Google’s A2A docs explicitly call out multi‑identity federation as a core challenge. A user U might be interacting with Agent A that requires system A’s identity (say, enterprise LDAP), while Agent A internally needs to delegate to Agent B that requires system B’s identity (say, an external SaaS provider). Protocols have to support carrying and scoping these identities without forcing users to re‑authenticate manually for every hop.

Identity providers and OAuth/OIDC platforms are quickly adapting to this new reality. Infrastructure like Logto, Auth0 or in‑house identity providers can already issue tokens that agents carry through MCP and A2A calls. The open question is not whether this is possible – it clearly is – but how we standardize patterns so that a tool built today doesn’t become a security or governance liability tomorrow.

On top of auth, observability and policy enforcement will likely move into shared “agent gateways”. Those gateways can terminate MCP and A2A traffic, centralize logging, enforce rate limits, attach user and agent identities and even filter which tools or agents are accessible in which contexts. This starts looking a lot like API gateways – just tuned for AI traffic instead of vanilla HTTP.

Stepping back, MCP and A2A are quietly reshaping how we think about software integration and coding tools. For developers, a coding assistant plugged into MCP and ACP (the Agent Client Protocol for IDEs) can discover tools, call language servers, integrate with version control and talk to other coders’ agents – all via standard protocols. For enterprises, multi‑agent systems can interoperate across teams and vendors without rewiring everything for each new use case.

The long‑term shift is from “hard‑wired apps” to “agent ecosystems”. Just as USB and HTTP made it possible to connect arbitrary devices and services, MCP and A2A aim to make tools and agents pluggable. The winners will be the teams that treat these protocols not as shiny logos, but as foundational infrastructure for how their systems talk, collaborate and evolve over time.

Related posts: