multi-gmail-cowork-mcp
Allows connecting and managing multiple independent Gmail accounts, enabling search, read, compose, and send email operations with results attributed to the account alias and verified email address.
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., "@multi-gmail-cowork-mcpSearch all connected Gmail accounts for emails from David."
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.
multi-gmail-cowork-mcp
A small, self-hosted MCP server that lets one Claude custom connector search, read, compose, and send through multiple, independently-authenticated Gmail accounts. Built to be deployed by anyone into their own Google Cloud project, with zero shared infrastructure and zero code changes required per deployment.
Claude Cowork
|
v
Your private Multi-Gmail MCP (your own Cloud Run project)
|
+-- Gmail account: "personal"
+-- Gmail account: "work"
+-- Gmail account: "billing"
+-- ...more, added any time via the admin pageAsk Claude things like:
"Search my work Gmail for emails from David."
"Search all connected Gmail accounts for 'invoice 4831'."
"Read the latest email from ACH Works, whichever account received it."
"Which of my Gmail accounts received an email from John yesterday?"
Every result is explicitly attributed to the account alias and email address it came from. If you ask for an account that isn't connected, or whose authorization has expired, you get a clear error — this server never silently substitutes a different account.
What this is not
Gmail only. No Calendar, Drive, Docs, Sheets, or Contacts. No permanent-delete tool. No shared backend, no central account, no telemetry.
Related MCP server: Gmail MCP
Privacy model — who can see your email
Google <-> Your Google Cloud deployment <-> Claude / AnthropicYou deploy this into your own Google Cloud project, using your own Google OAuth client and your own Cloud Run service.
Google issues/can revoke the OAuth grants; it sees ordinary OAuth traffic.
Your deployment is the only place Gmail refresh tokens are ever stored.
Claude/Anthropic sees whatever the tools return when Claude calls them (same as any other MCP tool) — nothing more, nothing when you're not using it.
The author of this repository sees none of your email, ever. There is no shared server. Your cousin's deployment and your deployment have nothing in common except the source code.
Read SECURITY.md for the full trust-boundary and design-rationale writeup — including exactly why authentication is implemented the way it is, and this project's known limitations. This README does not repeat that reasoning.
Architecture at a glance
Language/runtime: TypeScript on Node.js 20+, using the official
@modelcontextprotocol/sdkand Google'sgoogle-auth-library.Transport: Streamable HTTP (the current MCP-recommended remote transport), stateless — every request is handled independently, so it scales cleanly on Cloud Run with no session affinity required.
Claude <-> server auth: MCP OAuth 2.1 authorization-code flow with PKCE/S256, Dynamic Client Registration, short-lived access tokens, rotating refresh tokens, and deployment-local authorization state in Secret Manager.
Server <-> Google auth: standard OAuth 2.0 with PKCE, one grant per connected Gmail account,
gmail.modifyscope (read, compose, send, and mailbox modification; no permanent delete).Account storage: one Google Secret Manager secret holding a small JSON array (alias, email, refresh token). No database.
Admin UI: a few unstyled HTML pages behind HTTP Basic Auth — just enough to connect or disconnect accounts.
Prerequisites
A Google account and a Google Cloud project with billing enabled (the bootstrap prints the exact billing page if billing is not linked).
A Claude plan that supports custom connectors (for connecting to Cowork/claude.ai).
Nothing else is required for a deployment: Google Cloud Shell already includes
gcloud,curl,openssl, andjq.
Cost and billing
Cloud Run requires a billing-enabled project. This deployment is sized for personal/small-business use: min instances 0 (scales to zero when idle) and max instances 3. Normal usage — a handful of searches, reads, and sends per day — stays well inside Google Cloud's Always Free allowance for Cloud Run, so the realistic ongoing cost is $0. That is not a guarantee: a sustained burst of requests beyond the free allowance would incur normal Cloud Run charges. The bootstrap prints an optional budget-alert link if you want a notification before any spend.
One-command Cloud Shell setup (recommended)
Open this repository in Google Cloud Shell using the button above (or use Open in Cloud Shell on GitHub).
Authenticate if Cloud Shell asks, then run:
./scripts/bootstrap.shThe script asks you to select a project (or creates one), checks billing, enables the required APIs, creates the dedicated Cloud Run runtime service account, assigns only the Secret Manager roles it needs, creates all secrets, deploys Cloud Run, and prints PASS/FAIL checks. It is safe to rerun: existing secrets, account records, OAuth credentials, and Cloud Run services are preserved.
The script never prints a password, OAuth client secret, refresh token, account-store JSON, or
MCP OAuth token. Secret values are written as exact bytes (no trailing-newline credential bug).
Use ./scripts/bootstrap.sh --check for a read-only Cloud Shell prerequisite check.
The one unavoidable Google browser step
Google does not provide a safe, supported API/CLI operation for creating a general-purpose web OAuth client. When the bootstrap asks, open the Google Auth Platform page it prints and do the following:
Configure the app as External, add the scope
https://www.googleapis.com/auth/gmail.modify, and add the Gmail addresses you will use as test users.Create an OAuth client with application type Web application.
Enter the exact callback URI printed by the script:
https://<your-cloud-run-host>/oauth/google/callback.Paste the resulting Client ID and Client Secret into the hidden prompts in Cloud Shell.
If Google shows an unverified-app warning, that is expected for a personal deployment. Publish the consent screen to In production if you want refresh tokens to remain valid beyond the Testing-mode seven-day limit; verification is not required for a personal/small deployment.
At the end, bootstrap prints the Admin URL, exact Google OAuth callback URL, MCP URL, and the next human action. Claude authenticates to the MCP endpoint through its supported OAuth flow; there is no static connector header to copy or put in a URL.
Connect Gmail accounts
Retrieve the admin password (generated by the bootstrap, never printed) with the command the bootstrap printed at the end:
gcloud secrets versions access latest --secret=admin-password --project=YOUR_PROJECT_IDThen open the printed Admin URL and sign in with username
adminand that password.Enter a short alias such as
personalorwork, click Add Gmail Account, and complete Google authorization. The authorization URL requestsconsent select_account, so Google shows the account chooser every time. The address displayed after callback is the address Google actually authorized; it is not taken from the alias field.Repeat for as many Gmail accounts as desired. Each alias is independent and all results are attributed to both alias and verified Gmail address.
Connect Claude Cowork
In Claude, open Settings → Connectors → Add custom connector and enter exactly:
Connector name:
Multi GmailRemote MCP URL: the printed URL ending in
/claude-mcpOAuth Client ID: leave blank (the server supports Dynamic Client Registration)
OAuth Client Secret: leave blank
The /mcp route remains available for existing clients; use /claude-mcp for new Claude
connectors so its OAuth resource identity is independent of older connector records.
Click Add, then Connect. Claude discovers the MCP authorization metadata, registers
itself, and opens the deployment's Authorize MCP access page. Sign in there with username
admin and the admin password stored in your own admin-password Secret Manager secret, then
approve. Claude redirects through its callback at
https://claude.ai/api/mcp/auth_callback, stores the OAuth tokens, and reconnects. Do not
enter the Gmail OAuth client ID or secret in Claude — those belong only to Google's Gmail setup.
After the connector is connected, ask Claude to call list_accounts, then run an
alias-specific search for each account and search_all_accounts to verify attribution.
Verify your deployment
scripts/acceptance_test.mjs proves every tool works end-to-end against your own
deployment — account isolation, no-fallback on a bad alias, drafts, and send with
arrival and correct From identity. It performs the full MCP OAuth flow as a real
remote client and never prints tokens:
MCP_BASE_URL=https://your-service.run.app \
MCP_ADMIN_PASSWORD='...' # Secret Manager -> admin-password
node scripts/acceptance_test.mjsThe send test sends one email account-A → account-B and one account-B → account-A,
so the recipient is always an account you own. Set SKIP_SEND=1 to skip sends.
Local development (optional)
For source development only, install Node.js 20+, run npm install, copy .env.example to
.env, set TOKEN_STORE=file, and use npm run dev. Local Gmail OAuth requires a separate
OAuth client callback such as http://localhost:8080/oauth/google/callback; do not reuse or
commit production secrets. Windows users can use scripts/setup.ps1 and scripts/deploy.ps1
instead of the Cloud Shell bootstrap.
Reauthorizing / revoking accounts
After upgrading from the earlier read-only release, each existing account is marked Needs
Gmail permission upgrade. Open /admin, click Reauthorize for the same alias, and
complete Google's consent screen. The callback verifies that Google actually granted
https://www.googleapis.com/auth/gmail.modify before replacing that alias's stored refresh
token. Until then, read tools continue to work with the old grant, while write tools return a
clear reauthorization message; no other alias is ever used.
To remove access, click Disconnect next to an account. This revokes the grant with Google (best-effort) and removes it from the credential store immediately — Claude will get a clear "not connected" error if it's asked for that alias afterward, never a silent fallback.
To reconnect the same alias after revoking access on Google's side, use Connect account with the same alias — it overwrites the old record only after successful Google authorization.
Write tools and safety
The deployed server exposes create_draft and send_email. Both require an explicit
connected-account alias and never fall back to another account. send_email always sends
from the selected Gmail identity; the result includes that verified address. The tools use
gmail.modify, not the broader mail.google.com scope, and there is no permanent-delete
tool. Claude connector permissions should allow read tools automatically while keeping
create_draft and send_email set to Needs approval.
Updating and rotating
Update the deployment after changing source or to pick up a new secret version: rerun
./scripts/bootstrap.sh(idempotent — preserves accounts, tokens, and the OAuth client) or, on Windows,scripts/deploy.ps1. Existing Gmail connections and the Claude connector are unaffected.Rotate the admin password: add a new Secret Manager version for
admin-passwordand redeploy. Existing Claude connector tokens stay valid (they are not derived from the admin password); only future MCP consent approvals use the new password.Rotate
oauth-state-secret: this signs every MCP OAuth token, so rotating it invalidates the Claude connector's existing tokens — reconnect Claude afterward. Pending Gmail-linking state tokens (10-minute lifetime) also invalidate; connected Gmail accounts are untouched.Rotate a Gmail account's grant: reconnect the alias from the admin page (see Reauthorizing / revoking accounts).
How to delete everything
Remove Gmail access: disconnect each account from
/admin, or revoke access directly at https://myaccount.google.com/permissions.Tear down the deployment:
gcloud run services delete multi-gmail-mcp --region us-central1 gcloud secrets delete mcp-oauth-state admin-password oauth-state-secret google-client-id google-client-secret gmail-mcp-accounts gcloud iam service-accounts delete multi-gmail-mcp-run@YOUR_PROJECT_ID.iam.gserviceaccount.comDelete the OAuth client: Cloud Console -> APIs & Services -> Credentials -> delete the OAuth client ID, and optionally delete the OAuth consent screen configuration.
Or simplest: delete the whole Google Cloud project.
Troubleshooting
"Account needs to be reconnected" errors: the stored refresh token was rejected by Google (revoked, expired, or the consent screen is stuck in "Testing" — see below). Reconnect it from
/admin.Refresh tokens keep dying after ~7 days: your OAuth consent screen is still in "Testing" publishing status. Publish it to "In production" (see step 3) — it can stay unverified, that's fine for personal use.
Claude can't reach the connector / connection fails silently: confirm the service URL resolves over plain HTTPS with no redirect to a different host, then open the MCP URL ending in
/claude-mcpin Claude and click Connect again. The server must return OAuth metadata and a 401 challenge when called without an access token; no static request header is required.gcloud run deployfails on APIs not enabled: re-runscripts/setup.ps1, or rungcloud services enable run.googleapis.com cloudbuild.googleapis.com artifactregistry.googleapis.com secretmanager.googleapis.com gmail.googleapis.com iam.googleapis.com.Local dev can't reach Google over HTTPS (certificate errors): this is almost always a local machine issue (a corporate proxy or antivirus doing TLS interception), not a bug in this project — check your machine's trusted root certificates.
Google OAuth Testing vs. longer-term use
Google Cloud OAuth clients start in Testing publishing status. While in Testing,
refresh tokens for sensitive/restricted scopes (which includes gmail.modify) expire
after 7 days, regardless of how few users you have — this will silently break the
connector on a weekly basis if left as-is.
The fix is not Google verification (a multi-month process built for public SaaS). It's
simpler: click Publish app to move the consent screen to In production. For an app
requesting only gmail.modify and staying under 100 total connected Google accounts,
Google's own documentation treats this as a fully supported personal/small-scale use case —
no verification required. The only visible effect is that each newly-connected account sees
a one-time "Google hasn't verified this app" click-through warning before granting consent.
That warning is expected; it does not mean anything is misconfigured. See
SECURITY.md for the underlying rules and
sources.
Repository layout
src/ TypeScript source (server, MCP tools, admin/setup UI, OAuth flows)
scripts/ bootstrap.sh (Cloud Shell), setup.ps1/deploy.ps1 (Windows),
acceptance_test.mjs (verify any deployment end-to-end)
.env.example Local-dev configuration template (placeholders only)
SECURITY.md Trust model, design rationale, known limitationsLicense
MIT — see LICENSE.
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.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceServer for Gmail integration in Claude Desktop with auto authentication support. This server enables AI assistants to manage Gmail through natural language interactions.26,6781,165MIT
- AlicenseNot gradedqualityDmaintenanceA server that allows Claude to search and retrieve emails from your Gmail account, supporting functions like searching emails, retrieving full content of specific emails, and listing recent messages.7Apache 2.0
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables Claude AI to interact with Gmail, supporting email sending, reading, searching, labeling, draft management, and batch operations through natural language commands.2MIT
- -licenseNot gradedqualityNot gradedmaintenanceA Model Context Protocol server that enables Claude to interact with Gmail through a secure OAuth2 connection, providing email management capabilities like listing, sending, deleting, and organizing emails.
Related MCP Connectors
Manage Gmail end-to-end: search, read, send, draft, label, and organize threads. Automate workflow…
Manage Gmail messages, threads, labels, drafts, and settings from your workflows. Send and organiz…
Read, search, send, organize, draft and schedule email across your inboxes from any MCP client.
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/reconexus/multi-gmail-cowork-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server