{
  "markdown": "# apple-mail-mcp\n\n<p align=\"center\">\n  <img src=\"assets/icon.png\" alt=\"apple-mail-mcp icon\" width=\"320\" height=\"320\">\n</p>\n\n**The only way to give Claude (or any LLM) access to Apple Mail and iCloud.**\n\nGmail and Outlook have APIs. iCloud doesn't. If you're a Mac user whose email lives in Apple Mail — iCloud, iCloud+, or any account synced through it — there's no web API an LLM can call. This server bridges that gap using AppleScript on your local machine.\n\nIt gives Claude full control over Apple Mail: read, search, compose, reply, move, flag, and delete messages using natural language, against your real inbox, with no cloud intermediary.\n\nBuilt on [AppleScript](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/) via `osascript`, with an optional MailKit extension for real-time new-mail events.\n\n---\n\n## Tools\n\n| Tool | Description |\n|------|-------------|\n| `list_folders` | List all accounts and their mailboxes |\n| `create_folder` | Create a new mailbox/folder in an account (idempotent) |\n| `list_emails` | Paginate messages in a mailbox (newest-first) |\n| `get_email` | Read a message's full headers and body |\n| `search_emails` | Filter by sender, subject, date range across mailboxes |\n| `compose_email` | Create a draft or send a new message immediately |\n| `reply_email` | Reply to a message, open as draft or send immediately |\n| `move_email` | Move a message to any mailbox |\n| `move_matching` | Bulk-move all messages matching a filter into a mailbox |\n| `archive_email` | Move to Archive (iCloud) or All Mail (Gmail) |\n| `move_to_junk` | Move to Junk (iCloud) or Spam (Gmail) |\n| `flag_email` | Set or clear the flag on a message |\n| `mark_read` | Mark a message as read or unread |\n| `delete_email` | Move to Deleted Messages (iCloud) or Trash (Gmail) |\n| `create_rule` | Create a native Mail rule filing sender domains into a folder (optionally sort existing mail too) |\n| `list_rules` | List all Mail rules with their move-target folder and matched sender domains |\n| `delete_rule` | Delete a Mail rule by name |\n| `get_pending_events` | Drain real-time new-mail events from the MailKit bridge |\n| `summarize_email` | Summarize a message in 2-3 sentences via local AI |\n| `classify_email` | Classify by category, priority, and action-required via local AI |\n| `draft_reply` | Draft a reply body via local AI (review before sending) |\n| `triage_inbox` | Bulk-classify up to 20 messages, sorted by priority |\n\n---\n\n## Requirements\n\n- **macOS** (tested on Sonoma / Sequoia / macOS 26)\n- **Apple Mail** open and configured with at least one account\n- **Node.js 18+**\n- **LM Studio** (optional) — for local AI tools; any OpenAI-compatible server works\n\n---\n\n## Installation\n\n### npx (recommended)\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"apple-mail\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@jdot6/apple-mail-mcp\"]\n    }\n  }\n}\n```\n\nRestart Claude Desktop, then ask: *\"What folders do I have in my mail?\"*\n\n### Bootstrap script\n\nClones the repo, builds it, and patches the Claude config automatically:\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/jayvee6/apple-mail-mcp/master/install.sh | bash\n```\n\n### Manual\n\n```bash\ngit clone https://github.com/jayvee6/apple-mail-mcp.git\ncd apple-mail-mcp\nnpm install && npm run build\n```\n\nAdd to `~/Library/Application Support/Claude/claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"apple-mail\": {\n      \"command\": \"/opt/homebrew/bin/node\",\n      \"args\": [\"/path/to/apple-mail-mcp/dist/index.js\"]\n    }\n  }\n}\n```\n\nUse `which node` to get the full path to your Node binary. Restart Claude Desktop.\n\n### Automation Permission\n\nThe first time you use a mail tool, macOS will ask whether to allow `node` to control Mail. Click **Allow**. If you accidentally deny it, go to **System Settings → Privacy & Security → Automation** and re-enable it for your terminal or Node.js runtime.\n\n---\n\n## Local AI (optional)\n\nThe AI tools run against any local LLM via [LM Studio](https://lmstudio.ai) or any OpenAI-compatible server. Email data never leaves your machine with the default config.\n\nConfigure via environment variables in `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"apple-mail\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@jdot6/apple-mail-mcp\"],\n      \"env\": {\n        \"APPLE_MAIL_AI_PROVIDER\": \"lmstudio\",\n        \"APPLE_MAIL_AI_ENDPOINT\": \"http://localhost:1234\",\n        \"APPLE_MAIL_AI_MODEL\": \"gemma-4-it\"\n      }\n    }\n  }\n}\n```\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `APPLE_MAIL_AI_PROVIDER` | `lmstudio` | `lmstudio` \\| `openai` \\| `foundation` \\| `none` |\n| `APPLE_MAIL_AI_ENDPOINT` | `http://localhost:1234` | Base URL for the AI server |\n| `APPLE_MAIL_AI_MODEL` | `gemma-4-it` | Model identifier |\n| `APPLE_MAIL_AI_API_KEY` | *(none)* | Bearer token for remote providers |\n| `APPLE_MAIL_AI_ENRICH_EVENTS` | *(off)* | Set to `1` to auto-classify new mail events |\n| `APPLE_MAIL_AI_ALLOW_REMOTE` | *(off)* | Set to `1` to allow a non-localhost AI endpoint |\n\n> **Privacy note:** If you point `APPLE_MAIL_AI_ENDPOINT` at a remote server (e.g. OpenAI), full email content will be sent to that server. The server blocks this by default — you must set `APPLE_MAIL_AI_ALLOW_REMOTE=1` to acknowledge and enable it.\n\n---\n\n## Companion Skill — Email Compose Review\n\nThe `skill/SKILL.md` file in this repo is a Claude skill that adds a multi-agent review pipeline to every email Claude drafts. Before opening a compose window, Claude runs the draft through five parallel reviewers:\n\n| Reviewer | Checks |\n|---|---|\n| Slop detector | AI writing tells, filler phrases, corporate buzzwords |\n| Copy editor | Spelling, grammar, punctuation |\n| Active voice | Passive → active constructions |\n| Correctness | Names, dates, facts match the context |\n| Logic & clarity | Clear ask, logical structure, appropriate length |\n\nAn arbiter synthesizes the reviews into a revised draft and changelog. Claude shows you the result and waits for your approval before opening the draft in Mail. `send: true` is never used for LLM-drafted email — you send from Mail yourself.\n\nTo install the skill in Claude Code:\n```bash\n/skill install /path/to/apple-mail-mcp/skill/SKILL.md\n```\n\n---\n\n## How It Works\n\n```\nClaude ──stdio──▶ MCP server (Node.js)\n                      │\n                      ├── runScript(\"list_messages\", [...args])\n                      │        │\n                      │        └── osascript scripts/applescript/list_messages.applescript\n                      │                 │\n                      │                 └── Apple Mail (AppleScript dictionary)\n                      │\n                      └── HTTP bridge  ◀── MailKit extension (optional)\n                          localhost:27182\n```\n\n**Message references** are composite keys that uniquely identify a message without a fragile integer index:\n\n```\n{account}::{mailbox}::{RFC 2822 Message-ID}\n\ne.g.  iCloud::INBOX::<CABx3f...@mail.gmail.com>\n```\n\nEvery list/search result includes a `message_ref`. Tools that operate on individual messages (`get_email`, `reply_email`, `move_email`, etc.) take this ref as input. The account and mailbox components scope the AppleScript lookup to the right mailbox; the RFC 2822 ID is the stable identifier. Mail's `whose` predicate makes the per-message lookup O(1).\n\n---\n\n## MailKit Bridge (optional)\n\nThe `MailKitBridge/` directory contains an Xcode project for a Mail extension that fires a local HTTP POST to `localhost:27182/event` when new messages arrive. This populates `get_pending_events` in real time rather than requiring a manual poll.\n\nThe MCP server starts the HTTP listener on startup regardless — it's a no-op if the extension isn't installed.\n\nTo build and install the extension: open `MailKitBridge/MailKitBridge.xcodeproj` in Xcode, build the **MailKitBridgeApp** scheme, run the app once to register the extension, then enable it in **Mail → Settings → Extensions**.\n\n---\n\n## Development\n\n```bash\nnpm run dev          # run with tsx (no build step)\nnpm run build        # compile TypeScript → dist/\nnpm run typecheck    # type-check without emitting\n```\n\nAppleScript files live in `scripts/applescript/` and are invoked directly via `osascript` — no compilation needed. You can test them standalone:\n\n```bash\nosascript scripts/applescript/list_folders.applescript\nosascript scripts/applescript/list_messages.applescript \"iCloud\" \"INBOX\" \"1\" \"5\"\n```\n\n---\n\n## Security Notes\n\n- The HTTP bridge binds to `127.0.0.1` only — not reachable from outside the machine.\n- Script names are validated against `path.basename()` before use to prevent path traversal.\n- Arguments are passed to `osascript` via `execFile` (not a shell), so there is no shell-injection surface.\n- AppleScript calls time out after 30 seconds to prevent hangs if Mail is frozen or showing a permission prompt.\n- Email content in AI prompts is enclosed in XML delimiters (`<email>…</email>`) to guard against prompt-injection attacks in message bodies.\n- Remote AI endpoints are blocked by default — set `APPLE_MAIL_AI_ALLOW_REMOTE=1` to explicitly opt in to sending email data off-device.\n\n---\n\n## License\n\nMIT\n",
  "bytes": 9269,
  "sha": "ca42d4eb62adc1e59e15adcfd76a3cccdc1106584035358ceb72067703beac45",
  "repo_slug": "jayvee6/apple-mail-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_jayvee6_apple_mail_mcp_5f844120/readme"
}