{
  "markdown": "<!-- mcp-name: io.github.parasxos/apple-mail-mcp -->\n<div align=\"center\">\n\n# ✉️ apple-mail-mcp\n\n### Your Apple Mail, fully agent-operable.\n\n**Runs locally on your Mac.** It opens the Mail store read-only, returns only\nwhat a client asks for, and sends only when the client explicitly calls the\nsend tool. No third-party relay, no cloud copy of your mail.\n\nUse **Claude Code, Claude Desktop, Codex, Cursor, VS Code, or any local MCP client** to search,\nread, triage, and send email through Apple Mail — your mailbox becomes\nsomething you can\n**ask, search and delegate to** — find anything in seconds, file hundreds of\nmessages through a reviewed plan, send polished mail as the right identity,\nand let Exchange deliver scheduled messages even while your Mac is asleep.\n\n![ci](https://github.com/parasxos/apple-mail-mcp/actions/workflows/ci.yml/badge.svg)\n![tools](https://img.shields.io/badge/MCP%20tools-21-brightgreen)\n![platform](https://img.shields.io/badge/platform-macOS%20%2B%20Mail.app-orange)\n![python](https://img.shields.io/badge/Python-3.11%E2%80%933.14-blue)\n![mcp](https://img.shields.io/badge/MCP%20SDK-1.x%20%2B%202.x-purple)\n![contract](https://img.shields.io/badge/wire%20contract-frozen%20v1-blue)\n\n</div>\n\n---\n\n![demo: uvx install, status, and a Claude search over a 298k-message store](docs/assets/demo.gif)\n\n## ✨ What you can do\n\n🔍 **Ask your mailbox questions.** *\"What did Stefan send me about the memo\nlast week?\"* Search runs at database speed — sender, mailbox, dates, unread,\nattachments — and reconstructs whole conversations.\n\n🕳️ **Find what Mail itself can't.** Mail's built-in search only skims the\nfirst line of most messages. apple-mail-mcp indexes every message **body** on your\nMac — and for Exchange accounts it even fetches the bodies Mail never\ndownloaded, straight from your own mailbox on the server. Queries that\nreturned nothing return twenty.\n\n🎭 **Send as the right you.** Work mail through the work lane, personal\nthrough Gmail — one parameter picks the identity. Every message is composed\nfrom scratch as clean, standards-correct email that renders everywhere,\n*including Outlook* (the AppleScript compose path that arrives blank in\nOutlook is the reason this project exists).\n\n⏰ **Schedule like \"Send Later\", but scriptable.** A scheduled message is\nfrozen in full — attachments, identity, exact text. Exchange can execute it\nserver-side at the requested time, lid closed; other providers use a local\nbackground sender and deliver on its next pass (or just after the Mac wakes).\n\n🗂️ **Triage at scale, without fear.** *\"File these 40 newsletters\"* becomes a\nreviewable plan: nothing moves until it is approved, every message is\nre-checked before it is touched, and the result is verified against Mail's\nown records afterward. Delete means Mail's Trash — nothing is ever erased.\n\n📝 **Draft where your drafts live.** Compose into your real Exchange Drafts\nfolder, ready to open in Outlook or OWA — created, never auto-sent.\n\n## ⚡ Why it's different\n\nEvery other Apple-Mail MCP drives AppleScript for both finding and acting.\nThis one doesn't — and it shows:\n\n| Operation | AppleScript whose-clause | apple-mailbox-mcp |\n|---|---|---|\n| 🔍 Search 300k messages | seconds-to-timeout | **milliseconds** |\n| 🎯 Address one message in a 71k mailbox | **7–10 s** ([measured](docs/benchmarks.md)) | **< 0.1 ms** |\n| ✉️ Send mail | body renders **blank in Outlook** | renders everywhere, plain+HTML |\n| ⏰ Schedule mail | — | server-side on Exchange; reliable local queue everywhere else |\n| 🗂️ Bulk triage | one call per message, fire-and-forget | one reviewed plan, one apply, **verified** |\n\nEvery number above was measured on a live ~300,000-message store; the\nscript and full method are in [docs/benchmarks.md](docs/benchmarks.md).\n\nIf the benchmarks hold up on your mailbox, a ⭐ helps others find this.\n\n## 🛡️ Built to be trusted\n\n- ✅ **Plan → review → apply → verify.** Bulk actions are frozen into a plan\n  you can read before anything happens; the outcome is confirmed against\n  Mail's own store afterward — never assumed.\n- 🗑️ **Nothing is ever erased.** \"Delete\" files into Mail's Trash, and\n  destructive plans have their own separate, capped door.\n- 👓 **Read-only mail mode.** Set `EMAIL_MCP_READ_ONLY=1` and only the 11\n  non-mutating mail tools exist in the session. Search may still maintain its\n  local body index, and attachment retrieval writes the requested file to the\n  configured temporary directory.\n- 💾 **A crash-safe scheduled queue.** Manifest updates are flushed and\n  atomically replaced, so an interrupted rewrite keeps the last valid record.\n  If a file is damaged independently, diagnostics name it instead of claiming\n  the queue is empty, while healthy scheduled messages keep moving.\n- 🧾 **A local, best-effort activity ledger.** Sends, schedules,\n  cancellations and triage runs are recorded without making an unwritable log\n  block mail. For reconciliation, the message itself, its Message-ID and its\n  scheduled record remain authoritative.\n- 🔒 **No third-party mail relay.** Mail content stays local except for mail\n  you send and optional access to your own provider for Exchange/IMAP body\n  backfill, drafts and server-side scheduling. SMTP passwords stay in the\n  macOS Keychain or 1Password; Microsoft OAuth tokens live in a private 0600\n  cache under `~/.email-mcp/graph/`.\n- 📜 **A written contract.** Since v1.0 every tool's shapes, error codes and\n  caps evolve additively, held in place by 800+ automated tests.\n- 🤝 **Clear to every MCP client.** All 21 tools identify what they do, explain\n  every input, and declare whether they read, change or can remove data. Newer\n  clients receive structured results; older clients keep the same JSON text.\n  Both the maintained MCP 1.x line and current MCP 2.x are tested.\n- 🧱 **Built to evolve without breaking your workflow.** Email rules are\n  isolated from MCP, Mail.app, Exchange, delivery, and local storage. Provider\n  or SDK changes stay at the edge while the 21-tool contract remains stable.\n  The dependency rules are enforced in CI and explained in the\n  [architecture guide](https://github.com/parasxos/apple-mail-mcp/blob/main/docs/architecture.md).\n- 📦 **Releases you can verify.** Every tagged release is built and installed\n  in a clean environment before publishing. GitHub includes the wheel, source\n  archive, SHA-256 checksums and signed build provenance—not just source code.\n- 🩺 **Self-diagnosing.** `apple-mail-mcp status` gives one readable readiness,\n  scheduling and recovery screen. `apple-mail-mcp doctor` provides the complete\n  diagnostic detail and an exact fix for anything red.\n\n## 🚀 Quick start\n\n1. **Grant Full Disk Access** to your terminal app\n   (System Settings → Privacy & Security → Full Disk Access), then **quit and\n   reopen the terminal**. This is Apple's one manual toggle — there is no\n   pop-up for it.\n\n2. **Install and set up:**\n\n   ```bash\n   uvx apple-mailbox-mcp setup     # or: pipx install apple-mailbox-mcp\n   # or via Homebrew:\n   brew install parasxos/tap/apple-mail-mcp && apple-mail-mcp setup\n   ```\n\n3. **Register with your client** — one line for Claude Code:\n\n   ```bash\n   claude mcp add --transport stdio --scope user apple-mail -- uvx apple-mailbox-mcp\n   ```\n\n   or the same JSON block for Claude Desktop / Cursor / VS Code\n   (`claude_desktop_config.json` / `.cursor/mcp.json` / `.vscode/mcp.json`):\n\n   ```json\n   {\n     \"mcpServers\": {\n       \"apple-mail\": { \"command\": \"uvx\", \"args\": [\"apple-mailbox-mcp\"] }\n     }\n   }\n   ```\n\n4. **Verify:** `uvx apple-mailbox-mcp status` prints one readiness screen —\n   or just ask your client to run the `doctor` tool; every red line comes\n   with its exact fix. The first body-index build on a large mailbox runs in\n   the background and can take a few minutes; search works immediately and\n   completes as the index fills.\n\nBefore running `setup`, grant your terminal app **Full Disk Access**\n(System Settings → Privacy & Security → Full Disk Access) — that is how\nreading stays fast and local. There is no pop-up for this one; it is Apple's\none manual toggle, and `setup` walks you to the exact pane if it finds it\nmissing.\n\n`setup` asks everything in plain words (bare Enter accepts the recommended\nanswer), offers a sending identity, builds the body-search index, verifies\nthe nightly refresh actually runs, and ends by printing the one block you\npaste into your MCP client:\n\n```json\n{\n  \"mcpServers\": {\n    \"apple-mail\": { \"command\": \"apple-mail-mcp\" }\n  }\n}\n```\n\nSetup ends with a clear **ready** verdict or numbered recovery steps. Grant\n**Automation → Mail** when triage first asks for it. Check the installation,\nthe next scheduled message, and failed scheduled sends anytime with\n`apple-mail-mcp status`; use `apple-mail-mcp doctor` for the full technical detail.\n\n> 💡 *New to the terminal?* Three things that look wrong and aren't:\n> `brew install pipx` wants a typed `y` (Enter alone is rejected);\n> `pipx ensurepath` may print a ⚠️ — the \"pipx is ready to go!\" line after it\n> is the verdict; and after `ensurepath`, close and reopen the terminal once\n> so `apple-mail-mcp` is found.\n\n## 🔌 Works with\n\nEvery client below speaks stdio MCP; the command is always `uvx apple-mailbox-mcp`.\n\n### Claude Code\n```bash\nclaude mcp add --transport stdio --scope user apple-mail -- uvx apple-mailbox-mcp\n```\n\n### Claude Desktop\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n```json\n{ \"mcpServers\": { \"apple-mail\": { \"command\": \"uvx\", \"args\": [\"apple-mailbox-mcp\"] } } }\n```\n\n### Cursor\nAdd the same block to `~/.cursor/mcp.json` (or per-project `.cursor/mcp.json`).\n\n### VS Code (Copilot MCP)\nAdd the same block under `\"servers\"` in `.vscode/mcp.json`.\n\n### Codex CLI\n```toml\n# ~/.codex/config.toml\n[mcp_servers.apple-mail]\ncommand = \"uvx\"\nargs = [\"apple-mailbox-mcp\"]\n```\n\n### Any stdio MCP client\nPoint it at `uvx apple-mailbox-mcp`. The wire contract is additive-only since v1.0.\n\n## 🔧 Troubleshooting\n\n| Symptom | Fix |\n|---|---|\n| Client says the server failed to start, but `uvx apple-mailbox-mcp` works in your terminal | GUI apps don't inherit your shell PATH. Use the absolute path: `\"command\": \"/opt/homebrew/bin/uvx\"` (find yours with `which uvx`). |\n| `database is locked` or empty results | Full Disk Access is missing for the app that *launches* the server (the client, not the terminal). Grant it, then fully quit and reopen that app. |\n| Search finds recent mail but not bodies of old mail | The body index is still building — first build on a 100k+ mailbox takes minutes. `status` shows progress. |\n| Send fails with `transport_unavailable` | Run `doctor`: it names the failing lane (Keychain item missing, SSH socket cold, SMTP host unreachable) and prints the exact fix. |\n| Triage does nothing the first time | Grant **Automation → Mail** when macOS asks; the prompt appears on first use, not at install. |\n\n## 🧰 The 21 tools\n\n| Group | Tools |\n|---|---|\n| 🔍 **Read** (8) | `search_emails` (full-body search) · `get_email` · `get_emails_batch` · `get_thread` · `list_mailboxes` · `list_recent` · `get_attachment` · `refresh_mail` |\n| ✉️ **Send** (6) | `send_email` · `reply_email` (threaded, quoted) · `create_draft` · `schedule_email` · `list_scheduled` · `cancel_scheduled` |\n| 🗂️ **Triage** (5) | `triage_plan` · `triage_plan_delete` · `triage_apply` · `mailbox_create` · `mailbox_delete` |\n| 🩺 **Meta** (2) | `doctor` (full diagnostics with fix-it strings) · `audit` (the local ledger) |\n\nAttachments both ways, size-budgeted. Replies thread correctly in every\nclient. Scheduling survives sleep — a message due while the lid was closed\ngoes out on the first tick after wake, or exactly on time via Exchange.\n\n## 🎭 Your addresses, your lanes\n\nThe From: address decides how mail travels. `~/.email-mcp/identities.toml`:\n\n```toml\ndefault = \"work\"\n\n[work]                    # sent through a host you already trust, over SSH\nfrom_addr = \"you@example.org\"\ndriver    = \"ssh_sendmail\"\nhost      = \"bastion.example.org\"   # any login host you already SSH to\n\n[gmail]                   # classic SMTP — the app password stays in 1Password\nfrom_addr = \"you@gmail.com\"\ndriver    = \"smtp\"\nhost      = \"smtp.gmail.com\"\nop        = \"op://Personal/gmail app password/password\"\n```\n\nExchange identities can add one sign-in to unlock the extras: drafts filed in\nyour real Drafts folder, and scheduled sends executed by the server itself —\nlid closed, Mac asleep. `setup` offers it in one plain question. Reading\nneeds no sending configuration at all.\n\n---\n\n<div align=\"center\">\n\n21 tools · 849 tests · additive wire contract since v1.0\nLive-calibrated end-to-end on a 305k-message store.\n\nBuilt for one Mac — and for anyone else whose Mac runs Mail.app.\n\n</div>\n",
  "bytes": 12759,
  "sha": "50fc03d0aa557f0a99753a4567fbc0ad737c9f2650971a19ffdde65f65e96816",
  "repo_slug": "parasxos/apple-mail-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_parasxos_apple_mail_mcp_98d04f47/readme"
}