gmail-mcp-server
by ktsenapathy
README.md
# Gmail MCP Server
A [Model Context Protocol](https://modelcontextprotocol.io) server that lets
an AI assistant (Claude Desktop, Claude API, etc.) read unread Gmail messages
and create threaded draft replies — without ever sending email automatically.
---
## What this server does
| Tool | Description |
|------|-------------|
| `get_unread_emails` | Returns up to 50 unread inbox messages: sender, subject, date, body, and IDs |
| `create_draft_reply` | Saves a threaded draft reply in Gmail Drafts (user must send manually) |
| `get_reply_context` | *(Stretch goal)* Returns a style guide, templates, and knowledge-base snippets to guide better replies |
The server communicates with Claude Desktop over **stdio** using the MCP
JSON-RPC protocol. It never sends email — only creates drafts.
---
## Prerequisites
- Python 3.10+
- A Google account
- [Claude Desktop](https://claude.ai/download) installed
---
## Quick start
### 1. Clone and install
```bash
git clone <this-repo>
cd gmail-mcp-server
bash scripts/setup.sh
source .venv/bin/activate
```
### 2. Set up Gmail API credentials
Follow the detailed guide in [`docs/gmail_api_setup.md`](docs/gmail_api_setup.md).
**Summary:**
1. Create a Google Cloud project.
2. Enable the **Gmail API**.
3. Configure the **OAuth consent screen** (External, test mode is fine).
4. Add scopes: `gmail.readonly` + `gmail.compose`.
5. Create an **OAuth 2.0 Desktop App** credential.
6. Download `credentials.json` → place in project root.
### 3. Authenticate
```bash
python scripts/auth_check.py
```
A browser window opens. Sign in and approve access. `token.pickle` is saved.
### 4. Test the server manually
```bash
# Start the server (press Ctrl-C to stop)
gmail-mcp
```
The server waits for JSON-RPC on stdin. You can send a test message:
```bash
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | gmail-mcp
```
### 5. Configure Claude Desktop
Edit `claude_desktop_config.json` (see [`docs/claude_desktop_config.md`](docs/claude_desktop_config.md)):
```json
{
"mcpServers": {
"gmail": {
"command": "/absolute/path/to/.venv/bin/python",
"args": ["-m", "gmail_mcp_server.server"],
"cwd": "/absolute/path/to/gmail-mcp-server",
"env": {
"GMAIL_CREDENTIALS_PATH": "/absolute/path/to/credentials.json",
"GMAIL_TOKEN_PATH": "/absolute/path/to/token.pickle"
}
}
}
}
```
Restart Claude Desktop. The gmail tools will appear automatically.
---
## Example Claude prompts
```
Check my unread emails and tell me which ones need urgent attention.
```
```
I have an unread email about a refund request. Draft a polite reply
using our style guide, then save it as a draft.
```
```
Fetch my 5 newest unread emails. For each one, tell me the sender,
subject, and a one-sentence summary.
```
```
Use get_reply_context to see our templates, then create a draft reply
to the meeting invite email.
```
---
## Project structure
```
gmail-mcp-server/
├── src/
│ └── gmail_mcp_server/
│ ├── __init__.py
│ ├── server.py # MCP server entry point & tool definitions
│ ├── auth.py # OAuth 2.0 credential management
│ ├── gmail_tools.py # Gmail API logic (read emails, create drafts)
│ └── context.py # Stretch-goal: style guide, templates, KB search
├── context/
│ ├── style_guide.md # Writing style guide (edit to match your voice)
│ ├── templates.json # Reply templates
│ └── knowledge_base/ # .md/.txt files Claude can search
├── scripts/
│ ├── setup.sh # One-time environment setup
│ └── auth_check.py # OAuth flow + credential verification
├── docs/
│ ├── mcp_concepts.md # How MCP tools work (detailed explanation)
│ ├── gmail_api_setup.md # Step-by-step Google Cloud setup
│ └── claude_desktop_config.md # Claude Desktop config + example prompts
├── pyproject.toml
├── .env.example
└── .gitignore
```
---
## How MCP tools work (summary)
MCP tools are **callable functions** that an LLM can invoke via JSON-RPC:
1. **Discovery** — Claude calls `tools/list`; the server returns tool names,
descriptions, and JSON Schemas for their arguments.
2. **Decision** — The LLM decides which tool to call based on the description
and the user's request.
3. **Invocation** — Claude calls `tools/call` with the tool name and arguments.
4. **Result** — The server returns a `TextContent` block (JSON string) that
Claude reads and incorporates into its response.
See [`docs/mcp_concepts.md`](docs/mcp_concepts.md) for a full explanation with
sequence diagrams and annotated code.
---
## Stretch goal: external context
The `get_reply_context` tool pulls in:
- **Style guide** (`context/style_guide.md`) – tone, structure, phrases to use/avoid.
- **Templates** (`context/templates.json`) – starting points for common reply types.
- **Knowledge base** (`context/knowledge_base/`) – searched by keyword.
To connect real cloud sources:
- **Google Docs** – enable the Docs API, add `documents.readonly` scope,
fetch document content via `docs.documents().get()`.
- **Notion** – install `notion-client`, query a database with your integration token.
- **Vector search** – replace `search_knowledge_base()` in `context.py` with
`chromadb` or `hnswlib` for semantic search over larger document sets.
---
## Security notes
- `credentials.json` and `token.pickle` are in `.gitignore` — never commit them.
- The server only requests `gmail.readonly` and `gmail.compose` scopes.
- No email is ever sent automatically; `create_draft_reply` only calls
`drafts.create`, not `messages.send`.
- The OAuth consent screen is in "Testing" mode by default — only you can authenticate.
---
## Troubleshooting
| Problem | Fix |
|---------|-----|
| Tools don't appear in Claude Desktop | Check `command` path uses `.venv/bin/python`; restart Claude Desktop |
| `credentials.json not found` | Download from Google Cloud Console and place in project root |
| `Access blocked` in browser | Add your email to Test Users in OAuth consent screen |
| `Token revoked` error | Delete `token.pickle` and re-run `auth_check.py` |
| Empty email body | Email may be HTML-only; `gmail_tools.py` extracts `text/plain` parts |
For more, see [`docs/gmail_api_setup.md`](docs/gmail_api_setup.md).
---
## License
MIT
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues