ProtonMail MCP Server
Email management for AI agents through ProtonMail and Proton Bridge
Send, read, search, and organize emails from Claude Code, Claude Desktop, Cursor, or any MCP-compatible client.
Quick start
Install from npm (recommended)
npx @ronamosa/protonmail-pro-mcp
Or install globally:
npm install -g @ronamosa/protonmail-pro-mcp
protonmail-pro-mcp
Install from source
git clone https://github.com/ronamosa/protonmail-pro-mcp.git
cd protonmail-pro-mcp
npm install
npm link
Verify the install:
which protonmail-pro-mcp
Prerequisites -- Node.js >= 18 and Proton Bridge running locally.
Configuration
cp .env.example .env # then fill in your credentials
Security --
PROTONMAIL_PASSWORDis the bridge-generated password, not your ProtonMail login. Never commit.envfiles.
Local development (Cursor)
To test this repo's built output instead of the published npm package:
npm run build
cp .cursor/mcp.json.example .cursor/mcp.json # add your Bridge credentials
Restart Cursor MCP (Settings → MCP → reload). The local server runs node dist/index.js from this workspace.
Manual attachment test (Bridge required)
Sends a self-addressed email with two attachments named dupe.txt, then verifies ambiguous lookup and index-based retrieval:
cp .env.example .env # if you have not already
npm run build
npm run test:attachments:manual
The script leaves the test email in INBOX so you can also exercise get_email_by_id and get_attachment from Cursor.
Usage
Add to ~/.claude.json under mcpServers, or run claude mcp add:
{
"mcpServers": {
"protonmail": {
"type": "stdio",
"command": "npx",
"args": ["@ronamosa/protonmail-pro-mcp"],
"env": {
"PROTONMAIL_USERNAME": "[email protected]",
"PROTONMAIL_PASSWORD": "your-bridge-password"
}
}
}
}
Add to ~/.config/claude/claude_desktop_config.json:
{
"mcpServers": {
"protonmail": {
"command": "npx",
"args": ["@ronamosa/protonmail-pro-mcp"],
"env": {
"PROTONMAIL_USERNAME": "[email protected]",
"PROTONMAIL_PASSWORD": "your-bridge-password"
}
}
}
}
Add to .cursor/mcp.json in your project:
{
"mcpServers": {
"protonmail": {
"command": "npx",
"args": ["@ronamosa/protonmail-pro-mcp"],
"env": {
"PROTONMAIL_USERNAME": "[email protected]",
"PROTONMAIL_PASSWORD": "your-bridge-password"
}
}
}
}
protonmail-pro-mcp --transport http --port 3000
Endpoints: POST /mcp, GET /mcp, DELETE /mcp (Streamable HTTP). Health check at GET /health.
Tools
Threading
Replies thread when the message carries In-Reply-To and References (RFC 5322 §3.6.4).
Subject-line matching alone is not threading — Gmail happens to group on it, most clients do not.
create_reply_draft is the tool to reach for: give it the parent's emailId and a body, and it
derives the recipients, the Re: subject and both headers itself. Assembling the chain by hand is
easy to get wrong, and a wrong chain threads one level deep and then breaks.
create_reply_draft({ emailId: "INBOX:4821", body: "Sounds good." })
create_draft, update_draft and send_email also accept inReplyTo and references directly
for cases the helper does not cover.
Every outgoing message now carries a generated Message-ID, so replies to your own sent mail
thread as well. send_draft forwards the draft's threading headers to SMTP — without that a
correctly threaded draft would send un-threaded.
A parent with no Message-ID cannot be threaded to. create_reply_draft returns
threaded: false in that case rather than pretending otherwise.
Architecture
src/
index.ts Entry point, transport selection, graceful shutdown
server.ts McpServer setup, tool registration
config.ts Zod-validated environment configuration
logger.ts Structured stderr logger with credential redaction
types.ts Shared TypeScript interfaces
services/
smtp.ts nodemailer wrapper (lazy connection)
imap.ts imapflow + mailparser wrapper (lazy connection, auto-reconnect)
tools/
sending.ts send_email, send_test_email
reading.ts get_emails, get_email_by_id, search_emails
drafts.ts create_draft, create_reply_draft, update_draft, delete_draft, send_draft
actions.ts mark_email_read, star_email, move_email, delete_email
folders.ts get_folders, sync_folders
system.ts get_connection_status
- McpServer API (SDK v1.29+) with Zod input validation on every tool
- Tool annotations (
readOnlyHint,destructiveHint,openWorldHint) per MCP spec - Dual transport -- stdio for local use, Streamable HTTP for remote deployment
- Lazy connections -- SMTP and IMAP connect on first use, not at startup
- Credential redaction -- passwords scrubbed from all log output
- Soft delete --
delete_emailmoves to Trash first; permanent delete only from Trash
Development
npm run dev # Watch mode with tsx
npm run typecheck # Type checking without emit
npm run lint # ESLint
npm run format # Prettier
npm test # Run tests
npm run build # Rebuild (symlink picks up changes automatically)
Credits
Originally scaffolded from anyrxo/protonmail-pro-mcp. Completely rewritten with modern MCP SDK, Zod validation, dual transport, and full tool implementations.
License
MIT