gmail-multi-mcp
Allows managing multiple Gmail accounts, including searching, reading, composing drafts, and sending emails with verified send-as aliases.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@gmail-multi-mcpsearch my work account for emails from boss@company.com"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
gmail-multi-mcp
MCP server exposing several Google Workspace accounts — across separate orgs and domains — to Claude at the same time, with verified send-as alias support.
Why this exists
The built-in Gmail connector (https://gmailmcp.googleapis.com/mcp/v1) authenticates
one Google identity and its create_draft takes no from parameter, so it can only
ever draft as the connected account. Adding a second custom connector for a second
account is blocked separately: Claude keys custom connectors by URL alone and rejects
a duplicate URL.
So this is one server holding N accounts, with an account argument on every tool
and a validated from argument on the compose tools.
Related MCP server: claude-gmail-mcp
Tools
Tool | Purpose |
| Configured accounts and their keys |
| Send-as identities on an account, and which are usable |
| Gmail query syntax search |
| One message, full bodies |
| Every message in a thread |
| Drafts, optionally filtered |
| Create a draft, optionally as an alias or as a threaded reply |
| Merge changes into an existing draft |
| Send an existing draft — only if |
| Compose and send — only if |
Sending is off by default. Routines run unattended with no approval step, so the send tools are not even registered unless you opt in.
Setup
1. One OAuth client per Workspace org
This is the part that determines whether the whole thing works. The Gmail scopes used here are restricted, which means:
External + Testing → refresh tokens expire after 7 days. Unusable.
External + Published → Google verification plus an annual CASA Tier-2 security assessment. Weeks of work.
Internal → no verification, refresh tokens do not expire. ✅
An Internal app is only internal to one org, so three orgs need three OAuth clients. For each one, signed in as an admin of that domain:
Google Cloud Console → create or pick a project owned by that Workspace org.
APIs & Services → Library → enable Gmail API.
APIs & Services → OAuth consent screen → User Type Internal → fill in app name and support email.
Data access / Scopes → add:
https://www.googleapis.com/auth/gmail.readonlyhttps://www.googleapis.com/auth/gmail.composehttps://www.googleapis.com/auth/gmail.settings.basic
Credentials → Create credentials → OAuth client ID → application type Desktop app. Desktop clients accept loopback redirects on any port, so there is nothing to register. Copy the client ID and secret.
In that org's Admin console → Security → Access and data control → API controls → App access control, confirm the app is not blocked. Restricted scopes are blocked by default in some orgs; if so, allowlist it by client ID and mark it Trusted.
2. Authorize each account
Run once per account. It prompts for the three values and opens your browser:
npm run auth⚠️ Do not use npm run auth -- --account x --client-id y. npm's PowerShell shim
strips flag names and forwards only their values, so the script receives positional
junk and exits. For non-interactive use, call node directly — that passes flags intact:
node src/auth-cli.js --account work --client-id <id> --client-secret <secret>Credentials land in ~/.gmail-multi-mcp/accounts.json at mode 0600. The --account
value is the key you will pass as account in every tool call, so keep it short.
This one file is deliberately kept outside Drive: it holds three sets of OAuth
client secrets and non-expiring refresh tokens, and those should not sync to cloud
storage. Everything else lives here in _Shared Tools.
3. Point Claude at it
Claude runs the bundle, not src/index.js — see Why a bundle.
{
"mcpServers": {
"gmail-multi": {
"command": "node",
"args": ["H:\\My Drive\\_Shared Tools\\gmail-multi-mcp\\gmail-multi-mcp.mjs"]
}
}
}To enable sending, add "env": { "GMAIL_MULTI_ALLOW_SEND": "1" }.
Why a bundle
This project lives in Google Drive, and Drive cannot host node_modules. Syncing
~3,500 dependency files truncated @modelcontextprotocol/sdk/package.json to 0 bytes,
which surfaced as a misleading Invalid package config at startup. Drive also refuses
directory junctions (Incorrect function), so node_modules cannot be redirected off
the volume either.
So dependencies are installed on local disk, bundled into a single file, and only that file is written back to Drive. It needs nothing but Node to run, and there is no dependency tree left for sync to corrupt.
After changing anything under src/:
npm run buildthen restart Claude Desktop. src/auth-cli.js is not bundled — it imports only Node
built-ins, so it runs from Drive as-is.
Cloud routines
Cloud sessions have no access to your home directory, so credentials come from the
environment instead. Set GMAIL_MULTI_ACCOUNTS on the cloud environment to the
contents of accounts.json — raw JSON, or base64 if the shell mangles quotes — and
commit a .mcp.json to a repository the routine clones.
*.googleapis.com and accounts.google.com are already on the default Trusted
network allowlist, so no allowlist change is needed.
The two things this server is careful about
Unverified From addresses. Gmail does not reliably error when you set a From
the account cannot send as — it silently substitutes the primary address. A draft
meant to go out as one business quietly goes out as another. So every from is
checked against users.settings.sendAs.list first and rejected if it is not verified.
The primary address reports an empty verificationStatus rather than accepted, so
it is admitted via isPrimary.
Draft updates. drafts.update is a full PUT replace, not a patch. update_draft
reads the existing draft, merges your changes over it, and rebuilds — preserving
threadId and the In-Reply-To/References headers, without which the draft
silently detaches from its thread. The draft id is stable across updates even though
the underlying message id changes each time, so key any state off draftId.
Development
npm testCovers the MIME builder: base64url alphabet, multipart structure, RFC 2047 header
encoding, threading headers, line wrapping, and payload extraction. No parser is
needed — drafts are read back with format=full, which returns a decoded tree.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/in2guitar/gmail-multi-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server