proton-mail-ro
by chang-ryan
README.md
# proton-mail-ro
A **read-only** MCP server for Proton Mail, over the local Proton Bridge.
Seven tools, all of which read. No way to send, delete, flag, move, or touch a credential.
```
mail__search search every folder by text / from / to / subject / body / date
mail__get_message read one message in full
mail__get_thread read a whole thread
mail__list_folders enumerate mailboxes
mail__list_messages recent messages in a folder, headers only
mail__get_unread unread inbox messages, headers only
mail__get_attachments attachments as base64, nothing written to disk
```
## Why this fork exists
Forked from [jorgenclaw/proton-mcp](https://github.com/jorgenclaw/proton-mcp), which is a
capable 36-tool server for the whole Proton suite. The upstream code is clean — no
exfiltration, no obfuscation, `execFile` with array args throughout, one outbound call in
the entire tree. The problem is not the code, it is the **capability surface** when you point
it at an assistant.
Upstream exposes, in one server:
- `pass__get_item`, `pass__get_totp` — reads stored passwords and mints live 2FA codes.
The tool description says *"Use for autonomous 2FA."*
- `mail__send_message`, `reply`, `forward` — sends mail as you
- `mail__delete_message`, `drive__delete`, `pass__trash_item`, `calendar__delete_event`
- `drive__upload` / `download` — moves files in and out of Proton Drive
Read arbitrary email **plus** read the password vault **plus** mint TOTP codes **plus** send
mail is a complete account-takeover kit. And mail is untrusted input: a crafted message sitting
in the mailbox can attempt to instruct the model reading it. No code change fixes that. The only
real mitigation is to not grant the capability.
So: if the job is "find the notice the tax agency sent me," the tool for it reads mail and
does nothing else.
## What changed
**Deleted outright** — `pass/`, `drive/`, `vpn/`, `calendar/`, `mail/smtp-client.js`, and the
four mutating IMAP operations (`markMessage`, `starMessage`, `deleteMessage`, `moveMessage`).
Removed, not feature-flagged.
**Read-only is hard-wired.** All three `openBox` helpers pass `readOnly=true` as a literal.
No code path in the process can mutate a mailbox, even by mistake.
**Search actually searches.** Upstream walked a hardcoded `['INBOX','Sent','Drafts','Archive']`
and capped at 10 hits per folder, so anything in a custom folder or All Mail was invisible.
This enumerates real folders via `getBoxes` and supports structured IMAP criteria — `from`,
`subject`, `body`, `since`, `before` — which is what you need to find one letter in years of mail.
**`get_message` and `get_attachments` take a folder.** Upstream only ever opened INBOX, so
anything filed elsewhere could be found by search but not read.
**Config loading works.** Upstream read `PROTON_BRIDGE_USERNAME` / `PROTON_BRIDGE_PASSWORD`
while its own `.env.example` shipped `PROTON_BRIDGE_USER` / `PROTON_BRIDGE_PASS` — and nothing
imported `dotenv`, so a `.env` was never read at all. Both spellings are accepted now and the
file is actually parsed.
**Non-loopback hosts are refused.** The IMAP connection is plaintext (`tls: false`), correct for
a Bridge on `127.0.0.1` and catastrophic anywhere else. Pointing `PROTON_BRIDGE_IMAP_HOST` off-box
throws instead of putting the password on the wire.
**Message bodies are labelled untrusted.** Every response carrying a body includes an `_untrusted`
field stating that the content is data, not instruction. Defense in depth, not a guarantee.
**Dependencies pinned.** Upstream used `"@modelcontextprotocol/sdk": "latest"`. `nodemailer` is
gone with the send path.
## Setup
Proton Bridge must be running and listening on `127.0.0.1:1143`:
```sh
lsof -nP -iTCP:1143 -sTCP:LISTEN
```
Credentials, either way round:
```sh
mkdir -p ~/.proton-mcp
cat > ~/.proton-mcp/bridge.json <<'JSON'
{ "username": "you@example.com", "password": "<bridge password, not your Proton password>" }
JSON
chmod 600 ~/.proton-mcp/bridge.json
```
or `PROTON_BRIDGE_USERNAME` / `PROTON_BRIDGE_PASSWORD` in the environment.
The Bridge password is the one Proton Bridge generates per account — not your Proton login.
Then register the server:
```sh
claude mcp add proton-mail-ro -- node /path/to/proton-mail-ro/index.js
```
## Scope
Reading a mailbox means reading everything in it. This server cannot act on what it reads, but
it can surface anything the account holds, so point it only at mailboxes you are willing to have
read in full.
Licensed as upstream. See `LICENSE`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues