gmail-mcp
by mortenv
README.md
# gmail-mcp
MCP server for reading Gmail and creating drafts via AI assistants (Claude, OpenClaw, etc.).
**Security model:**
- 🔒 Read-only by default — no send capability, ever
- 📋 Drafts only — human must open Gmail and send manually
- 🔍 Query whitelist — only configured filter queries are allowed
- 👤 Optional recipient whitelist for drafts
- 🔑 API key authentication for HTTP/SSE mode
## Tools
| Tool | Description |
|------|-------------|
| `list_filters` | Show configured allowed search queries |
| `search_email` | Search Gmail (query must match a whitelisted filter) |
| `get_email` | Fetch full content of an email by ID |
| `create_draft` | Create a draft — **NOT sent**, human reviews in Gmail |
## Setup
### 1. Google Cloud credentials
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
2. Create a project → Enable **Gmail API**
3. Create OAuth2 credentials (Desktop app type)
4. Download as `credentials.json` and place in the project folder
### 2. Install
```bash
git clone https://github.com/mortenv/gmail-mcp
cd gmail-mcp
pip install -e .
# or with uv:
uv sync
```
### 3. Configure
```bash
cp config.example.yaml config.yaml
```
Edit `config.yaml`:
- Add your filter queries (Gmail search syntax)
- Optionally restrict draft recipients
### 4. Authenticate
First run opens a browser for OAuth2 login:
```bash
gmail-mcp config.yaml
```
Token is cached in `token.json` — subsequent runs don't need the browser.
### 5. Connect to Claude / OpenClaw
**stdio mode (local):**
```json
{
"mcpServers": {
"gmail": {
"command": "gmail-mcp",
"args": ["/path/to/config.yaml"]
}
}
}
```
**HTTP/SSE mode (remote server):**
```bash
export GMAIL_MCP_API_KEY=$(python -c "import secrets; print(secrets.token_hex(32))")
gmail-mcp --http config.yaml
```
```json
{
"mcpServers": {
"gmail": {
"url": "https://your-server:8001/sse",
"headers": { "X-API-Key": "your-key" }
}
}
}
```
## Filter syntax
Uses standard Gmail search syntax:
```yaml
filters:
- query: "label:inbox"
label: "Inbox"
- query: "from:boss@company.com"
label: "From boss"
- query: "label:invoices newer_than:30d"
label: "Recent invoices"
```
The AI can narrow results by appending terms to a base query:
`"label:inbox subject:urgent"` — allowed if `label:inbox` is whitelisted.
## Security notes
- `credentials.json` and `token.json` are gitignored — never commit them
- OAuth scopes: `gmail.readonly` + `gmail.compose` (no `gmail.send`)
- Drafts require human review — the server has no way to send email
## License
MIT