IMAP MCP
# IMAP MCP
An MCP server that gives Claude read, manage and send access to any IMAP mailbox,
for the mail that Google and Microsoft connectors do not cover: hosting company
mailboxes (xneelo, cPanel, Plesk), self hosted Dovecot, anything that speaks
plain IMAP and SMTP.
Runs locally over stdio. Your password stays in a local .env file, and mail goes
directly from this machine to your mail server.
## What Claude gets
| Tool | What it does |
| --- | --- |
| `list_accounts` | Configured mailboxes, and whether each password is set |
| `list_folders` | Every folder, plus the detected Sent, Trash and Drafts folders |
| `search_messages` | Search by sender, recipient, subject, text, date, unread, flagged. Newest first, header only by default |
| `get_message` | One message: headers, body as text, attachment list |
| `get_attachment` | Save one attachment to disk and return the path |
| `mark_read` | Mark read or unread |
| `set_flag` | seen, flagged, answered, draft, deleted |
| `move_messages` | Move or archive to another folder |
| `delete_messages` | Move to Trash, or erase permanently after confirmation |
| `send_message` | Send new mail, after a preview and confirmation |
| `reply_to_message` | Threaded reply, sender only or reply all, after a preview |
| `create_draft` | Save a draft for you to send yourself |
## Safety rules built in
- **Reading never marks mail as read.** Every fetch uses BODY.PEEK and folders
open read only, so Claude browsing the mailbox does not change its state.
`get_message(mark_seen=True)` is the only exception and has to be asked for.
- **Sending and permanent deletion take two steps.** The first call returns the
exact message or the exact target plus a `confirmation_token` and does
nothing. Only a second call with `commit=True` and that token acts. Change any
argument between the two calls and the token stops matching.
- **Delete means Trash.** `delete_messages` moves to the Trash folder unless you
pass `permanent=True`.
- **Per account read_only.** Set `"read_only": true` on an account and every
write tool refuses, while reading keeps working.
- **Sent mail is filed.** SMTP does not copy what it sends, so after a send the
same bytes are appended to the Sent folder, where your normal mail client
expects them.
- **Attachments go to disk**, never into the conversation.
## Setup
1. Install:
```
uv venv --python 3.12
uv pip install -e ".[dev]"
```
2. Copy `accounts.example.json` to `accounts.json` and fill in your mail server
details. Ask your host for the IMAP and SMTP settings if you do not have them.
Passwords do not go in this file.
3. Copy `.env.example` to `.env` and add one password per account. The variable
name is the account name, uppercased, with anything that is not a letter or
digit turned into an underscore: account `work` reads `IMAP_PASSWORD_WORK`.
Add `SMTP_PASSWORD_<NAME>` only if the SMTP password differs.
4. Prove the account works before wiring it in:
```
.venv\Scripts\python.exe scripts\smoke.py
```
5. Register the server with Claude Code:
```
claude mcp add --scope user imap -- "C:\Claude Projects\IMAP MCP\.venv\Scripts\python.exe" -m imap_mcp.server
```
Restart Claude Code and check `/mcp`.
## Account fields
| Field | Default | Notes |
| --- | --- | --- |
| `name` | required | How you refer to the account in a prompt |
| `imap_host` | required | |
| `username` | required | Usually the full email address |
| `imap_port` | 993 | 143 for starttls or none |
| `imap_security` | `ssl` | `ssl`, `starttls` or `none` |
| `smtp_host` | none | Leave blank to disable sending |
| `smtp_port` | 587 | 465 for ssl |
| `smtp_security` | `starttls` | `ssl`, `starttls` or `none` |
| `smtp_username` | `username` | Only if it differs |
| `from_address` | `username` | The address mail is sent as |
| `from_name` | blank | Display name on outgoing mail |
| `sent_folder`, `trash_folder`, `drafts_folder` | detected | Set these only if detection picks the wrong folder |
| `read_only` | false | Blocks every write tool for this account |
| `verify_tls` | true | Set false only for a host whose certificate is broken. The connection stays encrypted, the server identity stops being checked |
| `timeout` | 60 | Seconds |
Sent, Trash and Drafts are found from the server's SPECIAL-USE flags, falling
back to the usual names including the Dovecot style `INBOX.Sent`.
### Shared hosting and certificates
Hosts like xneelo point `mail.yourdomain.co.za` at a shared server whose
certificate is issued for the server's own name, so strict TLS verification
fails on the vanity hostname even though the connection is fine. Find the real
server name and use that instead:
```
python -c "import socket; print(socket.gethostbyaddr(socket.gethostbyname('mail.yourdomain.co.za')))"
```
That returns something like `www12.cpt3.host-h.net`, which its certificate does
cover. The tradeoff is that if the host migrates your mailbox to another server,
the hostname changes and login starts failing: rerun the line above and update
`accounts.json`. The alternative is keeping the vanity hostname with
`"verify_tls": false`.
## Not supported
OAuth2, so Gmail and Microsoft 365 are out of scope: they have first party
connectors already. Password authentication over TLS only. Gmail with an app
password does work if you want it here anyway.
## Tests
```
.venv\Scripts\python.exe -m pytest # 35 unit tests, no network
```
End to end against a throwaway mail server in Docker, which exercises all 12
tools including sending, moving and permanent deletion without touching a real
mailbox:
```
docker run -d --rm --name imapmcp-greenmail -p 3143:3143 -p 3025:3025 ^
-e GREENMAIL_OPTS="-Dgreenmail.setup.test.all -Dgreenmail.hostname=0.0.0.0 -Dgreenmail.auth.disabled" ^
greenmail/standalone:2.1.0
.venv\Scripts\python.exe scripts\e2e_greenmail.py
docker stop imapmcp-greenmail
```
TDQS
Scored across 12 tools
Most tools have distinct purposes, but mark_read and set_flag overlap on the 'seen' flag, and delete_messages vs set_flag's 'deleted' could confuse agents. However, descriptions clarify the differences, so ambiguity is limited.
All 12 tools follow a consistent verb_noun pattern in snake_case (e.g., delete_messages, get_attachment, list_folders). No stylistic deviations or mixed conventions.
12 tools is within the ideal 3-15 range. Each tool covers a core email operation (send, read, search, manage), with no redundancies or missing essentials.
The surface covers key IMAP workflows: send, reply, draft, search, get message, attachment download, move, delete, flags, and folder/account listing. Minor gaps exist (e.g., folder creation, expunge, raw message fetch), but agents can accomplish typical tasks without failures.