Send & Receive Emails with Google ADK
Use the AgentMail MCP server directly in Google ADK to send and receive emails
Google ADK agents connect to AgentMail through ADK’s built-in MCP client. Point the toolset at the hosted AgentMail MCP server and the agent discovers its email tools when it connects. On this page you will watch the agent create its own @agentmail.to inbox, send an email, and reply to one it receives.
0. Get API keys
AGENTMAIL_API_KEYauthenticates the email tools. Generate one from the AgentMail Console, or follow the Quickstart if this is your first AgentMail project.- A Gemini API key authenticates the model calls. Generate one from Google AI Studio.
Keep both values at hand. Step 2 puts them in a .env file that the adk command loads when the agent starts.
1. Install ADK with MCP support
The Python package needs Python 3.10 or newer.
pip install "google-adk[mcp]"The mcp extra and the @modelcontextprotocol/sdk package install the MCP client the toolset connects through, at a version ADK works with. @google/adk-devtools provides the adk command you will run the agent with.
2. Define the agent
One file defines the agent. The toolset points ADK’s MCP client at the hosted AgentMail server with your API key in the x-api-key header, and the agent picks up the server’s current email tools each time it connects. The full tool catalog and the server’s other connection options are on MCP and Skills.
# email_agent/agent.py
import os
from google.adk.agents import Agent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StreamableHTTPConnectionParams
root_agent = Agent(
model="gemini-flash-latest",
name="email_agent",
instruction=(
"You are an email agent with your own AgentMail inbox. "
"You can create inboxes, send email, and read and reply to threads."
),
tools=[
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://mcp.agentmail.to/mcp",
headers={"x-api-key": os.environ["AGENTMAIL_API_KEY"]},
),
)
],
)The adk command finds the agent by convention:
- Python: save
agent.pyin a folder namedemail_agent, next to an empty__init__.py. ADK loads the folder as a package and uses theroot_agentit defines. - TypeScript: save
agent.tsin your project folder. ADK uses therootAgentit exports.
Put both keys in a .env file in the same folder as the agent file. adk run and adk web load it before the agent starts.
# email_agent/.env
GOOGLE_API_KEY="<GOOGLE_API_KEY>"
AGENTMAIL_API_KEY="<API_KEY>"3. Test sending emails
Start the agent from a terminal:
# from the folder that contains email_agent/
adk run email_agentAt the [user]: prompt, ask the agent to create an inbox and email an account you already check, whether that is Gmail, Outlook, or another client:
Create an inbox with the display name "Support agent", then send an email from it
to you@example.com with the subject "Hello from my agent" and a one-line
introduction. Report the inbox address back to me once the email is sent.Moments later the email shows up in that account, sent from a brand-new @agentmail.to address. The agent calls the create_inbox tool, then send_message, and reports back:
[email_agent]: I created the inbox faircost773@agentmail.to and sent your email
to you@example.com with the subject "Hello from my agent".Save the inbox address from the reply. You will email it in the next step.
This prompt leaves the username to AgentMail, which generates an available one.
To watch each tool call instead of reading terminal output, run adk web (Python) or npx adk web (TypeScript) from the same folder and open http://localhost:8000.
4. Test receiving and replying
From your everyday account, send an email to the inbox address from step 3. Give it a subject and a question the agent can answer.
Back at the [user]: prompt, ask the agent to handle it. You should get the reply in your account, threaded under the message you sent.
Look for new mail in <inbox address>, open the most recent thread, and post a
brief reply in that thread.Replace <inbox address> with the address from step 3. A new adk run has no memory of the last one, which is why the prompt spells out the inbox address instead of trusting the agent to remember it.
The agent finds the conversation with list_threads, reads it with get_thread, and answers with reply_to_message. Mail takes about two seconds in each direction, so an agent that reports an empty inbox has probably checked before your email arrived. Ask it to check again.
Scope the agent’s tools
The toolset exposes every tool the server publishes. For an agent that should only answer incoming mail, list exactly what the job needs:
McpToolset(
connection_params=StreamableHTTPConnectionParams(
url="https://mcp.agentmail.to/mcp",
headers={"x-api-key": os.environ["AGENTMAIL_API_KEY"]},
),
tool_filter=["list_threads", "get_thread", "reply_to_message"],
)With this filter in place, the agent can read and answer mail in inboxes that already exist, and nothing else.