protonmail-mcp
# protonmail-mcp
An MCP (Model Context Protocol) server for **ProtonMail**, connected through
[ProtonMail Bridge](https://proton.me/mail/bridge).
Unlike generic IMAP MCP servers, this connector is **Bridge-aware**:
- Auto-detects a local Bridge install and discovers its IMAP/SMTP ports and
TLS certificate.
- Verifies TLS against Bridge's own certificate — **never `verify=False`**
(enforced by a test that scans the source tree).
- Understands ProtonMail's model: labels are folders under `Labels/`, custom
folders live under `Folders/`, and destructive operations on the virtual
`All Mail` view are refused with an explanation.
- Turns every Bridge failure mode into an actionable message: *not
installed*, *not running*, *wrong bridge password*, *certificate mismatch*.
## Prerequisites
- [ProtonMail Bridge](https://proton.me/mail/bridge) installed, running, and
logged in (Bridge requires a paid Proton plan).
- Python ≥ 3.12, or just [`uv`](https://docs.astral.sh/uv/) — it provisions
Python for you.
## Install
```bash
# Guided setup: discovers Bridge, writes config, checks the login
uvx protonmail-mcp setup
# Run the MCP server (stdio)
uvx protonmail-mcp
```
### MCP client configuration
Claude Code:
```bash
claude mcp add protonmail -- uvx protonmail-mcp
```
Claude Desktop (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"protonmail": {
"command": "uvx",
"args": ["protonmail-mcp"]
}
}
}
```
## Configuration
`~/.config/protonmail-mcp/config.toml` (created by `setup`, permissions 600):
```toml
[[accounts]]
name = "default"
email = "you@proton.me"
display_name = "Your Name"
password = "<bridge password from Bridge → Mailbox details>"
# Optional — only needed when Bridge uses non-default ports:
# imap = { port = 1143 }
# smtp = { port = 1025 }
```
Multiple `[[accounts]]` blocks are supported; tools take an `account`
parameter (default `"default"`).
Environment variables configure a single account without a file:
`PROTONMAIL_MCP_ADDRESS`, `PROTONMAIL_MCP_PASSWORD`, and optionally
`PROTONMAIL_MCP_USERNAME`, `PROTONMAIL_MCP_ACCOUNT_NAME`,
`PROTONMAIL_MCP_IMAP_HOST`, `PROTONMAIL_MCP_IMAP_PORT`,
`PROTONMAIL_MCP_SMTP_HOST`, `PROTONMAIL_MCP_SMTP_PORT`.
## Tools
### Reading
| Tool | Description |
|---|---|
| `list_accounts` | List configured accounts (no credentials) |
| `list_mailboxes` | Folders with message/unread counts |
| `list_emails` | Paginated listing with unread/sender/date filters; `mailbox="Labels/<name>"` lists labeled mail |
| `get_email` | Full body, headers, threading ids, attachment metadata |
| `search_emails` | Keyword search across subject, sender, and body |
| `get_thread` | Conversation reconstruction via Message-ID/References |
| `download_attachment` | One attachment, base64, capped at 5 MB |
### Sending
| Tool | Description |
|---|---|
| `send_email` | New email (text or HTML, cc/bcc); Bridge files it into Sent |
| `reply_email` | Reply with In-Reply-To/References threading, quoting, reply-all |
| `forward_email` | Forward with the original quoted |
| `save_draft` | Save to Drafts without sending |
### Organisation
| Tool | Description |
|---|---|
| `move_email` | Move between folders |
| `delete_email` | To Trash by default; permanent only with `permanent=true`; refused on All Mail |
| `mark_email` | Read/unread, flagged/unflagged |
| `create_mailbox` | New folder (bare names go under `Folders/`) |
### ProtonMail labels
| Tool | Description |
|---|---|
| `list_labels` | Labels (folders under `Labels/`) |
| `add_label` | Copy the email into `Labels/<name>` |
| `remove_label` | Delete the email's copy from the label folder (located by Message-ID) |
| `create_label` / `delete_label` | Manage label folders |
### Diagnostics
| Tool | Description |
|---|---|
| `bridge_status` | Bridge install, ports (and how they were discovered), certificate, accounts |
| `check_health` | IMAP + SMTP login and latency per account; structured guidance when Bridge is down |
| `ping` | Server liveness |
## Security
- All Bridge connections use STARTTLS, verified against Bridge's own
self-signed certificate loaded as the *only* trust root (certificate
pinning). TLS verification is never disabled.
- Passwords live in a `chmod 600` config file (or env vars) and are never
logged; validation errors name keys, not values.
- Message bodies are never logged at info level or above.
- Attachment downloads are capped at 5 MB.
- Everything stays on 127.0.0.1 — this server talks only to your local
Bridge, never to Proton's servers directly.
## Development
```bash
uv sync
uv run ruff format --check . && uv run ruff check .
uv run mypy
uv run pytest
```
Conventional Commits are required — see [CONTRIBUTING.md](CONTRIBUTING.md).
The product requirements, including live-verification results against a
real Bridge v3 install, live in [`docs/prd.md`](docs/prd.md). The
behavioral reference for Proton label semantics is the sibling
[email-mcp](https://github.com/codefuturist/email-mcp) TypeScript server.
**Bridge v3 notes** (verified against a real install):
- Port settings live in Bridge's encrypted vault, so discovery falls back to
the defaults (1143/1025) with a logged notice; override ports in the
config if you changed them in Bridge.
- The TLS certificate also lives in the vault and must be exported once:
Bridge → Settings → Advanced settings → "Export TLS certificates", saving
`cert.pem` to `~/.config/protonmail-mcp/` (or set `PROTONMAIL_MCP_CERT`
to its location). The `setup` wizard walks you through this.
## License
LGPL-3.0-or-later — see [LICENSE](LICENSE).
TDQS
Scored across 23 tools
Most tools target distinct actions, but several boundaries blur: list_labels overlaps with list_mailboxes since labels appear as folders, create_mailbox can create labels when passed a Labels/ path, and remove_label vs delete_label could easily be confused. The descriptions help, but an agent still faces real misselection risk.
The vast majority of tools follow a clear verb_noun snake_case pattern: list_emails, send_email, create_label, download_attachment. Exceptions like bridge_status and ping break the pattern slightly, but there is no chaotic mixing of styles.
23 tools is on the heavy side for a single server and falls in the borderline range where each tool must clearly earn its place. Most tools are individually justified for a full email client, but the set feels larger than ideal and could be trimmed by merging health-check or label-related operations.
The tool surface covers the core email lifecycle well: list, get, search, send, reply, forward, draft, move, delete, mark, thread, attachments, folders, and labels. Notable gaps include no way to attach files when sending or replying, and no label rename/update operation, but agents can work around most of these gaps.