owenkaplinsky's picture
update from github stable code (#3)
3370983 verified
raw
history blame
3.02 kB
"""
Gmail MCP Server
================
This file implements a Model Context Protocol (MCP) server that bridges
a local Gmail API client to an AI model (e.g. Claude or LangGraph agents).
How it works:
-------------
- The LLM connects to this server through an MCP client (e.g. MultiServerMCPClient)
using STDIO as a transport layer.
- When the server starts, it authenticates with Gmail (via OAuth2) and registers
all available Gmail operations as MCP tools (send, read, search, label, etc.).
- The MCP client fetches these tool definitions and exposes them to the LLM.
- When the LLM decides to use one (e.g. “send an email”), it triggers a tool call,
which this server executes and returns the result.
Why these arguments:
--------------------
--creds-file-path : path to the Google OAuth2 client credentials (for login)
--token-path : path to the saved access/refresh token (for session reuse)
Together, these allow the MCP server to securely spin up a Gmail session and
respond to model-issued actions via standard I/O.
run as follows:
>>> python -m src.mcp_servers.examples.gmail.send_email
"""
import asyncio
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
from langchain_openai.chat_models.base import ChatOpenAI
from pathlib import Path
from .settings import GMailSettings
from dotenv import load_dotenv
load_dotenv()
UV_PATH = "/Users/sebastianwefers/.local/bin/uv" # <= full path to uv (important)
MODEL = ChatOpenAI(model="gpt-4o", temperature=0)
settings = GMailSettings()
async def main():
# 1) Connect to the Gmail MCP server via stdio
client = MultiServerMCPClient(
{
"gmail": {
"command": UV_PATH,
"args": [
"--directory", str(settings.gmail_mcp_dir),
"run", "gmail",
"--creds-file-path", str(settings.creds),
"--token-path", str(settings.token),
],
"transport": "stdio",
}
}
)
# 2) Fetch tool specs from the server
tools = await client.get_tools()
# 3) Build a simple agent with those tools
agent = create_agent(MODEL, tools)
# 4) Test: ask the agent to list unread emails or send a draft
result = await agent.ainvoke({
"messages": [
{
"role": "system",
"content": (
"You are an automated agent authorized to use Gmail MCP tools, "
"including sending emails through the user's authorized account."
),
},
{
"role": "user",
"content": (
"Send an email to sebastianwefersnz@gmail.com and say hello."
),
},
]
})
print("\n\n~~~ RESULT ~~~")
print(result['messages'][-1].content)
print("~~~ END RESULT ~~~")
if __name__ == "__main__":
asyncio.run(main())