Apple Mail MCP server - Native AppleScript integration for macOS Mail.app
The server defines 25 tools with reasonable naming conventions (verb_noun style: list_accounts, search_emails, compose_email, etc.). Most tools have descriptions present, but quality is uneven. Several tools (check_fda, check_accessibility, check_automation) have exceptionally detailed descriptions with remediation steps and GitHub issue references, these are production-grade. However, tools 13-25 lack visible input schema definitions in the provided source code, and some descriptions are sparse. The codebase shows strong security mindfulness (AppleScript injection hardening via whitelist in MutationToolScriptBuilder.swift, TCC permission checks), but schema completeness and consistency across all tools cannot be fully verified from the provided excerpt. Per-tool analysis reveals high variance: permission-check tools score 75-85, composition tools score 40-55 due to missing schema visibility.
Export a batch of emails to markdown files
Check whether Accessibility (GUI-scripting) is granted via AXIsProcessTrusted(). Required for the #175 wrapper-free compose path (compose_email / create_draft use mailto + keystrokes so the body isn't wrapped in <blockquote type="cite"> on mobile clients). Returns status plus steps to grant it. Separate grant from check_fda. If denied, compose still works but the body is wrapped in a quote on some mobile clients.
Check whether Automation (Apple Events to Mail) is granted TO THIS BINARY — the third TCC axis after check_fda and check_accessibility (#293). Non-prompting probe (AEDeterminePermissionToAutomateTarget, askUserIfNeeded=false). Four states with remediation: granted / denied (recorded -1743 — macOS never re-prompts; System Settings entry or tccutil reset, #288) / not-determined (run any Mail tool to trigger the prompt) / Mail-not-running (open Mail.app first; the probe deliberately has no side effects). Note (#288): the binary holds its OWN grant — osascript working in your shell does NOT mean this binary is authorized. Zero-TCC compose fallback: open_mailto (#287).
Check whether Full Disk Access is granted (functionally probes the Apple Mail Envelope Index). Returns status plus the exact steps to grant it if not. Use when SQLite-only features (search_emails projection=ids/count, export_emails_markdown) fail with an 'unavailable' error.
Incomplete input schema visibility: 12 tools (search_emails, get_email, get_emails_batch, export_emails_markdown, batch_export_emails_markdown, check_automation, and others) lack visible schema definitions in provided source code. Cannot verify parameter types and descriptions for LLM guidance.
Sparse descriptions for mutation tools: compose_email, create_draft, reply_email, forward_email, check_for_new_mail, synchronize_account have short descriptions (under 60 chars) that do not explain when to use each over alternatives, what side effects occur, or what the return value contains. LLM cannot reliably distinguish 'create_draft' from 'compose_email' from descriptions alone.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 54 | <=2025-11-25 | v2 |
Trigger Mail.app sync for new messages
Compose and send an email
Create an email draft
Create a new mailbox (folder) in an account
Delete a mailbox (folder) from an account
DEPRECATED — renamed to batch_export_emails_markdown
Set the flagged status of a message
Forward an email
Get detailed information about a specific mail account
Get a single email by ID with full content
Get multiple emails by ID with full content, returned as an array
List all mail accounts configured in Apple Mail
List emails in a mailbox. Returns an envelope object {results, returned, limit, truncated} (NOT a bare array): `truncated` is true when more emails matched than `limit` — raise `limit` or narrow the query to retrieve the rest. On the SQLite fast path `truncated` is definitive (limit+1 fetch); on the AppleScript fallback it is a best-effort `returned == limit` heuristic (#204).
List all mailboxes (folders) for an account
Set the junk mail status of a message
Set the read status of a message
Reply to an email
Search for emails across all accounts/mailboxes. Returns structured results with pagination envelope {results, returned, limit, truncated}.
Set the background color of a message
Set the flag index (color) of a message
Synchronize an account
Missing output schema documentation: The provided source code does not show output schema definitions for any tools. LLMs cannot plan chained calls without knowing what fields are returned (e.g., does search_emails return account_id? What pagination fields does list_emails return?). Blocks downstream tool selection.
Parameter relationship documentation gaps: Tools accept account_name and account_id, with guidance that account_id 'disambiguates when multiple accounts share a display_name' (issue #202 referenced). However, descriptions do not explicitly state whether account_name is required if account_id is provided, or vice versa. Ambiguity invites incorrect LLM usage.
Deprecated tool not removed: export_emails_markdown is marked as DEPRECATED in description ('renamed to batch_export_emails_markdown'), but both tools remain published. Ambiguity over which to call. Should retire the deprecated version or clarify the distinction.
Mutation tool descriptions lack state-change clarity: Tools like mark_read, flag_email, set_flag_color have 50-60 char descriptions stating only the action (e.g., 'Set the read status of a message'). No statement of whether the call is idempotent, whether it triggers Mail.app sync, or what error conditions exist. LLMs cannot reason about retry safety.