MCP x ADK - Engineering agents that execute, not just predict

Article #3 of Navigating the AI Agent Landscape: A Developer’s Guide to A2A, ADK, and MCP

This article marks the third episode in our series exploring the foundational protocols shaping the AI agent ecosystem. Our previous discussions introduced the Agent-to-Agent (A2A) protocol for seamless inter-agent communication and clarified the distinct yet complementary roles of A2A, the Model Context Protocol (MCP), and the Agent Development Kit (ADK)This article explores the MCP, demonstrating how it empowers individual AI agents to interact with the external world of tools and data.

This article provides a code-centric guide for developers looking to integrate MCP capabilities within agents built using Agent Development Kit (ADK). Our exploration is anchored around a practical use case: building a Financial Advisory Agent that connects to an MCP server to access real-time market data — all within a structured, agent-driven workflow.

A quick refresher: MCP core concepts

MCP is an open protocol that standardizes how applications pass contextual information to large language models (LLMs). Similar to how USB-C offers a unified interface for connecting hardware across devices, MCP provides a consistent, interoperable interface for integrating LLMs with various data sources, APIs, and tools — simplifying context injection and reducing integration complexity.

MCP operates on a client-host-server architecture :

  • Host: The AI application or agent environment (e.g., an IDE, a desktop AI app, or an ADK agent) that orchestrates interactions, manages clients, and enforces security policies.
  • Client: Resides within the Host and maintains a dedicated, one-to-one connection with an MCP server, mediating communication.
  • Server: A lightweight program exposing specific functionalities (data, tools, or prompts) via MCP primitives, connecting to local systems or remote services.

MCP Servers primarily expose three types of primitives :

  • Tools: Server-exposed, executable functions that large language models (LLMs) can invoke to interact with external systems. These tools enable LLMs to perform actions such as querying databases, calling APIs, or executing computations, thereby extending their capabilities beyond static data retrieval. Each tool is uniquely identified and includes metadata describing its schema, facilitating seamless integration and dynamic operations.
  • Resources: Read-only, addressable content entities that provide structured, contextual data to the AI model for reasoning, like log files or configuration data.
  • Prompts: Reusable templates that servers expose to clients, enabling standardized interactions with LLM. These prompts can accept dynamic arguments, incorporate contextual data from resources, and guide specific workflows, facilitating consistent and efficient LLM operations.

Communication within MCP uses JSON-RPC 2.0 messages over various transport mechanisms, including standard input/output (stdio) for local processes and HTTP with Server-Sent Events (SSE) for remote connections.

TL;DR

Use Case: The Automated Financial Advisor

Imagine a financial advisor or an individual investor aiming to:

  • Retrieve real-time stock prices and historical data.
  • Access a company’s income statements, balance sheets, and cash flow statements.
  • Perform quick financial calculations, like debt-to-equity ratios or return on investment.
  • Stay updated on market news.

Manually gathering and analyzing this information can be time-consuming and prone to error. Our Automated Financial Advisory Agent aims to streamline these operations by providing an AI agent capable of interacting directly with financial data sources and performing calculations. This agent, built with Google’s Agent Development Kit (ADK), leverages the Model Context Protocol (MCP) to access these capabilities.

Specifically, it integrates with the Financial Datasets MCP Server, which provides tools to:

  • Retrieve income statements, balance sheets, and cash flow statements for companies.
  • Obtain current and historical stock prices.
  • Access company news.
  • and many others …

This use case is particularly powerful because it lays the groundwork for future multi-agent collaboration. Once our Financial Advisory Agent can access and process financial data, it can then collaborate with other specialized agents via Agent-to-Agent (A2A) communication to tackle more complex financial planning workflows.

Pattern 1: Equipping the Financial Advisor Agent with Market Data (ADK as an MCP Client)

A common pattern when integrating the Model Context Protocol (MCP) with Google’s **Agent Development Kit (ADK)**is to configure your ADK agent as an MCP client — consuming capabilities exposed by external MCP-compliant servers. For our Automated Financial Advisory Agent, this setup enables seamless access to structured financial data, such as stock prices, financial statements, and market news.

Setting up the Financial MCP Server

To get started, clone the official financial-datasets/mcp-server repository

mkdir articles cd articles mkdir article3 cd article3 mkdir mcp-pattern1 cd mcp-pattern1 git clone https://github.com/financial-datasets/mcp-server cd mcp-server 
Set up your Python Environment & install Dependencies

