Skip to main content
Glama
Raphael-Barret

mail-mcp

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 uv

Linux: install git with your package manager (sudo apt install git, sudo dnf install git, ...), then uv:

curl -LsSf https://astral.sh/uv/install.sh | sh

Windows:

winget install --id Git.Git -e
winget install --id astral-sh.uv -e

Close 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 pytest

All 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.toml

Windows:

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-secret fails 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

git or uv not found (Windows)

Close and reopen PowerShell after winget install.

mail is failed or absent in /mcp

Check the server starts: uv run mail-mcp in the project folder. If uv is not found by Claude Code, register with the full path of uv (which uv, or (Get-Command uv).Source on Windows).

"Config introuvable"

The configuration file is not where the table in step 3 says. Create it, or set MAIL_MCP_CONFIG.

"Aucun secret dans le trousseau"

Run uv run mail-mcp set-secret <account-name> with exactly the name used in the configuration.

"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

list_accounts

configured accounts and their write capabilities

always

list_messages

latest messages of a folder

always

search_messages

full-text search

always

read_message

reads one message

always

read_thread

reads the thread (by Message-ID and References, current folder)

always

create_draft

creates a draft, without sending it; can reply to a message

if an account has allow = ["draft"]

archive_message

takes a message out of the inbox without deleting it

if an account has allow = ["archive"]

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 EXAMINE only and reads with BODY.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 pytest

To add a backend: implement MailBackend (and DraftingBackend / ArchivingBackend if it writes), then register it in mail_mcp.registry.BACKENDS.

License

MIT, see LICENSE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables LLMs to read, search, and manage emails via IMAP with secure, read-only access to email accounts.
    6
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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
  • A
    license
    A
    quality
    A
    maintenance
    Enables 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.
    6
    26 PyPI
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables 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