Skip to main content
Glama
sweetrb

apple-mail-mcp

by sweetrb

search-messages

Find messages by query, sender, subject, date, read, flag, or flag-color filters and return matching IDs for follow-up operations.

Instructions

Use when: finding messages by query/sender/subject/date/read/flag/flag-color filters and you need their ids for follow-up operations. Returns: matching messages with id, date, subject, sender, read state, and flagColor when flagged with an explicit color (plus partial-coverage diagnostics when some mailboxes were skipped). An IMAP search stops at its deadline (APPLE_MAIL_MCP_SEARCH_DEADLINE_MS, default 45s) or when the request is cancelled, returning the matches found so far with partial: true and timedOutMailboxes — narrow with mailbox/dateFrom rather than repeating it. Do not use when: you want a plain mailbox listing without filters (use list-messages), already have an id and want the body (use get-message), or want a whole conversation (use get-thread). Prefer this first to obtain the message ids that get-message/mark-as-read/delete-message/move-message and the batch tools require. Tip: use flagColor to find messages you tagged earlier (e.g. all 'orange' across mailboxes) — colored flags work as cross-mailbox labels this way, via flag-message/batch-flag-messages to set them and this filter to find them again, without moving anything into a dedicated folder.

Input Schema

NameRequiredDescriptionDefault
bodyNoText to search for in the message body (server-side IMAP BODY search). Requires the IMAP backend for the account searched, or the opt-in local body index (APPLE_MAIL_MCP_BODY_INDEX); otherwise AppleScript-only accounts cannot search bodies and are reported as not searched.
fromNoFilter by sender (substring match against the full sender string, i.e. display name + address — not an exact address match)
limitNoMaximum number of results (default: 50, max: 500)
queryNoText to search for in subject or sender
dateToNoEnd date filter (e.g., 'March 1, 2026')
isReadNoFilter by read status
offsetNoNumber of newest matches to skip (for pagination; IMAP accounts only). Without a mailbox, offset + limit may not exceed 5,000 — name a mailbox to page deeper.
accountNoAccount to search in (omit to search all accounts)
mailboxNoMailbox to search in (e.g., 'INBOX'). Omit to search all mailboxes.
subjectNoFilter by subject line (substring match)
dateFromNoStart date filter (e.g., 'January 1, 2026')
flagColorNoFilter to messages flagged with exactly this color (same palette as flag-message: red/orange/yellow/green/blue/purple/gray — 'grey' accepted). A message flagged with Mail's plain default (no explicit color) never matches. Implies isFlagged: true — pairing this with isFlagged: false is rejected as contradictory. Caveat on IMAP accounts only: 'red' is Mail's all-bits-clear encoding, wire-identical to a plain (colorless) flag, so red: true in results and flagColor: 'red' in this filter both also match a plain flag there — this is inherent to Apple's $MailFlagBit0/1/2 scheme, not specific to this server. AppleScript-only accounts distinguish red correctly (Mail's own `flag index` 0 vs -1).
isFlaggedNoFilter by flagged status

Output Schema