Create and activate a virtual environment:

cd articles/article3 python3 -m venv .venv # Create a virtual environment named .venv source .venv/bin/activate  # On Windows: .venv\Scripts\activate 

Install required packages:

pip install "mcp[cli]" httpx 
Configure Environment Variables

Copy the .env.example file to .env file. Add the API key (Sign up and get a free API key from https://www.financialdatasets.ai/ for free) to the .env file

FINANCIAL_DATASETS_API_KEY=your-financial-datasets-api-key 
Start the Server

Run the MCP server:

python server.py 
Testing the MCP Financial Data Server

Once the server is running, you should see a message like:

financial-datasets-mcp - INFO - Starting Financial Datasets MCP Server... 

This means the server is ready to accept JSON-RPC requests from any MCP-compatible client, including your ADK agent.

Create an Agent to connect to the Financial Data Server

Now, here’s how to set up the ADK agent (agent.py) to connect to this financial data server. You can either run the code is from Github or follow along in this notebook.

Step 0: Prerequisites

Open a new terminal (leave the mcp-server running on the first terminal). Create a separate folder for the client code and activate the virtual env

cd articles/article3/mcp-pattern1 source mcp-server/.venv/bin/activate mkdir mcp-client 

Install ADK

pip install google-adk 

GCP Project: If you are using VertexAI on GCP, make sure to set up a project in GCP and install gcloud

pip install gcloud 

Step 1: Configurations

  • .env file

Create a .env file (Or copy .env.example available in the Github repo to .env). This is critical for API Keys and configuration.

  • Add the necessary variables. In this tutorial we are using Gemini 2.0. Get a key for free from https://aistudio.google.com/apikey. If you are using Vertex AI on GCP, get the project name and location.
#.env content GOOGLE_API_KEY=YOUR_GEMINI_API_KEY  GOOGLE_GENAI_USE_VERTEXAI = SET THIS TO FALSE IF YOU ARE USING API KEY AND TRUE OTHERWISE GOOGLE_CLOUD_PROJECT=YOUR_GCP_PROJECT_ID GOOGLE_CLOUD_LOCATION=YOUR_GCP_PROJECT_LOCATION 

Add .env to your .gitignore file immediately! Never commit secrets

  • __init__py

Create the file init.py in the folder mcp-client with contents:

from . import agent 

Step 2: Import required Libraries and Tools

Import all necessary modules including ADK’s LlmAgent, MCPToolset

import os from google.adk.agents import LlmAgent from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, StdioServerParameters 

Step 3: Define the external financial server path

Set the path to your financial data server script and define how the agent will launch it.

Note: We will be running this code from mcp-pattern1 folder and hence the provided folder structure.

FINANCIAL_SERVER_SCRIPT_PATH = os.path.abspath("mcp-server/server.py") print(f"Financial Advisory Agent connecting to: {FINANCIAL_SERVER_SCRIPT_PATH}")  MCP_COMMAND = 'python'  # Assumes the server is a Python script MCP_ARGS = [     FINANCIAL_SERVER_SCRIPT_PATH ] 

Step 4: Create the Root Agent and attach the MCP Tool

Define an LlmAgent and attach a filtered MCPToolset that only allows specific tools to be used by the agent.

  root_agent = LlmAgent(     model='gemini-2.0-flash',     name='financial_advisor_agent',     instruction=(         'You are an automated financial advisor. '         'You can retrieve real-time stock prices, historical financial statements, and company news. '         'Use the available tools to answer questions about financial markets and companies.'     ),     tools=[         MCPToolset(             connection_params=StdioServerParameters(                 command=MCP_COMMAND,                 args=MCP_ARGS,             ),             tool_filter=['get_current_stock_price', 'get_company_news']  # Expose only specific tools         )     ] ) 

Note: The tool_filter lets you explicitly specify which tools the agent is allowed to use. This is a subset of all tools exposed by the server and provides a layer of control — perfect for limiting capabilities

Step 5: Run the Agent

Once your agent is defined, you can run it and verify that it connects successfully to the external financial data server.

If you are running on VertexAI in GCP, authenticate to gcloud before running the script

cd articles/article3/mcp-pattern1 gcloud auth login --update-adc gcloud config set project <YOUR-PROJECT_ID> gcloud auth application-default set-quota-project <YOUR-PROJECT_ID> 

Now run the script

adk run mcp-client 

Sample output

/articles/article3/mcp-pattern1$ adk run mcp-client/ Log setup complete: /tmp/agents_log/agent.20250527_022609.log To access latest log: tail -F /tmp/agents_log/agent.latest.log Financial Advisory Agent connecting to: articles/article3/mcp-pattern1/mcp-server/server.py Running agent financial_advisor_agent, type exit to exit. [user]: what is the price of MSFT 2025-05-27 02:26:17,574 - financial-datasets-mcp - INFO - Starting Financial Datasets MCP Server... 2025-05-27 02:26:17,591 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest 2025-05-27 02:26:17,602 - financial-datasets-mcp - INFO - Starting Financial Datasets MCP Server... 2025-05-27 02:26:19,370 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest 2025-05-27 02:26:20,161 - httpx - INFO - HTTP Request: GET https://api.financialdatasets.ai/prices/snapshot/?ticker=MSFT "HTTP/1.1 200 OK" 2025-05-27 02:26:20,167 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest [financial_advisor_agent]: The current price of MSFT is 450.18. 

Let’s make sure the values are right!

Let’s get some company news, this time, that of Google!

[user]: What is the news for GOOGL? 2025-05-27 02:35:07,491 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest 2025-05-27 02:35:09,230 - mcp.server.lowlevel.server - INFO - Processing request of type CallToolRequest 2025-05-27 02:35:09,715 - httpx - INFO - HTTP Request: GET https://api.financialdatasets.ai/news/?ticker=GOOGL "HTTP/1.1 200 OK" 2025-05-27 02:35:09,862 - mcp.server.lowlevel.server - INFO - Processing request of type ListToolsRequest [financial_advisor_agent]: Here's the latest news about GOOGL:  *   **Alphabet Gets Vote of Confidence After Google I/O** *   **Why Alphabet Stock Was Rising Again Today** *   **Renaissance Hedge Fund’s Biggest Q1 Buys Revealed** *   **The Rise of Multimodal AI Market: A $4.5 billion Industry Dominated by Tech Giants - Google (US), Microsoft (US), OpenAI (US) | MarketsandMarkets™** *   **Google Just Won the AI Race. Here's Everything Investors Should Know About the Recent Announcements.**  [user]: exit 

Pattern 2: Exposing ADK Tools via a Custom MCP Server

In this pattern, we transform a standalone ADK tool — like a Celsius-to-Fahrenheit converter — into a reusable, network-accessible tool. Rather than embedding the tool within a specific agent, we expose it through a custom MCP server

This setup allows the ADK tool to be accessed by any MCP-compatible agent or application, promoting interoperability, modularity, and clean separation of concerns. The MCP server handles tool discovery and execution via standard methods like list_tools() and call_tool().

Step 0: Environment Setup and Configurations
cd articles/article3 source .venv/bin/activate mkdir mcp-pattern2 cd mcp-pattern2 mkdir mcp-server 

Install required packages:

pip install mcp 

Step 1: Import required Libraries

Import all the necessary modules from both the MCP SDK and the ADK in the file unit_converter_server.py

import asyncio import json import os  # MCP Server Imports from mcp import types as mcp_types from mcp.server.lowlevel import Server, NotificationOptions from mcp.server.models import InitializationOptions import mcp.server.stdio  # ADK Tool Imports from google.adk.tools.function_tool import FunctionTool # ADK <-> MCP Conversion Utility from google.adk.tools.mcp_tool.conversion_utils import adk_to_mcp_tool_type from typing import Dict, Any, List 

Step 2: Define the ADK Tool to be exposed

We’ll define a simple convert_celsius_to_fahrenheit function and wrap it using ADK’s FunctionTool.

# --- Define the custom unit conversion tool --- async def convert_celsius_to_fahrenheit(celsius: float) -> str:     """     Converts a temperature from Celsius to Fahrenheit.     Args:         celsius: The temperature in Celsius.     Returns:         The temperature in Fahrenheit as a formatted string.     """      fahrenheit = (celsius * 9/5) + 32     return f"{celsius}C is {fahrenheit:.2f}F."  # Wrap with FunctionTool print("Initializing ADK 'convert_celsius_to_fahrenheit' tool...") adk_tool_to_expose = FunctionTool(convert_celsius_to_fahrenheit) print(f"ADK tool '{adk_tool_to_expose.name}' initialized and ready to be exposed via MCP.") 

Step 3: Create the MCP Server and register Tool handlers

Set up the MCP server and implement handlers to list and call the tool via the MCP interface.

# Create MCP Server instance print("Creating MCP Server instance...") app = Server("adk-unit-conversion-mcp-server")  # Handler to list tools @app.list_tools() async def list_mcp_tools() -> list[mcp_types.Tool]:     print("MCP Server: Received list_tools request.")     mcp_tool_schema = adk_to_mcp_tool_type(adk_tool_to_expose)     return [mcp_tool_schema]  # Handler to call a tool @app.call_tool() async def call_mcp_tool(name: str, arguments: dict) -> list[mcp_types.TextContent]:     print(f"MCP Server: Received call_tool request for '{name}' with args: {arguments}")     if name == adk_tool_to_expose.name:         try:             response = await adk_tool_to_expose.run_async(tool_context=None, args=arguments)             return [mcp_types.TextContent(type="text", text=response)]         except Exception as e:             return [mcp_types.TextContent(type="text", text=f"Failed to execute tool '{name}': {str(e)}")]     else:         return [mcp_types.TextContent(type="text", text=f"Tool '{name}' not implemented by this server.")] 

Step 4: Start the MCP Server over StdIO

Use stdio_server() to run the server locally and listen for requests over standard input/output.

async def run_mcp_stdio_server():     async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):         print("MCP Stdio Server: Starting handshake with client...")         await app.run(             read_stream,             write_stream,             InitializationOptions(                 server_name=app.name,                 server_version="0.1.0",                 capabilities=app.get_capabilities(                     notification_options=NotificationOptions(),                     experimental_capabilities={},                 ),             ),         ) 

Step 5: Launch the Server

Add an if __name__ == "__main__" block to start the server when the script is executed.

if __name__ == "__main__":     print("Launching MCP Server to expose ADK tools via stdio...")     try:         asyncio.run(run_mcp_stdio_server())     except KeyboardInterrupt:         print("\nMCP Server (stdio) stopped by user.")     except Exception as e:         print(f"MCP Server (stdio) encountered an error: {e}")     finally:         print("MCP Server (stdio) process exiting.") 

Step 6: Start the Server

python unit_converter_server.py 

Once the server is running, you should see a message like:

Initializing ADK 'convert_celsius_to_fahrenheit' tool... ADK tool 'convert_celsius_to_fahrenheit' initialized and ready to be exposed via MCP. Creating MCP Server instance... Launching MCP Server to expose ADK tools via stdio... MCP Stdio Server: Starting handshake with client... 

This means the server is ready to accept JSON-RPC requests from any MCP-compatible client, including your ADK agent.

Create an Agent to connect to the Unit Converter Server

Once your MCP server is running and exposing the tool, any other ADK agent (or compatible client) can access it using the MCPToolset. You can either run the code from Github or follow along in this notebook.

Prerequisites

Open a new terminal (leave the unit_converter_server running on the first terminal). Create a separate folder for the client code.

cd articles/article3/ source .venv/bin/activate cd mcp-pattern2 mkdir mcp-client 

GCP Project: If you are using VertexAI on GCP, make sure to set up a project in GCP and install gcloud

pip install gcloud 

Create .env file

Create a .env file (Or copy .env.example available in the Github repo to .env). This is critical for API Keys and configuration.

  • Add the necessary variables. In this tutorial we are using Gemini 2.0. Get a key for free from https://aistudio.google.com/apikey. If you are using Vertex AI on GCP, get the project name and location.
#.env content GOOGLE_API_KEY=YOUR_GEMINI_API_KEY 
GOOGLE_GENAI_USE_VERTEXAI = SET THIS TO FALSE IF YOU ARE USING API KEY AND TRUE OTHERWISE GOOGLE_CLOUD_PROJECT=YOUR_GCP_PROJECT_ID GOOGLE_CLOUD_LOCATION=YOUR_GCP_PROJECT_LOCATION 

Add .env to your .gitignore file immediately! Never commit secrets

Create __init__py

Create the file init.py in the folder mcp-client with contents:

from . import agent 

Define the Client Agent

You’ll use LlmAgent and configure it with MCPToolset to connect to the tool hosted on your custom MCP server.

import os from google.adk.agents import LlmAgent from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, StdioServerParameters  # Set path to the script running your custom MCP server UNIT_CONVERTER_SERVER_PATH = os.path.abspath("mcp-server/unit_converter_server.py") print(f"Unit Converter Agent connecting to: {UNIT_CONVERTER_SERVER_PATH}")  # Configure how to launch the server MCP_COMMAND = 'python' # Command to run the Python server script MCP_ARGS = [     UNIT_CONVERTER_SERVER_PATH ]  # Set up the ADK agent that will use the external tool root_agent = LlmAgent(     model='gemini-2.0-flash',     name='unit_conversion_agent',      instruction=(         'You are a helpful unit conversion assistant. '         'You can convert temperatures from Celsius to Fahrenheit. '         'Use the available tools to perform unit conversions.'     ),     tools=[         MCPToolset(             connection_params=StdioServerParameters(                     command=MCP_COMMAND,                     args=MCP_ARGS,                 ),                 tool_filter=['convert_celsius_to_fahrenheit']         )     ]   ) 

Run the Agent

Once your agent is defined, you can run it and verify that it connects successfully to the unit_converter_server

If you are running on VertexAI in GCP, authenticate to gcloud before running the script

cd articles/article3/mcp-pattern2 gcloud auth login --update-adc gcloud config set project YOUR_GCP_PROJECT_ID gcloud auth application-default set-quota-project YOUR_GCP_PROJECT_ID 

Now run the script

adk run mcp-client 

Sample output

Log setup complete: /tmp/agents_log/agent.20250527_054459.log To access latest log: tail -F /tmp/agents_log/agent.latest.log Unit Converter Agent connecting to: articles/article3/mcp-pattern2/mcp-server/unit_converter_server.py Running agent unit_conversion_agent, type exit to exit. [user]: what is 34 degree celsius in Farenheit [unit_conversion_agent]: 34 degrees Celsius is 93.20 degrees Fahrenheit. 

This is what Google Search says!

Security considerations for MCP-connected AI Agents

When building AI agents that interface with external tools, APIs, or data sources — especially via MCP — security is a critical concern. MCP is intentionally lightweight and protocol-agnostic, meaning it does not include built-in security enforcement. It’s entirely up to developers to implement protections at the agent, host, and tool levels.

Common risk areas in Tool-Integrated Agent Systems
  • Tool Poisoning
    Malicious content embedded in tool descriptions or response formats can influence model behavior, potentially causing incorrect or harmful actions.
  • Sensitive Data Exposure
    Tools may accidentally access or leak private information if not properly scoped or isolated — especially in multi-tenant or shared memory environments.
  • Unauthorized Access
    Without authentication controls, any process or user may connect to a local MCP server, potentially accessing privileged tools or data.
  • Local Server Vulnerabilities
    Stdio-based servers can inherit user-level access. Without sandboxing, they may unintentionally expose local files or network resources.
Recommended Mitigation Strategies
  • Principle of Least Privilege
    Limit what each agent, tool, and server can access. Only expose what is strictly required for the task.
  • Authentication & Authorization
    Use token-based systems (like OAuth or signed API keys) to control who can initiate MCP connections or access tools.
  • Input Validation
    Sanitize all tool inputs — especially those coming from untrusted sources — to guard against prompt injection or code manipulation.
  • Secrets Management
    Never hardcode API keys or tokens in code. Use environment variables or secure vault systems to manage credentials safely.
  • Secure Communication
    For remote connections, always use TLS to encrypt traffic between agents and MCP servers. Validate connection origins.
  • Logging & Monitoring
    Maintain detailed logs of all agent-tool interactions. This is essential for traceability, debugging, and detecting abuse or anomalies.

TL;DR

Looking ahead: Beyond the Single-Agent use case

In this article, we focused on extending a single ADK agent’s capabilities — connecting it to external tools via MCP and exposing custom ADK-built functionality through an MCP server. These patterns lay the foundation for scalable, interoperable AI systems.

But in real-world deployments, agents often need to collaborate, not just integrate.
They need to share context, negotiate responsibilities, and adapt to dynamic workflows — not as isolated components, but as intelligent participants in a larger system.

And Thank you for reading! Feel free to connect and reach out on LinkedIn to share feedback, questions and what you build with ADK and A2A