gmail-multi-mcp
# gmail-multi-mcp
Connect **multiple Gmail accounts** to Claude (or any [MCP](https://modelcontextprotocol.io)
client) from one local server. The official Gmail connector only supports a single Google
account ā this lets you search, read, draft, send, label, and organize mail across as many
accounts as you like, each addressed by a friendly alias.
Your OAuth tokens are stored **locally on your machine only** ā never uploaded anywhere.
## Features
- š¢ **Unlimited accounts** ā every tool takes an `account` parameter (`"personal"`, `"work"`, ā¦)
- š **Search & read** ā full Gmail search syntax, thread/message reading, attachment download
- āļø **Compose** ā create/list/delete drafts, send mail, replies with correct threading headers
- š·ļø **Organize** ā full label management, archive, trash
- š **Local-first** ā standard Google OAuth; tokens live in `~/.gmail-mcp/`, chmod 600
- š§© **22 tools**, works with Claude Code, Claude Desktop, Cursor, and any MCP client
## Prerequisites
- **Node.js ā„ 20**
- A Google account (and a free Google Cloud project ā setup below)
## 1. Install
```bash
git clone https://github.com/Vinksj/claude-gmail-multi.git
cd claude-gmail-multi
npm install
npm run build
```
## 2. Create your Google OAuth app (one-time, ~10 min)
You register one OAuth "app" with Google; it then works for all the accounts you connect.
1. Go to [console.cloud.google.com](https://console.cloud.google.com) ā create a project (e.g. `gmail-mcp`).
2. **APIs & Services ā Library** ā search **Gmail API** ā **Enable**.
3. **APIs & Services ā OAuth consent screen**:
- User type **External** ā Create.
- App name + your support email + your contact email ā Save and Continue.
- Scopes page ā Save and Continue. Test users page ā Save and Continue.
4. **Publish to production:** on the OAuth consent screen, set **Publishing status ā Publish app**.
*(In "Testing" mode Google expires your refresh token every 7 days. Publishing avoids that.
You'll click through a one-time "Google hasn't verified this app" warning per account ā that's
normal for a personal app: choose **Advanced ā Continue**.)*
5. **APIs & Services ā Credentials ā Create Credentials ā OAuth client ID**:
- Application type **Desktop app** ā Create ā **Download JSON**.
6. Save that file as `~/.gmail-mcp/credentials.json`:
```bash
mkdir -p ~/.gmail-mcp && chmod 700 ~/.gmail-mcp
mv ~/Downloads/client_secret_*.json ~/.gmail-mcp/credentials.json
chmod 600 ~/.gmail-mcp/credentials.json
```
> Note: newer Google Cloud UIs put these under **"Google Auth Platform"** (Branding / Audience /
> Clients) instead of "OAuth consent screen" ā same steps, different labels.
## 3. Connect your accounts
```bash
npm run auth -- --alias personal --email you@gmail.com
npm run auth -- --alias work --email you@company.com
```
Each opens a browser ā pick the matching Google account ā approve. The optional `--email` flag
aborts if the wrong account gets authorized (an easy mistake with multi-login browsers). Connect
as many as you want; re-run any time a token is revoked.
## 4. Register with your MCP client
**Claude Code:**
```bash
claude mcp add --scope user gmail-multi -- node "$(pwd)/dist/index.js"
```
**Claude Desktop / other clients** ā add to your MCP config:
```json
{
"mcpServers": {
"gmail-multi": {
"command": "node",
"args": ["/absolute/path/to/gmail-multi-mcp/dist/index.js"]
}
}
}
```
Tools appear as `gmail-multi`'s `search_threads`, `create_draft`, etc. Ask things like
*"search my work inbox for unread from this week"* or *"draft a reply in personal to Alice."*
## Tools
| Group | Tools |
|---|---|
| Accounts | `list_accounts`, `add_account` |
| Read | `search_threads`, `get_thread`, `get_message`, `download_attachment` |
| Compose | `create_draft`, `list_drafts`, `delete_draft`, `send_draft`, `send_message` |
| Labels | `list_labels`, `create_label`, `update_label`, `delete_label`, `label_thread`, `unlabel_thread`, `label_message`, `unlabel_message` |
| Cleanup | `archive_thread`, `trash_thread`, `trash_message` |
Every tool except `list_accounts` takes an `account` parameter (alias or email). Replies via
`replyToMessageId` get correct `In-Reply-To`/`References` headers and threading automatically.
## How it works
- One self-owned Google Cloud OAuth app (Desktop client) authorizes any number of accounts.
- Single scope: `https://www.googleapis.com/auth/gmail.modify` (read, search, drafts, send,
labels, archive, trash ā narrower than full `https://mail.google.com/`).
- Per-account refresh tokens stored in `~/.gmail-mcp/tokens/<alias>.json` (chmod 600); the
account registry is `~/.gmail-mcp/config.json`. Nothing leaves your machine.
```
~/.gmail-mcp/
āāā credentials.json # your OAuth client (you add this)
āāā config.json # alias ā email map (auto-managed)
āāā tokens/<alias>.json # per-account refresh tokens (auto-managed)
```
## Security notes
- Tokens are stored as plain files readable only by your user (chmod 600). On a single-user
machine with full-disk encryption this is reasonable; moving token storage to the OS keychain
is a sensible future hardening step.
- Never commit `~/.gmail-mcp/` ā it lives in your home directory, outside this repo, and the
repo's `.gitignore` excludes build artifacts and dependencies regardless.
- The `gmail.modify` scope cannot permanently delete mail ā `trash_*` tools move items to Trash
(recoverable for 30 days).
## Development
```bash
npm run build # tsc -> dist/
npm run inspect # MCP Inspector UI against the built server
npm run auth -- --alias <name> [--email <expected>]
```
Important: stdout is the JSON-RPC channel ā never `console.log` in server code; use `console.error`.
## License
MIT Ā© Saurabh Jain
TDQS
Scored across 22 tools
Every tool targets a distinct action and resource (accounts, threads, messages, drafts, labels, attachments). There is no ambiguity between similar operations like trash_thread vs trash_message or label_thread vs label_message, as the descriptions clearly differentiate the scope.
All tool names follow a consistent verb_noun pattern using snake_case (e.g., create_draft, list_labels, send_message). The verbs are clear and uniform, making the tool set predictable for an agent.
With 22 tools, the server covers the core Gmail API surface comprehensively, including account management. While this is above the typical 3-15 range for a well-scoped server, each tool serves a distinct purpose and the count is justified by the multi-account complexity.
The tool set covers CRUD operations for threads, messages, drafts, and labels, plus search, attachments, and account management. Minor gaps exist (e.g., no explicit mark-as-read or spam tools), but these are handled indirectly through labeling and the core workflows are well-supported.