macos-mail-mcp
Connect Claude to macOS Mail.app through 20 MCP tools for reading, organizing, and composing email.
Inspect accounts with
list_accountsandget_account_detail(server, port, SSL, mailbox count).Manage mailboxes with
list_mailboxes,get_mailbox_info, andcreate_mailboxfor top-level/nested folders; deleting/renaming is unsupported.Read and find mail with
list_messages(pagination/date filters),get_message(optionally across all account mailboxes), andsearch_messagesby subject/sender/content with safeguards and partial-result metadata.Organize messages with
move_message, bulkmove_messages,delete_messageto Trash,flag_messagewith optional color, andmark_read.Handle attachments with
list_attachments,save_attachment,save_all_attachments, andread_attachmentfor supported text files.Compose mail with
send_message(CC/BCC/attachments),reply_to_message(reply/reply-all), andforward_message; optionalfromAccountcontrols sender and results report the actualsender.Works with any account already configured in Mail.app; message IDs are volatile and compose tools confirm queueing, not delivery.
Allows management of emails in Apple's Mail.app on macOS, providing tools for reading, searching, composing, and organizing messages.
Enables interaction with Gmail accounts configured in macOS Mail.app, with tools to read, search, send, and manage emails.
Enables interaction with iCloud Mail accounts configured in macOS Mail.app, with tools to read, search, send, and manage emails.
Click on "Deploy 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., "@macos-mail-mcpShow my unread messages 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.
macos-mail-mcp
An MCP server for Apple Mail (macOS Mail.app) that connects Claude to your email via AppleScript. Provides 20 tools for reading, searching, managing, and composing emails.
Supported Accounts
Works with any email account configured in macOS Mail.app — iCloud, Gmail, Outlook/Exchange, Yahoo, Fastmail, custom IMAP/POP, etc. No code changes needed; just add the account in Mail.app and it becomes available through all 20 tools.
Related MCP server: imail-mcp
Requirements
macOS with Mail.app configured (with at least one email account)
Node.js 22.12+
An MCP client. Claude Code, Claude Desktop and Cowork are the ones set up below; any client that speaks MCP over stdio works.
Installation
Quick Install (npm)
The easiest way — no cloning or building required.
Claude Code and Claude Desktop use separate MCP configs. The
claude mcp addcommand below configures Claude Code only — it writes to~/.claude.json. Claude Desktop and Cowork read a different file (claude_desktop_config.json) and must be configured separately. Set up whichever you use, or both.
Claude Code (CLI):
claude mcp add --transport stdio --scope user macos-mail-mcp -- npx -y macos-mail-mcp@latest--scope user makes the server available in every project — the default local scope only registers it for the directory you run the command in. -y lets npx install the package on first run without an interactive prompt. @latest makes the auto-update behaviour explicit — see Staying up to date.
Claude Desktop (and Cowork):
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"macos-mail-mcp": {
"command": "/absolute/path/to/npx",
"args": ["-y", "macos-mail-mcp@latest"],
"env": { "PATH": "/absolute/path/to/node/bin:/usr/bin:/bin" }
}
}
}Both paths above are placeholders. Use the absolute path to npx — GUI apps don't inherit your shell's PATH, so a bare "npx" usually fails to launch, and the correct path differs per install. Find yours with which npx:
Apple Silicon Homebrew:
/opt/homebrew/bin/npxIntel Homebrew:
/usr/local/bin/npxnvm:
~/.nvm/versions/node/<version>/bin/npx
The env.PATH entry lets npx locate node for the same reason. Then fully quit Claude (Cmd+Q — closing the window isn't enough) and reopen; the config is only read at startup. If the server doesn't appear, check ~/Library/Logs/Claude/mcp*.log for spawn errors.
Staying up to date
Installed copies update themselves. npx re-resolves the published version every time
the server starts, so a new release is picked up without you touching the config.
@latest in the commands above makes that explicit rather than changing it. Why a bare
package name already re-resolves, why @latest is still worth writing, and what it costs are
in CLAUDE.md,
which the package does not ship.
Two consequences worth knowing:
Updates land at server start, not while it is running. A long-running Claude Desktop keeps serving the version it launched with. Quit and reopen it to pick up a release.
The check is a registry round-trip. With the registry unreachable the server fails to start rather than falling back to the cached copy. That is the price of always-current; pinning a version to avoid it gives up the updates.
What each version changed is in the changelog.
Install from Source
For working on the server itself. This path does not auto-update — it runs whatever
npm run build last produced in your working tree, which is exactly what you want while
developing and not what you want otherwise.
git clone https://github.com/marius-cetanas/macos-mail-mcp.git
cd macos-mail-mcp
npm install
npm run buildThen register with Claude Code. Use a distinct name so the local build does not shadow a published copy you may also have registered:
claude mcp add --transport stdio --scope user macos-mail-mcp-dev -- node /path/to/macos-mail-mcp/build/index.jsOr add to Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"macos-mail-mcp-dev": {
"command": "/absolute/path/to/node",
"args": ["/path/to/macos-mail-mcp/build/index.js"]
}
}
}Use the absolute path to node here too (find yours with which node) — same PATH reason as above. Then fully quit and reopen Claude.
macOS Permissions
On first use, macOS will prompt to grant automation permission for controlling Mail.app. Go to System Settings > Privacy & Security > Automation to manage this.
Tools
Accounts (2)
Tool | Description |
| List all mail accounts (name, type, enabled, full name, emails) |
| Get full account details (server, port, SSL, mailbox count) |
Account type is an open string: known IMAP/POP/iCloud/SMTP types use canonical names, and other
raw Mail type text is preserved. Backend-reported unknown remains unknown; the account's name
or email domain is not used to infer Exchange identity.
Breaking account-detail contract: serverName, port and usesSsl can now be null when
unsupported, missing or unavailable. Clients must handle null instead of relying on empty-string,
zero or false defaults. Genuine available values, including SSL false and port 0, are preserved.
Mailboxes (3)
Tool | Description |
| List mailboxes for an account or all accounts |
| Get mailbox details (message count, unread count) |
| Ensure a mailbox exists (top-level or nested), reporting whether it was created or already existed |
For create_mailbox, parentMailboxName can be an existing parent name or full path. The tool
resolves that parent, checks the full slash path within the requested account, and reuses an
existing mailbox or creates an absent one. It returns the full path read back from Mail as
mailboxName, with created: false, alreadyExisted: true for an existing target and
created: true, alreadyExisted: false after creation. Lookup/permission failures return errors.
Omit the parent to address the account directly.
Messages (8)
Tool | Description |
| List messages with pagination (limit/offset) and optional date filtering (after/before) |
| Get full message content, headers, recipients, attachments. Mailbox name is optional — omit to search all mailboxes in the account. |
| Bounded serial search with explicit slow-search opt-in and partial-result metadata; results identify account and full mailbox path |
| Move a message to a different mailbox |
| Bulk move multiple messages to a different mailbox in a single operation |
| Delete a message (moves to Trash) |
| Set/clear flag with optional color index (0-6) |
| Mark message as read or unread |
In get_message results, an absent recipient display name is the empty string in name.
The to/cc/bcc arrays preserve known names, addresses and recipient order.
Every message dateReceived from list/search/get uses UTC ISO 8601 at second precision:
YYYY-MM-DDTHH:mm:ssZ. It identifies an absolute instant for parsing and UTC-aware after/before
inputs; clients can render it in their preferred local timezone. Message-date scripts run in
isolated UTC subprocesses to avoid historical daylight-saving and repeated-clock ambiguity.
Unknown message IDs report plain decimal IDs and the requested account/mailbox, for example
Message 999999999 not found in account "Work", mailbox "INBOX". Account-wide get_message
reports that all mailboxes were searched. Only native missing-object/index errors from the ID
lookup are translated; permission, timeout, mailbox-resolution and later action/property errors
retain their original meaning. Bulk moves preserve per-ID failures and successful move counts.
move_messages validates every ID before looking up mailboxes or moving messages. Its result
reports moved, failed and an errors list containing each failed numeric ID and error text.
Dynamic integer fields use locale-independent decimal digits within JavaScript's safe integer range;
The shared formatter rejects invalid or out-of-range values. Account metadata treats an
unrepresentable port as unavailable and returns port: null.
Search safety and partial results
Breaking search contract: search_messages returns an object instead of an array, and limit
is now capped at 200 (default 50). Subject/sender searches require accountName and mailboxName
by default. A bounded mailbox-info preflight permits at most 1,000 messages; an unavailable or
invalid count requires deliberate allowSlow: true. That opt-in also permits subject/sender
searches across an account or all accounts. mailboxName always requires accountName.
Content searches require both scope names and allowSlow: true. Supply nonblank query text or
an after/before date filter. Date bounds are inclusive.
Search has a 45 second overall server budget, including discovery/preflight, with at most 10 seconds per stage/mailbox. This leaves headroom below the 60 second Cowork client ceiling reported in the original issue. Opting in does not extend these budgets. Mailboxes run serially in discovery order; results retain Mail's order within each mailbox. Duplicate account+message-ID pairs are removed, retaining the first mailbox path; equal IDs in different accounts are distinct.
The response always contains messages, partial, cancelled, limitReached, timedOut,
skipped, errors and warnings. Messages include accountName and the full mailboxName.
timedOut identifies the active scope that exceeded its budget. errors contains operational
failures with scope and message. skipped identifies known scopes not completed/scheduled, with
reason timeout, cancelled, error or limit; discovery failures can leave later scopes unknown.
A scope can have null account/mailbox names for broad discovery. partial means interruption,
an operational failure or skipped scopes. limitReached means the requested cap was reached;
more matches may exist even when partial is false. Invalid requests/count gates are MCP errors;
operational failures return the structured response, preserving earlier results.
The server stops scheduling after the first timeout, cancellation or operational failure. It
honors the MCP request's cancellation signal and terminates its search osascript process. The
SDK suppresses replies after client cancellation, so callers cannot rely on receiving partial
results after cancelling. Queued Apple events inside Mail cannot be cancelled: Mail may keep
working after the process stops. After a timeout, wait for Mail to recover or restart Mail before
retrying; repeated immediate searches can queue more work.
Attachments (4)
Tool | Description |
| List attachments with filename, MIME type, size, download status |
| Save a specific attachment to disk |
| Save all attachments from a message |
| Read UTF-8 attachment text inline using MIME type or a supported text extension |
read_attachment accepts text/* (including text/calendar for .ics), application/json,
application/xml and application/x-yaml, as well as the existing .txt, .csv, .json,
.html, .md, .xml and .log extensions. MIME matching ignores case, surrounding spaces/tabs
and parameters after ;, and requires a valid type/subtype base. If Mail's MIME property is
missing, blank or unavailable, it uses the same filename fallback as list_attachments and
get_message, including .ics → text/calendar. Unsupported-type errors include that effective
MIME type and suggest save_attachment.
Admission uses metadata and filenames; it does not inspect bytes to prove the content is text.
The inline reader supports valid UTF-8, preserves line endings and returns {name, content}.
It does not transcode other charsets, stream content or impose a size cap; use save_attachment
for binary files, other encodings or large attachments.
Both save tools create missing destination directories recursively before contacting Mail.
~ and ~/... expand to the home directory; relative paths resolve from the server's working
directory. Empty/NUL paths, regular-file destinations and failed directory/write/search checks
produce a path-bearing error. Created directories remain if a later Mail operation fails.
The filesystem can change after these checks, and Mail may have different privacy or filesystem
permissions from Node; native save errors still propagate in those cases.
Compose (3)
Tool | Description |
| Send a new email with optional CC, BCC, and attachments |
| Reply or reply-all to a message |
| Forward a message to a new recipient |
All three accept an optional fromAccount to choose which account sends, and report
the account actually used — see Choosing the sending account.
For send_message, attachmentPaths must contain absolute paths to readable regular files;
paths containing CR, LF or NUL are rejected. Every file is checked before composing. The script
checks both the parsed path count and the outgoing content's attachment count against the number
requested before calling send. A mismatch fails without sending; Mail must also return true
from send before the tool reports success. This confirms Mail accepted the send command, not delivery.
Choosing the sending account
By default Mail sends from whichever account is set under Settings → Composing →
"Send new messages from". Pass fromAccount to override it, using either the account
name or any address that account owns (matching is case-insensitive):
{ "to": "client@example.com", "subject": "Invoice", "body": "…",
"fromAccount": "you@work.com" }An unrecognised value is an error listing the accounts you can choose from — it never silently falls back to the default. Only enabled accounts can be selected.
Every compose tool returns the account it actually sent from, whether or not you passed
fromAccount:
{ "success": true, "sender": "Your Name <you@work.com>" }Omitting fromAccount is still the way to accept Mail's own choice; the sender in the
result tells you what that choice was, so a wrong sending account is visible immediately
rather than only discoverable later in the Sent mailbox.
On reply_to_message and forward_message, note that accountName is not a sender
selector — it identifies where the source message lives. Use fromAccount to control
who the reply or forward comes from.
Architecture
Three layers, and the boundary between them is what keeps shell and AppleScript injection out.
Tools (*.tools.ts) validate input with Zod and register with MCP. The bridge
(bridge/applescript-runner.ts) loads a template, substitutes parameters with escaping, prepends
the shared escapeForJson handler and runs osascript, never a shell. Scripts
(*.applescript) are templates with {{param}} placeholders that return JSON. Handlers never
build script text themselves. The source tree and how to add a tool are in
CONTRIBUTING.md,
which the package does not ship either.
Known Limitations
AppleScript Foundation
This MCP communicates with Mail.app via AppleScript, which is a stable but legacy automation layer. Mail.app's scripting dictionary has been largely unchanged for years, but future macOS updates could require script adjustments. This is an inherent trade-off of the approach — AppleScript is the only officially supported way to automate Mail.app without writing a native plugin.
Performance
Large mailbox searches — Mail's
whosequery may scan/load matches before applying the result limit. The search safeguards refuse risky defaults, bound server waiting and retain completed scopes; they cannot cancel Apple events already queued inside Mail. Opted-in searches can still leave Mail busy after the tool stops.IMAP attachment downloads — Attachments on IMAP accounts may not be downloaded locally. The tools check download status and report clearly when an attachment needs to be opened in Mail.app first.
Message IDs
Mail.app's internal message IDs are volatile — they can change when the app reindexes, or after move/delete operations. This means multi-step workflows (e.g., list → flag → move) should re-fetch message IDs between mutations. For single-step operations this is not an issue.
Provider-Specific Behavior
Account connection details — Server getters are used for reported IMAP/POP/iCloud/SMTP types; other types return null connection fields. The Mail dictionary inspected for this change declares pop/smtp/imap/iCloud/unknown, with no Exchange enumerator. If a backend reports Exchange as unknown, that value remains unknown; other raw type strings are preserved. Native Exchange/provider account retrieval has not been exercised by the local fixture tests.
Gmail labels —
move_messageadds the destination label but may not remove the original (Gmail uses labels, not folders).
Other Limitations
Attachments on replies/forwards — AppleScript does not support adding new attachments to reply/forward messages (Mail.app limitation).
MIME type detection — Uses the same extension fallback for list/get/read when Mail.app's native MIME property is missing, blank or unavailable. It does not identify content from file bytes.
Mailbox management — Creating mailboxes is supported, but deleting and renaming mailboxes is not possible via AppleScript (Mail.app limitation).
Known issues
An end-to-end run of every tool against 2.0.0 filed twelve findings, #84 to #95; 2.1.0 changed nothing in the server. The current source inserts reply/forward text and validates readback (#84), and validates multiple attachment paths and prepared attachment counts (#85). File reads now preserve valid UTF-8 text, line endings and trailing newlines (#86), and numeric JSON formatting preserves mixed move results under comma-decimal coercion (#87). Nested mailbox creation uses resolved full paths at the account and validates path readback (#88); existing targets are reused with explicit status metadata (#89). Executable AppleScript helper tests and Mail dictionary compilation cover these changes. Native Mail content insertion, attachment enumeration and delivery still require an end-to-end check. Inline attachment reading now accepts supported MIME types and shared filename fallbacks (#94); native Mail attachment retrieval remains unexercised by fixture tests. Other findings are in the open issues.
Roadmap
get_thread— Retrieve all messages in a conversation thread. Mail.app has no native threading support; implementation would require parsing RFC headers (Message-ID,In-Reply-To,References) which is slow on large mailboxes. Not scheduled: 2.0.0 and 2.1.0 shipped without it.
Development
npm run dev # Watch mode (TypeScript compiler)
npm test # Run tests
npm run test:coverage # Tests + coverage report
npm run test:watch # Watch mode tests
npm run build # Build for productionThe suite covers src/ fully, and vitest.config.ts enforces 100% statement,
branch, function and line thresholds. CI runs test:coverage, so new code
without tests fails the build.
On macOS, tests/domains/compose/send-attachments.applescript.test.ts executes the production
attachment path parser and count/send guards and compiles the complete send template with its
shared handlers. It never creates or sends a Mail message. These executable AppleScript checks
are skipped on other platforms; the template wiring assertions still run there.
tests/bridge/read-utf8-file.applescript.test.ts executes the production body, attachment-path,
attachment-name and inline-content reads against local UTF-8 fixtures, checking JSON roundtrips
for LF, CRLF, CR, trailing newlines, empty files, Unicode, controls and BOMs. It also compiles all
affected templates. These macOS checks do not exercise Mail's attachment saving, content insertion
or delivery; other encodings and binary content are outside the UTF-8 reader's contract.
tests/bridge/integer-for-json.applescript.test.ts executes numeric formatting and partial move
result assembly with large IDs, audits every dynamic integer JSON field, and compiles all domain
templates. Its macOS checks use pure serialization fixtures; native Mail lookups and moves remain
unexercised.
tests/domains/mailboxes/create-mailbox.applescript.test.ts executes production path construction
and readback guards and compiles the complete creation template. It executes the production
existence/status branches and response assembly with fixture Mail primitives, checking existing/new
statuses and lookup/creation errors. Native mailbox creation and provider behavior remain unexercised.
tests/domains/messages/recipient-names.applescript.test.ts executes both production recipient
serializers and message JSON assembly using local recipient records, and compiles both lookup
templates. It does not read native Mail messages.
tests/domains/accounts/account-metadata.applescript.test.ts executes production type mapping and
account JSON with local records/getter fixtures, checks unavailable metadata and supported values,
and compiles both account templates. It does not query native accounts. SMTP server settings are
declared by Mail's dictionary; this does not establish that SMTP servers appear in account queries.
Search controller tests use fake clocks/bridge calls to exercise budgets, count gates, partial results and SDK cancellation. Bridge tests verify abort checks, search-process SIGKILL options and temp cleanup; the search template's pure guards execute and its complete script compiles. These checks do not run native Mail searches or demonstrate cancellation of queued Apple events.
tests/bridge/date-to-utc-iso.applescript.test.ts executes production date formatting with actual
AppleScript dates at known instants, including historical DST, both fall-back occurrences,
negative/zero epochs, offsets and year boundaries in English/Romanian process locales. It checks
getter/JSON and filter reconstruction; registered/caller tests verify selective UTC environments
and timestamp/error propagation. All shared script contexts compile. Native Mail date reads and
provider behavior remain unexercised; host, Node and Mail timezone settings are unchanged.
tests/domains/messages/attachment-mime.applescript.test.ts executes the production MIME helpers,
all three metadata loops and the inline-read flow with local lookup/save fixtures. It checks MIME
case/parameters/fallbacks, every existing extension mapping, admission before saving, UTF-8/JSON
readback, errors and temp cleanup. All shared template contexts compile, and registered-tool tests
cover result/error propagation. These checks do not read or save native Mail attachments.
tests/bridge/resolve-message.applescript.test.ts executes production lookup/error boundaries,
account-wide search and partial bulk-move flows with replaced Mail transport, and audits all
13 lookup sites. tests/domains/messages/save-directory.test.ts prepares real local directories
and executes the save-path initialization/JSON expressions with special-character paths.
Registered-tool tests cover path and message errors; all shared contexts compile. These checks
do not perform native Mail lookups, moves or attachment saves, and do not prove Mail permissions.
Changelog
Every version's changes are in CHANGELOG.md. It ships inside the npm package, so
an installed copy carries its own version's entries alongside its package.json; and each
GitHub release from 2.1.0 on opens its notes with that version's section, the commit list folded
beneath — when the section was recorded before the tag, which is the procedure here; a version
recorded late, as 1.3.1 was, gets the commit list alone. The 2.0.0 major changed only the Node.js
floor — the server itself was unchanged — which is the kind of fact this file exists to say, and
the reason it now ships (#96).
License
MIT
Available Tools
20 toolscreate_mailboxA
Ensure a mailbox (folder) exists in a Mail.app account. For nesting, resolve the parent and use its full slash path at the account. Returns the full path read back from Mail and explicit created/alreadyExisted booleans; an existing mailbox is reused.
| Name | Required | Description | Default |
|---|---|---|---|
| accountName | Yes | The name of the account to create the mailbox in | |
| mailboxName | Yes | The child name to create, or a full slash path when parentMailboxName is omitted | |
| parentMailboxName | No | An existing parent mailbox name or full path for nesting; omit to create directly at the account |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does well on the important traits: it is a mutation that is safe to repeat because an existing mailbox is reused, and it discloses the exact return contract (full path read back from Mail, plus created/alreadyExisted booleans). It omits prerequisites such as Mail.app permissions, account existence, and failure behavior when the parent path is invalid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with purpose then nesting then return contract, with no filler. The phrase 'use its full slash path at the account' is slightly compressed and could be read as ambiguous, which is the only structural blemish.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description appropriately spells out the return values, and it covers the idempotency semantics an agent needs. What remains thin for an unannotated mutation tool is environmental context: permission requirements and error conditions for a non-existent account or parent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3; the description adds beyond the schema by framing the nesting convention (resolve the parent, pass its full slash path at the account) and by implying mailboxName is interpreted as a full path when the parent is omitted. It does not clarify path separator edge cases or whether the account name must match an entry from list_accounts.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a precise verb+resource: ensure a mailbox (folder) exists in a Mail.app account. The word 'ensure' immediately signals idempotent creation, which is a meaningful distinction from a plain create and cannot be inferred from the name alone.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives real operative guidance: for nesting, resolve the parent and pass its full slash path, and it notes that an existing mailbox is reused rather than failing. It does not explicitly point to siblings such as list_mailboxes or get_mailbox_info as the way to resolve or verify a mailbox, leaving that inference to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_messageA
Delete a message. Uses Mail's delete verb which routes to the correct Trash.
| Name | Required | Description | Default |
|---|---|---|---|
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the behavioral burden. It adds a useful transparency detail: deleting uses Mail's delete verb and routes to the correct Trash rather than permanently erasing the message. However, it does not mention return behavior, reversibility beyond the Trash implication, or permission/side-effect considerations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two short sentences with no filler. The primary action is front-loaded, and the second sentence adds a meaningful behavioral clarification about Trash routing. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has only three required parameters, all schema-documented, and the description explains the operational routing to Trash. However, it still has gaps: there is no output schema, no indication of what the response looks like, and no guidance on success/failure conditions. This is adequate but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage for all three required parameters, so the schema already documents messageId, accountName, and mailboxName clearly. The description adds no parameter-level meaning beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a direct, specific action: 'Delete a message.' The operation is unambiguous and distinct from the sibling tools, since no other sibling provides deletion and the closest operations (move_message, flag_message) are clearly different.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool should be used when a message must be deleted, but it does not explicitly discuss alternatives such as move_message, whether deletion is preferable to moving, or when not to use this tool. Usage context is inferable rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
flag_messageB
Set or clear the flag on a message. Optionally specify a flag colour index.
| Name | Required | Description | Default |
|---|---|---|---|
| flagged | Yes | Whether to flag (true) or unflag (false) the message | |
| flagIndex | No | The flag colour index (optional, default -1) | |
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden of behavioral disclosure. It only states the basic set/clear action and optional colour index; it does not explain side effects, whether the operation requires an existing message, whether it is idempotent, or what the response contains.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short and front-loaded: it states the core purpose in the first sentence and adds the optional modifier in a single second sentence. There is no redundant or distracting content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple flagging operation, the basic action and parameter schema are present, and all parameters are individually documented. However, with no annotations and no output schema, the description does not fully communicate behavioral outcomes or the relationship between flagged and flagIndex, leaving the agent to guess some edge-case behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all parameters. The description only mirrors the optional flagIndex concept and does not add materially to the parameter semantics provided by the input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Set or clear the flag') and the resource ('on a message'), and adds the optional flag colour dimension. It is not tautological, though it does not explicitly differentiate itself from sibling tools like mark_read.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, and does not mention exclusions or related sibling tools. An agent would have to infer the intended context purely from the wording of the schema and sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
forward_messageA
Forward an existing email message to a new recipient. Returns the sender the forward was sent from. Does not support adding new attachments (Mail.app limitation).
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | The recipient email address to forward to | |
| body | No | Optional text to prepend to the forwarded message body | |
| messageId | Yes | The numeric ID of the message to forward | |
| accountName | Yes | The name of the account containing the mailbox. This locates the source message only — it does not control which account sends. Use fromAccount for that. | |
| fromAccount | No | Account to send from — a Mail account name ("Google") or one of its addresses ("you@gmail.com"), as reported by list_accounts. Matching is case-insensitive and an unrecognised value is an error, never a silent fallback. Omit to use Mail's default sending account; either way the account used is returned as `sender`. | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden, and it does meaningful work: it discloses that the tool returns the sender account, and it flags an important behavioral limitation (no new attachments due to Mail.app). It could add more about side effects or failure modes, but the core behavior is transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise sentences. The main action is front-loaded, the return value is specified, and the limitation is stated directly with no unnecessary filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the schema already covers all parameter semantics, the description is nearly complete: it explains the action, the return value, and the attachment limitation. The only missing piece is explicit routing guidance among the related sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All parameters have complete descriptions in the schema, so the description does not need to compensate. It adds useful behavioral context around the sender and attachment limitation, but it does not provide additional parameter-specific details beyond what the schema already contains.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: forward an existing email message to a new recipient. This clearly distinguishes it from siblings like send_message and reply_to_message because it explicitly describes forwarding an existing message rather than composing a new one or replying to the original sender.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage is implied by the purpose: use this when a user wants to forward an existing message to a new recipient. However, the description does not explicitly mention when not to use it or name alternatives like send_message for new emails or reply_to_message for replying to the sender.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_account_detailB
Get detailed information about a specific Mail.app account by name. Unavailable serverName, port and usesSsl values are null; account type preserves raw Mail values beyond known canonical types.
| Name | Required | Description | Default |
|---|---|---|---|
| accountName | Yes | The name of the account to retrieve |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, and "Get" implies a non-destructive read but never says so. It does add genuine behavioral context about the return values — unavailable serverName, port, and usesSsl come back as null, and account type preserves raw Mail values beyond canonical types — yet says nothing about behavior when the account name is unknown or about permissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the purpose and followed by return-value caveats; no filler. The second sentence is somewhat dense with field names, but every clause conveys information the agent would otherwise have to guess.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema, the description covers purpose, the lookup key, and the noteworthy null/raw-type quirks of the response. The missing piece is failure behavior for an unknown account name, which would matter for correct usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the single accountName parameter is already documented in the schema. The description only restates that lookup is by name, adding no format, casing, or resolution rules for the name. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Get detailed information about a specific Mail.app account by name" gives a clear verb plus resource and the lookup key, which separates it from list_accounts at a glance. It does not explicitly name the sibling, but the singular-account 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit statement of when to use this versus list_accounts, nor any prerequisite about where the account name must come from. The only implied guidance is "by name," leaving the agent to infer that list_accounts must be called first to discover valid names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_mailbox_infoB
Get detailed information about a specific mailbox in a Mail.app account
| Name | Required | Description | Default |
|---|---|---|---|
| accountName | Yes | The name of the account that contains the mailbox | |
| mailboxName | Yes | The name of the mailbox to retrieve |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must carry the full burden of behavioral disclosure. It indicates a read operation but does not describe what 'detailed information' contains, what happens if the mailbox does not exist, whether authentication requires to be ready, or that the operation is safe to call idempotently.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no filler or repetition. It front-loads the primary action ('Get detailed information') and scopes it to a specific mailbox. It earns a 5; it just lacks a bit of detail that would make it fully informative.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Although the parameter schema is clear, the description lacks any indication of what the 'detailed information' will contain, and there is no output schema to infer from. It also doesn't clarify why an agent would actually use this tool in the workflow vs list_mailboxes to get names. For a tool expected to return meaningful content, this is a notable gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema covers 100% of the two parameters with clear descriptions ('The name of the account that contains the mailbox', 'The name of the mailbox to retrieve'). The description adds no new semantics beyond the schema, but the schema is complete, so this meets the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states a specific verb (Get) and a resource ('detailed information about a specific mailbox'), scoped to 'a Mail.app account.' It distinguishes from list_mailboxes implicitly by targeting one mailbox rather than enumerating them, but it never names a sibling tool or explicitly calls out what differentiates it from get_account_detail.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The word 'specific' implies a use case where the agent already knows which mailbox to query, as opposed to listing mailboxes. However, the description provides no explicit direction on when to use this tool versus list_mailboxes or get_account_detail, and there are no stated exclusions or prerelems.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_messageA
Get the full details of a single message by its ID, including body, headers, recipients, and attachments. If mailboxName is omitted, searches all mailboxes in the account (slower but useful when you don't know which mailbox the message is in).
| Name | Required | Description | Default |
|---|---|---|---|
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the message | |
| mailboxName | No | The name of the mailbox containing the message (omit to search all mailboxes in the account) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description takes the full burden. It discloses that omitting mailboxName searches all mailboxes and notes the performance cost, which is useful. It does not explicitly discuss error handling, output structure beyond high-level fields, or confirm the absence of side effects, but the read-only nature is strongly implied by the operation name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is only two sentences, front-loads the core operation, and spends one efficient sentence on the optional parameter. No redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a fairly simple read-only-style tool, the description is reasonably complete: it explains the primary call, the optional override, and the kind of result returned. It lacks details on error behavior or exact output structure, but it gives enough for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already explains every parameter. The description adds slight extra context about mailboxName being slower when omitted, but most parameter meaning is already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the operation as retrieving a single message by ID and names its major components (body, headers, recipients, attachments). This distinguishes it from tools like list_messages or search_messages, since the focus is on one message's full details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context for when the optional mailboxName parameter is useful and why omitting it is slower. It does not explicitly name sibling tools as alternatives, but the usage guidance is contextually sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsA
List all Mail.app accounts with their type, enabled status, and email addresses. Known types are canonicalized; other raw Mail type text is preserved, including backend-reported unknown.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the behavioral burden, and it discloses non-obvious normalization semantics: known types are canonicalized while raw Mail type text is preserved, including backend-reported unknown values. It does not describe ordering, pagination, or permission requirements, but for a simple read-only listing this is solid disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler. The primary capability is front-loaded, and the second sentence adds a genuinely useful caveat about type canonicalization rather than restating the first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter listing tool with no output schema, the description sufficiently explains what is returned and how account types are represented. It is slightly incomplete in not mentioning ordering or whether disabled accounts are included, but nothing critical to correct invocation is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there are no parameter semantics to explain; the baseline for a parameterless tool is 4. The description correctly avoids inventing filtering options that do not exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List all Mail.app accounts') and enumerates the returned fields (type, enabled status, email addresses). It is clearly distinguishable from the sibling get_account_detail, which implies a single-account lookup.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: 'List all' signals enumeration versus a detail lookup, but the description never explicitly says when to prefer this over get_account_detail or list_mailboxes. An agent can infer the distinction from sibling names, but no routing guidance is given.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_attachmentsA
List all attachments for a message, including their name, MIME type, file size, and download status.
| Name | Required | Description | Default |
|---|---|---|---|
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral transparency burden. It conveys that this is a listing operation and that download status is returned, but it does not explicitly state whether it is read-only or whether any state is changed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One concise sentence that starts with the verb, identifies the resource, and lists the important return fields. There is no redundant or unnecessary content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is sufficient for a straightforward listing tool with fully documented parameters. It states what is listed and which fields are returned; the main gaps are the lack of an explicit read-only statement and detailed output format, but these are minor for this kind of tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for all three parameters, so the schema already explains messageId, mailboxName, and accountName. The description adds no parameter-level meaning, so the baseline score is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List all attachments for a message', and enumerates the output fields. It clearly differs from read/save-related siblings by being a listing operation, but it does not explicitly compare against sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied: an agent would call this when it needs attachment metadata for a message before reading or saving attachments. However, there is no explicit when-to-use/when-not-to-use guidance, and alternatives such as get_message or read_attachment are not mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_mailboxesA
List mailboxes in a Mail.app account, or all mailboxes across all accounts
| Name | Required | Description | Default |
|---|---|---|---|
| accountName | No | The name of the account to list mailboxes for; omit for all accounts |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the disclosure burden. 'List' conveys a read-only action and the description clarifies the two account scopes, but it does not mention authentication requirements, how empty or invalid accountName are handled, or the exact set of mailbox properties returned. It is adequate for a simple read-only utility but leaves some behavior unspecified.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with no unnecessary words. It presents the main verb and resource first, then the alternative scopes. Every part adds meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter, no-nested, no-output-schema tool, the description is complete. It tells the agent what the tool does and exactly how the one optional parameter affects behavior.",
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: accountName is already described as the account to list mailboxes for, or omitted for all accounts. The tool description mostly restates this same guidance, so it adds little beyond the schema. Baseline 3 applies because the schema already documents the only parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool lists mailboxes and defines its two valid scopes: a single Mail.app account or all accounts. The verb-resource pairing is unambiguous and distinguishes it from sibling tools like list_accounts (accounts vs mailboxes) and get_mailbox_info (single mailbox details).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool by defining the scope, and it explicitly says to omit accountName for all accounts. However, it gives no direct guidance about when to prefer this tool over alternatives such as list_accounts or get_mailbox_info, so usage context is mostly self-evident rather than spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_messagesB
List messages in a mailbox with pagination. Provide accountName and mailboxName to scope the listing.
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | Only return messages received after this ISO 8601 date (e.g. 2024-01-15T00:00:00Z) | |
| limit | No | Maximum number of messages to return (default 25) | |
| before | No | Only return messages received before this ISO 8601 date (e.g. 2024-12-31T23:59:59Z) | |
| offset | No | Number of messages to skip for pagination (default 0) | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox to list messages from |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
There are no annotations, so the description carries the full burden of behavioral disclosure. It communicates that listing is a read operation with pagination, but it does not mention ordering, inclusivity of before/after filters, the shape of the returned results, or any indirect behaviors. This is a meaningful gap for a tool with no annotation support.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is only two sentences, front-loads the primary action and pagination behavior, and includes no fluff or redundancy. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the schema fully describes all parameters and the tool is a straightforward listing operation, the description is mostly adequate. It could be improved by noting the intended pagination flow or expected message chronology, but it is not severely incomplete for an agent to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already covers all six parameters with 100% description coverage, including defaults and date formats. The description adds minimal semantic value beyond reaffirming that accountName and mailboxName scope the request, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource ('List messages in a mailbox') and adds the pagination aspect, making the core purpose clear. It does not explicitly distinguish this from sibling tools like search_messages or get_message, so it does not fully earn a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description tells the agent to provide accountName and mailboxName, which clarifies the required scope for the operation. However, it gives no guidance on when to choose this tool over related alternatives such as search_messages or get_message.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mark_readB
Mark a message as read or unread.
| Name | Required | Description | Default |
|---|---|---|---|
| read | Yes | Whether to mark the message as read (true) or unread (false) | |
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden. It states the state change but omits any side effects, return behavior, permissions, or error handling. It does clarify that both read and unread states are supported.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence with no filler. It front-loads the core action and the full range of intended behavior (read or unread) efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple, well-parameterized tool with fully documented schemas, but the description lacks behavioral context and usage guidance. It is minimally viable but leaves gaps around side effects and selection among siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, and all four parameters already have clear meanings. The description adds no additional parameter context, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: marking a message as read or unread. It is specific enough to identify the operation, though it does not explicitly contrast with similar siblings like flag_message.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives such as flag_message or get_message. The context is implied only by the tool name and action.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_messageA
Move a message to a different mailbox. Gmail uses labels rather than folders. Moving a message adds the destination label but may not remove the original.
| Name | Required | Description | Default |
|---|---|---|---|
| messageId | Yes | The numeric ID of the message | |
| toMailbox | Yes | The name of the destination mailbox | |
| accountName | Yes | The name of the account containing the mailboxes | |
| mailboxName | Yes | The name of the mailbox currently containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full behavioral disclosure burden. It does this well by revealing the non-obvious consequence: moving a message adds the destination label but may not remove the original label. It does not, however, describe return values or any side effects beyond the label behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences express the operation and its most important caveat without any filler. The main action is front-loaded, and the Gmail label explanation is kept to exactly what the agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple mutating tool with no output schema and no annotations, so the description must carry most of the contextual load. It covers the critical label behavior, but it could additionally mention what the result looks like or when the original label is removed. Still, the core decision-relevant context is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already provides descriptions for all 4 parameters, giving 100% schema coverage, so the baseline is 3. The description adds a little semantic context by explaining what 'moving' means in terms of destination label vs original label, but it does not detail each parameter's meaning beyond what the schema supplies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb+resource structure ('Move a message to a different mailbox') and immediately clarifies the Gmail label model, which distinguishes this tool from folder-based move operations. It singles out a single message action, which differentiates it from sibling move_messages.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The context implies this tool is for moving a single message, and the Gmail label caveat gives important situational guidance. However, it does not explicitly say when to use move_message versus move_messages or any other sibling, so the usage guidance is mostly inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_messagesA
Move multiple messages to a different mailbox in a single operation. More efficient than calling move_message multiple times.
| Name | Required | Description | Default |
|---|---|---|---|
| toMailbox | Yes | The name of the destination mailbox | |
| messageIds | Yes | Array of numeric message IDs to move | |
| accountName | Yes | The name of the account containing the mailboxes | |
| mailboxName | Yes | The name of the mailbox currently containing the messages |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure, but it only states the high-level action and an efficiency claim. It does not explain whether the operation removes messages from the source mailbox, what happens if some messageIds are invalid, whether the operation is atomic beyond 'single operation,' or any permission/authorization requirements. This is a meaningful gap for a batch mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact sentences with no filler. The core action is front-loaded, and the second sentence adds practical guidance about efficiency versus the sibling tool. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has a relatively straightforward batch-move operation with all required parameters documented in the schema, but there is no annotations or output schema. The description omits important execution context such as error handling, source-mailbox behavior after the move, or whether the operation is atomic despite the 'single operation' phrase. It is adequate for basic invocation but not fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already describes all four required parameters with 100% coverage. The description reinforces the notion of multiple messages and 'a different mailbox,' but it does not materially expand on parameter semantics or constraints beyond what the schema provides. The baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource—'Move multiple messages to a different mailbox'—and clearly differentiates this batch operation from the alternative move_message by describing it as a single operation and more efficient than calling move_message multiple times. The purpose is immediately unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly sets the context: moving multiple messages at once and doing so more efficiently than repeatedly calling move_message. It does not explicitly spell out when not to use the tool, such as 'for a single message use move_message,', but the efficiency comparison makes the intended use case reasonably apparent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_attachmentA
Read valid UTF-8 attachment text inline. Accepts text/*, application/json, application/xml, application/x-yaml MIME types or .txt, .csv, .json, .html, .md, .xml, .log extensions. Uses extension-based MIME fallback when unavailable. Use save_attachment for binary files.
| Name | Required | Description | Default |
|---|---|---|---|
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message | |
| attachmentName | Yes | The name of the attachment to read |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full disclosure burden. It does useful work — declaring UTF-8-only decoding, the accepted MIME/extension set, and extension-based MIME fallback — but says nothing about what happens when the type is unsupported, whether content is truncated or size-limited, or what the response looks like (no output schema exists).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with zero filler: capability first, accepted inputs second, alternative tool last. The routing hint is placed where an agent scanning for alternatives will find it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with full schema coverage and no output schema, the description covers the essential decision inputs: what qualifies as readable and where to go otherwise. The remaining gap is error/edge-case behavior for unsupported attachments, which is minor but not trivial given there is no output schema to explain returns.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with all four required parameters individually documented (messageId, accountName, mailboxName, attachmentName). The description adds no parameter-level meaning such as whether attachmentName is a path, display name, or identifier, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Read ... attachment text inline') plus the content constraints (valid UTF-8) that define the operation. It also explicitly names the sibling it is not ('Use save_attachment for binary files'), so an agent can separate the two without inspecting schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear routing rule: text MIME types and listed extensions go here, binary files go to save_attachment. It enumerates exactly which inputs qualify, but does not say what to do with attachments that fall in neither bucket (e.g., an unlisted text-like extension) or how to discover attachments in the first place.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reply_to_messageA
Reply to an existing email message. Returns the sender the reply was sent from. Does not support attachments (Mail.app limitation).
| Name | Required | Description | Default |
|---|---|---|---|
| body | Yes | The reply body text | |
| replyAll | Yes | Whether to reply to all recipients (true) or just the sender (false) | |
| messageId | Yes | The numeric ID of the message to reply to | |
| accountName | Yes | The name of the account containing the mailbox. This locates the source message only — it does not control which account sends. Use fromAccount for that. | |
| fromAccount | No | Account to send from — a Mail account name ("Google") or one of its addresses ("you@gmail.com"), as reported by list_accounts. Matching is case-insensitive and an unrecognised value is an error, never a silent fallback. Omit to use Mail's default sending account; either way the account used is returned as `sender`. | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden of behavior disclosure. It does disclose the returned value ('sender') and the unsupported attachment behavior, but it does not explicitly state that this sends a message as a side effect or describe the reply content/thread behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two compact sentences with high information density: the core action, the key return value, and the attachment limitation. There is no filler or redundant restating of the tool name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The schema already covers all six parameters, and the description adds the most decision-relevant behavioral facts. It stops just short of fully complete because it does not outline the full return structure or emphasize the potentially irreversible sending side effect, and there is no output schema to fill that gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already well documented in the input schema. The description adds no additional parameter-level semantics, so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Reply to an existing email message.' It clearly distinguishes the tool from sending a new message or forwarding by the word 'Reply' and by referencing an existing message, though it does not name sibling tools explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than explicit: it is for replying to an existing email. It also calls out a meaningful limitation, 'Does not support attachments (Mail.app limitation),' but does not explicitly say when to choose send_message or forward_message instead.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_all_attachmentsB
Save all downloaded attachments from a message to disk. Creates the destination directory recursively before contacting Mail.
| Name | Required | Description | Default |
|---|---|---|---|
| savePath | No | The directory path to save the attachments to (default ~/Downloads) | ~/Downloads |
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are supplied, so the description carries the full burden. It usefully discloses that the destination directory is created recursively and that this happens before contacting Mail, but it says nothing about overwrite behavior for files that already exist, what happens when a message has no attachments, or permission/error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and free of filler. The ordering detail ('before contacting Mail') is slightly niche but does convey real behavior about partial failure, so it earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
It states the core action, the destination handling, and the mutation footprint for a 4-parameter tool with full schema coverage. The gaps are return values (output schema absent) and overwrite/duplicate handling, which would round out a write tool with no annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the schema already documents savePath with its default. The 'creates the destination directory recursively' clause adds real meaning by telling the agent that savePath need not already exist, but that is the only genuine addition beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb and resource: 'Save all downloaded attachments from a message to disk.' The word 'all' implicitly separates it from the singular save_attachment sibling, but it never names that alternative explicitly, so an agent must infer the distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance at all. With siblings list_attachments, save_attachment, and read_attachment in the lineup, the definition should say when bulk-saving beats enumerating or saving one attachment, and it does not.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_attachmentA
Save a specific attachment from a message to disk. Creates the destination directory recursively before contacting Mail.
| Name | Required | Description | Default |
|---|---|---|---|
| savePath | No | The directory path to save the attachment to (default ~/Downloads) | ~/Downloads |
| messageId | Yes | The numeric ID of the message | |
| accountName | Yes | The name of the account containing the mailbox | |
| mailboxName | Yes | The name of the mailbox containing the message | |
| attachmentName | Yes | The name of the attachment to save |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it does disclose a real side effect plus ordering: the destination directory is created recursively before Mail is contacted, meaning a filesystem write can occur even if the mail operation fails. It omits equally important behavior for a disk-write tool: whether an existing file of the same name is overwritten, and what the tool returns (e.g., the resolved path).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, both front-loaded: the action first, then the side-effect ordering. Nothing is padded or repeated from the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a five-parameter tool with full schema coverage, no output schema, and no annotations, the description supplies the one non-obvious behavioral fact (recursive directory creation before the Mail call). Remaining gaps around overwrite behavior are secondary for an agent that just needs to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all five parameters, including the savePath default of ~/Downloads, are already documented in the schema. The description adds no new meaning about path semantics, filename collisions, or how attachmentName is matched, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Save a specific attachment from a message to disk" gives a concrete verb (save), a concrete resource (attachment), and a destination (disk). The word "specific" implicitly separates it from the sibling save_all_attachments, but that sibling is never named, so the differentiation is inferential rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: the agent can infer this tool is for one attachment while save_all_attachments handles bulk, but no sentence says when to pick one over the other. There is also no guidance on prerequisites, such as whether the attachment must first be listed via list_attachments.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_messagesA
Search one mailbox safely by default. Broad, content or large-mailbox searches require explicit allowSlow. Returns an object with messages and partial/timeout/skipped/error metadata within a 45 second server budget. Mail's queued Apple events can outlive process cancellation; wait or restart Mail after a timeout.
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | Include messages received on/after this ISO date | |
| field | Yes | Field to search; content requires allowSlow and a single account/mailbox | |
| limit | No | Maximum unique results, 1–200 (default 50) | |
| query | No | Search text; may be empty when after or before is supplied | |
| before | No | Include messages received on/before this ISO date | |
| allowSlow | No | Explicitly permit broad searches, content searches or mailboxes over 1,000 messages; queued Mail work may outlive cancellation | |
| accountName | No | Mail account; default searches require both account and mailbox | |
| mailboxName | No | Mailbox name or full path; requires accountName |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full load and does so well: it discloses a 45-second server budget, partial/timeout/skipped/error metadata in the response, and the non-obvious side effect that queued Apple events can outlive process cancellation, including remediation ('wait or restart Mail'). These are exactly the behaviors an agent could not infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences lead with the default-safe scope before the cost/constraint, which is the right front-loading. Some phrasing is compressed to the point of being cryptic ('Broad, content or large-mailbox searches'), but nothing is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an eight-parameter, no-output-schema tool, the description covers the return envelope shape, the timeout budget, and the cancellation caveat, so an agent has enough to call it and interpret failure. It stops short of defining what counts as 'broad' (left to the schema's 1,000-message note) or describing result ordering.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so all eight parameters are already documented, including the field enum and the allowSlow constraint. The description restates only the content-search constraint already present in the field and allowSlow schema entries, adding no new semantics; baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Search one mailbox') and immediately scopes it to single-mailbox, default-safe operation, which separates it from a broad content sweep. It never names list_messages or get_message explicitly, so sibling differentiation is implied rather than stated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives a clear rule for when the slow path applies: broad, content, or large-mailbox searches 'require explicit allowSlow'. That is genuine when/when-not guidance, though no alternative tool is named for the cases where this one is the wrong choice.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_messageA
Compose and send a new email message as plain text. Returns success when the message is queued for sending, along with the sender the message was sent from; actual delivery is not confirmed. Check Mail's Sent or Outbox mailbox to verify delivery.
| Name | Required | Description | Default |
|---|---|---|---|
| cc | No | CC recipient email address (optional) | |
| to | Yes | The recipient email address | |
| bcc | No | BCC recipient email address (optional) | |
| body | Yes | The plain text body of the email | |
| subject | Yes | The subject of the email | |
| fromAccount | No | Account to send from — a Mail account name ("Google") or one of its addresses ("you@gmail.com"), as reported by list_accounts. Matching is case-insensitive and an unrecognised value is an error, never a silent fallback. Omit to use Mail's default sending account; either way the account used is returned as `sender`. | |
| attachmentPaths | No | Absolute paths to readable regular files to attach. CR, LF and NUL in paths are unsupported; invalid files fail before composing (optional). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations supplied, the description carries the full burden and does real work: it discloses that success means 'queued for sending', that 'actual delivery is not confirmed', and how to verify via Sent or Outbox. It stops short of stating that sending is irreversible/unrecallable or what authorization the account needs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the action, then the return contract, then the verification step. No filler and no repetition of the name or schema fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter mutation tool with no output schema and no annotations, the description covers the essential gaps: what a success response contains (`sender`) and that delivery is unconfirmed. Attachment and account-selection behavior is left entirely to the schema, but overall an agent has enough to call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so recipient, subject, body, cc, bcc, fromAccount and attachmentPaths are already well documented in the schema, including the fromAccount fallback and error behavior. The description only adds the plain-text constraint on the body, which is a marginal addition over structured data.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb+resource pair ('Compose and send a new email message') and adds a format constraint ('as plain text'). It does not distinguish itself from siblings like reply_to_message or forward_message, which also send mail, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the description of composing a new message; there is no explicit guidance on when to use this instead of reply_to_message or forward_message, which are direct alternatives in the sibling list. The only routing hint is about verification (check Sent/Outbox), not about tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
3 tool updates
v3.0.0- Changed
create_mailbox2 fields changed- changed
Input schema / properties / mailboxName / descriptionPrevious value: -"The name of the new mailbox to create"New value: +"The child name to create, or a full slash path when parentMailboxName is omitted" - changed
Input schema / properties / parentMailboxName / descriptionPrevious value: -"The name of the parent mailbox for nesting; omit for top-level"New value: +"An existing parent mailbox name or full path for nesting; omit to create directly at the account"
- Changed
search_messages11 fields changed- changed
Input schema / properties / accountName / descriptionPrevious value: -"Limit search to a specific account (omit to search all accounts)"New value: +"Mail account; default searches require both account and mailbox" - changed
Input schema / properties / after / descriptionPrevious value: -"Only return messages received after this ISO 8601 date (e.g. 2024-01-15T00:00:00Z)"New value: +"Include messages received on/after this ISO date" - added
Input schema / properties / allowSlowAdded value: +{ + "default": false, + "description": "Explicitly permit broad searches, content searches or mailboxes over 1,000 messages; queued Mail work may outlive cancellation", + "type": "boolean" +} - changed
Input schema / properties / before / descriptionPrevious value: -"Only return messages received before this ISO 8601 date (e.g. 2024-12-31T23:59:59Z)"New value: +"Include messages received on/before this ISO date" - changed
Input schema / properties / field / descriptionPrevious value: -"The field to search in"New value: +"Field to search; content requires allowSlow and a single account/mailbox" - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum number of results to return (default 50)"New value: +"Maximum unique results, 1–200 (default 50)" - removed
Input schema / properties / limit / exclusiveMinimumRemoved value: -0 - changed
Input schema / properties / limit / maximumPrevious value: -9007199254740991New value: +200 - added
Input schema / properties / limit / minimumAdded value: +1 - changed
Input schema / properties / mailboxName / descriptionPrevious value: -"Limit search to a specific mailbox (omit to search all mailboxes)"New value: +"Mailbox name or full path; requires accountName" - changed
Input schema / properties / query / descriptionPrevious value: -"The search query string (optional when using date filters)"New value: +"Search text; may be empty when after or before is supplied"
- Changed
send_message1 field changed- changed
Input schema / properties / attachmentPaths / descriptionPrevious value: -"List of absolute file paths to attach (optional)"New value: +"Absolute paths to readable regular files to attach. CR, LF and NUL in paths are unsupported; invalid files fail before composing (optional)."
19 tool updates
v1.3.2- Changed
create_mailbox1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
delete_message3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
flag_message5 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / flagIndex / maximumAdded value: +9007199254740991 - added
Input schema / properties / flagIndex / minimumAdded value: +-9007199254740991 - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
forward_message5 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - changed
Input schema / properties / accountName / descriptionPrevious value: -"The name of the account containing the mailbox"New value: +"The name of the account containing the mailbox. This locates the source message only — it does not control which account sends. Use fromAccount for that." - added
Input schema / properties / fromAccountAdded value: +{ + "description": "Account to send from — a Mail account name (\"Google\") or one of its addresses (\"you@gmail.com\"), as reported by list_accounts. Matching is case-insensitive and an unrecognised value is an error, never a silent fallback. Omit to use Mail's default sending account; either way the account used is returned as `sender`.", + "type": "string" +} - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
get_account_detail1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_mailbox_info1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
get_message3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
list_attachments3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
list_mailboxes1 field changed- removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
list_messages3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / limit / maximumAdded value: +9007199254740991 - added
Input schema / properties / offset / maximumAdded value: +9007199254740991
- Changed
mark_read3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
move_message3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
move_messages3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageIds / items / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageIds / items / minimumAdded value: +-9007199254740991
- Changed
read_attachment3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
reply_to_message5 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - changed
Input schema / properties / accountName / descriptionPrevious value: -"The name of the account containing the mailbox"New value: +"The name of the account containing the mailbox. This locates the source message only — it does not control which account sends. Use fromAccount for that." - added
Input schema / properties / fromAccountAdded value: +{ + "description": "Account to send from — a Mail account name (\"Google\") or one of its addresses (\"you@gmail.com\"), as reported by list_accounts. Matching is case-insensitive and an unrecognised value is an error, never a silent fallback. Omit to use Mail's default sending account; either way the account used is returned as `sender`.", + "type": "string" +} - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
save_all_attachments3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
save_attachment3 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / messageId / maximumAdded value: +9007199254740991 - added
Input schema / properties / messageId / minimumAdded value: +-9007199254740991
- Changed
search_messages2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / limit / maximumAdded value: +9007199254740991
- Changed
send_message2 fields changed- removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / fromAccountAdded value: +{ + "description": "Account to send from — a Mail account name (\"Google\") or one of its addresses (\"you@gmail.com\"), as reported by list_accounts. Matching is case-insensitive and an unrecognised value is an error, never a silent fallback. Omit to use Mail's default sending account; either way the account used is returned as `sender`.", + "type": "string" +}
20 tool updates
v1.2.0- First observed
create_mailbox - First observed
delete_message - First observed
flag_message - First observed
forward_message - First observed
get_account_detail - First observed
get_mailbox_info - First observed
get_message - First observed
list_accounts - First observed
list_attachments - First observed
list_mailboxes - First observed
list_messages - First observed
mark_read - First observed
move_message - First observed
move_messages - First observed
read_attachment - First observed
reply_to_message - First observed
save_all_attachments - First observed
save_attachment - First observed
search_messages - First observed
send_message
TDQS
Scored across 20 tools
Each tool targets a distinct resource+action, and singular/plural pairs (move_message vs move_messages, save_attachment vs save_all_attachments) are clearly differentiated by their descriptions. The only real overlap is list_messages versus search_messages (and get_message's fallback that scans all mailboxes), which could occasionally cause misselection when an agent just wants to find a message.
Nearly everything follows a predictable snake_case verb_noun pattern (list_accounts, get_message, move_message, save_attachment, reply_to_message). The one deviation is mark_read, which uses verb_adjective rather than verb_noun, though its meaning remains obvious.
20 tools is on the heavy side of the typical 3-15 band, but for a full email client each tool maps to a real operation (account, mailbox, message, attachment, and compose surfaces). Nothing looks redundant enough to cut outright, so the surface is scoped reasonably.
Message lifecycle is well covered (list, search, get, send, reply, forward, move, flag, mark_read, delete) along with attachment handling. However, the mailbox lifecycle is partial — create_mailbox exists with no delete_mailbox or rename_mailbox — and there is no draft/update-message support or batch flag/delete, leaving notable dead ends for common workflows.
Maintenance
Related MCP Connectors
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
Your IMAP mailbox as an MCP server: read, search and (if you allow it) organize mail. Open source.
A MCP server for Gmail that lets you search, read, and draft emails and replies.
Connect any mailbox to Claude, ChatGPT & AI: read, send, reply, schedule & search emails.
Related MCP Servers
- AlicenseAqualityCmaintenanceMCP server that gives Claude and other MCP hosts full access to Mail.app on macOS — search, read, send, reply, flag, move, and more across all accounts configured in Mail.app.24115 npm1MIT
- AlicenseBqualityDmaintenanceMCP server that connects Claude to iCloud Mail, enabling reading, searching, sending, and organizing emails via IMAP/SMTP.14PolyForm Noncommercial 1.0.0
- AlicenseAqualityDmaintenanceA read-only MCP server that lets Claude Desktop interact with Apple Mail on macOS via AppleScript. It enables listing mailboxes, searching emails, and reading email content without making network calls.3MIT
- AlicenseAqualityBmaintenanceAn MCP server that provides programmatic access to Apple Mail, enabling AI assistants like Claude to read, send, search, and manage emails on macOS.25MIT