imap-mcp
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., "@imap-mcp find the invoice from Hetzner"
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.
imap-mcp
All your mailboxes, one MCP server, read-only.
Point it at any number of IMAP accounts (Gmail, Fastmail, iCloud, Migadu, self-hosted, anything that speaks IMAP) and your MCP client can list, search, and read across every one of them in a single call. Ask "what's unread across all my accounts?" or "find the invoice from Hetzner" and get answers that span providers, not one inbox at a time.
Strictly read-only. No send, no delete, no flag changes, no folder moves.
Every fetch uses BODY.PEEK, so reading a message never marks it as read.
Your mailboxes look exactly the same after a session as before it.
No secrets on disk. The config file names an environment variable per account; passwords only ever exist in the server process environment. Bring your own secret manager, or just export a variable.
Why IMAP
Assistant mail integrations usually connect one Gmail or one Outlook account. IMAP is the protocol nearly every provider already speaks, so one small server covers your whole mail footprint with a single read-only code path, no OAuth apps to register, and nothing granted write access.
Related MCP server: imap-mcp
Quickstart
Requires Python 3.12+ and uv.
git clone https://github.com/LeeFlannery/imap-mcp
cd imap-mcp
cp accounts.example.toml accounts.toml
$EDITOR accounts.toml # add your accounts
export PERSONAL_IMAP_PASSWORD='...'
uv run imap-mcp # starts the MCP server on stdioThat's it. Register it with your MCP client (below) and start asking about your mail.
Configure accounts
accounts.toml is gitignored and holds no secrets:
[[account]]
key = "personal" # short id used in tool calls
label = "you@example.com (Fastmail)" # optional, defaults to email
email = "you@example.com" # IMAP login
host = "imap.fastmail.com"
port = 993 # optional, defaults to 993
password_env = "PERSONAL_IMAP_PASSWORD" # env var holding the password
enabled = true # optional, defaults to trueAdd one [[account]] block per mailbox. enabled = false keeps an account
listed but never logs into it. Set IMAP_MCP_ACCOUNTS=/path/to/accounts.toml
to keep the config outside the repo.
Provider cheat sheet
Provider | Host | Password |
Gmail / Google Workspace |
| App password (requires 2FA; the spaces Google shows are stripped automatically) |
Fastmail |
| |
iCloud |
| |
Yahoo |
| |
Migadu |
| Mailbox password |
Outlook.com / Microsoft 365 | not supported | Microsoft has retired IMAP basic auth; OAuth is not implemented here |
All standard providers use port 993 (implicit TLS), the default.
Passwords
Each account's password_env names an environment variable that must be set
when the server runs. Any of these work:
# plain export in the shell that launches your MCP client
export PERSONAL_IMAP_PASSWORD='...'
# direnv, sops, pass, whatever you already use
# 1Password: put op:// references in an env file and wrap the command
op run --env-file=op.env -- uv run imap-mcpRegister with an MCP client
Claude Code
claude mcp add imap -- uv run --directory /path/to/imap-mcp imap-mcpOr in .mcp.json / your user MCP config:
{
"mcpServers": {
"imap": {
"command": "uv",
"args": ["run", "--directory", "/path/to/imap-mcp", "imap-mcp"]
}
}
}Claude Desktop and other clients
Same command and args in the client's MCP server config
(claude_desktop_config.json, etc.). Any stdio MCP client works.
Either way, the password env vars must be visible to the spawned process:
export them in the environment the client launches from, or wrap the command
in your secret injector, e.g. "command": "op",
"args": ["run", "--env-file=/path/to/op.env", "--", "uv", "run", ...].
Tools
list_accounts() configured accounts with live status. Run this first;
it tells you which mailboxes are queryable and what to pass as account.
{"account": "personal", "email": "you@example.com", "enabled": true, "status": "ok"}list_emails(account?, since?, unread_only?, limit?) recent mail, newest
first. Omit account to merge all enabled accounts into one timeline.
search_emails(query, account?, since?, limit?) free-text search over
sender, subject, and body. Also cross-account unless you name one.
Both return compact rows:
{"account": "personal", "id": "4711", "from": "billing@hetzner.com",
"subject": "Invoice 2026-07", "date": "2026-07-03T09:12:44+00:00",
"unread": true, "snippet": "Your invoice for July..."}get_email(account, id) one full message by the id from a row, with
plain-text body preferred over HTML. Reading it does not mark it read.
Dates are ISO (YYYY-MM-DD); since filters everywhere; limit applies per
account when merging. If one account is down, its error comes back as a row
and the other accounts still answer.
Troubleshooting
status: "no-credential": the account'spassword_envvariable is not set in the server's environment. Remember the server inherits its env from whatever launched it (your MCP client), not from your interactive shell.status: "unreachable: MailboxLoginError"on Gmail/iCloud/Yahoo: you're using the account password; these providers require an app password (see cheat sheet).Config not found: the server looks for
accounts.tomlnext topyproject.toml, or whereverIMAP_MCP_ACCOUNTSpoints.
Development
uv run pytest31 tests, no network: the IMAP layer is faked. The suite locks in the
read-only contract (mark_seen=False on every fetch), per-account error
isolation, and config handling.
License
MIT
Available Tools
4 toolsget_emailA
Fetch one full email (plain-text body preferred) by account + message id.
id is the value returned in list_emails/search_emails rows (IMAP UID).
Reading does not mark the message as read.
Inputs: id (required), account (required).
list_accountsA
List configured mail accounts and whether each is reachable right now.
Performs a live IMAP login per enabled account. Returns status so the caller knows which mailboxes are queryable.
Inputs: no named parameters. Returns: result
list_emailsA
List recent emails, newest first.
account: account key (see list_accounts). Omit to merge ALL enabled accounts.
since: ISO date (YYYY-MM-DD) lower bound, optional.
unread_only: only unseen messages.
limit: max rows (per account when merging).
Inputs: limit, since, account, unread_only. Returns: result
search_emailsA
Search emails across from/subject/body text, newest first.
query: free text; matched against sender, subject, and body (IMAP OR).
account: omit to search ALL enabled accounts.
since: ISO date (YYYY-MM-DD) lower bound, optional.
limit: max rows (per account when merging).
Inputs: query (required), limit, since, account. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 4 tools
Each tool targets a distinct operation: listing accounts, listing emails, searching emails, and fetching a single email. There is no overlapping purpose between them, and the parameters clearly differentiate list_emails from search_emails.
All tools follow a consistent verb_noun snake_case pattern: list_accounts, list_emails, search_emails, get_email. The naming is predictable and uniform.
With 4 tools, the server is well-scoped for basic email retrieval. Each tool earns its place, covering the essential actions without unnecessary bloat or redundancy.
The set covers the core email-reading workflow: identify accounts, list/search emails, and fetch full content. Minor gaps like flag management or folder operations exist, but the primary use case is fully supported.
Maintenance
Related MCP Connectors
Your IMAP mailbox as an MCP server: read, search and (if you allow it) organize mail. Open source.
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Hosted MCP server for your Gmail, Outlook and IMAP mail, with mailboxes and scopes set per agent.
Your own IMAP mailbox in any MCP client: search, read, flag, move; send and delete need confirm.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceRead-only MCP server for Gmail that enables searching threads, reading messages, and listing labels without any write access.124 npmMIT
- AlicenseNot gradedqualityDmaintenanceRead-only MCP server for IMAP email access, enabling AI agents to read, search, and monitor email without sending or deleting messages.27 npmMIT
- AlicenseNot gradedqualityBmaintenanceA read-only MCP server that gives Claude unified access to multiple Gmail and Microsoft 365 accounts, enabling email search, reading, and listing through one connection.283 npmMIT
- AlicenseNot gradedqualityDmaintenanceA read-only Gmail MCP server enabling users to search and read emails via Gmail search syntax without sending, deleting, or modifying anything.283 npmMIT