gmail-mcp
Provides tools for reading, searching, sending, drafting, labeling, filtering, and threading Gmail messages through the Gmail API, with scope-gated access and security safeguards.
π§ gmail-mcp
Read, search, send, draft, label, filter, and thread Gmail from any MCP-enabled AI assistant. Wraps the Gmail API with scope-gated tools and in-process safeguards.
Hardened + enhanced fork ofGongRzhe/Gmail-MCP-Server (archived 2026-03-03), via ArtyMcLabin/Gmail-MCP-Server. Since the divergence point: 180+ commits and an extensive rewrite β security hardening, Gmail-surface improvements (reply-all, send-as alias, thread-level tools, download-to-disk, recipient pairing, batch ops with retryβ¦), supply-chain hygiene, and CI gating. Every PR goes through CodeRabbit + dual-model Qodo Merge before merge. See SECURITY.md for the controls and threat model, and the comparison table below for the parent-forks delta.
A Model Context Protocol (MCP) server that lets AI assistants (Claude Desktop, Claude Code, Cursor, Continue, OpenClawβ¦) read and manage a Gmail account through scope-gated tools. Exposes the Gmail v1 API surface you actually need (messages, threads, labels, filters, attachments, drafts, reply-all) behind a single npx install.
Positioning. Upstream calls this fork the maximalist one. The label is accurate from the outside, but it misframes the intent. klodr/gmail-mcp is built around four properties β and the code, tests and CI/CD all exist to pay rent on these and only these:
Secure β input sanitization, recipient pairing, rate limiting, sender resolution, and audit logging are enforced in the server (not in the operator's attention). The Gmail surface is mediated, not exposed raw.
Autonomous β designed to stay safe when no human is watching every action. Different threat model from upstream's "I use it daily in my own workflow"; the in-process middleware is what bridges that gap.
Tested β 781 vitest cases across 39 files, 99.25% statement coverage (89% branch), plus a fast-check property-based fuzz suite and a dedicated hardening test file.
Resilient under acceleration β 17 CI/CD workflows (CodeQL, OSV, Gitleaks, leak-detect, Scorecard, Socket, SLSA, lockfile lint, signed releasesβ¦) track the security ecosystem at the pace it actually changes β days, sometimes hours. Recent concrete instance: qs CVE-2026-8723, surfaced and shipped within hours of the public advisory across the klodr/* MCP family.
Full rationale and the per-tool design trade-offs live in docs/DESIGN_DECISIONS.md.
β¨ Why this MCP?
Comparison of the three maintained forks of the original Gmail MCP server, focusing on what an agent platform actually needs β prompt-injection safety, supply-chain integrity, and operational hygiene:
Capability | GongRzhe/Gmail-MCP-Server (original, unmaintained) | ArtyMcLabin/Gmail-MCP-Server (intermediate fork) | klodr/gmail-mcp (this repo) |
Core Gmail surface | |||
Send / draft / read / search messages | β | β | β |
Label CRUD | β | β | β |
Filter CRUD | β οΈ | β fixed | β |
Batch modify / delete | β | β | β |
Reply threading ( | β orphaned replies | β | β |
Reply-all tool | β | β | β |
Send-as alias ( | β | β | β |
Thread-level tools ( | β | β | β |
Download email to disk ( | β | β | β |
Download attachment | β | β | β |
OAuth / authorization | |||
| β | β | β |
Tool list filtered by granted scopes | β | β | β |
OAuth credentials file mode | β | β | β |
Security β input handling | |||
CRLF header injection sanitization ( | β | β οΈ partial | β |
Path traversal in | β | β fixed | β |
Path jails (attachment source + download destination) blocking prompt-injected exfiltration | β | β | β |
Symlink-safe writes ( | β | β | β |
Zod bounds on | β | β | β |
Cryptographic MIME boundary ( | β | β | β |
MCP protocol & tool surface | |||
MCP SDK version | v0.4.x | v1.27.x | v1.29.x |
Tool annotations ( | β | β | β |
| β | β | β |
Publishing / discoverability | |||
Published on npm | β stale β no future releases (repo archived) | β (consumed as a GitHub install from the intermediate fork) | β dedicated scoped package, signed releases |
Active maintenance (last 30 d) | β (archived 2026-03-03) | β οΈ sporadic | β daily review cycle (CodeRabbit + human) |
Supply-chain integrity | |||
Node.js floor | β | β | β
|
CI: CodeQL Advanced ( | β | β | β |
CI: OpenSSF Scorecard (weekly scan + badge) | β | β | β |
CI: Socket Security supply-chain alerts | β | β | β |
CI: CodeRabbit assertive reviews on every PR | β | β | β |
Release: signed builds (Sigstore + SLSA in-toto attestation + npm provenance) | β | β | β |
Release: single-file ESM bundle | β | β | β |
Testing | |||
Unit/property tests | β (0 tests) | β οΈ (97 tests) | β (781 tests, 39 files) |
Statement coverage across | 0% | 16.14% | 99.25% (89% branch) |
Fast-check property-based fuzz suite | β | β | β |
Hardening-specific test file (jails, CRLF, O_EXCL) | β | β | β |
CI/CD hardening | |||
Shell-injection-safe GitHub Actions workflows | β | β | β |
Workflows use least-privilege | β | β | β |
All GitHub Actions pinned by full commit SHA | β | β | β |
Operational | |||
| β | β | β |
| β | β | β |
klodr/gmail-mcp is the only one of the three with (a) source-path jails that make prompt-injection attachment exfiltration inert, (b) a modern supply chain (Scorecard, Socket, Sigstore), and (c) an in-repo review policy (.coderabbit.yaml) that every PR must pass before merge.
Related MCP server: google-mcp
π¦ Installation
npm install -g @klodr/gmail-mcpOr directly via npx:
npx -y @klodr/gmail-mcpRequires Node.js 22+.
βοΈ Configuration
1οΈβ£ Google Cloud OAuth credentials
Open the Google Cloud Console.
Create a project and enable the Gmail API.
Under APIs & Services β Credentials, create an OAuth 2.0 Client ID (Desktop or Web). For Web, add
http://localhost:3000/oauth2callbackto the authorized redirect URIs.Download the JSON, rename it to
gcp-oauth.keys.json, place it at~/.gmail-mcp/gcp-oauth.keys.json(or override withGMAIL_OAUTH_PATH=/abs/path/gcp-oauth.keys.json).
2οΈβ£ Authenticate (once)
npx -y @klodr/gmail-mcp auth --scopes=gmail.readonlyAlways pass --scopes with the minimum you actually need β the MCP filters the tool list at startup based on the granted scopes, so a read-only token doesn't expose write tools to the LLM. A browser opens for Google's consent flow; tokens are written to ~/.gmail-mcp/credentials.json (mode 0o600).
3οΈβ£ Register the server with your MCP client
{
"mcpServers": {
"gmail": {
"command": "npx",
"args": ["-y", "@klodr/gmail-mcp"]
}
}
}Client-specific config file:
Claude Code:
~/.claude.jsonClaude Desktop:
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) /%APPDATA%\Claude\claude_desktop_config.json(Windows)Cursor:
~/.cursor/mcp.jsonOpenClaw:
~/.openclaw/openclaw.json
See llms-install.md for an LLM-readable install guide.
π OAuth scopes
Scope shorthand | Full Gmail scope | What it grants |
|
| Read messages, threads, labels (filter tools require |
|
| Readonly + apply/remove labels, delete messages |
|
| Create drafts |
|
| Send messages |
|
| Manage labels only |
|
| Manage filters |
Recipes:
# Read-only browsing
npx @klodr/gmail-mcp auth --scopes=gmail.readonly
# Read + send (mailing-list bot)
npx @klodr/gmail-mcp auth --scopes=gmail.readonly,gmail.send
# Everything (default; explicit)
npx @klodr/gmail-mcp auth --scopes=gmail.modify,gmail.settings.basic
# Default + permanent delete (delete_email / batch_delete_emails)
# gmail.modify authorizes trash; mail.google.com is the only scope
# that authorizes purging from Trash. Both are listed because the
# tool gate does exact scope-name matching β a token holding only
# mail.google.com would not enable the gmail.modify-gated tools,
# even though Google's scope hierarchy would technically accept the
# same calls.
npx @klodr/gmail-mcp auth --scopes=gmail.modify,mail.google.com,gmail.settings.basicπ‘οΈ Safeguards
In-process middleware (autonomy enforcement)
The runtime constraints that an autonomous LLM client cannot violate are enforced in the server, not in the operator's attention span. Seven in-process modules sit on the tool entry path; the ones that are opt-in only activate when the matching env var is set.
Always-on (active for every call out of the box):
sanitize.tsβ strips/escapes input the LLM provides (CRLF injection, control characters, NUL bytes) before it reaches Gmail headers, filenames, or filesystem paths.sender-resolver.tsβ resolves thefromparameter against the account's authorized send-as aliases only. Spoofing the sender field is rejected before the Gmail API send call.rate-limit.tsβ bounds Gmail API call volume per tool family (send,delete,modify,drafts,labels,filters) over rolling daily/monthly windows. The state is persisted to disk so it survives restarts. Disable withGMAIL_MCP_RATE_LIMIT_DISABLE=truefor test runs only.gmail-errors.tsβ normalizes Gmail API failure modes into typed errors so retries and surfacing to the LLM are deterministic.middleware.tsβ composes the always-on chain and binds it to every tool entry point. New tools inherit the pipeline by construction.
Opt-in (off by default, set the env var to engage):
recipient-pairing.tsβ refuses to send mail to addresses that are not on the operator-controlled allow-list (~/.gmail-mcp/paired.json). No fresh outbound destinations from a hallucinated address. Engages whenGMAIL_MCP_RECIPIENT_PAIRING=true; gates thesend_email/reply_*/forward_email/draft_email/update_draftfamily only.audit-log.tsβ append-only JSONL trail of every tool call (name, redacted args, outcome) with structural-key-preserving redaction so operators can replay decisions post-hoc. Engages whenGMAIL_MCP_AUDIT_LOG=/abs/path/audit.jsonlis set.
Configure each module via the env vars below:
Knob | Env var | Default | Notes |
Attachment jail |
|
| Every attachment path ( |
Download jail |
|
|
|
OAuth keys path |
|
| Google Desktop/Web OAuth client credentials. |
Credentials path |
|
| Access/refresh tokens. File mode |
Rate limit state dir |
|
| Where the rolling call-history for rate limiting is persisted ( |
Rate limit overrides |
| see below | Override the per-bucket daily/monthly caps. Buckets: |
Rate limit disable |
| unset (limiter active) | Kill-switch for the entire limiter. Use only for test suites or controlled batch operations. |
Audit log |
| unset (no audit trail) | Opt-in append-only JSONL log of every tool call (name, redacted args, outcome). File mode |
Dry-run |
| unset (real calls) | When |
π οΈ Tools
The exact set depends on the OAuth scopes granted at auth time. Full catalog:
Messages β
send_email,draft_email,read_email,search_emails,modify_email,delete_email,download_email,download_attachment,batch_modify_emails,batch_delete_emails,reply_all,reply_to_email,forward_emailDrafts β
list_drafts,get_draft,update_draft,delete_draft,send_draft(fullusers.drafts.*surface;draft_emailabove creates the initial draft)Threads β
get_thread,list_inbox_threads,get_inbox_with_threads,modify_threadLabels β
list_email_labels,create_label,update_label,delete_label,get_or_create_labelFilters β
list_filters,get_filter,create_filter,delete_filter,create_filter_from_templateRecipient pairing β
pair_recipient(manage the~/.gmail-mcp/paired.jsonallowlist whenGMAIL_MCP_RECIPIENT_PAIRING=true)
Every write tool is annotated with destructiveHint / readOnlyHint / idempotentHint per the MCP spec so policy-aware clients can gate on HITL confirmation.
π search_emails query syntax
search_emails accepts Gmail's native search operators β from:, to:, subject:, has:attachment, after:YYYY/MM/DD, before:YYYY/MM/DD, is:unread, label:<name>, etc. They combine freely: from:alice@example.com after:2026/01/01 has:attachment. Full reference: Google's Gmail search operators cheat sheet.
πΊοΈ Roadmap
See ROADMAP.md.
π Ecosystem
Other MCP servers in the klodr family
π§ klodr/gmail-mcp β Gmail (you are here)
π klodr/faxdrop-mcp β Send real faxes via FaxDrop
π¦ klodr/mercury-invoicing-mcp β Mercury banking + invoicing
Wider Gmail-MCP landscape
29 standalone repositories and 349 forks of the original GongRzhe server are reviewed in docs/COMPETITORS.md β which ideas we borrowed, which we chose not to, and where klodr/gmail-mcp sits on the maturity axes.
π€ Contributing
See CONTRIBUTING.md for the test / build / lint checklist and release process.
π Security
See SECURITY.md for the vulnerability-reporting process and the current security model, and ASSURANCE_CASE.md for the threat model, trust boundaries, and CWE/OWASP mitigation table.
π Project continuity
See CONTINUITY.md for the handover plan if the maintainer becomes unavailable.
π License
MIT β see LICENSE.
π History
klodr/gmail-mcp is the maintenance fork of a two-step upstream chain:
GongRzhe/Gmail-MCP-Server β the original server. Unmaintained since August 2025 (7+ months with zero maintainer activity and 72+ unmerged pull requests).
ArtyMcLabin/Gmail-MCP-Server β Arty MacKiewicz's active fork. Since divergence from Gong, it merged community contributions including: reply-all (#3 by @MaxGhenis),
list_filtersfix (#4 by @nicholas-anthony-ai), CI/CD shell-injection hardening (#9 by @JF10R),download_email(#13 by @icanhasjonas), tool annotations (#14 by @bryankthompson), CC/BCC fields inread_email(#21 by @panghy), and draft lifecycle toolssend_draft/delete_draft/update_draft(#30 by @thisisambros). Reply-threading auto-resolution and the--scopesflag were folded in directly by the maintainer.
klodr/gmail-mcp carries all of the above forward and adds the supply-chain / path-jail / review-policy layer (see comparison table above). Credit to every PR author along the chain.
Maintenance
Latest Blog Posts
- 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/klodr/gmail-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server