Stalwart Mail Mcp

io.github.cybersmurfv2.3.0更新于 Oct 2, 2026

Mail and contacts on a self-hosted Stalwart server via JMAP: search, read, OCR, send, drafts.

概览

AI 生成的概览

让助手通过 JMAP 在自建 Stalwart 邮件服务器上搜索、阅读、OCR、起草、发送邮件并管理联系人。

功能
使用邮箱自身凭据通过 JMAP 连接 Stalwart 邮箱。工具可列出邮箱账户与文件夹、搜索邮件和会话、按 id 获取邮件与附件、提取 PDF 文本并对扫描件做 OCR、发送新邮件或回复、创建、发送和删除草稿,以及搜索或添加联系人。另有远程模式,可将服务器运行在 Stalwart 旁作为自定义连接器。
适用场景
适合自建 Stalwart 邮件服务器、希望助手协助分拣、阅读和回复邮件(含扫描附件)的场景,无需在服务器上安装任何东西。也适用于小型自建环境中的共享邮箱和通讯录。
运行要求
以本地进程运行(npx 或 Claude Desktop 扩展包),需要 Node.js。必须提供 STALWART_URL、STALWART_USER 和 STALWART_PASSWORD(或 OAuth 令牌),并能访问该服务器。可选 OCR 需要服务商密钥或本地模型;MAIL_LANG 等变量可调整行为。
安装前请注意
发送立即生效且无法撤销;发送、草稿、联系人编辑和附件保存等能力可关闭。STALWART_PASSWORD 与 MAIL_OCR_API_KEY 属于机密。OCR 是唯一会把内容发给第三方的功能,介意时可选用本地服务商。密码多次错误可能导致 IP 被封禁。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Stalwart Mail Mcp,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

Stalwart Mail MCP

Česky

An MCP server that lets Claude Desktop (or any MCP client that speaks stdio) work with a mailbox on your own Stalwart mail server: search and read mail including attachments and scans, reply in a thread, send, keep drafts, and look up or add contacts.

It talks JMAP with the mailbox's own credentials. Nothing is installed on the server.

text
Claude Desktop ──stdio──▶ dist/index.cjs (Node, this MCP server)                              │  HTTPS · JMAP (RFC 8620 / 8621 / 9610)                              ▼                 https://mail.example.com/jmap   (reverse proxy → Stalwart)

There is also a remote mode: the same server run next to Stalwart, added to Claude as a custom connector, so the mailbox works in claude.ai, the mobile apps and every desktop chat — people sign in through Stalwart's own OAuth and the server holds no credentials. See docs/remote.md.

How it fits into a small self-hosted setup — reverse proxy, what to expose, shared mailboxes, branded builds for a family or a team — is described in docs/small-infrastructure.md.

Tools

Names carry a prefix, mail_ by default (a branded build can change it).

ToolWhat it does
mail_list_mailboxesaccounts (own + shared), folders with counts, allowed senders, address books
mail_search_emailsfull text / from / to / subject / folder / date / unread / has attachment, or a whole thread
mail_get_emaila whole message by id (HTML → text) with a numbered list of attachments
mail_get_attachmentan attachment's content: text, PDF page by page, OCR of scans and photographed documents, images; saves the file to disk
mail_send_emailsend a new mail or a reply (in_reply_to_id, reply_all), attachments from disk
mail_create_draftthe same, but only saved to Drafts
mail_send_draft / mail_delete_draftsend / delete a draft by id
mail_search_contactsaddress books of every account plus senders and recipients from the mail history
mail_add_contactnew contact (own or shared address book)

Sending is immediate and cannot be undone, so the tool descriptions tell the model to send only on the user's explicit instruction and to create a draft otherwise.

Install

Claude Desktop (extension)

Download stalwart-mail.mcpb from the latest release and open it — Claude Desktop offers to install it. Or build it yourself:

bash
npm install./pack.sh                  # → stalwart-mail.mcpbopen stalwart-mail.mcpb    # Claude Desktop → Install

Fill in the server address, the mailbox e-mail and password. Optional: the language and a Mistral API key for OCR. The password is kept in the operating system's keychain.

