gmail-mcp
by alf239
README.md
# gmail-mcp — multi-account Gmail MCP server
One local MCP server that serves several Gmail accounts, each under a short
alias (`alice-work`, `bob-work`, ...). Every tool takes an `account`
parameter, and the `GMAIL_ACCOUNTS` env var restricts a server instance to a
subset of accounts — so each Cowork workstream sees only its own two inboxes.
**Capabilities:** search/read threads, manage labels, create drafts.
**Deliberately absent:** sending. There is no send tool, so no agent connected
to this server can send mail — a human reviews drafts and sends from Gmail.
(Note: the underlying OAuth scope `gmail.modify` would technically allow
sending; the restriction is enforced by this server's tool surface, not by
Google. Don't point other software at the stored tokens.)
## 1. Google Cloud setup (once, ~5 minutes)
1. Go to https://console.cloud.google.com/ and create a project (any name,
e.g. `gmail-mcp`).
2. **APIs & Services → Library** → search "Gmail API" → **Enable**.
3. **APIs & Services → OAuth consent screen**:
- User type: **External**, fill in the app name + your email.
- Under **Audience / Test users**, add **all four Gmail addresses**.
(In Testing mode only listed test users can authorize — that's fine,
and you skip Google's app verification entirely.)
4. **APIs & Services → Credentials → Create credentials → OAuth client ID**:
- Application type: **Desktop app**.
- Download the JSON and save it as `~/.gmail-mcp/credentials.json`.
> Heads-up: in Testing mode Google expires refresh tokens after **7 days**
> unless the consent screen is published. After everything works, go back to
> the consent screen and click **Publish app** (you can ignore the
> verification warning for personal use) so tokens stop expiring weekly.
## 2. Authorize each account (once per account)
```sh
uv run gmail-mcp auth alice-work # browser opens; sign in as that account
uv run gmail-mcp auth alice-personal
uv run gmail-mcp auth bob-work # the other person signs in here
uv run gmail-mcp auth bob-personal
uv run gmail-mcp accounts # verify: alias -> email [ok]
```
Sign in with the matching Google account each time — the alias is whatever
you type, so double-check the account picker. Tokens land in
`~/.gmail-mcp/tokens/`, readable only by your macOS user.
## 3. Wire into Claude — one server entry per workstream
Register the same server twice with different `GMAIL_ACCOUNTS`, then enable
the matching one in each workstream/session.
**Claude Desktop / Cowork** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"gmail-stream-a": {
"command": "uv",
"args": ["run", "--project", "/path/to/gmail-mcp", "gmail-mcp", "serve"],
"env": { "GMAIL_ACCOUNTS": "alice-work,bob-work" }
},
"gmail-stream-b": {
"command": "uv",
"args": ["run", "--project", "/path/to/gmail-mcp", "gmail-mcp", "serve"],
"env": { "GMAIL_ACCOUNTS": "alice-personal,bob-personal" }
}
}
}
```
**Claude Code**, per workstream folder (or with `claude mcp add`), in
`.mcp.json`:
```json
{
"mcpServers": {
"gmail": {
"command": "uv",
"args": ["run", "--project", "/path/to/gmail-mcp", "gmail-mcp", "serve"],
"env": { "GMAIL_ACCOUNTS": "alice-work,bob-work" }
}
}
}
```
If `uv` isn't on the app's PATH, use its absolute path (`which uv`).
## Tools
| Tool | What it does |
|---|---|
| `list_accounts` | Aliases + emails this instance serves |
| `search_threads` | Gmail query syntax (`from:`, `newer_than:7d`, ...) |
| `get_thread` | Full thread with decoded message bodies |
| `list_labels` / `create_label` | Labels, incl. nested `Clients/Acme` |
| `modify_thread_labels` | Add/remove by name or ID; archive = remove `INBOX` |
| `create_draft` | New draft or threaded reply (`reply_to_thread_id`) |
| `list_drafts` | Existing drafts |
## Layout
- `~/.gmail-mcp/credentials.json` — OAuth client secret (shared by all accounts)
- `~/.gmail-mcp/accounts.json` — alias → email registry
- `~/.gmail-mcp/tokens/<alias>.json` — per-account tokens
- `GMAIL_MCP_HOME` overrides the config dir; `GMAIL_ACCOUNTS` restricts visible accounts
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues