Skip to content

tirth97/gmail-modify-mcp

Repository files navigation

gmail-modify-mcp

A tiny Model Context Protocol server that adds one tool to any MCP client (Claude Code, Claude Code Desktop, Claude Desktop, and — with path A below — hosted Cowork):

gmail_modify_labels(message_id, add_label_ids?, remove_label_ids?)

Why it exists: Anthropic's hosted Gmail MCP connector at gmail.mcp.claude.com supports reads and draft creation but cannot modify message labels, which blocks every inbox-management workflow — archive, mark read/unread, star, trash, categorize. Tracked upstream in anthropics/claude-code#36547.

Run this server alongside the hosted connector. The hosted one handles all the read tools, this one handles label mutations.

What it can do

Action Call
Archive remove_label_ids=["INBOX"]
Mark as read remove_label_ids=["UNREAD"]
Mark as unread add_label_ids=["UNREAD"]
Star add_label_ids=["STARRED"]
Move to trash add_label_ids=["TRASH"]
Apply custom label add_label_ids=["Label_1234567890"]

Permanent delete is intentionally not supported — the OAuth scope used (gmail.modify) does not grant it.

CLI reference

gmail-modify-mcp           run the MCP server on stdio (default; no subcommand needed)
gmail-modify-mcp serve     same as above, explicit
gmail-modify-mcp auth      run the OAuth consent flow (prompts for credentials if needed)
gmail-modify-mcp status    print the authenticated account profile (sanity check)

The server also exposes a gmail_setup MCP tool that accepts client_id and client_secret (plus optional endpoint overrides) for setup directly from Claude Code chat.


Two ways to use this

Option A — Use a hosted instance Option B — Run it yourself locally
Who runs the server? A public HTTPS endpoint (not yet deployed) You, on your own machine
Works with hosted Cowork (claude.ai web)? ✅ Yes (the only way) ❌ No — Cowork runs in Anthropic's cloud and can't reach a local stdio process
Works with Claude Code (CLI)? ✅ Yes ✅ Yes
Works with Claude Code Desktop / Claude Desktop (chat app)? ✅ Yes ✅ Yes
Your Gmail credentials leave your machine? Yes — to whatever machine runs the hosted instance No — everything stays local
Setup effort Paste one URL into Cowork's connector dialog ~10 minutes, see below
Status today Planned / not live ✅ Working — instructions below

Option A is not implemented yet. Until that's built, everyone uses Option B.


Option A — Use a hosted instance (planned)

Not live yet. When it is, the UX will be:

  1. Visit https://<hosted-instance>/authorize once in your browser, grant Gmail access.
  2. Open claude.ai → Settings → Connectors → Add custom connector.
  3. URL: https://<hosted-instance>/mcp. Auth header: the bearer token you're given at the end of step 1.
  4. Done — gmail_modify_labels appears alongside the hosted Gmail read tools in every Cowork session.

The architecture, security model, and phased task list are tracked separately and not in this repo yet.


Option B — Run it yourself locally

Everything below is what's working today. All of it ran end-to-end on a Windows 11 machine in ~10 minutes.

Prerequisites

  • Python 3.11 or newer
  • Git
  • A Google account whose Gmail you want this to manage
  • Access to the Google Cloud Console at https://console.cloud.google.com/ (free)
  • One of: Claude Code (CLI), Claude Code Desktop (ccd), or the legacy Claude Desktop installed

Step 1 — Install the Python package

Pick one of these. Both produce the same gmail-modify-mcp command.

Step 1a — pipx (recommended, truly cross-OS, no venv to activate)

pipx installs Python CLIs into isolated venvs and exposes them on your global PATH. Same commands on macOS, Linux, and Windows.

# install pipx once
python -m pip install --user pipx && python -m pipx ensurepath

# install this tool straight from GitHub
pipx install git+https://github.com/tirth97/gmail-modify-mcp.git

After this, gmail-modify-mcp is a regular command on your PATH. Upgrade later with pipx upgrade gmail-modify-mcp. uv tool install git+https://github.com/tirth97/gmail-modify-mcp.git works equivalently if you prefer uv.

Step 1b — Clone + editable install (best for hacking on the code)

git clone https://github.com/tirth97/gmail-modify-mcp.git
cd gmail-modify-mcp
python -m venv .venv

# macOS / Linux / WSL / Git Bash
./.venv/bin/python -m pip install -e .

# Windows PowerShell / cmd.exe
.\.venv\Scripts\python.exe -m pip install -e .

The gmail-modify-mcp entry-point now lives at .venv/bin/gmail-modify-mcp (POSIX) or .venv\Scripts\gmail-modify-mcp.exe (Windows). It's on PATH only when the venv is activated.

To skip venv activation, the repo ships two thin launcher scripts at the project root that forward to the venv entry point:

# macOS / Linux / WSL / Git Bash
./gmail-modify-mcp status

# Windows cmd.exe
gmail-modify-mcp status

# Windows PowerShell
.\gmail-modify-mcp status

These detect both .venv/bin/ and .venv/Scripts/ automatically and fail with a clear "venv not found" message if you skipped the install step.

Step 2 — Create Google Cloud OAuth credentials

Manual, browser-only. Do not skip sub-steps 3 and 4 below or you'll get Error 403: access_denied.

  1. Open https://console.cloud.google.com/ and create (or pick) a project.
  2. APIs & Services → Library → Gmail API → Enable.
  3. APIs & Services → OAuth consent screen → choose External.
  4. Under Test users, click + Add users and add your own Gmail address.
  5. APIs & Services → Credentials → + Create credentials → OAuth client ID.
  6. Application type: Desktop app. Name it anything. Click Create.
  7. Copy the Client ID and Client Secret shown on the screen — you'll paste them in the next step.

Advanced: If you prefer, you can still download the JSON, rename it to credentials.json, and place it in the project root (or wherever GMAIL_MCP_CREDENTIALS points). The interactive setup in Step 4 is only triggered when no credentials.json exists.

Step 3 — Wire it into your Claude client

Depending on which Claude you use, pick one (or more — they're independent).

Step 3a — Claude Code Desktop / Claude Desktop (the chat app)

Both the newer Claude Code Desktop (ccd) app and the legacy Claude Desktop app read MCP servers from the same config file:

OS Path
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json
Linux ~/.config/Claude/claude_desktop_config.json

Open it (create it if it doesn't exist) and add a mcpServers entry. If the file already has other top-level keys like preferences, preserve them — just add mcpServers alongside.

If you installed via Step 1a (pipx):

{
  "mcpServers": {
    "gmail-modify-mcp": {
      "command": "gmail-modify-mcp",
      "args": []
    }
  }
}

If you installed via Step 1b (clone + venv), point at the absolute path of the entry script inside your venv:

{
  "mcpServers": {
    "gmail-modify-mcp": {
      // macOS / Linux
      "command": "/absolute/path/to/gmail-modify-mcp/.venv/bin/gmail-modify-mcp",
      // Windows
      // "command": "C:\\absolute\\path\\to\\gmail-modify-mcp\\.venv\\Scripts\\gmail-modify-mcp.exe",
      "args": []
    }
  }
}

Then fully quit the app (system tray → right-click → Quit on Windows, ⌘Q on macOS — closing the window is not enough) and reopen it. In a new chat ask:

What MCP tools do you have available?

gmail_modify_labels should be in the list.

Step 3b — Claude Code (CLI)

Two ways. Pick whichever fits your workflow.

Project-scoped .mcp.json — auto-discovered when Claude Code is launched from this directory. The repo ships .mcp.json.example with placeholder paths:

# macOS / Linux / WSL / Git Bash
cp .mcp.json.example .mcp.json
# Windows PowerShell
Copy-Item .mcp.json.example .mcp.json

Edit the new .mcp.json and replace /absolute/path/to/gmail-modify-mcp with your real clone path. The real .mcp.json is gitignored — your absolute paths never leak into a public commit.

Globally via claude mcp add — available everywhere, not tied to a directory:

# If installed via pipx
claude mcp add --scope user gmail-modify-mcp -- gmail-modify-mcp

# If installed via clone (point at the venv entry script)
claude mcp add --scope user gmail-modify-mcp -- \
  "/absolute/path/to/gmail-modify-mcp/.venv/bin/gmail-modify-mcp"

Step 3c — Hosted Cowork (claude.ai web)

Not supported by Option B. Cowork runs in Anthropic's cloud and can only connect to MCP servers that are reachable from Anthropic's public IP ranges over HTTPS. A local stdio server on your laptop is, by definition, not reachable. Use Option A (the hosted instance — not live yet) when you need Cowork support, or use Claude Code / Claude Desktop today.

Step 4 — First-run OAuth consent

Now authorize the server with your Google account. Pick one of the two options below.

Option A — Via terminal (works everywhere)

gmail-modify-mcp auth

If no credentials.json exists, it will prompt you to paste the Client ID and Client Secret from Step 2:

OAuth client secrets not found. Let's set them up.

You need a Google Cloud OAuth client ID (Desktop type).
Create one at: https://console.cloud.google.com/apis/credentials

Paste your Client ID: 362580762768-xxxx.apps.googleusercontent.com
Paste your Client Secret: GOCSPX-xxxx
Auth URI (press Enter for default):
Token URI (press Enter for default):
Redirect URI (press Enter for default):

Credentials saved to: .../credentials.json
Authorized as: you@gmail.com
Token cached at: .../token.json

Most users should press Enter for the Auth URI, Token URI, and Redirect URI prompts to use the Google defaults. Override these only if Google changes their endpoints.

Option B — Via Claude Code chat (no terminal needed)

If you already wired the server into Claude Code (Step 3b), just open a chat and tell Claude:

Set up Gmail with client ID YOUR_CLIENT_ID and client secret YOUR_CLIENT_SECRET.

Claude will call the gmail_setup tool, which saves your credentials and opens the browser for consent.

Verify

gmail-modify-mcp status
# Authorized as : you@gmail.com
# Messages total: 1341
# Threads total : 930

If you see the profile, you're done with the backend. Future runs refresh the token silently — you never have to auth again unless you delete token.json or change scopes.

Step 5 — Verify end-to-end

In a chat/session with both this server and the hosted Gmail connector enabled:

Find the most recent unread newsletter in my inbox and archive it.

Expected behavior: the model uses gmail_search_messages (hosted) to find a candidate → calls gmail_modify_labels (this server) with remove_label_ids=["INBOX"] → the message disappears from your inbox.

Or, for a harmless reversible test:

Star the most recent email from GitHub.

Then ask it to remove the star:

Unstar it again.

If both work, you're done.


File layout

gmail-modify-mcp/
├── .gitattributes             line-ending policy (LF for shell, CRLF for .bat)
├── .gitignore                 excludes credentials.json, token.json, .venv, .claude/, .mcp.json
├── .mcp.json.example          template for Claude Code project-scoped registration
├── LICENSE                    MIT
├── pyproject.toml             package metadata + gmail-modify-mcp entry point
├── README.md                  this file
├── gmail-modify-mcp           POSIX launcher (Option 1b) — forwards to .venv/bin
├── gmail-modify-mcp.bat       Windows launcher (Option 1b) — forwards to .venv\Scripts
├── credentials.json           (you provide; gitignored)
├── token.json                 (auto-created on first auth; gitignored)
└── gmail_mcp_server/
    ├── __init__.py
    ├── auth.py                OAuth desktop flow + token refresh
    └── server.py              FastMCP server, gmail_modify_labels tool, CLI

Environment variables

Variable Default Purpose
GMAIL_MCP_CREDENTIALS <project>/credentials.json Override OAuth client secrets path.
GMAIL_MCP_TOKEN <project>/token.json Override cached token path.

Useful if you want to keep secrets in %APPDATA% / ~/.config instead of the project root.

Security notes

  • The OAuth scope used is https://www.googleapis.com/auth/gmail.modify. This grants read + label modification but not permanent delete. That's intentional.
  • credentials.json and token.json are in .gitignore. Don't git add -f them. The gitignore also catches Google's default client_secret*.json download filename.
  • Move-to-trash is supported via add_label_ids=["TRASH"]. The TRASH label is reversible — the message stays in Trash for 30 days before Google purges it.
  • This server only exposes one tool. It cannot read messages, send mail, or change account settings.
  • .mcp.json is gitignored because it contains absolute local paths. Always copy from .mcp.json.example.

Troubleshooting

Symptom Fix
OAuth client secrets not found credentials.json is missing. Run gmail-modify-mcp auth and paste your Client ID/Secret when prompted.
Error 403: access_denied in the consent browser You weren't added as a Test user in the OAuth consent screen. Go back to Step 2.4.
Top-level key in credentials.json is "web" instead of "installed" You created a Web OAuth client. Make a Desktop app client instead and re-download.
invalid_grant / scope errors Delete token.json and re-run gmail-modify-mcp auth.
HttpError 403: Insufficient Permission from modify Cached token has narrower scope. Delete token.json and re-consent.
Server "hangs" after launch Correct: stdio MCP servers wait for a client. Claude Code launches them on demand.
gmail-modify-mcp: command not found in a fresh terminal (Option 1b) Your venv isn't activated. Either activate it or use the ./gmail-modify-mcp launcher.
Restarted the chat app but tool still missing You closed the window instead of fully quitting. System-tray Quit on Windows, ⌘Q on macOS.
Want Cowork (claude.ai web) support Option B cannot do this. Wait for Option A, which requires a hosted HTTPS MCP endpoint.

Related issues

  • #36547gmail_modify_labels missing from hosted Gmail MCP (the reason this exists)
  • #32266gmail_send_draft missing from hosted Gmail MCP

License

MIT

About

Local MCP server adding gmail_modify_labels (archive/star/trash/label) for Claude Code. Fills the gap in Anthropic's hosted Gmail connector (anthropics/claude-code#36547).

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors