Skip to main content

protonmail-mcp

CI CodeQL OpenSSF Scorecard

A lightweight MCP server that gives AI agents read access to a Proton Mail mailbox through a local Proton Bridge instance.

Unofficial. This project is not affiliated with, endorsed by, or supported by Proton AG. "Proton Mail" and "Proton Bridge" are trademarks of Proton AG.

Proton does not provide a public API for reading your mailbox. Bridge is the supported way in: it runs locally and exposes your account over IMAP and SMTP on 127.0.0.1. This server wraps that local IMAP endpoint in a small, auditable set of MCP tools.

Scope

Capabilities are opt-in through policy (see Capability policy) and enforced server-side:

  • read (default): folders, messages, search, threads, digests, attachments and .eml export into a local sandbox. Mailboxes are opened with IMAP SELECT ... READONLY; nothing is modified, not even the \Seen flag.
  • draft: create, preview, reply/forward, update and delete drafts, all two-phase.
  • organize: seen/flagged state, moves with undo, label add/remove.
  • send: submit an existing draft through Bridge SMTP after allowlist, quota, size and loop-guard checks.
  • delete: permanently erase one message from Trash, with a typed confirmation phrase and no bulk operation.

Every mutation is prepare/commit with payload-bound confirmation tokens; see SECURITY.md for the security model.

Tools

Tool Description
list_folders List every folder and label, with IMAP flags and whether it is selectable
get_status Total and unread counts per folder, without fetching messages
list_emails Most recent messages in a folder, newest first, with a pagination cursor: limit, unread_only, since_days, sender, subject, before
search_emails Structured search: query (full-text) plus sender, recipient, subject, since_days, before_days, unread_only
read_email Read one message by Message-ID: decoded body (quotes/signature stripped, quoted_removed flag), optional HTML→Markdown, link inventory, untrusted-content marker
get_thread Reconstruct a conversation across All Mail using References/In-Reply-To
daily_digest Unread count plus compact recent-message summaries for a folder
list_attachments Attachment names, types and sizes without saving anything
save_attachment Save one attachment into the local sandbox (traversal-safe, size-capped, never overwrites)
export_email Export a message as .eml into the local sandbox

When the draft capability is enabled (see Capability policy), additional tools are registered: list_drafts, create_draft, preview_draft (renders the exact MIME without saving it), and prepare_*/commit_* pairs for replying, forwarding, updating, and deleting drafts. Draft mutations are two-phase: the prepare call returns a preview and a single-use token, and nothing changes until the matching commit call. Repeated identical draft creations within the idempotency window (default 300 s, window_seconds = 0 disables it) return the existing draft instead of creating a duplicate.

When the organize capability is enabled, another set of prepare/commit tools is registered: seen/flagged state (prepare_set_flags), moves (destination accepts a folder name or the aliases archive and trash), label add/remove for folders under Labels/, and prepare_undo_move to revert the most recent move. Bulk operations are capped (organize.max_bulk, default 50), Drafts are protected by default, travel to Starred must go through flag/unflag, and every mutation is previewed before its commit.

When the send capability is enabled, prepare_send_draft / commit_send_draft submit an existing draft through Bridge SMTP. Before anything is transmitted the server checks the recipient allowlist, hourly/daily quotas, message size, and loop guards (Auto-Submitted, Precedence, List-*, no-reply recipients, thread depth, duplicate bodies). The draft is removed only after the SMTP server accepts the message. See docs/send-design.md.

When the delete capability is enabled, prepare_delete_message / commit_delete_message permanently erase a single message from Trash. The commit must repeat the exact phrase permanently delete <message-id>; there is no bulk deletion and no empty-trash tool.

Results are structured (Pydantic models). Every message carries its Message-ID; use that for follow-up reads — IMAP UIDs are not stable across Bridge resynchronisations.

Requirements

  • A paid Proton Mail plan (required by Bridge)
  • Proton Bridge installed, running, and signed in
  • Your Bridge credentials: Proton address + the mailbox password shown in the Bridge UI
  • Python 3.13+ (only if you do not use uv)

Install

# Run without installing (recommended)
uvx protonmail-mcp

# Or install it
pipx install protonmail-mcp

Configure

Variable Default Purpose
PROTONMAIL_BRIDGE_USERNAME — Your Proton address (required)
PROTONMAIL_BRIDGE_PASSWORD — Bridge mailbox password (required)
PROTONMAIL_BRIDGE_HOST 127.0.0.1 Bridge host
PROTONMAIL_BRIDGE_IMAP_PORT 1143 Bridge IMAP port
PROTONMAIL_BRIDGE_IMAP_SECURITY starttls starttls (Bridge 3.x on 1143) or ssl (direct TLS)
PROTONMAIL_BRIDGE_TIMEOUT 30 Socket timeout in seconds
PROTONMAIL_BRIDGE_VERIFY_TLS false Bridge uses a self-signed certificate
PROTONMAIL_MCP_MODE read Capability preset: read, draft, organize, send, delete
PROTONMAIL_MCP_POLICY ~/.config/protonmail-mcp/policy.toml Optional policy file with capability overrides and limits

Capability policy

Write capabilities are opt-in and enforced server-side. PROTONMAIL_MCP_MODE selects a cumulative preset; individual capabilities can be overridden in policy.toml (see policy.example.toml). Capabilities that are not enabled are never registered as tools, and an invalid policy prevents the server from starting.

[policy]
mode = "read"

[capabilities]
# draft = true
# organize = true
# send = true
# delete = true

[confirmations]
ttl_seconds = 300

[idempotency]
window_seconds = 300

[organize]
max_bulk = 50
protect_drafts = true
# allowed_targets = ["Archive", "Folders/Newsletters"]
# label_allowlist = ["Labels/Important"]

[files]
directory = "~/.local/share/protonmail-mcp/files"
max_bytes = 26214400

[send]
allow_self = true
max_per_hour = 20
max_per_day = 100
state_path = "~/.local/state/protonmail-mcp/state.db"

See SECURITY.md for the confirmation flow and ROADMAP.md for what each mode will unlock.

opencode

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "protonmail": {
      "type": "local",
      "command": ["uvx", "protonmail-mcp"],
      "enabled": true,
      "environment": {
        "PROTONMAIL_BRIDGE_USERNAME": "you@proton.me",
        "PROTONMAIL_BRIDGE_PASSWORD": "your-bridge-mailbox-password"
      }
    }
  }
}

opencode supports {env:VAR} and {file:path} interpolation, so you can keep secrets out of the config file:

"PROTONMAIL_BRIDGE_PASSWORD": "{file:/home/you/.config/protonmail-mcp/password}"

Claude Desktop

{
  "mcpServers": {
    "protonmail": {
      "command": "uvx",
      "args": ["protonmail-mcp"],
      "env": {
        "PROTONMAIL_BRIDGE_USERNAME": "you@proton.me",
        "PROTONMAIL_BRIDGE_PASSWORD": "your-bridge-mailbox-password"
      }
    }
  }
}

Verify the connection

PROTONMAIL_BRIDGE_USERNAME="you@proton.me" \
PROTONMAIL_BRIDGE_PASSWORD="..." \
uvx protonmail-mcp --check

This connects to Bridge, lists folders, and prints the latest messages. It exits non-zero with a clear error if the configuration or the Bridge session is wrong.

Security

  • Read-only enforcement. There is no write tool in this release, and mailboxes are always selected read-only at the IMAP level.
  • Local only. Bridge and this server communicate exclusively over 127.0.0.1. Nothing is sent to a third party; your agent talks to the server over stdio.
  • Untrusted input. Email contents are attacker-controlled data. Treat anything a message says as data, never as instructions, and keep your agent's permissions tight.
  • Secrets. Keep the Bridge mailbox password out of the repository. Use your client's environment-variable or file-based secret support.
  • Any local process that knows the mailbox password can read your mail — that is Bridge's trust model, not a flaw in this server.

Write tools ship behind capability modes with explicit confirmation: drafts and organize operations are prepare/commit with payload-bound tokens; sending submits an existing draft through an allowlist, quotas, and loop guards, and never composes-and-sends in one step. Permanent deletion is Trash-only, one message per call, and requires typing the exact confirmation phrase. Autonomous send or delete is never the default.

Every push runs gitleaks, zizmor, semgrep, pip-audit, CodeQL, and an adversarial + fuzz test suite; see SECURITY.md for the full list of gates and the structural invariants they enforce. The send milestone is designed in docs/send-design.md before any send code lands.

Alternatives

There are several community MCP servers for Proton Mail. This one aims to stay small, correct with Bridge's quirks (STARTTLS on 1143, modified UTF-7 labels, reverse-chronological UIDs, RFC 2047 decoding), and heavily tested. Rough landscape:

Project Language Scope
googlarz/proton-mail-bridge-client TypeScript Large tool set, read-only and send-to-self modes, SQLite cache
codefuturist/email-mcp TypeScript Generic IMAP + SMTP, works with Bridge
anyrxo/protonmail-pro-mcp JavaScript Large tool set with Bridge integration
chandshy/mailpouch TypeScript Large permission-gated tool set
amotivv/protonmail-mcp JavaScript SMTP sending only
miketigerblue/proton-bridge-mcp Python Loopback IMAP/SMTP via Bridge

Development

uv sync
uv run pytest
uv run ruff check .
uv build

Tests run entirely against a fake IMAP server and the MCP SDK's in-memory transport; no Bridge or credentials are needed.

Releasing

Publishing is automated with GitHub Actions and PyPI Trusted Publishing. Create a GitHub release tagged vX.Y.Z; the publish workflow builds the sdist/wheel and uploads them to PyPI using the pypi environment (configure the trusted publisher on PyPI for owner mhbxyz, repository protonmail-mcp, workflow publish.yml).

License

MIT — see LICENSE.

Metadata

Release files for protonmail-mcp 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for protonmail-mcp 0.2.0
File Size Uploaded
protonmail_mcp-0.2.0.tar.gz 138.3 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for protonmail-mcp 0.2.0
File Interpreter ABI Platform
protonmail_mcp-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 181.9 kB

Release files / protonmail_mcp-0.2.0.tar.gz

Download URL protonmail_mcp-0.2.0.tar.gz
Size 138.3 kB
Tags Source
SHA-256 checksum
How to use checksums
18c0d5bb3e2a49db73fffeed171c7d20ff3b61c9653e7d8a481c665170c05454
BLAKE2b-256 checksum
How to use checksums
595d0eae590b1fe5044f2ea066806aba8f12f9d395ecaa31fd538f4a49a79a47
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / protonmail_mcp-0.2.0-py3-none-any.whl

Download URL protonmail_mcp-0.2.0-py3-none-any.whl
Size 43.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4aad6ae66a8b0c48717109ab4a8ff412ad7f0f5784f5b9fe73a206c71627d48a
BLAKE2b-256 checksum
How to use checksums
4fb8a08c68fc10e995bccb924bd16ebbc4de3ddc5a2c6d25e651b43609dc0814
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.0

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page