Skip to main content
Glama

Read Email

read_email
Read-only

Use this when the user wants the full content of an email that lives in the Mac's Apple Mail (message ID from list_emails/search_emails). For a Microsoft 365 message ID from m365_list_emails, use m365_read_email. Pass account= (and mailbox= if known, both from list_emails/search_emails) so the lookup targets one account instead of scanning all of them. Call sequentially, not in parallel — concurrent calls serialize behind Mail.app's JXA lock and later calls will time out.

Performance: body fetch is the primary latency source (avg 20s on slow IMAP). Pass include_body=false to skip it and get metadata-only (fast). Pass max_body_chars=N to cap the body at N chars after HTML stripping (default 30000; 0=unlimited). Response includes body_fetch_ms when fetch took >2s, body_omitted=true when skipped, body_truncated_at=N when cut.

When a body isn't cached on this Mac, read_email returns metadata with body_omitted=true and body_omit_reason="not_downloaded" (iCloud/IMAP optimized storage) rather than making Mail fetch it (that can be slow and tie Mail up). If the user wants it anyway, retry with force_download=true to have Mail pull the body over IMAP now and return it (waits up to ~60s). Off by default; ignored while Mail is in a cooldown.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
accountNoMail.app account the message lives in (returned alongside the id). Passing it skips searching the other accounts.
mailboxNoFolder the message lives in (returned alongside the id). Passing it skips searching the other folders.
message_idYesThe message id returned by list_emails or search_emails. Accepts the bare id or the <angle-bracketed> form.
include_bodyNoReturn the message body, not just its headers.true
force_downloadNoAsk Mail to fetch the full message from the server when only part of it is cached locally. Slower, and it needs the account to be online.false
max_body_charsNoCap on how many characters of the body to return. Defaults to 30000; the reply says when it truncated.30000

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
ccNo
idNo
toNo
bodyNo
dateNo
fromNo
unreadNo
accountNo
mailboxNo
subjectNo
body_omittedNo
body_fetch_msNo
body_truncated_atNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed6 schema fields changed
    • addedInput schema / properties / account / description
      Added value: +"Mail.app account the message lives in (returned alongside the id). Passing it skips searching the other accounts."
    • addedInput schema / properties / force_download / description
      Added value: +"Ask Mail to fetch the full message from the server when only part of it is cached locally. Slower, and it needs the account to be online."
    • addedInput schema / properties / include_body / description
      Added value: +"Return the message body, not just its headers."
    • addedInput schema / properties / mailbox / description
      Added value: +"Folder the message lives in (returned alongside the id). Passing it skips searching the other folders."
    • addedInput schema / properties / max_body_chars / description
      Added value: +"Cap on how many characters of the body to return. Defaults to 30000; the reply says when it truncated."
    • addedInput schema / properties / message_id / description
      Added value: +"The message id returned by list_emails or search_emails. Accepts the bare id or the <angle-bracketed> form."
  2. Changed6 schema fields changed
    • removedInput schema / properties / account / description
      Removed value: -"Mail.app account the message lives in (returned alongside the id). Passing it skips searching the other accounts."
    • removedInput schema / properties / force_download / description
      Removed value: -"Ask Mail to fetch the full message from the server when only part of it is cached locally. Slower, and it needs the account to be online."
    • removedInput schema / properties / include_body / description
      Removed value: -"Return the message body, not just its headers."
    • removedInput schema / properties / mailbox / description
      Removed value: -"Folder the message lives in (returned alongside the id). Passing it skips searching the other folders."
    • removedInput schema / properties / max_body_chars / description
      Removed value: -"Cap on how many characters of the body to return. Defaults to 30000; the reply says when it truncated."
    • removedInput schema / properties / message_id / description
      Removed value: -"The message id returned by list_emails or search_emails. Accepts the bare id or the <angle-bracketed> form."
  3. Changed6 schema fields changed
    • addedInput schema / properties / account / description
      Added value: +"Mail.app account the message lives in (returned alongside the id). Passing it skips searching the other accounts."
    • addedInput schema / properties / force_download / description
      Added value: +"Ask Mail to fetch the full message from the server when only part of it is cached locally. Slower, and it needs the account to be online."
    • addedInput schema / properties / include_body / description
      Added value: +"Return the message body, not just its headers."
    • addedInput schema / properties / mailbox / description
      Added value: +"Folder the message lives in (returned alongside the id). Passing it skips searching the other folders."
    • addedInput schema / properties / max_body_chars / description
      Added value: +"Cap on how many characters of the body to return. Defaults to 30000; the reply says when it truncated."
    • addedInput schema / properties / message_id / description
      Added value: +"The message id returned by list_emails or search_emails. Accepts the bare id or the <angle-bracketed> form."
  4. Changed1 schema field changed
    • addedInput schema / properties / force_download
      Added value: +{
      +  "default": "false",
      +  "type": "boolean"
      +}
  5. First observed

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already declare readOnlyHint and destructiveHint, but the description adds substantial behavioral context: the JXA concurrency lock, performance latency (~20s on slow IMAP), body omission behavior for not-downloaded messages, force_download retry with ~60s wait, and truncation behavior. This goes well beyond annotations and informs the agent about side effects and timing.

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 longer than average (three paragraphs) but every sentence carries operational value—alternatives, performance, caching, and concurrency. It is front-loaded with the core purpose and sibling differentiation. Slightly verbose, but the complexity of the tool justifies the length.

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 (performance, caching, concurrency), the description covers all necessary aspects: when to use, parameter semantics, performance notes, error/fallback behaviors, and explicit alternatives. The output schema handles return value documentation, so no critical information is missing.

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?

While the schema covers all 6 parameters, the description adds crucial semantic value: it explains the performance impact of include_body, the meaning of max_body_chars truncation, the purpose of account/mailbox for skipping scans, and the force_download retry scenario. These details are not in the schema and materially improve correct usage.

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 reads the full content of an email from Apple Mail, identifies the message ID source (list_emails/search_emails), and explicitly distinguishes it from m365_read_email. The verb and resource are specific, and the scope is unambiguous.

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?

It explicitly tells the agent when to use this tool (Apple Mail email) and when to use the alternative (m365_read_email for Microsoft 365). It also provides sequential-call guidance and performance-based recommendations (include_body, max_body_chars). No ambiguity about selection.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources