{"id":47629093,"url":"https://github.com/like-a-freedom/rusty_apple_mail_mcp","last_synced_at":"2026-04-22T07:01:05.329Z","repository":{"id":346111790,"uuid":"1188549349","full_name":"like-a-freedom/rusty_apple_mail_mcp","owner":"like-a-freedom","description":"Local-first Apple Mail MCP","archived":false,"fork":false,"pushed_at":"2026-04-10T11:57:54.000Z","size":286,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-10T13:12:02.702Z","etag":null,"topics":["apple-mail","claude","email","mcp","mcp-server","model-context-protocol","rmcp","rust","vscode"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/like-a-freedom.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-22T08:34:44.000Z","updated_at":"2026-04-10T11:57:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/like-a-freedom/rusty_apple_mail_mcp","commit_stats":null,"previous_names":["like-a-freedom/rusty_apple_mail_mcp"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/like-a-freedom/rusty_apple_mail_mcp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-a-freedom%2Frusty_apple_mail_mcp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-a-freedom%2Frusty_apple_mail_mcp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-a-freedom%2Frusty_apple_mail_mcp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-a-freedom%2Frusty_apple_mail_mcp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/like-a-freedom","download_url":"https://codeload.github.com/like-a-freedom/rusty_apple_mail_mcp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/like-a-freedom%2Frusty_apple_mail_mcp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32125094,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-22T00:31:26.853Z","status":"online","status_checked_at":"2026-04-22T02:00:05.693Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apple-mail","claude","email","mcp","mcp-server","model-context-protocol","rmcp","rust","vscode"],"created_at":"2026-04-01T23:05:14.553Z","updated_at":"2026-04-22T07:01:05.320Z","avatar_url":"https://github.com/like-a-freedom.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rusty Apple Mail MCP Server\n\n![Rust 2024](https://img.shields.io/badge/rust-2024-orange?style=flat-square\u0026logo=rust)\n![Protocol MCP](https://img.shields.io/badge/protocol-MCP-6f42c1?style=flat-square)\n![Transport stdio](https://img.shields.io/badge/transport-stdio-0a7ea4?style=flat-square)\n![Platform macOS](https://img.shields.io/badge/platform-macOS-111827?style=flat-square\u0026logo=apple)\n![Access read-only](https://img.shields.io/badge/access-read--only-15803d?style=flat-square)\n\nRead-only MCP server for Apple Mail on macOS.\n\nIt gives an LLM or AI agent fast local access to Apple Mail metadata, message bodies, and attachment text **without AppleScript and without IMAP/POP/EWS network calls**.\n\n## Why this matters\n\nApple Mail already contains the data an agent needs, but it is buried in a local SQLite index and scattered `.emlx` files.\n\nThis project exposes that storage through a small, intent-driven MCP interface so an agent can:\n\n- locate messages by subject, date range, sender, participant, mailbox, or account;\n- fetch a full message including metadata, recipients, body, and attachment summary;\n- extract readable text from supported attachments;\n- operate completely **locally** and **read-only**.\n\nIn practice, it empowers AI workflows to search and read your mail archive safely and quickly, without relying on Mail.app automation like AppleScript (which damn slow and throws timeouts regularly) or network protocols.\n\n## What the server can do\n\nThe current tool set is intentionally compact:\n\n| Tool | What it does |\n|---|---|\n| `search_messages` | Search by subject, dates, sender, participant, account, or mailbox |\n| `list_accounts` | Discover account identifiers; set `include_mailboxes=true` for combined account+mailbox discovery |\n| `get_message` | Read one message in full; recipients omitted by default (`include_recipients=true` to include) |\n| `get_attachment_content` | Extract readable attachment content |\n| `list_mailboxes` | List mailboxes/folders with message counts |\n\n## Installation\n\n### Prerequisites\n\n- macOS\n- Apple Mail installed and synced at least once\n- Rust toolchain (`rustup`, `cargo`)\n\n### Build from source\n\n```bash\ncargo build --release\n```\n\n### Install locally\n\n```bash\ncargo install --path .\n```\n\nThis installs the binary under the name `rusty_apple_mail_mcp`.\n\n## Running the server\n\nTo start from source:\n\n```bash\ncargo run --release\n```\n\nOr with the installed binary:\n\n```bash\nrusty_apple_mail_mcp\n```\n\nFor interactive experimentation, use the MCP Inspector:\n\n```bash\nnpx -y @modelcontextprotocol/inspector ./target/release/rusty_apple_mail_mcp\n```\n\n## Configuration\n\nThe server is configured **only** through environment variables:\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `APPLE_MAIL_DIR` | no | `~/Library/Mail` | Root folder of the Mail data |\n| `APPLE_MAIL_VERSION` | no | `V10` | Envelope Index version subdirectory |\n| `APPLE_MAIL_ACCOUNT` | no | unset | Comma-separated account selectors such as `Work Email` or `user@example.com`; when set, the whole server is restricted to the resolved account(s) |\n| `RUST_LOG` | no | unset | Standard Rust tracing filter used by `tracing_subscriber`; controls server logs written to stderr |\n\nExample setup:\n\n```bash\nexport APPLE_MAIL_DIR=\"$HOME/Library/Mail\"\nexport APPLE_MAIL_VERSION=\"V10\"\nexport APPLE_MAIL_ACCOUNT=\"Work Email\"\nexport RUST_LOG=\"warn\"\n```\n\n### `RUST_LOG` values\n\nThe server reads `RUST_LOG` through `tracing_subscriber::EnvFilter`, so it accepts the usual Rust tracing filter syntax.\n\nCommon values:\n\n- `error` — only errors\n- `warn` — warnings and errors\n- `info` — startup and high-level operational logs\n- `debug` — includes per-request debug logs\n- `trace` — very verbose tracing\n- `off` — disables logging\n\nYou can also scope logs per module/crate:\n\n- `rusty_apple_mail_mcp=debug`\n- `rusty_apple_mail_mcp=trace,rusqlite=warn`\n- `info,rmcp=warn`\n\nWhen `RUST_LOG` enables `debug` for this crate, `search_messages` logs timing breakdowns to stderr, including:\n\n- total matched rows\n- SQL query time\n- metadata hydration time from SQLite\n- body preview fallback time\n- total request time\n\n### Account scoping\n\nIf `APPLE_MAIL_ACCOUNT` is set, the server resolves each selector through macOS `~/Library/Accounts/Accounts4.sqlite` and then restricts **all** tools to the matched Mail account IDs.\n\n- Matching is case-insensitive and trims whitespace.\n- Supported selectors include human-friendly account names and email addresses.\n- Startup fails fast if a selector matches zero accounts or multiple accounts.\n- `list_accounts` returns `account_name` and `email` when available, so valid selector values are discoverable from the MCP interface itself.\n\n## VS Code integration\n\nExample minimum `.vscode/mcp.json` configuration:\n\n```json\n{\n    \"servers\": {\n        \"mail_mcp\": {\n            \"command\": \"rusty_apple_mail_mcp\",\n            \"args\": [],\n            \"env\": {\n                \"APPLE_MAIL_DIR\": \"/Users/your-user/Library/Mail\",\n                \"APPLE_MAIL_VERSION\": \"V10\",\n                \"APPLE_MAIL_ACCOUNT\": \"Work Email\",\n                \"RUST_LOG\": \"warn\"\n            }\n        }\n    }\n}\n```\n\n## Usage\n\nTypical usage pattern:\n\n1. Call `list_accounts` (optionally with `include_mailboxes=true`) to discover accounts and mailboxes.\n2. Use `search_messages` to build a shortlist of candidates.\n3. Call `get_message` to fetch the full message you care about.\n4. Use `get_attachment_content` when you need the text of a particular attachment.\n\n### Token efficiency\n\nThe server is optimized to minimize token consumption:\n\n- **Compact tool descriptions** — routing hints live in `ServerInfo.instructions` (loaded once), not repeated per-tool on every request.\n- **HTML → plain text** — HTML email bodies are converted to clean text via DOM parsing (using `scraper`), typically 10–20× smaller than raw HTML.\n- **`status: \"success\"` omitted** — the status field only appears on error/not_found/partial responses.\n- **Recipients omitted by default** — `get_message` skips To/CC lists unless `include_recipients=true`.\n- **Compact dates** — ISO 8601 without seconds (`2024-09-15T00:00Z`).\n- **`has_body` removed** — always true for indexed messages; no longer wasting tokens.\n\n### Sample search request\n\n```json\n{\n    \"subject_query\": \"invoice\",\n    \"account\": \"imap://ACCOUNT-ID\",\n    \"limit\": 10\n}\n```\n\n### Sample message retrieval\n\n```json\n{\n    \"message_id\": \"12345\",\n    \"include_body\": true,\n    \"include_attachments_summary\": true,\n    \"body_format\": \"text\",\n    \"include_recipients\": false\n}\n```\n\n`include_recipients` defaults to `false` — set it to `true` when you need the To/CC lists (saves tokens on corporate mail with 50+ recipients).\n\n### Combined account + mailbox discovery\n\nInstead of calling `list_accounts` then `list_mailboxes` separately, use `include_mailboxes=true`:\n\n```json\n{\n    \"include_mailboxes\": true\n}\n```\n\nThis returns accounts with their mailboxes grouped, saving one round-trip.\n\n## How it works\n\nThe server draws from two local sources:\n\n- **Envelope Index** – the SQLite database Apple Mail uses as a metadata index and relationship store\n- **.emlx files** – the canonical bodies and attachments for individual messages\n\nSearch queries hit the lightweight index, keeping them fast; bodies and attachments are loaded on-demand from the `.emlx` files.\n\n## Development\n\nHandy commands while working on the codebase:\n\n```bash\ncargo test\ncargo clippy --all-targets --all-features -- -D warnings\ncargo doc --no-deps\n```\n\n## Limitations\n\n- macOS only\n- read-only access only\n- stdio transport only\n- requires Apple Mail storage to be present on disk\n- some binary attachment formats may yield metadata instead of extracted text\n\n## TL;DR\n\nNeed an AI agent to safely search and read Apple Mail on your Mac? This project provides a clean, read-only MCP layer over Apple Mail’s native storage — fast index-based searches, on‑demand body hydration from `.emlx`, and zero write access.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flike-a-freedom%2Frusty_apple_mail_mcp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flike-a-freedom%2Frusty_apple_mail_mcp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flike-a-freedom%2Frusty_apple_mail_mcp/lists"}