Skip to content
Ernesto Cobos edited this page Jul 1, 2026 · 7 revisions

cobos-apple-mail-mcp Wiki

Unified Apple Mail MCP server — fast on-disk reads/search plus complete AppleScript writes, behind one safety layer. 31 MCP tools. Author: Ernesto Cobos. License: GPL-3.0-or-later.

This Wiki is the deep documentation; the README is the quickstart and pitch. CLAUDE.md is the fast-routing index for anyone (human or agent) working on the code itself.

Install

uvx cobos-apple-mail-mcp serve            # zero-install run (canonical MCP path)
# or:  pipx install cobos-apple-mail-mcp  (add [attachments] for PDF/DOCX text search)
apple-mail-mcp init && apple-mail-mcp index build

Then register apple-mail-mcp serve with your client — see Install per client. The install-to-first-run flow and the required macOS permissions (Full Disk Access + Automation) are on Permissions and troubleshooting.

flowchart LR
    A["1 · Install<br/>uvx / pipx / .pyz"] --> B["2 · Permissions<br/>Full Disk Access + Automation"]
    B --> C["3 · init + index build"]
    C --> D["4 · Register with<br/>your MCP client"]
    D --> E["5 · Ask your agent<br/>about your inbox"]
    classDef done fill:#3f9142,stroke:#245127,color:#fff
    class A,B,C,D,E done
Loading
flowchart TB
    Agent["MCP client / agent"] --> Tools["tools/*<br/>MCP tool surface"]

    Tools --> Resolver["core/resolver.py<br/>id → live message"]
    Resolver --> Identity["core/identity.py<br/>canonical Message-ID"]

    Tools -->|reads| ReadPath["Read path<br/>direct-on-disk"]
    Tools -->|writes| WritePath["Write path<br/>via guard()"]

    subgraph Reads["Read path (never writes Mail)"]
        direction TB
        EnvReader["read/envelope_reader.py<br/>Envelope Index immutable=1"]
        Emlx["read/emlx_parser.py<br/>.emlx from disk"]
        Indexer["read/indexer.py + watcher.py"]
        IndexDB[("index.db<br/>disposable, rebuildable")]
        Search["read/search.py + vector_search.py<br/>FTS5 + hybrid"]
        Threader["read/threader.py + knowledge/*<br/>JWZ threading + triage"]
        EnvReader --> Indexer
        Emlx --> Indexer
        Indexer --> IndexDB
        IndexDB --> Search
        IndexDB --> Threader
    end

    subgraph Writes["Write path"]
        direction TB
        Guard["core/safety.py guard()<br/>read_only + batch caps + dry_run"]
        Undo["core/undo.py<br/>journal + undo_last"]
        JXA["write/jxa_executor.py<br/>osascript, timeout + kill"]
        Guard --> JXA
        Guard --> Undo
    end

    ReadPath --> Reads
    WritePath --> Writes
    JXA --> Mail["Mail.app<br/>AppleScript / JXA"]
    Resolver -.verify id.-> JXA
Loading

High-level subsystem map: an MCP client hits tools/*, which resolve a canonical Message-ID via core/resolver.py and split into a direct-on-disk read path (Envelope Index and .emlx feeding the disposable index.db for search and threading) and a write path that always passes through core.safety.guard() before write/jxa_executor.py drives Mail.app.

Pages

Knowledge map (subsystem → source → page)

The authoritative copy of this table lives in CLAUDE.md — it's the fast routing index used when working on the code; this Wiki is where each row's page actually lives.

Clone this wiki locally