Server · #350 trending MCP repo · ↗ +2 stars this week

Mail MCP

tecnologicachile/mail-mcp

Secure IMAP/SMTP/EWS/Graph API MCP server in Rust — Microsoft 365, Hotmail, Gmail, Zoho, OAuth2, multi-account

Stars
114
This week
+2
Forks
34
Open issues
13
Latest release
v0.6.1
Star trend · last 9 days+2 ★
Oct 29, 2026: 112 starsOct 30, 2026: 112 starsOct 31, 2026: 112 starsNov 1, 2026: 114 starsNov 2, 2026: 114 starsNov 3, 2026: 114 starsNov 4, 2026: 114 starsNov 5, 2026: 114 starsNov 6, 2026: 114 starsNov 7, 2026: 114 stars

Documentation

README

View on GitHub ↗

mail-mcp

Production-ready email MCP server for AI agents
IMAP + SMTP + EWS + Microsoft Graph API — built in Rust

Release License Stars


Most email MCP servers only do IMAP reads. This one does everything: read, search, send, reply, forward, bulk operations, Microsoft Graph API, and Exchange Web Services — with real OAuth2, multi-account, and multi-provider support. Written in Rust for speed and safety.

What's New in v0.6.1

  • Message content stays out of the logs at RUST_LOG=info. At that level the rmcp library logged every JSON-RPC response in full, which with the HTTP transport put message subjects and bodies in the server log (the journal, for a systemd service). When RUST_LOG sets a global level of info or more verbose, rmcp is now capped at warn unless RUST_LOG names it (for example RUST_LOG=info,rmcp=info while debugging). The stdio transport did not log responses, and with RUST_LOG unset nothing changes. If you run v0.6.0 or earlier over HTTP, set RUST_LOG=info,rmcp=warn.
  • EWS setup scope fixed. Microsoft now rejects https://outlook.office365.com/EWS.AccessAsUser.All with AADSTS70011 (invalid_scope). The Quickstart uses https://outlook.office.com/EWS.AccessAsUser.All. Existing EWS tokens keep working; this only matters when getting a new one.

What's New in v0.6.0

Nothing changes for an existing install unless you opt in.

  • Self-update for shell and PowerShell installs. The installers now also install mail-mcp-update; run it to move to the latest release in place. Homebrew installs keep updating with brew upgrade.
  • Rotated OAuth2 refresh tokens are used, and can be persisted. Microsoft returns a new refresh token on every refresh; the server used to discard it and keep refreshing with the configured one until that one expired. It now refreshes with the newest token. Set MAIL_OAUTH2_TOKEN_STORE to a file path to also keep it across restarts (written 0600, never fatal if it cannot be written). Changing the refresh token in your config always wins over a stored one.
  • Send rules in tool and field descriptions. The preview-and-confirm rule and the "body_text and body_html are separate fields" rule now also appear on the send tools and body fields, for MCP gateways that do not forward the server instructions. See Running behind an MCP gateway for what else changes when mail-mcp sits behind a gateway.

What's New in v0.5.0

  • New: draft tools (draft_create, draft_update, draft_send, draft_delete, draft_list) closing #3 and #17. An agent can save a message in the account's own Drafts folder, revise it, and send it later, so a person can review it in their mail client first. The same five tools work on every backend: IMAP + SMTP, Exchange Web Services and Microsoft Graph, picked per account (EWS config, else Graph config, else IMAP). list_all_accounts reports the backend as drafts_with.
  • Separate gate: MAIL_DRAFTS_ENABLED (default false). It is independent of MAIL_IMAP_WRITE_ENABLED: every operation on an existing draft_id first checks that the target really is a draft (IMAP Drafts folder, EWS IsDraft, Graph isDraft), so enabling drafts never grants move or delete on other mail. draft_send also requires MAIL_SMTP_WRITE_ENABLED.
  • Graph accounts need the Mail.ReadWrite scope for drafts; see account setup. The EWS attachment flow (CreateItem with SaveOnly, then CreateAttachment) follows the approach proposed by @verdelyi in #14.
  • Fix: SMTP messages now carry a Message-ID on the sender's domain (#7). Before, lettre sent no Message-ID of its own, so the id returned by the send tools was empty and the Sent copy had none.
  • Verified live on IMAP (Zoho) and Microsoft Graph; the EWS draft path is covered by unit tests.

What's New in v0.4.17

  • New: imap_search_all_mailboxes by @tdabasinskas in #35. Runs one search in every selectable mailbox of an account and returns the newest matches, each labelled with its mailbox. Built for providers without an "All Mail" folder (iCloud), where one conversation is spread over INBOX, Sent Messages and project folders. The work is spread over MAIL_IMAP_SEARCH_CONCURRENCY connections (default 4, clamped to 1..=8); a mailbox that fails is reported and does not abort the search. Scope it with include_mailboxes / exclude_mailboxes.
  • Thread search by Message-ID by @tdabasinskas in #34. imap_search_messages takes a new thread_message_id criterion that matches a message and every message whose In-Reply-To or References carries it, so an agent can pull a whole conversation in one search.

What's New in v0.4.16

  • imap_list_mailboxes cap is now configurable and visible by @tdabasinskas in #33. The tool used to silently drop everything past 200 mailboxes — on accounts with more folders (e.g. 217 on iCloud), folders like Sent Messages simply never appeared. The cap is now set with MAIL_IMAP_MAX_MAILBOXES (default 200, clamped to 1..=10000), and the response carries two additive fields, total and truncated, so clients can always tell a capped list from a complete one. Nothing changes unless the variable is set.

What's New in v0.4.15

  • New: opt-in streamable HTTP transport by @tdabasinskas in #32. Set MAIL_MCP_TRANSPORT=http to serve MCP streamable HTTP (stateless) instead of stdio — useful for running the server on another machine behind an MCP gateway. Binds to 127.0.0.1:8000 at /mcp by default, configurable via MAIL_MCP_HTTP_HOST / MAIL_MCP_HTTP_PORT / MAIL_MCP_HTTP_PATH, with graceful shutdown on SIGINT/SIGTERM. The endpoint has no built-in authentication — keep it on loopback or behind an authenticating gateway; see docs/advanced-configuration.md#remote-http-transport. stdio remains the default: nothing changes unless the variable is set.

What's New in v0.4.14

Community release — both changes came from external contributors. Thank you!

  • New: MAIL_ATTACHMENT_UPLOAD_DIR — confine outbound file_path attachments by @mjones-PL in #31, closing #11. Without a restriction, send tools would read any file the server process can access — a prompt-injected model could exfiltrate SSH keys or .env files as attachments. Set this variable to a directory and every file_path is canonicalized (.. and symlinks resolved) and must land inside it; missing and out-of-scope files return the same error so the check cannot probe for file existence. Opt-in: when unset, behavior is unchanged. See docs/security.md#outbound-attachment-scope.
  • Fixed: FROM_EMAIL validation no longer rejects dotless internal hosts by @arwack in #30. Addresses the v0.4.13 upgrade caveat: noreply@localhost / alerts@intranet style addresses on corporate internal relays are accepted again, while the real typo checks (multiple @, whitespace, empty local part) remain. If you held the v0.4.13 upgrade because of this, v0.4.14 is safe.

What's New in v0.4.13

  • effective_from() helper + FROM_EMAIL startup validation by @arwack in #29 — the follow-up to their #19. The from_email → user fallback now lives in one place (SmtpAccountConfig::effective_from()), and MAIL_SMTP_<ID>_FROM_EMAIL is validated when the server starts instead of failing on the first send.
  • Behavior change — read before upgrading: a malformed FROM_EMAIL (multiple @, whitespace, empty local part, or a domain without a dot) now prevents the server from starting, for all accounts. Note that dotless domains such as user@localhost or alerts@intranet are currently rejected too; if you use an internal relay address like that, hold the upgrade — a follow-up relaxing the dot rule is under discussion in #29.
  • Hardened APPEND wire-format tests by @tordable in #28: mailbox quoting, announced literal length, and byte-for-byte payload are now asserted for every append test.

What's New in v0.4.12

Community release — both changes came from external contributors. Thank you!

  • iCloud mailbox aliases + reads no longer mark messages as read by @felipefdl in #16. Short mailbox names now resolve to each provider's real folder (Sent → Sent Messages on iCloud / [Gmail]/Sent Mail on Gmail, Trash → Deleted Messages, and so on, multi-language) in search, copy, and move. Raw message fetches now use BODY.PEEK[], so reading a message through the MCP no longer sets \Seen as a side effect — with a BODY[] fallback for servers that reject PEEK (the deprecated RFC822 item, removed in #23, stays out). Validated against a real iCloud mailbox by the author; includes alias-resolution tests and iCloud setup docs.
  • Optimized multi-stage Dockerfile + docker-compose by @monssefbaakka in #5. cargo-chef layer caching, TARGETARCH-aware musl cross-builds (amd64/arm64), and a scratch runtime image — 16.9 MB, down from 25.5 MB — verified to respond to MCP initialize/tools-list over stdio. The toolchain pin was bumped to Rust 1.90 (the codebase's let-chains require >= 1.88).

What's New in v0.4.11

Community bugfix release — both fixes came from external contributors. Thank you!

  • Fixed: save-to-Sent silently failed on strict IMAP servers (iCloud and others) by @dominikknafelj in #26, reported in #25. The \Seen flag introduced in v0.4.10 was sent without the RFC 3501 parenthesized flag-list syntax (APPEND "Sent" \Seen … instead of APPEND "Sent" (\Seen) …), because async-imap interpolates the flags argument verbatim. Strict servers rejected the APPEND and the sent copy was lost — while the tool still reported status: ok. Flags are now normalized before hitting the wire, and smtp_send_message / smtp_reply_message / smtp_forward_message responses include a new saved_to_sent field (true/false, or null when saving is disabled) so callers can detect archival failures. @tordable diagnosed and fixed the same root cause concurrently in #24.
  • Fixed: message reads returned empty on iCloud by @tdabasinskas in #23. Raw message fetches used the deprecated RFC822 item, which iCloud accepts but leaves unpopulated. Fetches now use the IMAP4rev1 BODY[] item — same \Seen semantics, works everywhere — with a mock-server regression test pinning the wire format.

What's New in v0.4.10

Community release — all three changes came from external contributors. Thank you!

  • NetEase IMAP compatibility (126.com / 163.com / yeah.net) by @pep-27 in #21. NetEase servers reject mailbox access from clients that don't identify themselves. mail-mcp now sends the RFC 2971 ID command after authentication whenever the server advertises the ID capability. Includes mock-server regression tests and NetEase setup docs in docs/account-setup.md.
  • MAIL_SMTP_<ID>_FROM_EMAIL — sender address override by @arwack in #19. For shared/group mailboxes where SMTP authenticates with a personal account but the From address should be the group address. Applies to send, reply (including reply-all self-address detection) and forward; falls back to _USER when unset.
  • Sent-mail copies are now marked \Seen by @ray-of-darkness in #9. Copies the MCP appends to the Sent folder after SMTP send no longer show up as unread.

What's New in v0.4.9

  • New tool imap_get_attachment — download a single attachment to disk. Until now the only ways to reach attachment bytes were imap_get_message (which returns attachment metadata and optional extracted PDF text, never the binary) and imap_get_message_raw (capped at 1 MB and base64-encoded into the response). A 7 MB email with X-ray images could not be retrieved at all — over the cap, and dumping it into the response would blow up the model's context anyway.
  • How it works: call imap_get_attachment with the message_id plus a selector — either part_id (the value imap_get_message reports for each attachment) or filename. The server fetches the full message (no size cap on the server side), extracts and decodes just that one part, and writes it to disk, returning { file_path, filename, content_type, part_id, size_bytes }. The binary never enters the response, so context stays small. The saved path feeds straight into a local reader (e.g. an image-description tool or a PDF reader).
  • Where files land: output_dir argument if given, else the MAIL_ATTACHMENT_DOWNLOAD_DIR environment variable, else the system temp dir. Filenames are sanitized (basename only, control characters stripped) to prevent path traversal, and prefixed with the message UID and part id to avoid collisions.
  • Optional inline base64: set include_base64: true to also get the bytes in the response, but only when the attachment is at most max_inline_bytes (default 256 KiB). Off by default.

What's New in v0.4.8

  • SAVE_SENT is now per-account with a provider-aware default. Previously, saving a copy of outgoing mail to the Sent folder via IMAP APPEND was controlled by a single global flag, MAIL_SMTP_SAVE_SENT. The problem: providers that already save sent mail server-side (Gmail, Zoho) ended up with two identical copies in Sent, while a generic SMTP server or Office 365 (which do not auto-save on SMTP submission) lost the copy entirely when the flag was false.
  • Provider-aware default (when nothing is configured):
    • Gmail (smtp.gmail.com): saves server-side and deduplicates by Message-ID → the MCP does not append (false).
    • Zoho (smtp.zoho.com): saves server-side but does not deduplicate → the MCP does not append (false), avoiding the duplicate.
    • Office 365 / generic SMTP: do not auto-save on SMTP submission → the MCP does append (true), or the sent copy would be lost.
  • Per-account override: MAIL_SMTP_<ID>_SAVE_SENT=true|false takes priority over everything. The global MAIL_SMTP_SAVE_SENT still works as a coarse override (wins over the provider default, loses to the per-account override).
  • Precedence: per-account → global → provider-aware default.
Provider Auto-saves server-side MCP default
Gmail Yes (with dedupe) false
Zoho Yes (no dedupe) false
Office 365 (SMTP) No true
Generic SMTP / relays No true

What's New in v0.4.7

  • Critical fix — graph_send_message silently dropped attachments on threaded replies. When called with in_reply_to + attachments, the createReply → PATCH → send flow included the attachments in the PATCH against /me/messages/{id}. Microsoft Graph treats Message.attachments as a navigation property and silently discards the field on PATCH (2xx response, no error), so the message went out as single-part text/html with no file. The MCP returned status: ok and the caller assumed success. Invisible data loss.
  • The fix: in send_via_reply(), attachments are now uploaded one by one to POST /me/messages/{draft_id}/attachments between the PATCH and the send. Files < 3 MB go inline (JSON with base64 contentBytes); files ≥ 3 MB use createUploadSession with 4 MB chunked PUTs. The attachments field was removed from the PatchDraftRequest struct so the regression cannot be reintroduced by a type-correct edit.
  • No change to flows that already worked. send_via_sendmail (new messages without in_reply_to) uses POST /me/sendMail with attachments inline in the JSON — Graph DOES accept the field on that endpoint and never dropped it. That path is untouched.
  • Regression test added: patch_draft_request_never_serializes_attachments fails if anyone re-adds the field to the struct.
  • Reference: BUG_GRAPH_ATTACHMENTS.md at the repo root documents the full reproduction, root cause, and the empirical evidence behind the fix.

What's New in v0.4.6

  • Server-side enforcement of HARD RULE #1. Three releases of prompt-only hardening (v0.4.3 → v0.4.4 → v0.4.5) still left LLMs occasionally leaking literal </body_text><parameter name="body_html"> markup into the recipient's inbox. v0.4.6 adds a real validator that rejects the tool call before any SMTP / Graph / EWS attempt if body_text or body_html contains tool-call wrapper syntax. The check is wired into all 5 send paths (smtp_send_message, smtp_reply_message, smtp_forward_message, graph_send_message, ews_send_message).
  • The forbidden markers are case-insensitive and tightly scoped — only the pseudo-tags that have no legitimate use in human correspondence: <body_text>, </body_text>, <body_html>, </body_html>, <function_calls>, </function_calls>, <invoke name=, </invoke>, and <parameter name="body_*">. Generic technical content that happens to mention <parameter> for an XML schema or <invoke> in a code example still passes.
  • HARD RULE #1 wording updated to announce the server-side rejection, so the LLM knows it's a hard contract — not a suggestion it can ignore.
  • No breaking changes for clean callers: well-behaved messages send exactly as before.

What's New in v0.4.5

  • serverInfo now reports name="mail-mcp" + the crate version (the framework previously returned its own rmcp 0.16.0, which never changes between releases). Useful for verifying the active version with /mcp, and so any client-side cache keyed by (server, version) invalidates on each bump.
  • MCP instructions reorganized: the 3 critical anti-concatenation rules (which in v0.4.3 and v0.4.4 sat at the end of the block and could be lost to truncation / diluted attention) now appear as HARD RULE #1, #2, #3 at the TOP, right after the title. Consolidated into 3 short paragraphs (previously 3 long sections, ~1500 characters combined).
  • No functional changes to the server. Same SMTP/IMAP/EWS/Graph, same tool set, same behavior. Only the text exposed to the client changed.

Important for these rules to take effect

Clients that resume a session with claude --continue (or /resume) do NOT refresh the MCP system_prompt — they keep the one from that session's first handshake. If your session predates v0.4.5, the rules won't reach your context even if the on-disk binary is updated. To receive them, start a NEW session in the project (not --continue).

What's New in v0.4.4

  • Preview hygiene rule in MCP instructions: when the LLM shows the user the email preview before sending, it should render ONE clean version of the body (markdown-style bullets, bold, links as text + URL) and state that the message will go multipart — but it must NOT dump the raw HTML source (<p>, <strong>, <a href>...) into the preview. Two reasons:

    1. The human reviewer wants to read the message, not audit markup — showing the HTML is noise.
    2. Exhibiting both the plain-text string AND the HTML string side by side in the preview is exactly the context that has historically led LLMs to concatenate them in the eventual tool call (the bug v0.4.3 documented). Hiding the HTML source from the preview removes the temptation.

    Complements the PREVIEW DOES NOT EQUAL TOOL CALL rule introduced in v0.4.3.

What's New in v0.4.3

  • Server-side guidance against malformed tool calls. The MCP instructions block now explicitly tells the calling LLM that body_text and body_html are TWO SEPARATE JSON fields and must NEVER be concatenated. Previous wording ("send BOTH body_text AND body_html") was ambiguous and some LLMs interpreted it as "concatenate both with <body_text>...</body_html> pseudo-tags inside a single body_text string". When that happens, the recipient sees garbled duplicated content, AND any later Claude session that opens the saved copy via this MCP gets a Usage Policy block (the leaked <invoke>...</invoke> looks like a prompt-injection attempt to safety filters). The new instruction shows a CORRECT vs WRONG example and bans pseudo-tags / tool-call wrapper syntax inside email fields.

What's New in v0.4.2

  • Release pipeline fixed: the publish-npm job in the CI release workflow has been disabled. It was inherited from the upstream fork and tried to publish to @bradsjm/mail-imap-mcp-rs, a scope this org does not own — every release was 404-ing on that step. See "Releasing" below for the full explanation and how to re-enable npm publishing if needed.
  • Auto-trigger releases on tag push: .github/workflows/release.yml now fires on push: tags: ['v*'], so tagging vX.Y.Z and pushing is all it takes to cut a release. workflow_dispatch is retained as a manual escape hatch.
  • Cleanup: removed the dangling init-npm-placeholder.yml workflow (also referenced the fork's npm scope).
  • docs: README gains a "Releasing" section documenting the new flow and the npm decision.

What's New in v0.4.1

  • Fix: save_to_sent_folder now archives the exact RFC822 bytes that were sent (via lettre.formatted()), instead of a hand-rolled text-only stub. The Sent-folder copy keeps the HTML body, the multipart/alternative structure, and the RFC 2047-encoded subject — no more ??? where accents used to be, and HTML is no longer silently dropped.
  • Improved: localized Sent-folder detection — Enviado[s], Elementos enviados, Enviadas, Itens enviados, Envoyés, Éléments envoyés, Gesendet, Posta inviata, Verzonden, Wysłane, plus nested variants. Previously only English names were recognized, so Zoho/localized IMAP accounts fell through to a non-existent "Sent" folder.
  • Improved: smtp_forward_message accepts body_html (was hardcoded to plain-text only).
  • Improved: EWS send gains bcc, in_reply_to, references (via <t:InternetMessageHeaders>), plus full recipient + subject-length validation — now at parity with the SMTP and Graph send paths.
  • Improved: Graph API threading fallbacks now log. WARN when the message-lookup HTTP call fails (rate limit, 5xx, permissions) so operators see threading degraded due to a real error; DEBUG when the original message is legitimately not found.
  • Refactor: EWS XML parsing migrated from substring matching to quick-xml. Fixes a latent namespace-collision bug (<soap:Body> vs <t:Body>), correctly decodes XML entities and CDATA, and handles attribute values containing = (common in base64-like EWS item IDs).
  • Cleanup: zero warnings on cargo build --release.
  • Tests: 64 (up from 47).

Why This Project

mail-mcp Typical email MCP
IMAP read/write 18 tools 3-5 tools
SMTP send/reply/forward Yes No or broken
Microsoft Graph API Yes No
EWS (Exchange Web Services) Yes No
OAuth2 (XOAUTH2) Native No
Multi-account Yes Single account
Microsoft 365 + Hotmail Both work Usually neither
Language Rust (fast, safe) TypeScript/Python
Tests 64 unit + integration Mocks only
Warnings in release build 0 Varies

Feature Matrix

Provider IMAP SMTP Graph API EWS OAuth2 Multi-account
Microsoft 365 (enterprise) Yes Admin-dependent Yes Yes Yes Yes
Hotmail / Outlook.com Yes Blocked by MS Yes Yes Yes Yes
Gmail Yes Yes — — Yes Yes
Apple iCloud Yes Yes — — — Yes
Zoho Yes Yes — — — Yes
Fastmail Yes Yes — — — Yes
Any IMAP/SMTP server Yes Yes — — — Yes

EWS is the simplest way to add Microsoft accounts — single OAuth2 token for both reading and sending. Works even on tenants that block Graph API and IMAP.

Quickstart — Let Claude Code do it

Copy and paste this prompt into Claude Code and it will install, compile, and configure everything for you:

Install and configure the mail-mcp MCP server from https://github.com/tecnologicachile/mail-mcp

1. Clone the repo, build with cargo build --release
2. Add the MCP server to .claude.json with the binary path
3. For Microsoft accounts: use EWS (simplest) — run device code flow with
   client_id d3590ed6-52b3-4102-aeff-aad2292ab01c and scope
   https://outlook.office.com/EWS.AccessAsUser.All offline_access
   Then configure MAIL_EWS_<ID>_USER and MAIL_EWS_<ID>_REFRESH_TOKEN
4. For Gmail: configure MAIL_IMAP + MAIL_SMTP with App Password from
   https://myaccount.google.com/apppasswords
5. For Zoho: configure MAIL_IMAP + MAIL_SMTP with standard password
6. Enable write/send: MAIL_IMAP_WRITE_ENABLED=true, MAIL_SMTP_WRITE_ENABLED=true

My email accounts to configure:
- <your-email@example.com>

Replace the last line with your email(s). Claude Code will guide you through each step including the OAuth2 device code flow for Microsoft accounts.

Manual Setup (2 minutes)

Install a prebuilt binary:

# macOS and Linux (Homebrew)
brew install tecnologicachile/tap/mail-mcp

# macOS and Linux (shell installer)
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/tecnologicachile/mail-mcp/releases/latest/download/mail-mcp-installer.sh | sh

The shell and PowerShell installers also install mail-mcp-update, which updates an existing install to the latest release. With Homebrew, use brew upgrade mail-mcp.

# Windows
powershell -ExecutionPolicy Bypass -c "irm https://github.com/tecnologicachile/mail-mcp/releases/latest/download/mail-mcp-installer.ps1 | iex"

Or build from source:

git clone https://github.com/tecnologicachile/mail-mcp.git
cd mail-mcp
cargo build --release

Add to your MCP client config (Claude Code, Cursor, etc.). With a prebuilt binary, use "command": "mail-mcp":

{
  "mcpServers": {
    "mail": {
      "command": "./target/release/mail-mcp",
      "env": {
        "MAIL_IMAP_DEFAULT_HOST": "imap.gmail.com",
        "MAIL_IMAP_DEFAULT_USER": "you@gmail.com",
        "MAIL_IMAP_DEFAULT_PASS": "your-app-password",
        "MAIL_SMTP_DEFAULT_HOST": "smtp.gmail.com",
        "MAIL_SMTP_DEFAULT_PORT": "587",
        "MAIL_SMTP_DEFAULT_USER": "you@gmail.com",
        "MAIL_SMTP_DEFAULT_PASS": "your-app-password",
        "MAIL_SMTP_DEFAULT_SECURE": "starttls",
        "MAIL_IMAP_WRITE_ENABLED": "true",
        "MAIL_SMTP_WRITE_ENABLED": "true"
      }
    }
  }
}

That's it. Your AI agent can now read, search, send, reply, and manage emails.

Microsoft Account? Use Graph API

Microsoft blocks SMTP on personal accounts. Use Graph API instead:

{
  "env": {
    "MAIL_IMAP_DEFAULT_HOST": "outlook.office365.com",
    "MAIL_IMAP_DEFAULT_USER": "you@hotmail.com",
    "MAIL_IMAP_DEFAULT_PASS": "your-app-password",
    "MAIL_OAUTH2_DEFAULT_PROVIDER": "microsoft",
    "MAIL_OAUTH2_DEFAULT_CLIENT_ID": "9e5f94bc-e8a4-4e73-b8be-63364c29d753",
    "MAIL_OAUTH2_DEFAULT_CLIENT_SECRET": "none",
    "MAIL_OAUTH2_DEFAULT_REFRESH_TOKEN": "<your-token>"
  }
}

Get your token in 1 minute with device code flow. See Account Setup Guide.

37 MCP Tools

Read (10 tools)

Tool What it does
list_all_accounts List all accounts with capabilities (IMAP, SMTP, Graph, EWS)
imap_list_accounts List IMAP accounts
imap_verify_account Test connectivity and auth
imap_list_mailboxes List folders
imap_mailbox_status Message counts
imap_search_messages Search with cursor pagination; thread_message_id finds a message and its replies
imap_search_all_mailboxes Same criteria in every mailbox at once (e.g. a whole conversation spread over INBOX, Sent and project folders), newest first, labelled with the mailbox
imap_get_message Parsed message (text, HTML, attachments)
imap_get_message_raw RFC822 source
imap_get_attachment Download one attachment to disk (bypasses the raw size cap)

Write (11 tools)

Tool What it does
imap_update_message_flags Add/remove flags
imap_copy_message Copy (cross-account supported)
imap_move_message Move to folder
imap_delete_message Delete with confirmation
imap_create_mailbox Create folder
imap_delete_mailbox Delete folder
imap_rename_mailbox Rename folder
imap_append_message Append raw message
imap_bulk_move Move up to 500 at once
imap_bulk_delete Delete up to 500 at once
imap_bulk_update_flags Flag up to 500 at once

Send (5 tools)

Tool What it does
smtp_send_message Send email (text/HTML, CC/BCC)
smtp_reply_message Reply with threading headers
smtp_forward_message Forward with original inline
smtp_verify_account Test SMTP connectivity
graph_send_message Send via Microsoft Graph API (with reply threading)

EWS — Exchange Web Services (3 tools)

Tool What it does
ews_search_messages

…

Releases

Recent versions

All releases ↗
  1. v0.6.1
  2. v0.6.0
  3. v0.5.0
  4. v0.4.17
  5. v0.4.16
  6. v0.4.15