Skip to main content
Glama
multi-mail-mcp

multi-mail-mcp

by chang-ryan

multi-mail-mcp

Read-only, multi-account MCP server for Proton Mail (via Proton Bridge) and Gmail (IMAP).

mail__list_accounts    the mailboxes this session may read
mail__search           one account; Gmail takes Gmail search syntax in "query"
mail__list_messages    recent messages in a folder, headers only
mail__get_message      one message: headers, text body, attachment list
mail__get_thread       the whole conversation, oldest first
mail__list_folders     folders (Gmail: labels)
mail__get_attachments  base64, or saved into the session's save folder

No send, reply, draft, delete, move, flag, or mark-read. Mailboxes are opened read-only and bodies fetched with BODY.PEEK, so reading leaves no trace.

Design

  • Per-process scoping. MAIL_ACCOUNTS (required; * for all) lists the account ids a process may open. Unset is a startup error.

  • Fixed hosts. proton connects only to the local Bridge on 127.0.0.1; gmail only to imap.gmail.com:993 over TLS.

  • No secrets in files. Passwords come from the macOS Keychain (service multi-mail-mcp, account = account id).

  • Opt-in attachment saving. Only inside MAIL_SAVE_ROOT (symlinks resolved per level), documents and images only (no executables, archives, HTML or macro formats), 25 MB cap, sanitized names, never overwrites, attempts to mark files with the macOS quarantine flag and reports failures.

  • Defense in depth. Mutating IMAP methods are disabled on every connection; a mailbox the server opens read-write is refused; inputs reject control characters; messages over 40 MB are not fetched; hidden Unicode (tag characters, bidi overrides, zero-width) is stripped from output and every result is labelled untrusted; the registry is refused if group/other-writable or if it carries a secret; .npmrc sets ignore-scripts.

Related MCP server: rubit-mcp-mail

Setup

1. Registry — ~/.config/multi-mail-mcp/accounts.json (no secrets)

{
  "accounts": {
    "acme":     { "type": "proton", "user": "ops@acme-holdings.example",  "label": "Acme Holdings LLC" },
    "charity":  { "type": "proton", "user": "admin@example-charity.org",  "label": "Example Charity (non-profit)" },
    "personal": { "type": "gmail",  "user": "you@gmail.example",          "label": "Personal" },
    "widgets":  { "type": "gmail",  "user": "you@widgets-co.example",     "label": "Widgets Co (Google Workspace)" }
  }
}

Override the path with MAIL_MCP_CONFIG. Proton entries take an optional "port" (default 1143).

2. Proton: one Bridge, several accounts

Bridge handles several Proton accounts at once: Bridge > Add account. Each signed-in account gets its own Bridge-generated password (Bridge > account > Mailbox details); all share 127.0.0.1:1143, and Bridge routes by IMAP username. Bridge requires a paid Proton plan on each account.

3. Gmail: app password

Google Account > Security > 2-Step Verification (must be on) > App passwords. For a Workspace account the admin must also allow it: Admin console > Apps > Google Workspace > Gmail > End User Access > POP and IMAP access on, and 2-Step Verification allowed for the user.

4. Passwords into the Keychain

Run in your own terminal. -w as the last argument prompts, so the password never touches shell history:

security add-generic-password -U -s multi-mail-mcp -a acme     -l "multi-mail-mcp acme"     -w
security add-generic-password -U -s multi-mail-mcp -a personal -l "multi-mail-mcp personal" -w
# ...one per account id in accounts.json

5. Check

MAIL_ACCOUNTS='*' node /path/to/multi-mail-mcp/index.js --check

6. Register per harness

Claude Code reads .mcp.json from the folder a session starts in. Put one in each folder that should see mail: examples/entity.mcp.json scopes a session to one account and saves attachments into that folder; examples/all.mcp.json opens every account with saving off. Each names the server mail, so tools are mcp__mail__* everywhere and only the reachable accounts differ:

{
  "mcpServers": {
    "mail": {
      "command": "/absolute/path/to/node",
      "args": ["/absolute/path/to/multi-mail-mcp/index.js"],
      "env": {
        "MAIL_ACCOUNTS": "acme",
        "MAIL_SAVE_ROOT": "/absolute/path/to/Acme Holdings LLC/00 Inbox"
      }
    }
  }
}

Use an absolute node path: harnesses do not load nvm.

License

MIT. See LICENSE.

Security checks

Run npm test for offline regression tests. They use temporary registries and a local MCP process; no mailbox connections or Keychain password lookups are needed.

Attachment saving filters by filename extension, not file contents. Legacy .doc, .xls and .ppt files are refused because they can carry macros. An allowed extension does not prove that a file is safe. Each saved-file result reports quarantined; a failed macOS quarantine marking is returned with a warning.

Save-folder checks reject existing symlink escapes. They do not provide protection against another local process concurrently replacing directory components during a save.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    Safely searches, reads, flags, and drafts email through IMAP, with no send, delete, or move capabilities. Uses a local broker and OS credential store for secure authentication.
    16
    146 PyPI
    Apache 2.0
  • A
    license
    A
    quality
    A
    maintenance
    Enables read-only, provider-agnostic email access over IMAP, allowing users to list folders, search and read messages, and download attachments without ever marking messages as read.
    6
    23 PyPI
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables local, read-only access to multiple Gmail and Google Drive accounts through explicit per-account aliases, using bring-your-own Google OAuth with secure credential storage and no telemetry or write capabilities.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables searching and reading email across permitted accounts and mailboxes on macOS, plus optionally saving drafts for review, without sending or deleting messages.
    5
    MIT