Skip to main content
Glama
ganeshhgupta

gmail-mcp-server

by ganeshhgupta

gmail-mcp-server

MCP server exposing one tool, send_email, that sends Gmail messages (with optional file attachments) via the Gmail API. Built for use as a local stdio MCP server inside Claude Code.

Scope is deliberately narrow: gmail.send only (no read/modify access to the mailbox) — least privilege for a tool whose only job is sending mail.

This README is written from an actual first-time setup, including every error that came up along the way. Follow it top to bottom and you should not hit any of them.

PowerShell note: && does not work as a command separator in Windows PowerShell (that's bash/cmd syntax). Every multi-command line below is written as separate lines, or use ; if you want one line: cd C:\Users\GaneshGupta\gmail-mcp-server; python auth_setup.py


1. Google Cloud — enable the API and create OAuth credentials

Google's console UI for this was recently renamed from "OAuth consent screen" to Google Auth Platform, with the settings split across separate left-nav pages (Branding / Audience / Clients / Data Access / Verification Center). The steps below use the current names.

  1. Go to console.cloud.google.com. Create a new project or reuse an existing one.

  2. APIs & Services → Library → search "Gmail API" → Enable.

  3. APIs & Services → OAuth consent screen (this lands you in the new Google Auth Platform section) → fill in the Branding page:

    • App name: anything, e.g. gmail-mcp-tool

    • User support email: your Gmail address

    • Developer contact email: your Gmail address

    • Leave logo/App domain fields blank for now — you'll come back to App domain in step 4 if you hit the "incomplete configuration" error. Don't fill them speculatively; only do it if you actually see that error.

  4. Audience page (left nav) → under Test users+ Add users → enter your own Gmail address (the one that will send mail) → Save.

    If "Add users" is blocked by a yellow banner reading "Your app's OAuth configuration is incomplete... Please visit the Branding page" — this happens because gmail.send is a sensitive scope, which requires the App domain fields to be non-empty even for a Testing-only app. Fix:

    • Go to Branding → App domain, fill in:

      • Application home page: https://example.com

      • Application privacy policy link: https://example.com/privacy

      • Application terms of service link: https://example.com/terms

    • This will surface an Authorized domains field. Enter the bare domain only — no https:// prefix:

      • Correct: example.com

      • Wrong (rejected with "Invalid domain: must not specify the scheme"): https://example.com

    • Save on Branding (you should see a "Branding changes saved!" toast).

    • Go back to Audience → Add users and try again — it will go through this time.

    These URLs don't need to be real/functional — Google doesn't verify them while the app stays in Testing status, it just requires the fields to be filled.

  5. Clients page (left nav) → + Create client:

    • Application type: Desktop app

    • Name: anything, e.g. gmail-mcp-desktop

    • Create → Download JSON (button appears right after creation)

  6. The downloaded file will be named something like client_secret_<long-id>.apps.googleusercontent.com.json. Rename it exactly to client_secret.json and move it into:

    C:\Users\GaneshGupta\gmail-mcp-server\credentials\client_secret.json

    The exact filename matters — gmail_auth.py looks for it by that name and raises FileNotFoundError if it doesn't match (this is the most common thing to get wrong here).

Related MCP server: Gmail MCP Server

2. Install dependencies

cd C:\Users\GaneshGupta\gmail-mcp-server
pip install -r requirements.txt

3. One-time login

python auth_setup.py

What happens:

  1. A browser window opens to a normal Google sign-in.

  2. You'll land on "Google hasn't verified this app". This is expected — it's your own OAuth client, in Testing mode, requesting a sensitive scope. Click Continue (older UI: Advanced → Go to [app name] (unsafe)).

  3. Grant the "Send email on your behalf" permission.

  4. Browser shows "The authentication flow has completed. You may close this window."

  5. Terminal prints Authorized. Token saved to ...credentials\token.json.

If step 2 instead shows Error 403: access_denied / "has not completed the Google verification process... can only be accessed by developer-approved testers" — your Gmail address isn't in the Audience → Test users list yet. Go back to step 1.4 above.

Do this once. After this, server.py only ever silently refreshes the saved token — it never opens a browser again on its own.

python -c "from gmail_auth import load_credentials; c = load_credentials(); print('valid:', c.valid); print('scopes:', c.scopes); print('has refresh token:', bool(c.refresh_token))"

Expect valid: True, scopes: ['https://www.googleapis.com/auth/gmail.send'], has refresh token: True.

5. Register with Claude Code

claude mcp add gmail-sender --scope user -- python C:\Users\GaneshGupta\gmail-mcp-server\server.py

--scope user registers it globally — it becomes available in every Claude Code session on this machine from then on, not just the one where you ran the command. It will not appear retroactively in a session that's already running — MCP servers load at session start, so use a new terminal / new claude session to see it.

Verify:

claude mcp list

You should see gmail-sender in the list.

6. Using it

In any Claude Code session (after the registration above), just ask in natural language:

Send an email to jane@example.com with subject "Following up" and body "..." — attach C:\path\to\file.pdf

Claude Code will call the send_email tool directly. No further setup needed per-session.

Tool reference

send_email(to, subject, body, attachments=None, cc=None, bcc=None, html=False)

  • to / cc / bcc: comma-separated addresses

  • attachments: list of absolute local file paths, 15MB combined limit (Gmail's raw-send cap is 25MB; 15MB of raw files leaves headroom for base64 inflation + headers)

  • html: set true to send an HTML body instead of plain text

  • Returns {status, message_id, thread_id, to, subject, attachment_count}

Troubleshooting index

Symptom

Cause

Fix

FileNotFoundError: Missing OAuth client secret at ...

Downloaded JSON kept Google's default long filename

Rename to exactly credentials\client_secret.json

Error 403: access_denied — "has not completed Google verification"

Your account isn't a Test user yet

Audience → Test users → Add your Gmail address

Audience page: "Your app's OAuth configuration is incomplete" banner blocking Add users

Sensitive scope (gmail.send) requires App domain fields

Fill Branding → App domain (home page/privacy/terms) with any https:// URL, save

"Invalid domain: must not specify the scheme" on Authorized domain field

Entered https://example.com instead of bare domain

Enter example.com only, no http(s)://

"Google hasn't verified this app" warning during login

Expected — your own OAuth client in Testing mode

Click Continue (or Advanced → Go to app), this is normal, not an error

&& gives The token '&&' is not a valid statement separator

That's bash syntax, not PowerShell

Use ; or put commands on separate lines

gmail-sender not showing up in Claude Code

Registered after the current session started, or wrong scope

Open a new claude session; check claude mcp list; re-run claude mcp add with --scope user

Need to send from a different Gmail account

Token is tied to whichever account you logged in as

Delete credentials\token.json and re-run python auth_setup.py

Attachment rejected / send fails on large files

Combined attachments over 15MB

Split into multiple emails or compress

Notes

  • credentials/client_secret.json and credentials/token.json are gitignored — never commit them.

  • To send from a different Gmail account, delete credentials/token.json and re-run auth_setup.py.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

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/ganeshhgupta/gmail-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server