NameRequiredDescriptionDefault
countNo
backendNo
partialNo
messagesNo
stoppedByNo
failedMailboxesNo
omittedMessagesNo
backendByAccountNo
timedOutAccountsNo
timedOutMailboxesNo
failedMailboxReasonsNo
notSearchedMailboxesNo
skippedLargeMailboxesNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv2.20.47
    • changedInput schema / properties / body / description
      Previous value: -"Text to search for in the message body (server-side IMAP BODY search). Requires the IMAP backend for the account searched; AppleScript-only accounts cannot search bodies and are reported as not searched."New value: +"Text to search for in the message body (server-side IMAP BODY search). Requires the IMAP backend for the account searched, or the opt-in local body index (APPLE_MAIL_MCP_BODY_INDEX); otherwise AppleScript-only accounts cannot search bodies and are reported as not searched."
  2. Changed2 schema fields changedv2.20.45
    • addedOutput schema / properties / backend
      Added value: +{
      +  "enum": [
      +    "envelope-index",
      +    "applescript",
      +    "mixed"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / backendByAccount
      Added value: +{
      +  "additionalProperties": {
      +    "enum": [
      +      "envelope-index",
      +      "applescript"
      +    ],
      +    "type": "string"
      +  },
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
  3. Changed4 schema fields changedv2.20.29
    • removedInput schema / properties / dateTo / $ref
      Removed value: -"#/properties/dateFrom"
    • addedInput schema / properties / dateTo / pattern
      Added value: +"^[a-zA-Z0-9 ,/\\-:]+$"
    • addedInput schema / properties / dateTo / type
      Added value: +"string"
    • addedOutput schema / properties / failedMailboxReasons / propertyNames
      Added value: +{
      +  "type": "string"
      +}
  4. Changed3 schema fields changedv2.20.11
    • addedInput schema / properties / flagColor
      Added value: +{
      +  "description": "Filter to messages flagged with exactly this color (same palette as flag-message: red/orange/yellow/green/blue/purple/gray — 'grey' accepted). A message flagged with Mail's plain default (no explicit color) never matches. Implies isFlagged: true — pairing this with isFlagged: false is rejected as contradictory. Caveat on IMAP accounts only: 'red' is Mail's all-bits-clear encoding, wire-identical to a plain (colorless) flag, so red: true in results and flagColor: 'red' in this filter both also match a plain flag there — this is inherent to Apple's $MailFlagBit0/1/2 scheme, not specific to this server. AppleScript-only accounts distinguish red correctly (Mail's own `flag index` 0 vs -1).",
      +  "enum": [
      +    "red",
      +    "orange",
      +    "yellow",
      +    "green",
      +    "blue",
      +    "purple",
      +    "gray",
      +    "grey"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / stoppedBy
      Added value: +{
      +  "enum": [
      +    "deadline",
      +    "cancelled"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / timedOutMailboxes
      Added value: +{
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  5. Changed2 schema fields changedv2.19.19
    • addedInput schema / properties / offset
      Added value: +{
      +  "description": "Number of newest matches to skip (for pagination; IMAP accounts only). Without a mailbox, offset + limit may not exceed 5,000 — name a mailbox to page deeper.",
      +  "minimum": 0,
      +  "type": "integer"
      +}
    • addedOutput schema / properties / omittedMessages
      Added value: +{
      +  "items": {
      +    "additionalProperties": false,
      +    "properties": {
      +      "id": {
      +        "type": "string"
      +      },
      +      "mailbox": {
      +        "type": "string"
      +      },
      +      "reason": {
      +        "type": "string"
      +      },
      +      "uid": {
      +        "type": "number"
      +      }
      +    },
      +    "required": [
      +      "id",
      +      "mailbox",
      +      "uid",
      +      "reason"
      +    ],
      +    "type": "object"
      +  },
      +  "type": "array"
      +}
  6. Changed1 schema field changedv2.19.14
    • addedOutput schema / properties / failedMailboxReasons
      Added value: +{
      +  "additionalProperties": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
  7. Changed2 schema fields changedv2.19.12
    • addedInput schema / properties / body
      Added value: +{
      +  "description": "Text to search for in the message body (server-side IMAP BODY search). Requires the IMAP backend for the account searched; AppleScript-only accounts cannot search bodies and are reported as not searched.",
      +  "type": "string"
      +}
    • changedInput schema / properties / query / description
      Previous value: -"Text to search for in subject, sender, or content"New value: +"Text to search for in subject or sender"
  8. Changed1 schema field changedv2.17.2
    • addedOutput schema / properties / failedMailboxes
      Added value: +{
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  9. Changed2 schema fields changedv2.10.24
    • changedInput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
    • changedOutput schema / $schema
      Previous value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
  10. Changed1 schema field changedv2.10.8
    • changedOutput schema / additionalProperties
      Previous value: -falseNew value: +true
  11. Addedv2.9.0
  12. Removedv2.8.10
  13. Changed4 schema fields changedv2.8.2
    • changedInput schema / properties / limit / description
      Previous value: -"Maximum number of results (default: 50)"New value: +"Maximum number of results (default: 50, max: 500)"
    • addedInput schema / properties / limit / maximum
      Added value: +500
    • addedInput schema / properties / limit / minimum
      Added value: +1
    • changedInput schema / properties / limit / type
      Previous value: -"number"New value: +"integer"
  14. First observedv2.6.1

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and does so: it discloses the search deadline and its env var (APPLE_MAIL_MCP_SEARCH_DEADLINE_MS, 45s default), cancellation behavior, the partial: true / timedOutMailboxes return shape when mailboxes are skipped, and the remediation (narrow with mailbox/dateFrom instead of retrying). These are non-obvious operational traits an agent could not infer from the name or schema.

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?

Front-loaded and labeled (Use when / Returns / Do not use when / Tip), so an agent scans rather than reads. The flagColor tip is longer than strictly necessary for the retrieval decision it supports, but each section still carries distinct information.

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?

For a 13-parameter, zero-required search tool this covers the decision space fully: what it returns, how it degrades, how to recover from degradation, and how it chains into id-consuming siblings. An output schema exists, yet the description still outlines the payload, which is a bonus rather than a gap.

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

Parameters4/5

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

Schema coverage is 100%, so the baseline is 3; the description exceeds it by giving flagColor an operational meaning beyond the enum — a cross-mailbox label set via flag-message/batch-flag-messages and recovered here, and the advice to narrow with mailbox/dateFrom under timeout. It does not re-explain the other 12 params, but the schema already does that thoroughly.

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?

Opens with a specific verb+resource ('finding messages') and enumerates the exact filter dimensions (query/sender/subject/date/read/flag/flag-color). It explicitly names the sibling tools it is not (list-messages, get-message, get-thread), so an agent can disambiguate without opening a schema.

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?

Has an explicit 'Use when' / 'Do not use when' split with a named alternative for each excluded case, plus a routing rule ('Prefer this first to obtain the message ids that get-message/mark-as-read/delete-message/move-message require'). Nothing about selection is left to inference.

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