Skip to main content
Glama
LeChabrax

Apple Mail MCP Server

by LeChabrax

search_messages

Read-onlyIdempotent

Search email messages in Apple Mail by criteria like sender, subject, date, read status, or content. Filter results with multiple conditions to locate specific messages quickly.

Instructions

Search for messages matching criteria. Returns metadata-only rows.

Two corpus modes:

  • source=None (default): search the given account/mailbox using the IMAP/AppleScript SEARCH path. account is required.

  • source=[id1, id2, ...]: scope the search to the specific messages identified by the given ids. account/mailbox are ignored; the connector resolves each id self-sufficiently. The resulting message dicts are post-filtered by the other criteria (sender_contains, read_status, etc.) — full filter composition. The literal token "SELECTED" may appear in the list and is server-resolved at call time to Mail.app's current UI selection (zero-or-more messages). Mixed lists like ["SELECTED", "12345"] are valid. Missing ids drop out silently (partial-results).

For thread retrieval, call get_thread(message_id) to expand an anchor into thread member ids, then optionally pipe those ids into source=[ids] for filtered metadata browsing or into get_messages([ids]) for full bodies.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum results to return (default: 50).
sourceNoOptional list of message ids (with optional ``"SELECTED"`` sentinel) to restrict the search to. ``None`` (default) searches the account/mailbox normally.
accountNoMail.app account display name (e.g., "Gmail", "iCloud") or UUID (from list_accounts). Required when ``source is None``; ignored when ``source`` is a list. Names are convenient but unstable across renames; UUIDs are stable.
date_toNoInclusive upper bound on date received (full day included). ISO 8601 YYYY-MM-DD.
mailboxNoMailbox name. Defaults to the account's real receiving mailbox, which is resolved by asking Mail instead of assuming it is called "INBOX" (it is not, on some accounts). Ignored when ``source`` is a list.
date_fromNoInclusive lower bound on date received. ISO 8601 YYYY-MM-DD.
is_flaggedNoFilter by flagged status (true=flagged, false=not flagged).
read_statusNoFilter by read status (true=read, false=unread).
body_containsNoSubstring match against message body content. IMAP uses ``BODY`` predicate (sub-second); AppleScript reads ``content of msg`` per candidate (very slow on large mailboxes — measured 148s for 100 cold-cache messages). When the call commits to AppleScript with this filter set, a ``warnings`` field is included in the response. Case-insensitive on both paths.
text_containsNoSubstring match against headers + body (RFC 3501 ``TEXT`` semantics). On AppleScript, approximated as ``content + subject + sender`` (recipients and other headers not matched). Same perf characteristics as ``body_contains``.
has_attachmentNoFilter messages with (true) or without (false) attachments.
sender_containsNoFilter by sender email/domain substring.
subject_containsNoFilter by subject keywords substring.
include_attachmentsNoWhen True, each row includes an ``attachments`` field listing per-attachment metadata (name, mime_type, size, downloaded). Default False — opt-in because the AppleScript fallback path can be slow on cold caches (#142). Free on the IMAP fast path. To fetch attachment metadata for a known list of ids cheaply, prefer ``get_messages([ids])`` (default-on attachments, bounded cardinality).
received_within_hoursNoRelative-time filter. When set, only return messages received within the last N hours (hour precision). Composes with ``date_from`` / ``date_to`` — the most restrictive filter wins. Must be a positive int. Days = 24, weeks = 168, etc.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is clear. The description adds valuable behavioral context such as the 'SELECTED' sentinel behavior, silent dropping of missing IDs with partial results, and the differences in behavior between IMAP and AppleScript paths. Some performance details are implementation-specific and could become stale quickly.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections and code formatting for the two modes. The performance notes (e.g., 'measured 148s for 100 cold-cache messages') and inline details like issue references (#142) add credibility but slightly extend length. Every sentence adds value, though some performance specifics could be condensed without loss of meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (15 params, two modes, interactions with sibling tools like get_thread and get_messages), the description is remarkably complete. It covers mode selection, filter composition, performance trade-offs, and even error behavior like silently vanishing IDs. The presence of an output schema (though not shown in full) further supports the agent in understanding return types.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description enhances the parameter semantics significantly by explaining the 'SELECTED' sentinel, performance implications (e.g., body_contains being slow on AppleScript), free vs. costly operations (include_attachments), and composition semantics like 'most restrictive filter wins'. This goes beyond what the schema alone provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool searches messages and returns metadata-only rows, with a specific verb and resource. It goes further to distinguish two distinct modes (default mailbox search vs. scoped by message IDs), which is specific and actionable. It also differentiates from siblings like get_thread and get_messages by explaining when to use each for thread retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly outlines when to use the tool versus alternatives, stating 'For thread retrieval, call get_thread(...) to expand an anchor into thread member ids, then optionally pipe those ids into source=[ids] or get_messages([ids])'. It also explains conditions like when account is required (source is None) versus ignored (source is a list), and notes post-filtering behavior.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LeChabrax/apple-mail-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server