gmail-mcp

Your Gmail accounts, served to any MCP client, from your own Cloudflare Worker. Roughly ten minutes to deploy.

22 tools OAuth 2.1 + PKCE multi-account scope gmail.modify MIT
MCP clientClaude Code · claude.ai · mobile
your WorkerOAuth server + agent
Gmail APIone mailbox per grant

Every connection performs its own Google sign-in, so two mailboxes can be connected to one deployment at the same time — each permanently bound to the account chosen at its consent screen. Your refresh tokens stay in your own Cloudflare account.

1 Google Cloud

Create a project and switch the Gmail API on.

PROJECT="gmail-mcp-$(openssl rand -hex 3)"
gcloud auth login
gcloud projects create "$PROJECT" --name="gmail-mcp"
gcloud config set project "$PROJECT"
gcloud services enable gmail.googleapis.com

The consent screen and the OAuth client have no API, so these two are browser steps:

  1. OAuth consent screenExternal → app name and your email. While the app is unverified, add every mailbox you plan to connect under Test users.
  2. Credentials → Create credentials → OAuth client IDWeb application, with one authorized redirect URI:
    https://<your-domain>/callback
    Keep the client ID and secret for the next step.
Adding http://localhost:8788/callback as a second redirect URI now saves a trip back if you ever run bun run dev.

2 Cloudflare

Clone, point the Worker at your domain, and let the setup script do the rest.

git clone https://github.com/mkpoli/gmail-mcp && cd gmail-mcp
bun install
# edit wrangler.jsonc — set `name` and the routes `pattern` to your domain
bun run setup

bun run setup creates the KV namespace, prompts for each secret, generates the cookie key, and deploys. It is safe to re-run — every step can be skipped.

3 Decide who may sign in

ALLOWED_EMAILS is checked against the address Google reports as verified, after consent and before any grant exists.

ValueWho gets in
emptynobody — fail-closed default
you@gmail.com, work@co.comexactly those accounts
*@your-company.comany account in that domain
*any verified Google account
A grant only ever reaches the mailbox that authenticated it, so widening this list never widens access to accounts already connected. What * hands strangers is the use of your deployment, and your Google client's quota, for their own mail.

4 Connect

No client ID or secret on the client side — MCP clients register themselves.

claude mcp add --transport http gmail-personal https://<your-domain>/mcp
claude mcp add --transport http gmail-work     https://<your-domain>/mcp/work

Run /mcp in Claude Code to authenticate each one, signing in with the matching Google account. In claude.ai: Settings → Connectors → Add custom connector, paste the URL, leave the credential fields empty.

Any single-segment label works — /mcp/work, /mcp/family. It exists so clients that refuse two servers sharing a URL can still hold several mailboxes.

5 What you get

Read — search with Gmail operators, read messages and threads, download attachments
Compose — send, reply to everyone with quoting, full draft lifecycle, attachments and inline images
Organize — labels including nested ones, batch changes over many messages, reversible trash

Japanese, Chinese, emoji, and right-to-left text survive the round trip: subjects and filenames are RFC 2047 encoded, bodies carry their declared charset.