imap-mcp
by agimenezdev
README.md
# imap-mcp
[](https://github.com/agimenez-dev/imap-mcp/actions/workflows/ci.yml)
[](https://www.python.org/downloads/)
[](LICENSE)
A live **IMAP + SMTP** [MCP](https://modelcontextprotocol.io) server. It lets an
LLM read, search, send and manage email across multiple accounts over a real
mail connection — with sending that is **safe by default**.
```
You: "Reply to the vendor confirming we approved the quote, attach the PO."
LLM: → mail_send(..., confirm=false) # returns a preview, sends nothing
You: "Looks good, send it."
LLM: → mail_send(..., confirm=true) # now it actually goes out
```
## Why another email MCP
Email is the one integration where a careless agent does real damage — a wrong
auto-send can't be unsent. This server is built around that:
- **Confirm before send.** `mail_send` returns a preview and sends nothing unless
you pass `confirm=true`. No message ever leaves on the first call.
- **Read-only accounts.** Mark an account `readonly` and every mutating tool
(send, flag, move, delete) is refused for it — useful for mailboxes you only
want the model to *read*.
- **No secrets on disk.** The config file contains no passwords. Each account
says *where* its password comes from — an environment variable or a command
(your password manager) — and it's read on demand, held only in memory.
- **Multi-account.** Personal, work and shared mailboxes side by side, each with
its own host and credentials.
## Tools
| Tool | What it does |
| --- | --- |
| `mail_list(account, folder, limit, unseen_only)` | Recent messages (headers only) |
| `mail_search(account, query, folder, limit)` | Search From / Subject / body |
| `mail_read(account, uid, folder)` | Full message: body + attachment names |
| `mail_download_attachment(account, uid, folder, filename, dest_dir)` | Save attachments to disk |
| `mail_send(account, to, subject, body, cc, bcc, attachments, confirm)` | **Send — `confirm=true` required** |
| `mail_flag(account, uid, action, folder)` | Mark seen / unseen / flagged / deleted |
| `mail_move(account, uid, dest_folder, folder)` | Move between folders |
| `mail_folders(account)` | List IMAP folders |
| `mail_accounts()` | List configured accounts and credential status |
## Install
Requires Python 3.11+.
```bash
git clone https://github.com/agimenez-dev/imap-mcp
cd imap-mcp
uv sync # or: pip install -e .
```
## Configure
Create `~/.config/imap-mcp/accounts.toml` (or set `IMAP_MCP_CONFIG` to any path).
Start from [`accounts.example.toml`](accounts.example.toml):
```toml
[[account]]
address = "you@example.com"
host = "imap.example.com" # used for IMAP (993) and SMTP (465)
password_env = "MY_MAIL_PASSWORD" # read the password from this env var
[[account]]
address = "shared@example.com"
host = "imap.example.com"
password_command = "rbw get 'Shared Mailbox'" # ...or from a command's stdout
readonly = true # read-only: no send/flag/move
```
Each account resolves its password from **either** `password_env` (an environment
variable) **or** `password_command` (a shell command whose first line of stdout is
the password). The file itself never contains a secret.
## Use with Claude Desktop / Claude Code
```json
{
"mcpServers": {
"imap": {
"command": "uv",
"args": ["--directory", "/path/to/imap-mcp", "run", "imap-mcp"]
}
}
}
```
## Security notes
- Passwords are never written to disk by this server. They live in memory only
for the duration of a connection (cached per process to avoid re-prompting a
password manager on every call).
- Reads use `BODY.PEEK[]`, so reading a message does **not** mark it as seen.
- `readonly` accounts reject send/flag/move/delete at the application layer,
before any connection is opened.
- IMAP and SMTP use implicit TLS (ports 993 / 465) with certificate verification.
## Development
```bash
uv sync --extra dev
uv run pytest # config + MIME layers are covered without a mail server
uv run ruff check .
```
The IMAP/SMTP transport is a thin wrapper over the standard library; the tested
logic is the parts that are easy to get wrong — config/credential resolution and
MIME decoding.
## License
MIT — see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues