使用说明
ADK Agent with MCP Servers
Two examples of connecting a Google Agent Development Kit (ADK) agent to Model Context Protocol (MCP) servers:
| Example | Folder | MCP server | What the agent can do |
|---|---|---|---|
| Notion | remote_mcp/ | Notion's @notionhq/notion-mcp-server, started with npx |
Search and read your Notion workspace, create and update pages |
| Local SQLite | local_mcp/ | A custom MCP server in local_mcp/server.py | List, inspect, query, insert into and delete from a SQLite database |
Both agents use gemini-3.8-flash.
Prerequisites
- Python 3.12 (the version this project was tested with). Python 3.14 failed to install on an Intel Mac, because
cryptographyhas no prebuilt package for it there. - A Gemini API key
- For the Notion example: Node.js (for
npx) and a Notion integration token with access to the pages you want the agent to use
Setup
-
Create and activate a virtual environment, then install the dependencies.
python3.12 -m venv .venv source .venv/bin/activate pip install --only-binary cryptography google-adk "mcp<2" python-dotenvTwo details in the install command matter:
"mcp<2":local_mcp/server.pyuses the@app.list_tools()and@app.call_tool()decorators from the MCP Python SDK 1.x. They were removed in 2.x, and with 2.x the server crashes at startup ('Server' object has no attribute 'list_tools').--only-binary cryptography: makes pip use a prebuiltcryptographypackage. Without it, pip may try to compilecryptographyfrom source and fail if your Rust compiler is too old.
-
Copy the example environment file and fill in your keys.
cp .env.example .envVariable Used by GOOGLE_API_KEYBoth agents (Gemini) NOTION_API_KEYThe Notion agent
Quick start: run the server, pick an agent, ask questions
-
Activate the virtual environment from the project root. The agents start their MCP server with the
python3on your path, so the environment must be active.source .venv/bin/activate -
Start the ADK web server from the project root, not from inside an agent folder.
adk webIt prints
http://127.0.0.1:8000. Leave this terminal open, because agent errors are printed here. -
Open the URL in your browser and choose an agent from the dropdown at the top left:
local_mcp: questions about the sample SQLite databaseremote_mcp: questions about your Notion workspace
-
Ask questions in the chat box. For
local_mcp, start with "What tables are in the database?". The chat shows each tool call the agent makes and then its answer. -
Stop the server with Ctrl+C in the terminal. Restart it after any change to the agent files, because they are loaded at startup.
If something goes wrong, see Troubleshooting.
Example 1: Notion MCP server
How it works
The ADK agent never calls the Notion API itself. It talks to Notion's MCP server, which turns tool calls into Notion API requests:
- remote_mcp/agent.py reads
NOTION_API_KEYfrom the environment and fails withNOTION_API_KEY is not setif it is missing. - The agent's
MCPToolsetstarts the Notion MCP server as a subprocess withnpx -y @notionhq/notion-mcp-serverand passes it the key asNOTION_TOKEN. The first run downloads the package, so it can be slow. - The agent asks the server which tools it has. The server exposes the Notion API as tools, such as querying a database, inserting a block, writing a comment and creating a page.
- When you ask a question, Gemini decides which Notion tools to call. The server runs them against the Notion API and returns the results, and Gemini writes the answer from them.
- The agent's instructions in remote_mcp/prompt.py tell it to act without asking for confirmation when it already has what it needs, such as a page ID from an earlier step.
With the Notion tools, the agent can create documentation, search the workspace and answer questions from its content, manage tasks, generate code snippets from a task description, and build reports, release notes and project updates from several pages.
Give the agent access to your Notion content
A Notion integration can only see the pages and databases that have been shared with it.
- Create an integration at notion.so/profile/integrations and copy its token into
.envasNOTION_API_KEY. - Share the content you want the agent to use. Open the page or database, click
···→ Connections, and add your integration.
In the tested setup, the content is a To-Do list database in Notion, connected to an integration named ellieMCP.
Run it
From the project root, with the virtual environment active:
adk web
Open the URL that adk web prints, select remote_mcp as the agent, and ask questions about the shared content. Restart adk web after you change .env, because the file is read at startup.
Prompts to try with a To-Do list database:
- "Search my Notion workspace for my To-Do list."
- "What tasks are left to do on my To-Do list?"
- "Add a to-do called 'Test MCP agent' to my To-Do list."
Start with read-only questions. The agent can change your real Notion content, so test changes on a copy of the database.
Tested
Asking the agent which to-do items are left worked. It found the To-Do list database and returned the open items, which confirms that the agent, the Notion MCP server and the integration are connected.
Asking it to add an item failed with a quota-exceeded error. A request that adds an item takes several model calls (find the database, then insert), and the Gemini free tier limits how many requests you can send. The error is a model quota limit, not a Notion problem. It should go away with a paid tier, or after waiting for the quota to reset. Adding items hasn't been confirmed to work.
Example 2: Local SQLite MCP server
The agent in local_mcp/agent.py talks to a custom MCP server that wraps a SQLite database.
Files
| File | Purpose |
|---|---|
| local_mcp/create_db.py | Creates database.db with a users table and a todos table, and fills them with sample rows |
| local_mcp/server.py | The MCP server. It exposes the database tools over stdio |
| local_mcp/agent.py | The ADK agent. It starts the server and uses its tools |
| local_mcp/prompt.py | The agent's instructions, including sensible defaults for missing tool arguments |
Tools exposed by the server
| Tool | Description |
|---|---|
list_db_tables |
Lists the tables in the database |
get_table_schema |
Returns the column names and types of a table |
query_db_table |
Selects columns from a table with an optional WHERE condition |
insert_data |
Inserts a row into a table |
delete_data |
Deletes rows that match a WHERE condition. The condition cannot be empty |
Run it
-
Create the database. This is only needed once. The script does nothing if
database.dbalready exists.python3 local_mcp/create_db.py -
From the project root, with the virtual environment active, start the ADK web UI.
adk web -
Open the URL that
adk webprints and selectlocal_mcpas the agent. Try prompts such as:- "What tables are in the database?"
- "Show me all of Elliot's unfinished todos."
- "Add a todo for Mike: book flights."
- "Delete the todo about running."
You don't start the MCP server yourself. When the agent initializes its MCPToolset, it runs python3 local_mcp/server.py. The server then listens for tool calls from the agent over stdio. To run the server by hand, for example to debug it, use python3 local_mcp/server.py from the project root.
Logs
The server writes its activity to local_mcp/mcp_server_activity.log, and the file is overwritten on each start. Nothing is printed to the console. To see the log output there, add a logging.StreamHandler() to the handlers in server.py.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
zsh: command not found: adk |
google-adk isn't installed in the active environment |
Activate .venv and run the install command from Setup |
Failed building wheel for cryptography |
pip is compiling cryptography from source |
Use Python 3.12 and pip install --only-binary cryptography ... |
Failed to create MCP session: Connection closed |
The MCP server crashed at startup. With mcp 2.x, the error is 'Server' object has no attribute 'list_tools' |
pip install "mcp<2", then restart adk web |
address already in use on port 8000 |
An earlier adk web is still running, and your browser is talking to it |
Stop it (lsof -nP -iTCP:8000 -sTCP:LISTEN shows its process id, then kill <pid>), or run adk web --port 8001 |
404 NOT_FOUND ... model ... is no longer available |
The Gemini model name was retired | Change model= in both agent files to a current model |
400 ... Developer instruction is not enabled for this model |
The model doesn't accept a system prompt. Text-to-speech (tts) models are one example |
Use a plain text model, not tts, image, audio or live |
503 UNAVAILABLE ... high demand |
Google's servers are overloaded. It's temporary, and it isn't a problem with this project | Retry later, or switch to another text model |
Quota exceeded (429 RESOURCE_EXHAUSTED) |
The free tier of the Gemini API limits requests. Requests that need several tool calls, such as adding a Notion item, use the most | Wait for the quota to reset, use a lighter model such as gemini-2.5-flash-lite, or use a key with billing enabled |
To see which models your key can use:
python3 -c "
from dotenv import load_dotenv; load_dotenv()
from google import genai
client = genai.Client()
for m in client.models.list():
if 'generateContent' in (m.supported_actions or []): print(m.name)
"
Keep the client in a variable as shown. A temporary genai.Client() is closed before the loop finishes.
Project structure
mcp-adk/
├── local_mcp/
│ ├── agent.py # ADK agent for the SQLite example
│ ├── create_db.py # builds database.db with sample data
│ ├── database.db # SQLite database
│ ├── prompt.py # agent instructions
│ └── server.py # custom MCP server (stdio)
├── remote_mcp/
│ ├── agent.py # ADK agent for the Notion example
│ └── prompt.py # agent instructions
├── .env.example # template for API keys
└── requirements.txt
Notes
- The database tools build SQL from the values the model passes in, such as table names and
WHEREconditions. Use them on a local sample database only, not on data you care about. requirements.txtis currently empty. Install the packages with the command in Setup.- Both agents have been run.
local_mcpworks against the sample database.remote_mcpcan read a Notion To-Do list database. Adding items hasn't been tested, because the Gemini free tier ran out of quota.
