gmail-imap-mcp
Reads and sends Gmail over plain IMAP/SMTP using a Google App Password (no OAuth). Provides tools for Gmail-syntax search (e.g. from:, newer_than:, has:attachment, label:), reading full messages with HTML/text bodies and attachment lists, downloading attachments to disk, sending mail with CC/BCC and attachments, replying/reply-all with correct threading, and listing decoded folders and labels. Also ships a CLI and a local three-pane web UI over the same core.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
gmail-imap-mcp
Gmail for AI agents — App Password only. No OAuth, no Google Cloud project, no relay.
English · 简体中文
Your AI reads and sends your Gmail through plain IMAP/SMTP with a Google App
Password. One config file, pip install, done. No Google Cloud console, no
OAuth consent screen, no 7-day refresh-token expiry, no third-party server
seeing your mail.
Ships three front-ends over one core:
What it is | Why | |
MCP server |
| AI understands it without reading docs. Works in Claude Desktop, Cursor, Cherry Studio, Cline, any MCP client |
Skill / CLI |
| For agents that run shell commands (Claude Code, Codex, Aider) and for humans |
Web UI |
| When you'd rather click than prompt |
Quick start
# install the release wheel (PyPI publication is pending)
pip install "gmail-imap-mcp[mcp] @ https://github.com/luojinghao6-art/gmail-imap-mcp/releases/download/v0.1.7/gmail_imap_mcp-0.1.7-py3-none-any.whl"
gmail-imap config # paste a Google App Password (16 chars)Then point your AI at it — one line for any MCP client:
claude mcp add gmail -- gmail-imap-mcpNo App Password yet? Create one here — 2-Step Verification must be on first. Full details in Configure.
Related MCP server: mcp-imap
Why this exists
Most Gmail MCP servers fall into two camps, and both have a catch:
Option | Catch |
Google's hosted Gmail MCP ( | 23 tools, and not one of them sends mail. It requests |
Gmail API servers (e.g. | Full power, but you must create a Google Cloud project, enable the Gmail API, configure an OAuth consent screen, download |
| Very popular, archived in March 2026. Tutorials still recommend it |
Hosted aggregators (Composio, Zapier) | No GCP setup, but your mail and tokens flow through a third party |
App Passwords have none of these problems. Google still supports them for personal accounts with 2-Step Verification enabled, and they are exactly what IMAP/SMTP expects.
Trade-off, stated plainly: App Passwords are being tightened over time, and they do not exist for Google Workspace accounts whose admin disabled them. IMAP also cannot edit filters, read Gmail settings, or modify an existing draft. If you need those, use a Gmail API server.
Features
Send, reply, reply-all — HTML or plain text, multiple recipients, CC/BCC, attachments, and proper
In-Reply-To/Referencesso replies thread correctlySearch with Gmail's own syntax via the
X-GM-RAWIMAP extension:from:boss newer_than:7d,has:attachment filename:pdf,label:Work,is:unread in:anywhere— not the crippled subset of IMAPSEARCHBatched header fetch — one round trip per page instead of two per message (30 messages: ~25 s with the naive version, ~4 s now on a real account; the rest is TLS login plus one search round trip)
Mailbox-safe message references — every search hit carries its
mailboxand an account-widemsgid(X-GM-MSGID). UIDs are only unique inside a mailbox, so read/reply/download take the pair instead of guessingAttachment download and save-to-disk
Localised folder names decoded from IMAP modified UTF-7 (
[Gmail]/&XfJSIJZkkK5O9g-→[Gmail]/已删除邮件)SOCKS5 proxy support for networks where Gmail is blocked (
GMAIL_PROXY)Core, CLI and Web UI are standard library only. Only the MCP server needs the
mcppackage
Install
# from the v0.1.7 release wheel (no PyPI account needed)
pip install "gmail-imap-mcp[mcp] @ https://github.com/luojinghao6-art/gmail-imap-mcp/releases/download/v0.1.7/gmail_imap_mcp-0.1.7-py3-none-any.whl"
# or straight from the repo
pip install "git+https://github.com/luojinghao6-art/gmail-imap-mcp.git#egg=gmail-imap-mcp[mcp]"
# CLI only, zero dependencies
pip install "gmail-imap-mcp @ https://github.com/luojinghao6-art/gmail-imap-mcp/releases/download/v0.1.7/gmail_imap_mcp-0.1.7-py3-none-any.whl"Once the package is on PyPI, the short form works too:
pip install "gmail-imap-mcp[mcp]" or uvx --from "gmail-imap-mcp[mcp]" gmail-imap-mcp.
Requires Python 3.10+ — the bundled MCP SDK does not support 3.9.
Configure
1. Create an App Password
Turn on 2-Step Verification: https://myaccount.google.com/security (App Passwords do not exist without it)
Create one named e.g.
gmail-imap, copy the 16-character password
2. Save it
gmail-imap config
# Gmail address: you@gmail.com
# App Password (16 chars, hidden): xxxx xxxx xxxx xxxx
gmail-imap statusCredentials are stored at:
Windows —
%APPDATA%\gmail-imap-mcp\credentials.jsonmacOS / Linux —
~/.config/gmail-imap-mcp/credentials.json
with 0600 permissions. You can also skip the file entirely and set
GMAIL_ADDRESS / GMAIL_APP_PASSWORD environment variables — useful for
containerised MCP configs.
Connect it to your AI
Claude Desktop
claude_desktop_config.json:
{
"mcpServers": {
"gmail": {
"command": "uvx",
"args": ["--from", "gmail-imap-mcp[mcp]", "gmail-imap-mcp"],
"env": {
"GMAIL_ADDRESS": "you@gmail.com",
"GMAIL_APP_PASSWORD": "xxxx xxxx xxxx xxxx"
}
}
}
}Leave out env if you already ran gmail-imap config.
Claude Code / Cursor / any MCP client
claude mcp add gmail -- uvx --from "gmail-imap-mcp[mcp]" gmail-imap-mcpAs a Claude Code skill
Copy skill/SKILL.md to ~/.claude/skills/gmail/SKILL.md.
The skill drives the CLI, so the agent picks it up automatically when the user
mentions email.
Web UI

gmail-imap-ui # opens http://127.0.0.1:8765/
gmail-imap-ui --port 9000 --no-browserThree panes: folders, message list, reading pane. Compose with attachments,
reply / reply-all, Gmail-syntax search. Binds to 127.0.0.1 only and requires a
per-process token, so a random website cannot drive your inbox.
Email HTML is rendered inside a sandbox iframe with a strict CSP: scripts in
an email do not run, and remote images do not load (no tracking pixels). This
is deliberate.
MCP tools
Tool | What it does |
| Is it configured? Does IMAP login work? |
| Gmail-syntax search, returns headers + uid + msgid + mailbox |
| Full message: text, HTML, attachment list |
| Send |
| Reply, quoting the original, threading preserved |
| Folders and labels, decoded |
| Save one attachment to disk |
Pass the mailbox returned by gmail_search together with its uid. UIDs are
per-mailbox; without the mailbox a read can resolve to a different message in
All Mail. msgid is account-wide and never has that problem.
CLI
gmail-imap status
gmail-imap search --query "from:boss newer_than:7d" --limit 10
gmail-imap read --uid 12345 --mailbox "INBOX" --save-attachments "~/Downloads/gmail-imap"
gmail-imap read --msgid 1278455344230334865
gmail-imap send --to a@b.com --subject "Hi" --body "Hello"
gmail-imap send --to a@b.com --subject "Report" --body "See attached" --attach report.pdf --dry-run
gmail-imap labelsAdd --json to search / read / labels for machine-readable output.
--dry-run builds the message and prints the recipients without touching SMTP.
Security notes
Credentials are plaintext on disk. That is the same model as
~/.netrcor~/.aws/credentials. Restrict the file, never commit it, and revoke the App Password at Google if it leaks.App Passwords grant full mailbox access. They cannot be scoped down the way OAuth scopes can. Use a dedicated Google account if that matters to you.
Email is untrusted input. A message can contain instructions aimed at your AI.
server.pytells the model to treat email content as data, but prompt injection is not solvable with a sentence — review before letting an agent send mail on your behalf.The web UI is localhost-only and token-gated. It also rejects foreign
Hostheaders (DNS rebinding), checksOrigin/Refereron writes, requiresContent-Type: application/json, and sends CSP,X-Frame-Options: DENY,nosniffandno-referrer. Do not port-forward it.Credentials are owner-only on disk, and that is checked. The config file is created empty, locked down, and only then filled, so the password never exists under inherited permissions. POSIX verifies the mode with
stat; Windows resets the ACL — explicit and inherited ACEs alike — grants the current user (with inheritance on the config folder, so its contents stay usable), and reads the ACL back through PowerShell, which answers in ASCII so the console code page cannot corrupt the verdict. If that cannot be done the tool warns once, and withGMAIL_MCP_STRICT_PERMISSIONS=1it refuses:gmail-imap configdeletes the half-written file, and the audit write fails the send. If you would rather not keep the password in the JSON config, pointGMAIL_APP_PASSWORD_FILEat a keychain export or a mounted secret.This is a personal connector, not a shared service. An App Password is full-mailbox access, and any process running as your OS user can read the config. One account per OS user or container; do not run it multi-tenant.
Downloaded files are untrusted. Saving an attachment safely says nothing about what is inside it. Do not auto-open PDFs, archives or Office files that arrived by mail; if you want a scanner in the loop, see
GMAIL_MCP_SCAN_CMDbelow.
Code-level send controls
Prompt instructions are a suggestion; these are enforced in
gmail_imap_mcp.core for the MCP server, CLI and web UI alike:
Control | Effect |
|
|
| Attachments must resolve inside one of these roots ( |
always on | Files that look like credentials ( |
always on | Every send, reply and blocked attempt is appended as JSON to |
always on | Each send is recorded twice: |
always on | A partial delivery raises |
Code-level download controls
Attachments come from strangers, so inbound writes are constrained as well:
Control | Effect |
| Extra folders inbound attachments may be saved to. |
always on |
|
always on | Sender-supplied filenames are reduced to one path component: separators replaced, |
always on | An existing file is never overwritten — a |
| Run this command on every saved attachment. Exit 0 keeps the file; any other exit, or a scanner that cannot run, deletes it and fails the call |
| Writes a |
| Read the App Password from a file instead of the JSON config |
| A permission failure aborts instead of warning: no credentials are saved and the audit write fails the send |
Troubleshooting
Symptom | Cause |
| 2FA is off, or you used the account password |
| Wrong or revoked App Password (it is 16 chars, not your password) |
Connection timeout | Gmail unreachable. Try |
Search returns nothing that exists | Default scope is All Mail; try |
Chinese folder names look like | Fixed — decoded automatically since 0.1.0 |
Continuous live checks
.github/workflows/live.yml runs tests/test_live.py nightly against a real
mailbox. Add GMAIL_ADDRESS and GMAIL_APP_PASSWORD as repository secrets and
it runs; without them the step skips, so forks and pull requests never touch a
mailbox. On a public repo, use a dedicated account — anyone who can push to the
default branch can read Actions secrets.
Status
0.1.7 — closed three holes in the 0.1.6 hardening: a duplicated
_harden_dirshadowed the verifying one, the Windows ACL check used locale text mode and could raiseUnicodeDecodeError, and protecting a folder stripped its children's inherited ACEs.0.1.6 — permission hardening is verified instead of assumed; failures warn once, or are fatal under
GMAIL_MCP_STRICT_PERMISSIONS=1.0.1.5 — partial delivery (
PartialSendError) and unknown send state (SendStateUnknownError) are reported accurately.0.1.4 — the audit intent record is written before SMTP; a post-send audit failure says "sent, do not retry".
0.1.3 — owner-only credentials and audit files,
GMAIL_APP_PASSWORD_FILE,GMAIL_MCP_AUDIT_STRICT, the optionalGMAIL_MCP_SCAN_CMDhook, and a nightly live workflow.0.1.2 — inbound attachments confined to a download allowlist, security headers on attachment downloads, token redaction, opt-in live suite.
Working and dogfooded against a real personal Gmail account: search, read,
attachments, send, reply, web UI. The offline suite covers IMAP FETCH/SEARCH
fixtures, message construction and threading, attachment saving, UID/mailbox
resolution, the send policy and audit log, permission hardening, the web
token/Host/Origin/CSP, and the MCP tool schema. The real mailbox is exercised by
an opt-in live suite: GMAIL_IMAP_LIVE=1 python -m unittest tests.test_live
covers login, labels, search, read by uid and by msgid, attachment fetch and a
dry-run send. Not covered yet: draft editing, filters, Gmail settings (IMAP
cannot do these).
Issues and PRs welcome. Please open an issue before large changes.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Email for AI agents: read, search and send from your Gmail, Outlook, Yahoo, iCloud or IMAP inbox.
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Email inboxes and calendars for AI agents: send, receive, search, draft and schedule.
Related MCP Servers
- AlicenseNot gradedqualityNot gradedmaintenanceEnables AI assistants to interact with Gmail accounts through IMAP/SMTP, supporting reading, sending, replying to emails, managing threads, downloading attachments, and searching with Gmail syntax using simple app password authentication.-
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to interact with email accounts via IMAP and SMTP, supporting mailbox listing, email search, retrieval, sending, and management.MIT
- AlicenseBqualityBmaintenanceEnables AI agents to securely interact with Gmail and QQ Mail, including IMAP search/read/organization, attachments, and preview-confirmed sending.412MIT
- AlicenseAqualityCmaintenanceLets AI agents send email over SMTP and read, search, and manage email over IMAP or POP3 using app passwords or authorization codes, with attachment handling and support for common providers.735 npmMIT