Skip to main content

Command Palette

Search for a command to run...

Bridging Google ADK and MCP: Building Framework-Agnostic AI Tools

Updated
5 min read
D
Fullstack Software Engineer specialising in cloud architecture, system design, and AI. I write deep dives on building production systems — the decisions, the tradeoffs, and the reasoning behind them. No fluff, no tutorials you've seen a hundred times.

Introduction

The AI agent ecosystem is fragmented. Every framework — LangChain, Google ADK, CrewAI, AutoGen — has its own tool format, its own abstractions, and its own way of connecting agents to capabilities. If you build tools for one framework, you typically can't use them in another without rewriting them.

The Model Context Protocol (MCP) exists to fix this. MCP is an open standard that defines how agents and tools communicate — independent of the framework on either side. This post walks through a project that demonstrates exactly that: a custom MCP server that wraps Google ADK tools and exposes them to any MCP-compatible client.


The problem with tightly coupled tools

When you define a tool directly inside an ADK agent, it's coupled to that agent. If you want to use the same tool in a different agent, a different framework, or a different process, you have to rewrite it.

This is the same problem that HTTP solved for web services — before a common protocol, every client and server spoke their own language. MCP is that common protocol for AI tools.


Architecture overview

The project implements a full ADK ↔ MCP integration loop:

User
 └─► ADK LlmAgent (Claude Sonnet 4.6 via LiteLLM)
      └─► McpToolset (MCP client)
           └─► my_adk_mcp_server.py (custom MCP server, subprocess)
                ├─► ADK FunctionTool (create_file)
                └─► ADK FunctionTool (create_file_with_content)

Every layer in this chain communicates over a defined protocol. The agent doesn't know what the tools do — it knows what tools are available via MCP discovery. The MCP server doesn't know what model is driving the agent — it just handles tool calls.


Decision 1: Wrapping ADK FunctionTools in an MCP server

The MCP server (my_adk_mcp_server.py) is the architectural centrepiece. It takes ADK FunctionTool instances and exposes them as MCP tools — making them available to any MCP-compatible client, not just ADK agents.

This is the key pattern: write tools once in ADK, expose them everywhere via MCP.

The two tools exposed in this project are intentionally simple — create_file and create_file_with_content. The simplicity is deliberate: the point is the pattern, not the tools. Swap in any ADK FunctionTool and the architecture is identical.


Decision 2: stdio transport

MCP supports multiple transport mechanisms. This project uses stdio — the agent spawns the MCP server as a subprocess and communicates over stdin/stdout.

stdio is the right choice for local development and single-machine deployments:

  • No network ports to configure

  • No service discovery

  • No authentication setup

  • The server process lifecycle is managed by the agent

The tradeoff is that stdio doesn't work for distributed deployments where the agent and server run on different machines. For production systems with remote tool servers, HTTP SSE or WebSocket transport would be appropriate. For this use case, stdio is the simplest correct option.


Decision 3: LiteLLM for model flexibility

Google ADK natively targets Gemini models. This project routes through LiteLLM, which means the agent can be pointed at any LLM — Claude Sonnet 4.6, GPT-4o, Mistral, or any other LiteLLM-supported model — without changing the agent logic.

The model becomes a configuration detail:

# In agent.py
model="claude-sonnet-4-6"  # swap this for any LiteLLM-supported model

This is a small change with significant architectural implications. You can now benchmark different models against the same agent and tool setup, or switch models based on cost and latency requirements, without touching the agent or tool code.


Decision 4: McpToolset as the MCP client

Inside the ADK agent, McpToolset acts as the MCP client. It handles the connection to the MCP server, discovers available tools, and translates MCP tool calls into ADK-compatible invocations.

This means the agent definition is clean:

# agent.py — simplified
agent = LlmAgent(
    model="claude-sonnet-4-6",
    tools=[McpToolset(server_params=StdioServerParameters(
        command="python",
        args=["my_adk_mcp_server.py"]
    ))]
)

The agent doesn't enumerate its tools directly — it discovers them at runtime via MCP. Add a new tool to the MCP server and the agent picks it up automatically.


Running the agent

# CLI
adk run pilot_agent

# Web UI
adk web
# Open http://localhost:8000, select pilot_agent

Example interactions:

> Create a file called notes.txt
> Create a file called report.md with content "Hello, World!"

The agent resolves the intent, selects the appropriate MCP tool, and the MCP server executes it.


What I'd extend at larger scale

Add more ADK FunctionTools to the MCP server. The current tools are deliberately minimal. The pattern scales linearly — each new ADK tool added to the server becomes available to every MCP client automatically.

Switch to HTTP SSE transport for distributed deployments. stdio works for local development but isn't suitable for scenarios where the agent and tool server run in different environments. HTTP SSE transport makes the MCP server network-accessible.

Add tool authentication. The current setup assumes a trusted local environment. Production MCP servers exposed over a network need authentication — OAuth or API key validation at the MCP layer.

Multi-agent coordination. The MCP server can serve multiple agents simultaneously. This opens up multi-agent architectures where specialised agents share a common tool layer without duplicating tool implementations.


Conclusion

ADK and MCP are complementary, not competing. Wrapping ADK tools in an MCP server gives you the best of both: ADK's agent framework and tool primitives, with MCP's protocol-level interoperability.

The pattern is simple, the separation is clean, and the architecture scales naturally as you add more tools and more agents.

Full source: https://github.com/f2015537/building-agents-with-google-adk

More from this blog

T

The Stack Depth — Fullstack Engineering, System Design & AI

2 posts

Deep dives into fullstack engineering, system design, and AI. No fluff — just the decisions, the tradeoffs, and the reasoning behind production systems.