Facteur
Provides access to a Proton account across Proton Mail, Proton Pass, and Proton Calendar, enabling mail management, Pass item lookup and management, and read-only calendar access.
Provides read-only access to Proton Calendar events via calendar share links, including date-range queries, recurring event expansion, and event search.
Provides tools to list mailboxes, search and read emails, threads, and attachments, manage labels/folders, create drafts, and send, reply to, or forward mail through Proton Mail Bridge.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Facteur
An MCP server for a Proton account. Claude, ChatGPT, Cursor or any MCP client can use it to read, search, organize and send your Mail through Proton Mail Bridge, look up and manage Pass items through Proton's official pass-cli, and read your Calendar.
Facteur is French for postman.
AI app ──HTTPS + OAuth──▶ Facteur ─┬─ IMAP/SMTP (private network) ──▶ Proton Mail Bridge
├─ pass-cli, signed in as a Pass agent ──▶ Proton Pass
└─ calendar share links (ICS, read-only) ──▶ Proton CalendarRemote server with built-in OAuth 2.1. Add the URL as a custom connector in claude.ai, the Claude apps, ChatGPT or Claude Code, then approve it once in your browser. A static token also works for scripts.
Per-connection permissions. Each app gets read, organize & drafts, and/or send. A read-only connection doesn't even see the other tools.
Self-contained. Node 26 runs the TypeScript directly, so there is no build step. The only state is one JSON file and an audit log.
Tools
Tool | Scope | What it does |
| read | System mailboxes, folders and labels, with total and unread counts |
| read | Search one mailbox or |
| read | Full message: headers, readable body (HTML converted), attachments, labels, List-Unsubscribe |
| read | The whole conversation across folders (sent and received), oldest first |
| read | Images as images, text as text, PDFs and other files as embedded resources |
| write | Read/unread, starred, replied |
| write | To inbox, archive, spam, trash or any folder; returns the new ids |
| write | Add or remove labels (optionally creating the label) |
| write | To Trash, or permanently |
| write | Create, rename or delete folders and labels |
| write | Drafts that sync to every Proton app, for review before sending |
| send | New message: Markdown or plain text, Cc/Bcc, attachments, choice of sender address |
| send* | Reply or reply-all with threading headers, quoting, and the right sender address. Can save as a draft instead ( |
| send* | Forward with the original attachments, or save as a draft |
| send | Send a saved draft |
Proton Pass (only when PROTON_PASS_AGENT_TOKEN is set)
Tool | Scope | What it does |
| pass.read | Vaults shared with Facteur's agent |
| pass.read | Find items by title, username, email or website, optionally by vault or type. Non-secret fields only |
| pass.read | One item's non-secret details, plus the names of its secret fields |
| pass.read / pass.reveal | With |
| pass.read | Random password or passphrase |
| pass.write | Save a login, with a generated password by default |
| pass.write | Change fields ( |
| pass.write | Move to the Pass trash, or restore. Never deletes permanently |
Proton Calendar (only when FACTEUR_CALENDARS is set)
Tool | Scope | What it does |
| calendar.read | Events between two dates ( |
Proton Calendar has no API or CalDAV, so this is read-only, through each calendar's share link.
The bulk tools (mark, move, label, delete) take either ids or a search, so "archive every newsletter from last month" is one call. A max guard refuses searches that match more than expected.
Prompts are included for clients that support them: triage_inbox, summarize_unread, draft_reply and clean_up_newsletters.
Message ids look like INBOX/4521: the mailbox, a slash, then the IMAP uid.
Related MCP server: proton-bridge-mcp
Security
Facteur holds the keys to a mailbox, so it is built to be safe to expose:
Nothing is reachable without a token.
/mcprequires an OAuth access token or the static API token. Tokens are 256-bit random, stored only as SHA-256 hashes, and expire after 1 hour. Refresh tokens rotate on every use, and reusing an old one revokes the whole connection.Only the owner can approve a connection. The consent page sits behind Cloudflare Access, where the server verifies the Access JWT itself, or behind an admin password. Approving shows the app's name and where it sends you back, and lets you untick permissions. PKCE (S256) is mandatory, redirect URIs must match exactly, and the authorization codes are single-use and last 5 minutes.
Connections can be revoked at any time from the dashboard at
/.Every change is audited. Each move, delete, label, draft and send is appended to
/data/audit.jsonlwith the app, the message ids, and for sends the recipients and subject (never the body).Pass secrets are opt-in, per app. Facteur signs in to Pass as a Pass agent: a token limited to the vaults you choose, revocable from Pass, with Proton's own audit log (
pass-cli agent monitor facteur). Item lists and details never contain secret values. Values come only frompass_reveal, which needs thepass.revealscope (unticked on the consent page) and a reason that Proton records. Apps without that scope get a one-time link (single use, 10 minutes, behind your sign-in), and the value goes from Pass to your screen without passing through the AI. The static API token can't reveal unlessFACTEUR_API_TOKEN_SCOPESsays so.pass-cliruns with argument arrays (no shell). New passwords go over stdin, never on the command line. The session lives in a private directory that isn't persisted.Email content is treated as untrusted. Bodies and attachments are wrapped in
<email_body untrusted>markers. The server's instructions tell the model never to act on instructions found in mail, and to draft rather than send when unsure. The send tools are annotated as destructive and open-world, so clients ask before running them.Sending is limited to your own addresses. Mail can only go out from the addresses in
FACTEUR_FROM.Hardened HTTP. Responses have a strict CSP with no scripts and no framing. Requests are rate-limited per IP, forms are same-origin only, and session cookies are
HttpOnlywithSameSite=Lax. The container runs as the unprivilegednodeuser.Bridge never leaves the private network. Bridge's self-signed TLS is accepted only because the hop is internal. Set
BRIDGE_TLS_VERIFY=trueif your Bridge has a real certificate.
Threat model in one line: anyone who can reach the URL can register a client, but only you can approve it. Anyone holding a valid token can act on your mail within its scopes, so give apps only the scopes they need.
If you deploy from a public fork with a PaaS that builds pull-request previews (Coolify, Vercel...), turn previews off for this app. A preview build can inherit production secrets.
Run it
Docker (next to Bridge)
docker build -t facteur .
docker run -d --name facteur --network <bridge-network> -p 8080:8080 \
-v facteur-data:/data --env-file .env facteurSee .env.example. The required variables are BRIDGE_USER and BRIDGE_PASSWORD, the Bridge password shown by info in the Bridge CLI, not your Proton password. HTTP mode also needs FACTEUR_PUBLIC_URL, plus either FACTEUR_ADMIN_PASSWORD or Cloudflare Access (FACTEUR_ACCESS_TEAM and FACTEUR_ACCESS_AUD).
Variable | Default | |
|
| Bridge host name |
|
| |
|
|
|
|
| Verify Bridge's certificate |
|
| IMAP connections kept open at most |
|
| Allowed sender addresses, default first |
|
| Public origin, also the OAuth issuer |
| Approve connections with a password | |
| Approve connections through Cloudflare Access instead | |
| Static bearer token (≥ 24 chars) | |
| all but | What the static token may do |
| Pass agent token ( | |
|
| |
|
| How long a password sign-in lasts on the approval page and dashboard |
|
| OAuth state and audit log |
|
| Largest attachment returned to the model |
| system | Time zone for dates in tool output |
|
|
|
GET /healthz checks the process, and GET /healthz?deep also checks the IMAP connection.
Proton Pass
With pass-cli signed in as yourself (pass-cli login), create an agent that sees only the vaults you choose, then give its token to Facteur:
pass-cli agent create --expiration 1y --vault Personal --vault Work facteur # prints pst_…::…
pass-cli agent access grant facteur --vault-name Personal --role editor # only if it may editRenew it before it expires with pass-cli agent renew --expiration 1y facteur. See what it accessed with pass-cli agent monitor facteur.
Proton Calendar
In Proton Calendar, go to Settings → Calendars → your calendar → Share → Share with anyone (full view) and copy the link. The link contains the key to the calendar, so treat it as a secret.
Behind Cloudflare Access (recommended)
Create an Access application for the whole host, limited to yourself.
Add a bypass application for
/mcp,/token,/register,/revokeand/.well-known/*, since AI apps call those directly. Those paths are protected by the tokens.Set
FACTEUR_ACCESS_TEAMandFACTEUR_ACCESS_AUD. The consent page and dashboard then need no password.
Connect an app
The MCP URL is https://<your host>/mcp.
claude.ai / Claude Desktop / Claude mobile: Settings → Connectors → Add custom connector → paste the URL → Connect → approve.
Claude Code:
claude mcp add --transport http facteur https://<your host>/mcp, then run/mcpto sign in. Or skip OAuth with--header "Authorization: Bearer $FACTEUR_API_TOKEN".ChatGPT: Settings → Connectors → Create → paste the URL, authentication OAuth.
Cursor, VS Code, others: add a remote/HTTP MCP server with the URL. They discover OAuth on their own.
Local stdio (Bridge on your machine):
FACTEUR_TRANSPORT=stdio node src/main.tswith the Bridge variables set.
Develop
npm install
npm run check # tsc, types only
npm test # vitest
npm run dev # needs a Bridge; see .env.example
FACTEUR_URL=http://localhost:8080/mcp FACTEUR_TOKEN=... npm run smoke # end-to-end, never sendsLayout:
src/mail/holds everything that talks to Bridge: the IMAP pool, mailboxes, search, message parsing, composing and SMTP.src/mcp/holds the tools, prompts and output formatting.src/http/holds the OAuth server, consent pages and the MCP endpoint.
MIT licensed.
This server cannot be deployed
Maintenance
Related MCP Connectors
Your Gmail, Calendar, Drive, GitHub, Oura, wallet and confirmed profile facts in any MCP client.
Hosted email MCP for your own Gmail, Outlook.com, Microsoft 365, iCloud or IMAP inbox: read, search, draft, reply in thread, forward and file mail. It moves or flags up to 500 messages in one call, and a send leaves exactly one copy in Sent. A calendar is a separate connection, and connecting one adds diary and scheduling tools.
MCP server connecting AI agents to 100+ apps (Gmail, Slack, Notion, GitHub) via one-click OAuth.
Your mailboxes in ChatGPT and Claude: Gmail, iCloud, Fastmail, any IMAP. Passwords stay yours.
Related MCP Servers
- AlicenseAqualityAmaintenanceEnables AI agents to send, read, search, and organize emails via ProtonMail using Proton Bridge. Supports MCP-compatible clients like Claude and Cursor.1817 npm4MIT
- AlicenseAqualityAmaintenanceEnables AI assistants to read, organize, and send Proton Mail through the local Proton Bridge, with careful gating for sending and attachment access.251Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to interact with Proton Mail through a self-hosted server that works alongside Proton Mail Bridge. It provides read-only mailbox tools such as listing folders, searching mail, and retrieving messages while keeping Bridge isolated from the network.MIT
- AlicenseAqualityAmaintenanceEnables MCP clients to read and search Proton Mail and create draft-only emails with attachments through the local Proton Mail Bridge, while requiring out-of-band human approval before a draft can be committed.1355 PyPI6MIT