Any MCP client (stdio)

The server is on npm as stalwart-mail-mcp and in the MCP Registry as io.github.cybersmurf/stalwart-mail-mcp, so no checkout is needed:

json
{  "mcpServers": {    "stalwart-mail": {      "command": "npx",      "args": ["-y", "stalwart-mail-mcp"],      "env": {        "STALWART_URL": "https://mail.example.com",        "STALWART_USER": "[email protected]",        "STALWART_PASSWORD": "…"      }    }  }}

Claude Code: claude mcp add stalwart-mail --env STALWART_URL=https://mail.example.com --env [email protected] --env STALWART_PASSWORD=… -- npx -y stalwart-mail-mcp

Claude on the web, desktop chat and phone

Run the server next to Stalwart (stalwart-mail-mcp --http, or the Docker image) and add its URL as a custom connector — step by step in docs/remote.md.

Configuration

VariableMeaning
STALWART_URLpublic address of the server, e.g. https://mail.example.com (required)
STALWART_USERthe mailbox you sign in as (required)
STALWART_PASSWORDmailbox or app password — sent as Basic auth
STALWART_TOKENan OAuth access token instead of the password — sent as Bearer
MAIL_LANGauto (default: the machine's language, English when unsupported) or a locale code
MAIL_TOOL_PREFIXprefix of the tool names, default mail
MAIL_BRANDdisplay name of the server, default Stalwart Mail
MAIL_DOWNLOAD_DIRwhere attachments are saved, default ~/Downloads/Mail-Attachments
MAIL_TIMEZONEIANA zone for dates in the output, default the machine's zone
MAIL_OCR_PROVIDER, MAIL_OCR_API_KEY, MAIL_OCR_MODEL, MAIL_OCR_BASE_URLwho reads scans — see OCR providers
MISTRAL_API_KEYshortcut: with only this set, scans go to Mistral OCR
MAIL_ALLOW_SENDfalse removes send_email and send_draft
MAIL_ALLOW_DRAFTSfalse removes create_draft and delete_draft
MAIL_ALLOW_CONTACT_EDITfalse removes add_contact
MAIL_ALLOW_ATTACHMENTSfalse removes get_attachment
MAIL_SAVE_ATTACHMENTSfalse = opened attachments are only read, nothing is written to disk

What it is allowed to do

Every capability is a switch in the extension settings (or an env variable above), all on by default. A capability that is off is not offered as a tool at all, so it holds regardless of what the client's approval prompts remember:

  • sending off → a mailbox Claude can read and draft in, but never send from;
  • sending, drafts and contact edits off → a read-only mailbox;
  • saving attachments off → get_attachment reads the file from a temporary copy and is annotated read-only; with saving on it writes to the download folder and is annotated as a writing tool, which clients may treat differently when asking for approval.

Approvals themselves ("allow once / always allow") belong to the client, not to this server. In Claude Desktop they are set per tool in the extension's settings; a client may ask again after an update that changes a tool's definition.

Attachments and OCR

mail_get_attachment downloads the file and returns what the model can read:

  • text files as text, HTML converted to text;
  • PDFs as text page by page (page_from / page_to for long ones);
  • PDF pages without a text layer (scans) and photos go to the OCR provider you choose — the result is markdown including tables, and those pages are marked (OCR). A mixed PDF sends only its scanned pages;
  • images are returned as images; anything above ~600 kB or in HEIC is downscaled on macOS (sips);
  • other types (docx, xlsx, zip…) are only saved, and the path is returned.

Without a provider, or with ocr: false, a scan comes back as an image of page 1 (macOS) with a note. OCR is the only thing in this server that sends content anywhere besides your mail server — to the provider you picked, or nowhere at all with a local model.

OCR providers

MAIL_OCR_PROVIDERWhat it isNeedsReads PDFs
auto (default)Mistral when MISTRAL_API_KEY is set, a custom server when address and model are set, otherwise off——
mistralMistral OCR (mistral-ocr-latest)keydirectly
anthropicClaude through the official SDK (default model claude-opus-5-5)keydirectly
openai, openrouter, geminihosted OpenAI-compatible vision chat APIskey + modelpage images
ollama, lmstudiolocal models on localhostmodelpage images
customany other OpenAI-compatible serverMAIL_OCR_BASE_URL + modelpage images
offno OCR——

MAIL_OCR_API_KEY, MAIL_OCR_MODEL and MAIL_OCR_BASE_URL complete the choice. Examples:

bash
MAIL_OCR_PROVIDER=ollama      MAIL_OCR_MODEL=llama3.2-vision                         # fully localMAIL_OCR_PROVIDER=openrouter  MAIL_OCR_API_KEY=…  MAIL_OCR_MODEL=<a vision model>MAIL_OCR_PROVIDER=anthropic   MAIL_OCR_API_KEY=…MAIL_OCR_PROVIDER=custom      MAIL_OCR_BASE_URL=http://nas.lan:8000/v1  MAIL_OCR_MODEL=…

Providers that take images only get each scanned page as a PNG taken out of the PDF (the scan itself, scaled to 2000 px). A page that is not one big picture cannot be handed to them and is reported as unread; Mistral and Anthropic read any PDF. Pages are sent three at a time.

Things to expect: a local model can need a minute or more per dense page, which may exceed your client's tool timeout — read long scans in page ranges. General vision models transcribe well but, like every OCR, can misplace cells in tables with graphics; preview: true adds the page image so the model can check. With anthropic, a declined request is retried server-side on a fallback model (fallbacks: "default") on the current Claude models.

node test/live-ocr.mjs runs the provider configured in the environment against a scanned fixture (or your own file) and prints the result.

Languages

Tool titles, descriptions, output and error messages are localized. English is the source, Czech is written by hand, and German, Spanish, French, Italian, Dutch, Polish, Portuguese and Slovak are machine translations that no native speaker has reviewed yet — corrections are welcome.

To add or fix a language edit src/locales/<code>.ts (copy en.ts, keep the {placeholders} and line breaks) and register it in src/locales/index.ts. A locale may be partial; missing keys fall back to English. npm run test:offline checks every locale against the English keys.

Branded builds (presets)

For a family or a team you can ship an extension where the server address is pre-filled and people only type their e-mail and password. A preset is a folder with its own manifest.json (and optionally icon.png); see presets/example.

bash
./pack.sh --preset /path/to/preset     # → /path/to/preset/<name>.mcpb

The preset's manifest sets MAIL_TOOL_PREFIX, MAIL_BRAND, MAIL_LANG or MAIL_DOWNLOAD_DIR through env, and gives server_url a default. Keep the preset's name stable so Claude Desktop treats new builds as updates.

Tests

bash
npm run test:offline       # no mailbox needed: fake JMAP + fake OCR, the real server over stdioMISTRAL_API_KEY=… node test/offline.mjs --live-ocr    # also sends the fixtures to the real OCRSTALWART_URL=… STALWART_USER=… STALWART_PASSWORD=… node test/smoke.mjs          # real mailboxSTALWART_URL=… STALWART_USER=… STALWART_PASSWORD=… node test/smoke.mjs --send   # also sends a mail to yourself

The offline test covers attachments, OCR, the tool prefix, language selection and locale consistency. The smoke test creates a draft and deletes it; with --send it leaves one test message in the mailbox.

Good to know

  • A wrong password gets the IP banned by Stalwart after a few attempts. The server signs in on the first tool call, not at start, so restarting the client does not cause bans; calling tools repeatedly with a wrong password does.
  • Built for and used with Stalwart 0.16. The mail part is plain RFC 8620/8621 and may work with other JMAP servers, but that is untested; contacts need JMAP for Contacts (RFC 9610).
  • Email/query with "inMailbox": null is rejected by Stalwart — the filter must be absent or carry an id.
  • The extension bundle is one CommonJS file (~3.8 MB, most of it pdf.js from unpdf); the .cjs extension matters because package.json says "type": "module".
  • A tool result in Claude Desktop is capped at about 1 MB, hence the 600 kB limit for inline images.

License

MIT

来源:README.md,提交 b137704

工具

0
工具元数据尚未被收录。

版本历史

1
  1. v2.3.0最新Oct 2, 2026