
Your Mail Mcp
io.github.wildsurfer由 GitHub 帳號 wildsurfer 發布v0.5.0更新於 Oct 29, 2026
Read-only, self-hosted MCP access to IMAP email, mirrored locally and indexed by notmuch.
概覽
自架、唯讀的 MCP 伺服器,把 IMAP 信箱鏡像到本機,讓助理搜尋、閱讀與摘要郵件。
- 可以做什麼
- 以 notmuch 查詢搜尋、計數並列出符合的郵件或 maildir 路徑,可限定單一帳號
- 檢視單封郵件的標頭與解碼後內文,或取得純文字版本
- 讀取整串討論,預設排除垃圾郵件與垃圾桶的回覆
- 列出帳號、資料夾、標籤與同步狀態,並觸發或查看同步進度
- 依部件編號取得單一附件或 MIME 部分,圖片與文字直接內嵌,其他二進位檔給出簽章連結
- 適用情境
- 適合讓助理從自己的郵件歷史找答案,例如訂位代號、發票,或某人在往來郵件中承諾過什麼;也適合產生每日摘要,或為寫程式與寫作工作提供郵件脈絡,同時不必擔心它會寄送或刪除郵件。
- 執行需求
- 執行它的機器需要 Docker,映像檔從容器映像倉庫取得。需要 accounts 檔案列出每個 IMAP 主機、使用者名稱與密碼,密碼透過環境變數或 pass_cmd 指令提供。手機或遠端用戶端還需在 PUBLIC_URL 設定公開的 HTTPS 位址,並為 OAuth 同意步驟設定夠長的 OAUTH_PASSPHRASE。Gmail 需開啟兩步驟驗證並使用應用程式密碼;iCloud 需使用 @ 前的短使用者名稱。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Your Mail Mcp,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
your-mail-mcp
Your mail already holds the answers: booking references, gate codes, invoices, warranty periods, promises people made in writing. This server lets your AI assistant find them, and it can only read.
Ask it things like:
- "Find the booking reference for the June ferry."
- "What was the wifi password the hotel sent last summer?"
- "What did the accountant answer about VAT, and when?"
- "Collect everything between me and the builder about the roof, in order, and summarize who promised what."
- "What arrived this morning, across all my accounts, that actually needs me?"
Use it for:
- Search that understands questions. Full-text search over your whole history, every account in one index, phrased the way you think.
- Triage from your phone. A morning summary of what came in overnight, with junk already filtered out, from wherever you are.
- Mail as context for other work. Pull the client's requirements out of the thread and into your coding or writing session.
- Agents you can leave running. The process has no path that sends, deletes or moves a message. A malicious email that reaches your assistant gets read, and that is all that can happen to it. Scheduled digests and always-on agents are a calm thing to run.
Setup is two files and docker compose up -d. See Quick start.
How it works
A self-hosted MCP server. It mirrors one or more IMAP accounts into a local maildir with mbsync, indexes them with notmuch, and answers tool calls from that index. The Claude and ChatGPT apps attach over HTTPS with OAuth; Claude Code, Codex, Cursor and Claude Desktop attach over stdio on the same machine. Any MCP client works, so if you want full privacy you can attach one backed by a local LLM and your mail never leaves your machine.
Mail only ever moves left to right in that picture. The mirror is pull-only
by configuration. The one connection the Go code makes toward a provider is
an IMAP LIST per account, to learn what that server calls its junk and
trash folders; it never selects a mailbox and never fetches a message.
Security has the full list of what the process cannot do. The
diagram source is
docs/diagrams/how-it-works.html.
Quick start
On your machine, for your machine. Docker is the only requirement; the image
at ghcr.io/wildsurfer/your-mail-mcp is built by CI for amd64 and arm64.
Put your accounts in accounts.json. ${WORK_PASS} is replaced from the
environment, so the file itself holds no password:
Put the passwords in .env next to compose.yaml:
compose.yaml passes WORK_PASS and PERSONAL_PASS into the container. An
account with another variable name needs that name added under
environment: there as well.
Two provider details cost people the most time. Gmail accepts only an app
password over IMAP, and app passwords need 2-step verification turned on
first. iCloud wants the short name before @icloud.com as user; the full
address fails to log in. Every key of the file is in
the reference.
These two files hold your mail passwords. Keep the directory out of version
control and out of backups that leave the machine. If you would rather they
did not, give an account pass_cmd instead of password: a command that
prints the secret, such as cat /run/secrets/work_pass for a Docker secret,
or security find-generic-password -s your-mail -a work -w on a Mac. mbsync
runs it at connect time and nothing on disk or in the environment holds the
password. See the reference.
Today's INBOX mail is searchable within minutes. The full history follows at
whatever pace the provider allows, and the status tool reports how far it
has got. A large Gmail account takes days, because Google caps IMAP downloads
at about 2.5GB per day; set SYNC_TIMEOUT=8h in .env for that first
mirror. Provider notes has the details.
Then connect a client. Claude Code:
Cursor and VS Code add it in one click, once the stack is up:
[Add to Cursor] [Install in VS Code]
Claude Desktop, Cursor, Codex and other stdio clients
Any client that starts an MCP server as a command:
Each session is a bridge into the running container, so every client sees the same index and the same sync. Close the client and the session goes with it.
Claude Code can also take it as a plugin, which adds the server and an
email skill that knows the query syntax:
Without a running stack,
docker run -i --rm --env-file .env -v index:/index -v mail:/mail -v ./accounts.json:/config/accounts.json:ro ghcr.io/wildsurfer/your-mail-mcp
starts a daemon for the life of one session. Fine for a look; use compose for
anything you want kept fresh.
Use it from your phone
The Claude and ChatGPT smartphone apps reach a connector through the vendor's servers, so the server needs a public HTTPS address. A tunnel gives it one: the tunnel dials out, nothing listens on your home network, and the mail stays on your machine.
With Tailscale installed, one command, the same on macOS and Linux:
It prints a hostname like https://your-machine.your-tailnet.ts.net, and
--bg keeps it running across reboots. Put that hostname in .env together
with a passphrase, then restart:
OAUTH_PASSPHRASE is the only credential between the internet and your
mail. A wrong guess costs one second and guesses are serialised, and neither
of those saves a short passphrase. Use a long one you can still type on a
phone.
Funnel needs HTTPS certificates and the Funnel node attribute enabled for
your tailnet; the CLI offers to add the policy line the first time.
tailscale funnel status shows what is exposed, and
tailscale funnel --https=443 off takes it down.
Now add the connector. Neither the Claude nor the ChatGPT smartphone app can add one, so you do it once on the web, and it then appears on the phone.
- On claude.ai or in Claude Desktop, open Settings → Connectors and add a custom connector.
- Give it a name and the URL
<PUBLIC_URL>/mcp. Leave the advanced OAuth fields empty; the server registers clients itself. - Claude opens the consent page. Enter your
OAUTH_PASSPHRASE. - Open the Claude app on your phone. The connector is already there; turn it on for a conversation from the tools menu in the composer.
PUBLIC_URL has to match what you type into the client exactly. The server
publishes PUBLIC_URL + /mcp as the resource in its OAuth metadata, and a
mismatch there is the most common reason a connector refuses to add.
Cloudflare Tunnel instead of Tailscale, on your own domain
Use this for a hostname on a domain you own. mail.example.com below has to
be your domain, already added to your Cloudflare account; Cloudflare does
not hand out hostnames for named tunnels.
create prints the tunnel's UUID and the path of the credentials file it
wrote; cloudflared tunnel list prints the UUID again if you lose it. Route
the hostname, then write ~/.cloudflared/config.yml:
To keep it running: on Linux, sudo cloudflared service install. On macOS,
install it through Homebrew and use brew services start cloudflared,
because the sudo install path looks for its certificate under the root
user's home and will not find the one cloudflared tunnel login wrote to
yours.
Then set PUBLIC_URL=https://mail.example.com in .env and
docker compose up -d.
ChatGPT, and Claude Code or Codex from another machine
ChatGPT. Custom MCP connectors live behind developer mode, which needs a Pro, Plus, Business, Enterprise or Education account and is only available on the web.
- In ChatGPT on the web, open Settings → Security and login and turn on Developer mode. On Business and Enterprise workspaces an admin may have to allow it first.
- Add a connector for a remote MCP server with the URL
<PUBLIC_URL>/mcpand OAuth as the authentication. ChatGPT supports dynamic client registration, so there is nothing to paste. - Approve the consent page with your
OAUTH_PASSPHRASE. - Open ChatGPT on your phone and enable the connector in a chat.
These menus move. If the names above do not match what you see, look for developer mode in settings, then for the place that adds a connector by URL. ChatGPT disables some MCP write actions on mobile, which changes nothing here because this server has none.
Claude Code:
Codex:
Run it on a server
Pick this when the mirror should stay up whether or not your machine is on. It costs a few dollars a month and one real trade-off: a full plaintext copy of your mail moves onto a rented disk, with the app passwords next to it. The install is the quick start plus a tunnel, on someone else's computer, and the box needs hardening before it holds your mail. Both are in docs/server.md.
The tools
Eleven tools, all read-only:
search, ids, files and count take a notmuch query (from:, to:,
subject:, tag:, folder:, date:2026-01-01..2026-06-30, combined with
and/or/not), an optional account to scope to one account, and can include
junk and trash with include_excluded. Junk and trash are discovered per
account over RFC 6154 SPECIAL-USE, so the exclusion works whatever those
folders are named and in whatever language. While an account's mirror is
still filling, these four tools prepend a note naming the account and how
many messages are indexed so far.
Attachments are listed in show and thread and served by the attachment
tool one part at a time: images inline up to 5MB, textual parts as marked
text, and other binaries as a short-lived signed link to
GET /attachment/{id}/{part} (a bearer token works there too). Without an
HTTP listener, an oversized binary is saved under /index/attachments/ and
the tool returns the path to docker cp. That directory is capped at 1GB;
the oldest files go first.
Why not one of the others
There are around forty email MCP servers on GitHub. Nearly all of them talk live IMAP and ship a send path, which is the opposite of both choices this server rests on. Two are close enough to name.
igor47/notmuchproxy is the nearest
thing that already existed, and a large part of why this one has the shape
it does. It reads a notmuch archive you keep up to date yourself, has no
write path, and takes a bearer token or full OIDC. Its query validation,
which rejects an unknown prefix with an explanation, is reimplemented here as
validateQuery. Two things differ: it assumes you already run mbsync and
notmuch, where this server generates the mbsync configuration, syncs every
account in parallel and discovers junk and trash over IMAP; and it has no
account parameter. If you already run a notmuch setup you are happy with,
notmuchproxy is the smaller thing to deploy and you should use it instead of
this.
hgn/mcp-server-notmuch is stdio
only, so one client on one machine, and its handling of untrusted content is
the best in the survey. The single render() chokepoint here, which marks
every byte of mail text in one place so that no individual tool can forget
to, comes from its render.py.
The full survey, including which claims were read in source and which were
taken from a README, is in
docs/research/email-mcp-landscape.md.
Security
Read this before you point it at a mailbox you care about.
It cannot write. The generated mbsync configuration for every account
carries Sync Pull, Create Near, Remove Near and Expunge None (or,
for an account with expunge_local set, Expunge Near, which deletes local
files only), and the program writes that file itself, so nothing in it can
be edited into a push. Remove Near acts on the local side only: when a
folder is deleted or renamed on the server, its local copy stays with all
its mail, and only an empty local folder is removed.
The only IMAP operation in the Go code is LIST, issued per account at
startup and hourly to find the junk and trash folders; an account with
exclude_folders set by hand skips even that. The process has no path that
sends, deletes, moves or tags a message, and nothing in it holds write
access to any account.
Deleted mail stays in the mirror. Mail you delete on the server is kept
on disk and hidden from search through notmuch's deleted tag. Set
expunge_local: true on an account to physically remove those local copies
instead. The account is still never written to, but the mirror then stops
being a backup: whatever disappears remotely disappears locally on the next
pass.
How proven this is. One author, one operator, three real accounts: one iCloud and two Gmail. No third-party security review, and nobody else has deployed it. notmuchproxy has zero stars and a more convincing production story than this does.
Passwords are plain text inside the container. Account passwords come
from the environment and are written at startup into a generated mbsync
configuration at file mode 0600. That file is not encrypted. Anything that
can read the container's environment, or that file, can read them. An
account configured with pass_cmd instead keeps the secret in whatever the
command reads — a Docker secret, a keychain — and the environment and the
generated file hold only the command; the process still receives the
password in memory for the one IMAP LIST it performs itself. Disk
encryption, who can exec into the container and access to the host are the
operator's responsibility; the server makes no claim of encrypting
credentials at rest.
One passphrase, one consent. OAUTH_PASSPHRASE is checked in constant
time and gates the whole server with a single shared secret. It is not a
per-user credential system, and everyone holding the passphrase sees the
whole mailbox. It does not encrypt anything at rest. Treat it and the mail
passwords with the same care.
A mailbox is a secret store. Password resets, sign-in codes and magic links all arrive by mail, so read access alone is enough to take over accounts if it lands in the wrong hands or the wrong AI session. The read-only design and the untrusted-content markers remove the write path and the instruction channel; they do not make mail contents harmless. Connect clients you trust. Agent workflows that need their own inboxes need their own addresses, which is a different tool.
A known gap. search's thread summaries include a display name for every
message in a matching thread, which the sender controls. A message in a
folder excluded by default (junk, trash) can still put its own
attacker-chosen name in front of you this way, even though its body never
does. thread and show are not subject to this. It is not fixed in this
release.
For a server that faces the internet, docs/server.md lists the hardening steps in the order of how much each buys you.
Reference
- The accounts file: every key, with defaults.
- Environment variables: sync
interval and timeout, listener address,
INIT_MIRROR. - Provider notes: iCloud, Gmail, Dovecot.
- Troubleshooting: the startup refusals, and why junk is sometimes not excluded.
- Without Docker: release binaries and what they shell out to.
- Running it on a server: install script, hardening, your own domain with Caddy.
- Upgrading from 0.4.x.
- Design spec and the survey of email MCP servers.
來源:README.md,提交 4179264
工具
0版本歷史
2- v0.5.0最新Oct 29, 2026
- v0.4.0Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
