The JXA Mail MCP server provides fast programmatic access to Apple Mail on macOS through 7 tools, enabling email management, search, and automation via the Model Context Protocol.
Core Capabilities:
Account & Mailbox Management - List all configured email accounts and their mailboxes with unread counts
Email Retrieval - Fetch emails with standard properties (ID, subject, sender, date, read/flagged status) with filters for all emails, today's emails, unread emails, or flagged emails from specific accounts/mailboxes
Search & Discovery - Search emails by query string across subject and sender fields (case-insensitive), with optional FTS5 full-text search index for body content searches
Performance Optimizations:
87x faster email retrieval using JXA batch property fetching vs. traditional per-message iteration
700-3500x faster body search (~2ms vs ~7s) with optional SQLite FTS5 search index
Real-time index updates via
--watchflag for automatic synchronization when new emails arriveFast startup times (<5s) using disk-first sync approach
Configuration & Security:
Customizable via environment variables for default accounts, mailboxes, index location, and email limits
Built-in protections against SQL injection, JXA injection, XSS, DoS attacks, and path traversal
Works with Claude Desktop and other MCP-compatible tools through natural conversation
Enables programmatic interaction with Apple Mail on macOS, allowing for listing accounts and mailboxes, fetching recent, unread, or flagged emails, and searching for messages by sender or subject.
Allows for managing and retrieving email content from iCloud accounts configured within the Apple Mail application.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Apple Mail MCPShow me my unread emails from today"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Apple Mail MCP
A fast MCP (Model Context Protocol) server for Apple Mail, using optimized JXA (JavaScript for Automation) scripts with batch property fetching for 87x faster performance, plus an optional FTS5 search index for 700-3500x faster body search (~2ms vs ~7s).
Features
Email Tools (5 total)
Tool | Purpose | Parameters |
| List email accounts | - |
| List mailboxes | account (optional) |
| Unified email listing | account?, mailbox?, filter?, limit? |
| Get single email with content | message_id |
| Unified search with FTS5 | query, scope?, limit? |
Unified get_emails() Filters
Unified search() Scopes
Installation
No installation required
Use pipx run to run directly from PyPI:
With pipx (optional)
For faster startup, install globally:
From source
Requires Python 3.11+ and uv:
Quick Start
1. Add to Claude Code
2. Build the Search Index (Optional but Recommended)
For instant body search (~2ms instead of ~7s), build the FTS5 index:
3. Use with Claude
Once configured, you can search emails, get today's messages, find unread emails, and more through natural conversation.
CLI Commands
Real-Time Index Updates
Use --watch to automatically update the index when new emails arrive:
The file watcher monitors ~/Library/Mail/V10/ for .emlx changes and updates the index in real-time. Requires Full Disk Access.
Configuration
Environment Variables
Variable | Default | Description |
| First account | Default email account |
|
| Default mailbox |
|
| Index database location |
|
| Max emails per mailbox to index |
|
| Hours before index is stale |
Claude Code Config
FTS5 Search Index
The FTS5 index makes search() ~100x faster by pre-indexing email content.
How It Works
Build from disk:
apple-mail-mcp indexreads.emlxfiles directly (~30x faster than JXA)Startup sync: Index is synced with disk when server starts (fast, <5s)
Real-time updates:
--watchflag enables file watcher for automatic updatesFast search: Queries use SQLite FTS5 with BM25 ranking
Requirements
Building the index requires Full Disk Access for Terminal:
Open System Settings
Go to Privacy & Security → Full Disk Access
Add and enable Terminal.app (or your terminal emulator)
Restart terminal
The MCP server itself does NOT need Full Disk Access (uses disk sync).
Performance Comparison
Operation | Without Index | With Index | Speedup |
Body search | ~7,000ms | ~2-10ms | 700-3500x |
Startup sync | 60s timeout | <5s | 12x |
Initial index build | N/A | ~1-2 min | One-time |
Index size | N/A | ~6 KB/email | - |
Real-World Benchmarks (22,696 emails)
Query | Results | Time |
"invoice" | 20 | 2.5ms |
"meeting tomorrow" | 20 | 1.3ms |
"password reset" | 20 | 0.6ms |
"shipping confirmation" | 10 | 4.1ms |
Architecture
Design Principles
Disk-first sync: Fast filesystem scanning instead of slow JXA queries
Consolidated tools: 5 focused tools instead of 13 redundant ones
Builder pattern:
QueryBuilderconstructs optimized JXA scriptsHybrid indexing: Disk reading for speed, state reconciliation for sync
Async execution: All JXA calls use
asyncio.create_subprocess_execType safety: Python type hints and TypedDict for clear API contracts
Hybrid Access Pattern
Access Method | Use Case | Latency | When Used |
JXA (Live) | Real-time ops, small queries | ~100-300ms |
|
FTS5 (Cached) | Body search, complex filtering | ~2-10ms |
|
Disk (Batch) | Initial indexing, sync | ~15ms/100 emails |
|
Performance
Batch Property Fetching (87x faster)
Naive AppleScript/JXA iteration is extremely slow because each property access triggers a separate Apple Event IPC round-trip. We use batch property fetching instead:
Benchmark Results
Method | Time | Speedup |
AppleScript (per-message) | 54.1s | 1x |
JXA (per-message) | 53.9s | 1x |
JXA (batch fetching) | 0.62s | 87x |
Disk-First Sync (12x faster)
Sync Method | Time | Status |
JXA date-based (old) | 60s timeout | N/A |
Disk state reconciliation | <5s | Current |
Development
CI: Ruff lint and format checks run automatically on push/PR to main.
Releases: Tag a version to publish to PyPI automatically:
Security
Implemented Protections
Threat | Mitigation | Location |
SQL Injection | Parameterized queries |
|
JXA Injection |
|
|
FTS5 Query Injection | Special character escaping |
|
XSS via HTML Emails | BeautifulSoup HTML parsing |
|
DoS via Large Files | 25 MB file size limit |
|
Path Traversal | Path validation in watcher |
|
Data Exposure | Database created with 0600 permissions |
|
Known Issues
FTS5 search ignores account/mailbox filters
Body search via search() currently searches all indexed emails regardless of account/mailbox parameters. This is because the disk indexer stores account UUIDs from folder paths, while JXA returns friendly names (e.g., "iCloud"). The mismatch prevents filtering.
Impact: Search results may include emails from all accounts, not just the specified one.
Troubleshooting
ModuleNotFoundError after install
If you get ModuleNotFoundError: No module named 'apple_mail_mcp' even though
the package is installed, reset the virtual environment:
Full Disk Access denied
The apple-mail-mcp index command requires Full Disk Access to read Mail.app's
data files. Grant access in:
System Settings → Privacy & Security → Full Disk Access → Add Terminal
Then restart your terminal.
License
GPL-3.0-or-later