The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Fort Mail listing page.
Agent-operated email, in one Cloudflare Worker.
Your AI agent gets a real email client — every account you own, aggregated, triaged, and sendable-as — and you stop checking inboxes. Fortmail is the open-source version of the mail system running inside The Fort That Holds: one small worker, no framework, no server to babysit, free-tier friendly.
desk (needs a human), record
(worth keeping), ignore (bulk/OTP noise). A cron sweeps one scope every
5 minutes and caches the desk, so reading it is instant./mcp is a Model Context Protocol server with its own
OAuth (dynamic client registration + PKCE). MCP is vendor-neutral — connect
any agent that takes an MCP server (Claude, ChatGPT, Gemini, Cursor, your
own harness) and it gets the mail tools (list_accounts, get_desk,
triage, read_box, read_message, get_attachment, send) plus the
newsletter tools. read_message returns body text and attachment metadata;
get_attachment / GET /attachment fetch Gmail file bytes. There is
no LLM inside Fortmail itself — no model dependency, no API key to
any AI vendor; the intelligence is whatever agent you point at it.from address.steward@your-domain.com). Every unseen message there becomes a
GitHub pull request in a repo your agent watches — with the sender stamped
TRUSTED (you) or UNTRUSTED (everyone else) so the agent knows whether
it's holding instructions or just data. Email in, agent awake, audit trail
built in.Prereqs: a Cloudflare account (free tier works) and npx wrangler logged in.
Then connect mailboxes — see docs/SETUP.md for the full walkthrough (Gmail OAuth app, IMAP boxes, the steward bridge) and docs/AGENT.md for pointing your agent at it.
Or skip the manual setup entirely: fork this repo and point your coding
agent — any vendor — at it. AGENTS.md is a runbook the agent
can execute end-to-end; it will ask you only for the human-gated steps
(Cloudflare login, mailbox passwords, OAuth approvals).
The 60-second version, with KEY = your TRIGGER_KEY and W = your worker URL:
Connect your agent: add https://<your-worker>/mcp as a custom MCP connector.
It will walk the OAuth flow; the password prompt is your TRIGGER_KEY.
Email is untrusted input. Fortmail's bridge stamps every filed message by a
From-match against OWNER_EMAILS:
This is the prompt-injection line for email-driven agents: only the owner's address issues commands; everything else gets read, never obeyed. Keep the same rule in your agent's own instructions — the stamp is a signal, your agent's discipline is the enforcement. And spoofing exists: for anything consequential, gate on your explicit approval, not on a From header.
| Route | What |
|---|---|
/mcp | MCP server (OAuth-gated) — the agent's door |
/desk?key= | The cached triage desk, all scopes |
/triage?key=&scope= | Live triage (all, gmail, imap, &domain= filter) |
/cron-run?key= | Force one cron tick (or &scope= a specific one) |
/send?key=&from=&to=&subject=&text= | Send as any owned box |
/wallet-provision?key=&addrs=&host=&smtp= | Mint + seal new IMAP creds |
/wallet-import?key=&addr=&host=&smtp= | Seal an existing password (via X-Mailbox-Password header) |
/accounts?key= / /imapboxes?key= | List owned boxes |
/tool?key=&name= | Call any MCP tool over HTTP (GET query or POST JSON {name,arguments}) — same TRIGGER_KEY as /accounts |
/attachment?key=&address=&message=&attachmentId= | Fetch one Gmail attachment as raw bytes (Content-Type from the part). encoding=base64 returns JSON instead. Read-only; 4MB cap on JSON/tool payloads |
/connect?key= → /oauth/callback | Gmail account OAuth flow |
/import?key= | Import an existing Gmail refresh token |
/bridge-run?key=&dry=1 | Run/inspect the steward bridge now |
/news/subscribe?list= | Public signup (double opt-in) — see docs/NEWSLETTER.md |
/news/list?key= / /news/lists?key= | Create lists / list them with counts |
/news/send?key= | Queue a campaign (or test to one address) |
/news/campaign?key= / /news/drain?key= | Campaign progress / push the queue now |
/news/relay?key= | Seal the relay API key (or use broker-mode vars) |
/news/hook | Relay webhook → suppression on bounce/complaint |
SINCE search) so ancient mail
can never flood the desk.Hardening ideas, threat model, and known limits: docs/SECURITY.md.
Fortmail is one organ of The Fort That Holds — a sovereign, agent-operated stack built in the open. This repository is the whole mail tool. It is MIT-licensed and free to run. There is no Fortmail product page and no paid mail seed.
If you want the written route for other Fort pieces — the instructions you hand your own agent so it can walk a path that already worked — those live on the Grand Bazaar as Selfware Seeds (the rack is on the front page). Live ones today:
Agents can read the same list as catalog.json. None of that is required to run Fortmail.
MIT © The Fort That Holds LLC.