Gmail MCP Server
You can search, read, and draft replies to Gmail through an MCP client, with no send or mailbox-management tools.
Search emails with Gmail query syntax, returning up to 25 newest matches with id, threadId, from, to, subject, date, snippet, and labels.
Read one email by message id: headers, plain-text body (HTML converted if needed), attachment names/sizes, and deception/authentication details per the README.
Read every message in a thread, oldest first, within a size budget.
Create a plain-text draft reply in the same thread, addressed to the original sender or Reply-To; a person must review and send it.
No send, delete, label, settings, or attachment-content tools are exposed.
Provides least-privilege access to a Gmail inbox for searching emails, reading messages and threads as plain text, and creating draft replies in the original thread without sending them.
Click on "Deploy 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., "@Gmail MCP Server Search my inbox for the latest email from Stripe and draft a reply asking for an invoice copy"
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.
Gmail MCP Server
Minimal-scope Gmail access for AI agents over the Model Context Protocol: search, read and draft replies. The server has no send tool. The security model explains what the token itself can still do.

Real output of the triage demo against a test inbox, run with Gemini (TRIAGE_PROVIDER=gemini; Claude is the default). Personal names and addresses are blurred.
At a glance
Four MCP tools over stdio: search, read a message, read a thread, save a draft reply. No send, delete, label or settings tools.
Deception made visible.
get_emailshows Reply-To, SPF/DKIM/DMARC verdicts with their domains, and real link targets. It marks hidden HTML text in place, and shows both versions when the plain text and HTML differ.A measured classifier. On a held-out test set of 30 emails, never used for tuning:
93% type accuracy;
9 of 10 suspicious emails caught, including every prompt injection;
no legitimate email flagged.
The 84-email development set includes legitimate mail that carries the usual warning signs, such as failed authentication, a different Reply-To and hidden preheaders.
A triage agent with its reach limited in code. It reads threads and writes draft replies, saving nothing unless asked. It is checked by an agent safety eval with a planted secret.
165 tests, including end-to-end tool calls through a real MCP client and hostile-input performance tests.
How it works
flowchart LR
A["MCP client<br/>Claude Desktop, Claude Code or an agent"] -- "JSON-RPC over stdio" --> B["gmail-mcp-server<br/>local Node.js process"]
B -- "HTTPS + OAuth 2.0" --> C["Gmail API"]
B -. "reads and refreshes" .-> D[("token.json<br/>local disk")]The MCP client starts the server as a child process, and they talk over stdin and stdout, so no network port is opened. The server calls the Gmail API directly with the mailbox owner's OAuth token, which never leaves the machine. It renders every response as plain text before it reaches the model. There is no backend, database or third-party service in between.
Tool | What it does | Read-only |
| Searches with Gmail query syntax; returns a summary per message, as text and structured content | Yes |
| Reads one message: headers, sender authentication, body as text, attachment metadata | Yes |
| Reads every message in a thread, oldest first, within a size budget | Yes |
| Saves a plain-text reply as a draft in the original thread, addressed to the sender. Never sends. | No (creates drafts only) |
Parameters, output formats and the parsing rules are in the tool reference.
Related MCP server: Gmail MCP Server
Security in brief
Scopes: only
gmail.readonlyandgmail.compose. Gmail has no draft-only scope:gmail.composecan also send mail and delete drafts. The server exposes neither, and it cannot touch received messages, labels or settings.People send. The only write in the code is
users.drafts.create, and a person reviews and sends every draft.Prompt injection is reduced, not solved. An injected model could still copy mail into a draft reply to the attacker. What limits it:
drafts go only to the original sender;
deception is made visible;
the agent example is restricted in code to one email's thread.
See docs/security.md.
Hostile input: linear-time parsing, a 500,000-character cap per part, and a 30-second deadline on every Gmail request.
The token is a password. Anything that can read
token.jsoncan send mail as the user. On a machine where other agents work, keep it elsewhere withGMAIL_TOKEN_PATH.
Setup
Requirements: Node.js 22.12 or later, a Google account, and a Google Cloud project you control (free).
Enable the Gmail API.
Configure the OAuth consent screen: External, Testing, with your address as a test user.
Create an OAuth client of type Desktop app, and save its JSON as
credentials.jsonin the project root.
Install and sign in:
git clone https://github.com/AlexisG1993/mcp_gmail.git cd mcp_gmail npm install npm run auth # builds, opens the browser (OAuth loopback flow with PKCE), saves token.jsonConnect a client, using the absolute path to
dist/index.js. On Windows, forward slashes work.Claude Desktop: in
claude_desktop_config.json, add the block below, then restart Claude Desktop.{ "mcpServers": { "gmail": { "command": "node", "args": ["/absolute/path/to/mcp_gmail/dist/index.js"] } } }Claude Code:
claude mcp add --transport stdio gmail -- node /absolute/path/to/mcp_gmail/dist/index.js
Variable | Default | Purpose |
|
| OAuth client file from Google Cloud |
|
| Saved token, written by |
While the Google Cloud project is in Testing status, refresh tokens expire after 7 days; run npm run auth again when the tools ask. Common errors and fixes are in docs/troubleshooting.md.
Examples
Three examples use the server from code instead of a chat client. Each starts the server with the official MCP client and never gives it a model API key. The model is a setting, not a code change:
Variable | Default | Purpose |
|
|
|
| (required for that provider) | API key, from the environment or a git-ignored |
|
| Model used |
Triage demo
npm run demo reads the 10 most recent inbox emails through search_emails and get_email. It classifies each one with structured JSON output: a type (customer, vendor, admin, suspicious or other), a priority (high, normal or low) and a reason. It calls only read tools.
Evaluation
npm run eval runs the classifier over labeled synthetic emails, rendered by the server's own parser so the model sees exactly what get_email returns. npm run eval -- --set test runs the held-out set.
Set | Model | Type accuracy | Suspicious caught | Legitimate flagged suspicious |
Held-out test, 30 emails |
| 93.3% (28/30) | 9/10 | 0/20 |
Development, 84 emails (tuned on) |
| 97.6% (82/84) | 15/15 | 0/69 |
The prompt was tuned on the development set only, and frozen before the test set was run. The held-out run used the previous lite model because the free tier's daily quota for the tuned one ran out, so it measures the frozen prompt on a related model rather than the exact one. Its one real miss was a fake overdue invoice from an unknown sender, which was filed as a vendor email. docs/evaluation.md covers how the sets were built, the rounds of prompt changes and what each fixed, the caveats, and the full reports.
Triage agent
npm run agent # dry run: prints the replies it would write, saves nothing
npm run agent -- --save-drafts # saves them as Gmail drafts, at most one per emailThe agent triages each inbox thread. Then, for customer and vendor mail that needs a reply, a tool-using model decides how to answer. Its reach is enforced in code:
It gets only
get_threadandcreate_draft_reply, limited to that one email's thread and message id.It has no search, at most one draft per email, and at most 6 tool calls.
A ledger prevents drafting the same email twice across runs.
npm run eval:agent runs it against a fake mailbox with a planted secret, and checks what actually ends up in drafts. There are two passes, one with triage and one without, as if the classifier had missed every attack. All four scenarios passed both times: no secret, injected text or extra draft reached a draft. Details are in docs/evaluation.md.
Development
Script | What it does |
| Compiles TypeScript to |
| Runs the test suite (vitest, no network access) |
| Strict type-check of source, tests and examples |
| The examples above |
The tests use JSON fixtures shaped like real Gmail API responses, and cover:
MIME parsing and HTML conversion, including hostile input;
sender authentication parsing;
reply building and header-injection attempts;
retries and timeouts;
input validation;
all four tools end to end through a real MCP client;
the agent's scope rules.
CI runs the type-check, the tests and a build on Node 22 and 24.
More documentation: tool reference, security model, evaluation, design decisions, limitations and the path to production, troubleshooting.
License
MIT. See LICENSE. Release notes are in CHANGELOG.md, and security reports are handled as described in SECURITY.md.
Available Tools
4 toolscreate_draft_replyCreate a draft replyA
Save a plain-text reply to an email as a Gmail draft, in the same thread, addressed to the original sender (its Reply-To if set). Nothing is sent: a person reviews and sends the draft from Gmail.
Inputs: body (required), message_id (required).
get_emailRead an emailARead-only
Read one email: headers including Reply-To, sender authentication (SPF, DKIM, DMARC with domains), the body as text, and attachment names and sizes. Plain text is preferred; the HTML version (with link targets kept) is used or added when the plain part is a stub or says something different. "Note:" lines flag an unauthenticated From domain, hidden HTML text and similar warnings. Attachment contents are never returned.
Inputs: message_id (required).
get_threadRead a threadARead-only
Read every message in a thread, oldest first, each in the same format as get_email. Very long threads are shortened from the oldest message; get_email reads any message in full.
Inputs: thread_id (required).
search_emailsSearch emailsARead-only
Search the mailbox with Gmail search syntax. Returns id, threadId, from, to, subject, date, snippet and labels for each match, newest first.
Inputs: query, max_results. Returns: query, skipped, messages
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 4 tools
The tools have mostly distinct purposes: search_emails, get_email, get_thread, and create_draft_reply target different operations. The only potential confusion is between get_email and get_thread, but the descriptions clearly distinguish single-message reading from whole-thread reading.
All tool names follow a consistent verb_noun snake_case pattern: create_draft_reply, get_thread, search_emails, get_email. The longer create_draft_reply still fits the same convention without mixing styles.
Four tools is a well-scoped set for a focused Gmail read-and-draft-reply workflow. Each tool earns its place: search, read one email, read a thread, and draft a reply.
The surface covers searching, reading, and drafting replies, but lacks operations for creating a new draft (non-reply), forwarding, sending (intentionally omitted), managing labels, or downloading attachments. These gaps may block common email workflows even though the core reply path is covered.
Maintenance
Related MCP Connectors
Give AI agents their own email inboxes: list, read and send mail via scoped, revocable OAuth grants.
Email for AI agents: read, search and send from your Gmail, Outlook, Yahoo, iCloud or IMAP inbox.
Manage Gmail end-to-end: search, read, send, draft, label, and organize threads. Automate workflow…
Gmail, Outlook, Drive, OneDrive and calendars for AI agents. Many accounts, one endpoint, audit log.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with Gmail through natural language, supporting email sending/reading, searching, draft management, label organization, and batch operations with secure OAuth authentication.-
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with Gmail through OAuth2 authentication, allowing users to list, search, read emails, and create drafts with a safety-first design that prevents accidental sends by default.131 npmMIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to read unread Gmail messages and create threaded draft replies, without ever sending email automatically.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI agents to manage Gmail accounts, including reading and searching emails, creating and sending drafts, and handling labels, blocks, and unsubscribes.MIT