mail-mcp
Works with Dovecot (and other IMAP servers that accept a password) as a generic IMAP backend, configured per account with host, port, security and username, and the password kept in the system keychain. Enables listing, searching and reading messages and threads, plus optional draft creation and archiving (using the server's MOVE command, or a configured archive folder, when no recognised archive folder exists).
Connects to Gmail mailboxes over IMAP (imap.gmail.com, port 993, SSL) using a Google app password stored in the system keychain. Provides read-only tools by default: listing accounts, listing the latest messages of a folder, full-text (fuzzy on Gmail) search, reading a single message, and reading a thread by Message-ID/References. Optional per-account write capabilities allow creating (never sending) drafts, including replies, and archiving a message out of the INBOX while keeping it in All Mail.
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., "@mail-mcpshow me unread emails from the last week across all accounts"
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.
mail-mcp
English | Français
A local MCP server that gives an assistant (Claude Code, for example) access to several mailboxes, read-only by default.
Several accounts, one output format (account, id, sender, subject, date, unread, snippet).
Secrets stay in the system keychain (macOS Keychain, Windows Credential Manager, Secret Service on Linux), never in a file or in the repository.
Writes (drafts, archiving) are separate capabilities, off by default, enabled account by account in the configuration, never through a tool argument.
Mail content is treated as untrusted data, and every tool output says so.
Current state: IMAP backend (Gmail and any IMAP server that accepts a password). Planned: Gmail API, Microsoft Graph (see Known limitations).
Installation
Steps 1, 3 and 5 differ by system; the others are identical everywhere. Commands labelled Windows are for PowerShell.
1. Install the prerequisites
You need Git and uv. You do not have to install Python yourself: uv downloads a suitable version (3.11 or later) when it is needed.
macOS (with Homebrew):
brew install git uvLinux: install git with your package manager (sudo apt install git, sudo dnf install git, ...), then uv:
curl -LsSf https://astral.sh/uv/install.sh | shWindows:
winget install --id Git.Git -e
winget install --id astral-sh.uv -eClose and reopen PowerShell afterwards so that git and uv are found. Check with git --version and
uv --version.
2. Get the code and run the tests
Same on every system:
git clone https://github.com/Raphael-Barret/mail-mcp.git
cd mail-mcp
uv sync
uv run pytestAll tests should pass. They use no real account.
3. Create the configuration file
The default location depends on the system. Set MAIL_MCP_CONFIG to use another path.
macOS and Linux ($XDG_CONFIG_HOME is honoured if set):
mkdir -p ~/.config/mail-mcp
cp config.example.toml ~/.config/mail-mcp/config.toml
nano ~/.config/mail-mcp/config.tomlWindows:
New-Item -ItemType Directory -Force "$env:APPDATA\mail-mcp" | Out-Null
Copy-Item config.example.toml "$env:APPDATA\mail-mcp\config.toml"
notepad "$env:APPDATA\mail-mcp\config.toml"Edit it to describe your accounts (see Setting up accounts). One [accounts.<name>]
entry per account. Passwords never go in this file.
4. Store each password in the system keychain
For every account in the configuration, run this in a real terminal (not inside an assistant session). The password is typed with no echo, so it never lands in your shell history:
uv run mail-mcp set-secret <account-name>Where it is stored, and what to know:
macOS: the login Keychain. If you get "User interaction is not allowed", unlock it first with
security unlock-keychain ~/Library/Keychains/login.keychain-db.Windows: Credential Manager. Nothing to install or unlock.
Linux with a desktop session (GNOME, KDE): the keyring service normally runs and is unlocked at login.
Linux without a desktop (SSH, server, container): there is no keyring service, and
set-secretfails with an explicit message. Start one in a D-Bus session, from the shell that will also run your assistant (shown for Debian and Ubuntu; this sequence was tested in a container):sudo apt install gnome-keyring dbus dbus-run-session -- bash eval $(printf '%s' 'choose-a-keyring-password' | gnome-keyring-daemon --unlock --components=secrets) uv run mail-mcp set-secret <account-name>Keep working in that same shell afterwards, and start Claude Code from it: the server reads the secret through the same D-Bus session.
5. Register the server in Claude Code
Run it from inside the mail-mcp folder. The command is the same on macOS, Linux and Windows (PowerShell).
The user scope keeps the declaration out of the repository.
claude mcp add --scope user mail -- uv run --directory "$PWD" mail-mcp($PWD is the current folder in these shells. The folder path is stored as-is, so register again if you move
the project.)
6. Check that it works
Restart Claude Code, then open /mcp: mail should be listed as connected. Ask the assistant to run
list_accounts, then list_messages on one account. After every configuration change, restart the server
(/mcp, or restart Claude Code): the configuration is read at startup.
Related MCP server: MailBridge MCP
Setting up accounts
Gmail
Turn on 2-step verification, then create an app password at https://myaccount.google.com/apppasswords.
That is what goes in the keychain. Host imap.gmail.com, port 993, security = "ssl". On Gmail, archiving
removes the message from INBOX: it stays in "All Mail" (checked before it is removed).
Another IMAP server (school, company)
The settings are often published in an autoconfiguration file:
https://autoconfig.<domain>/mail/config-v1.1.xml (host, port, security, username format). Otherwise, read
them from your mail client's account settings. To archive on a server with no recognised archive folder, create
the folder in your mail client and name it in archive_folder.
Adding an account
An account is a few lines of configuration and a password in the keychain: no code to write.
[accounts.school]
backend = "imap"
host = "imap.example.edu"
port = 993
security = "ssl"
username = "first.last@example.edu"This works for any IMAP server that accepts a password (Dovecot, Zimbra, Cyrus, school and company servers). It does not work when the organisation is on Microsoft 365 or Google Workspace with password authentication turned off: that requires OAuth, which this server does not handle yet.
Troubleshooting
Symptom | Cause and fix |
| Close and reopen PowerShell after |
| Check the server starts: |
"Config introuvable" | The configuration file is not where the table in step 3 says. Create it, or set |
"Aucun secret dans le trousseau" | Run |
"Trousseau indisponible" (Linux) | No keyring service is running or it is locked: see step 4. |
"User interaction is not allowed" (macOS) | The Keychain is locked for this terminal: see step 4. |
Gmail refuses the login | 2-step verification must be on, and the password must be an app password, not your Google password. IMAP must be enabled in Gmail settings. |
Tools missing or account not listed after a change | The configuration is read at startup: restart the server. |
"Identifiant périmé" | The folder changed on the server: list it again to get fresh message ids. |
Tools
Tool | Effect | Available |
| configured accounts and their write capabilities | always |
| latest messages of a folder | always |
| full-text search | always |
| reads one message | always |
| reads the thread (by | always |
| creates a draft, without sending it; can reply to a message | if an account has |
| takes a message out of the inbox without deleting it | if an account has |
Every write call re-checks the configuration of the targeted account. There is no tool to send or delete.
Security model
Verifiable read-only. The read connection opens folders with
EXAMINEonly and reads withBODY.PEEK: nothing is marked as read. It has no write command, and a test proves it.Limited writes. The write connection is a separate class. It can only: append a draft, move a message, or remove a single message from the current folder once it exists elsewhere (a successful copy, or presence verified in "All Mail" on Gmail). It refuses if another message in the folder is already flagged as deleted. No code path deletes a message that does not exist elsewhere.
Drafts, never sending. A draft goes to the Drafts folder; you are the one who sends it. Addresses and subject are rejected if they contain a line break (header injection).
Untrusted content. A mail can contain instructions aimed at the assistant. Read outputs are wrapped in a warning, but the real defence is in how you use it: do not auto-approve the write tools, and review drafts.
Credentials are not scoped. An app password or an account password grants full rights on the server side. Read-only holds only because of this code and your configuration.
Known limitations
Microsoft 365 and Google Workspace without IMAP passwords: not supported (OAuth required). The Gmail API and Graph backends are planned, not written.
Verified against real accounts: reading, searching, drafting and archiving on Gmail; reading and drafting on a school server. The archiving path for a server without
MOVE(copy, then removal) is covered only by tests with a fake IMAP connection.Systems: macOS is used daily. CI (
.github/workflows/ci.yml) runs the tests on Ubuntu, Windows and macOS with Python 3.11, 3.12 and 3.13, starts the real MCP server over stdio on each, and on Windows stores and reads back a secret in the real Credential Manager. Linux was also checked in a container, including a headless keyring. Not done on Windows and Linux: a session with a real mail account, and the install steps run by hand from this README.Search: full text (
TEXT), fuzzy on Gmail; no Gmail-specific search syntax.Threads: rebuilt within the current folder only.
Drafts: plain text, no attachments. No sending and no deletion, by design.
Folder names: names detected from the server work; a name typed by hand with accented characters must be given in IMAP encoding (modified UTF-7).
Attachments: not read.
Language: messages returned by the tools, code comments and docstrings are in French.
Development
uv run pytestTo add a backend: implement MailBackend (and DraftingBackend / ArchivingBackend if it writes), then
register it in mail_mcp.registry.BACKENDS.
License
MIT, see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
- MailowsOAuthcom.mailows
Give AI agents their own email inboxes: list, read and send mail via scoped, revocable OAuth grants.
Your mailboxes in ChatGPT and Claude: Gmail, iCloud, Fastmail, any IMAP. Passwords stay yours.
Read, organise and send from your existing email accounts. Nothing sends without your approval.
Multiple Gmail accounts, editable Google Sheets & Docs for AI agents. Deny-by-default access rules.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables LLMs to read, search, and manage emails via IMAP with secure, read-only access to email accounts.6MIT
- AlicenseNot gradedqualityAmaintenanceEnables MCP-compatible AI assistants to securely search multiple mailboxes, reconstruct email threads, and inspect attachments through read-only tools without altering mailbox state.Apache 2.0
- AlicenseAqualityAmaintenanceEnables read-only, provider-agnostic email access over IMAP, allowing users to list folders, search and read messages, and download attachments without ever marking messages as read.626 PyPIMIT
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to securely access IMAP mailboxes with read-focused tools for searching, reading, listing messages, and creating drafts, while deliberately preventing sending or deleting emails.MIT