postfach-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@postfach-mcpShow me the latest messages in my inbox"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
postfach-mcp
A self-hosted remote MCP server that gives an AI assistant read-focused access to any IMAP mailbox: search, read, create drafts, light triage. Postfach is German for mailbox.
Deliberately no send, no delete — by design, not by configuration. E-mail is untrusted third-party input; an assistant that reads it can be manipulated by it. This server keeps the blast radius small: the worst a hijacked session can do is file a draft, create a folder or move a message — all of it sits in your mailbox, in plain sight, reversible. A send tool may appear in a later version, but only behind an explicit opt-in flag, unregistered by default. Feature requests to weaken this stance will be declined.
Status
v0.2.0 — in production use by the author against a real IMAP mailbox, with three client paths verified: Claude Code, claude.ai on the web, and the Claude Android app. Still a 0.x: the tool surface and configuration may change between releases. Changes are tracked in CHANGELOG.md.
Related MCP server: imap-mcp
Tools
Tool | Purpose |
| List all folders, optionally with message and unseen counts |
| Message and unseen counts for a folder |
| Newest messages in a folder |
| Page through the header data of a whole folder, oldest first |
| Server-side IMAP search, including arbitrary header matches |
| Full message: headers, body, attachment metadata |
| Build an RFC-822 message and file it in the drafts folder — never sends |
| Create a folder — creating only, no deleting, no renaming |
| Set or clear the seen flag |
| Set or clear the flagged star |
| Move messages to another folder, reporting the new uids when the server supports UIDPLUS |
Messages are addressed by folder + uid; UIDs are per-folder. Reading
never sets the seen flag — only mark_read does, when asked.
Installation
Requires Python 3.11+.
pip install git+https://github.com/unstko/postfach-mcpOr from a clone: pip install . — both install the postfach-mcp command.
Configuration
Everything is environment variables prefixed POSTFACH_MCP_; a commented
template is in .env.example. Missing or invalid variables
are reported together, each by name.
Variable | Default | Purpose |
| (required) | IMAP server to connect to |
| (required) | Login name |
| (required) | Password — use an app password if your provider offers them |
|
| IMAP over TLS port |
|
| Folder that receives created drafts; |
|
| From header for drafts, e.g. |
| — | Comma-separated additional sender identities |
|
|
|
| (required for | Bearer token, at least 32 characters ( |
| — | Comma-separated additional bearer tokens, same length rule — give each client its own so one can be revoked without touching the others |
|
| Bind address of the HTTP server |
|
| Port of the HTTP server |
|
| Comma-separated Host header allowlist — add the public name your proxy or tunnel uses |
| — | Reserved for a future explicit opt-in; not implemented in v0.1 |
Running
postfach-mcp check # probe the IMAP login, list folders, verify the drafts folder
postfach-mcp serve # run the HTTP server (--host/--port override the environment)check is the deploy diagnosis: it answers "are the credentials right, and
what is the drafts folder actually called on this server?" without starting
anything. serve exposes the MCP endpoint at /mcp and an unauthenticated
health probe at /api/health.
Connecting clients
Any Streamable-HTTP MCP client that can send an Authorization header
works. The two most common ones:
Claude Code
claude mcp add --transport http postfach https://mail.example.org/mcp \
-H "Authorization: Bearer <token>" --scope userclaude.ai custom connector (web and mobile apps)
claude.ai can talk to this server as a custom connector, which also makes it available in the Claude mobile apps — the connector is configured once and appears there automatically.
Custom connectors normally require OAuth, which this server does not offer. What it relies on instead is the request-header option in the add-connector dialog (authentication "None" plus a static header). At the time of writing Anthropic describes that option as available to a limited set of organizations, so it may not appear for your account — check the dialog before planning around it.
Configuration, and the three pitfalls that cost the author an afternoon:
URL: your public
https://…/mcpendpoint. Authentication: None. Add a request headerAuthorizationwith the valueBearer <token>— including the scheme and the space; the value is sent verbatim, so a bare token produces nothing but 401s.A connector's authentication settings cannot be changed later. To rotate a token, delete the connector and create it again. This pairs well with
EXTRA_TOKENS: give the connector its own token and it can be revoked without touching your other clients.The connection test in the dialog can fail even when everything is configured correctly (some of its probes are sent without the header). If the server logs show 401s from the dialog but your header is right, deleting and re-creating the connector is faster than debugging.
One consequence for your network setup: connector traffic originates from Anthropic's backend, not from your browser — the server must be reachable from the public internet, a VPN or tailnet is not enough for this path. To keep the exposed surface small you can restrict it to Anthropic's published egress IP range at your proxy or firewall; the bearer token remains the actual authentication either way.
Security model
No send, no delete. The server cannot transmit mail or destroy it; those tools do not exist at runtime. Drafts are filed via IMAP APPEND into your drafts folder and stay there until you act on them.
Mail content is untrusted. Bodies and headers are returned in structured fields, never interpreted; tool descriptions warn the model that message content is third-party input. Header fields of drafts are validated against CRLF injection.
Bearer token on every MCP request (constant-time comparison), minimum 32 characters. The health endpoint is the only unauthenticated route.
Host header allowlist (
ALLOWED_HOSTS) rejects requests addressed under any other name — DNS-rebinding protection. Behind a proxy or tunnel you must add the public host name, or every request fails with 421.Transport security is your job. The server speaks plain HTTP and binds to localhost by default; put a TLS-terminating reverse proxy, tunnel, or VPN in front of it. Do not expose the port directly.
Errors are terse. IMAP failures reach the client as one English sentence; credentials and tracebacks never do.
Limitations
One account per server instance.
Drafts carry no formatting beyond line and paragraph breaks, and IMAP cannot edit them in place — a changed draft means a new one.
Some clients render plain-text drafts through an HTML composer and lose all line breaks (observed in Spark on macOS and Android; webmail shows the same draft correctly).
DRAFT_FORMAT=htmlworks around this by adding an HTML alternative part.Attachments are reported as metadata only (name, type, size); their content is not retrievable.
Message bodies are capped at 50,000 characters, list/search results at 100 messages per call,
list_headersat 500 headers per page; drafts at 500,000 characters.Lossless export of raw messages is out of scope — for backups, use a dedicated tool such as
mbsyncorofflineimap.HTML-only messages are converted to text with a deliberately simple converter — layout is lost, links are kept visible.
mark_read,mark_flaggedandmove_messagestrigger an expunge in the source folder (imap-tools behavior; a move is IMAP-internally copy + delete + expunge). Harmless for this server, which never sets the deleted flag itself, but it also purges messages other clients have marked deleted in that folder.
Development
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
.venv/bin/python -m ruff check . && .venv/bin/python -m mypyTests run entirely without network access — enforced by the test suite itself, which fails any accidental socket connect.
License
Built with assistance from Claude Code.
This server cannot be deployed
Maintenance
Related MCP Connectors
- PO6 MailboxOAuthcom.po6
Give AI agents secure access to your email via private aliases with dedicated mailbox storage.
Connect any mailbox to Claude, ChatGPT & AI: read, send, reply, schedule & search emails.
Task-scoped email inboxes for AI agents: read mail, extract verification codes, and reply.
Stateful email for AI agents — read inboxes, reply in-thread, draft with approval.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables LLMs to read, search, and manage emails via IMAP with secure, read-only access to email accounts.6-
- AlicenseNot gradedqualityDmaintenanceRead-only MCP server for IMAP email access, enabling AI agents to read, search, and monitor email without sending or deleting messages.31MIT
- AlicenseAqualityDmaintenanceEnables LLM clients to read and search email via IMAP with tools for listing folders, searching messages, and fetching message content. It supports pagination, snippets, and thread context, and is designed for local AI workflows.10MIT
- FlicenseAqualityCmaintenanceEnables AI assistants to read and interact with a user's email inbox via IMAP, fetching recent emails and reading their full content.8-