mail-mcp
mail-mcp
Self-hosted, provider-agnostic mail service. Point it at any mailbox's IMAP/SMTP credentials and it exposes:
REST API mirroring the common mailbox operations: list folders, list/get/search messages, send, flag, move, delete, quota (best-effort).
Webhooks (
message.received) via a persistent IMAP IDLE watcher — fires an HTTP POST (with a per-webhook bearer secret) whenever new mail arrives, retried with exponential backoff (up to 6 attempts) if the receiving endpoint fails.MCP server (Streamable HTTP,
POST /mcp) exposing the same operations as tools, so any MCP-compatible agent can use it directly.
Multi-mailbox from the start: add as many accounts as you want to config/accounts.json.
Request bodies on the REST API are validated with Zod (lib/schemas.js) — invalid
payloads get a 422 ERR_VALIDATION_FAILED with field-level errors instead of reaching
the mail layer. Webhook subscriptions persist in SQLite (config/webhooks.sqlite,
via better-sqlite3) instead of a flat JSON file. Messages larger than
MAIL_MCP_MAX_MESSAGE_SIZE (default 25MB) are returned with bodyTruncated: true
and no parsed body/attachments, to avoid loading huge messages into memory.
Setup
npm install
cp .env.example .env # fill in MAIL_MCP_API_TOKEN and one MAILMCP_PASS_<ID> per accountCopy config/accounts.json.example to config/accounts.json (gitignored — no
passwords in this file either, those live only in .env):
[
{
"id": "example",
"user": "user@example.com",
"imap": { "host": "imap.example.com", "port": 993, "secure": true },
"smtp": { "host": "smtp.example.com", "port": 465, "secure": true }
}
]The password for account id: "example" is read from MAILMCP_PASS_EXAMPLE.
node index.jsRuns on 127.0.0.1:4900 by default (see MAIL_MCP_PORT). Put it behind a
reverse proxy with TLS if you need to reach it from outside the host.
systemd
An example unit is in deploy/mail-mcp.service — copy it to
/etc/systemd/system/, adjust paths, and it loads secrets from /root/mail-mcp/.env
via EnvironmentFile.
Auth
Every REST and MCP request requires Authorization: Bearer <MAIL_MCP_API_TOKEN>.
Tests
npm test # run once
npm run test:coverage # run with coverage reportCoverage covers the pure/logic modules (lib/schemas.js, lib/accounts.js,
lib/webhooks-store.js). lib/mailclient.js and lib/idle-watcher.js talk to
real IMAP/SMTP servers and are exercised through manual end-to-end testing
instead of unit tests — they're excluded from the coverage badge so it isn't
misleading.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/MauricioPerera/mail-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server