macos-apps-mcp
macos-apps-mcp is a local MCP server for reading, searching, writing, and guarded actions across core macOS apps, with permission diagnostics, audit logging, and dry-run previews.
Health and diagnostics: check server health, macOS permissions, current time, audit history, and tool usage.
Calendar and Reminders: list calendars/events/reminders/lists, check free/busy, create/update/delete events and reminders, complete reminders, create reminder lists.
Mail: search mailboxes, read overviews/stats/threads/bodies, inspect attachments, manage drafts and replies, move/trash/update status, undo moves/trashes, export mail, save attachments, report duplicates, and use gated send/reply-all/forward tools.
Notes: search/list notes, fetch note bodies, create/update/delete notes.
Contacts: search contacts and create contacts.
Messages: list chats, search messages by text, view conversations with a contact, and fetch message bodies read-only.
Photos: search photos and albums, view metadata, and export a still image.
Safari: list open tabs and open URLs.
Music: search the library/playlists, inspect now playing, control playback, play playlists, set volume, and set shuffle/repeat.
Shortcuts: list shortcuts and run them with optional input.
Safety controls: read-only mode, per-app adapter disabling, send gating, audit entries, Mail backups, and dry-run defaults for destructive or outbound actions.
Provides tools for interacting with Apple Calendar and Reminders (and eventually Mail) through native macOS frameworks, enabling management of events, reminders, and mail.
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-apps-mcpshow my upcoming calendar events"
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-apps-mcp
One local MCP server for Mail, Calendar, Reminders, Notes, Messages, Contacts, Photos, Safari, Music and Shortcuts on macOS. Searches and lists return pointers: an id, a one-line summary and a link that opens the item in its app. Bodies are a separate, capped fetch. Writes are tiered and audited; deletes, moves and sends preview first. macOS only. Python + FastMCP + uv. See DESIGN.md and CHANGELOG.md.
What you can ask
"What is on my calendar this week? When am I free on Thursday afternoon?"
events,free_busy"Which emails need a reply? Draft a reply to the first one."
mail_needs_response,mail_reply. The reply opens as a draft in Mail. It is not sent."Move the newsletters in my inbox to Archive. Show me first."
mail_search,move_mail,mail_undo. The move previews by default.mail_undoreverses it, within the known limits below.
Related MCP server: Apple Mail MCP Server
Safety and privacy
Local. No telemetry, and no network requests of its own: only a local unix socket (shim to daemon) and the dashboard on 127.0.0.1. Three tools reach past the Mac through the apps, when called: the send tools (off by default) send through Mail,
safari_openopens a page, andrun_shortcutruns a Shortcut that can call the web.Three tiers. Read, write and outbound. Send tools are absent until you enable them per app:
macos-apps-mcp allow-send mail(daemon) orMACOS_APPS_ALLOW_SEND=mail(stdio).MACOS_APPS_READ_ONLY=1registers reads only and wins over both.Dry run first.
dry_rundefaults to true fordelete_draft,move_mail,trash_mail,mail_undo,send_mail,reply_all,forward_mail,delete_reminder,delete_event,delete_noteandupdate_note. Other writes act when called.mail_replyopens a draft only.Audit log. Every write goes to
~/.local/state/macos-apps-mcp/audit.jsonl(under$XDG_STATE_HOMEwhen set). An update or delete by id also records the item as it was. Theaudittool reads the log back.Mail recovery. Before a Mail move or delete, each message is copied as
.emlunder~/.local/state/macos-apps-mcp/backup/mail/.mail_undoreverses the batch. No tool empties the Trash.Known limits. A message Mail downloaded only in part is backed up without its attachments. Moves and trashes through a Gmail label folder are refused, because Gmail reverts them about 2 minutes later.
sent: truemeans Mail accepted the message, not that it was delivered. All Mail facts.Dashboard. Under the signed
.appdaemon, a local page (127.0.0.1 only) shows every write, what it changed, and the backup behind each Mail batch. Invented data below:
First 5 minutes
Requires macOS, Python ≥ 3.12 and uv. uv provides uvx. The package is on PyPI. Point your MCP client at uvx. It fetches the package and runs it, so there is no clone and no venv path:
{
"mcpServers": {
"macos-apps": {
"command": "uvx",
"args": ["macos-apps-mcp"]
}
}
}If Claude Desktop cannot find uvx, set "command" to its full path: run which uvx in Terminal (a default uv install prints /Users/you/.local/bin/uvx).
For Claude Code:
claude mcp add macos-apps --scope user -- uvx macos-apps-mcpOr, instead of claude mcp add, install the Claude Code plugin. It starts the same server and adds a skill
that teaches the dry-run workflow. In Claude Code, run /plugin marketplace add elfensky/macos-apps-mcp, then
/plugin install macos-apps@macos-apps-mcp.
The CLI commands further down (allow-send, dedupe-mail) run the same way: uvx macos-apps-mcp allow-send.
Run doctor first. The doctor tool reports what is granted and opens no dialog (each Automation grant is read live; an app that is not running shows not_running). doctor(request=True), with you at the screen, opens the EventKit and Automation dialogs. The server needs:
EventKit: Calendar and Reminders.
Automation, one dialog per app: Mail, Notes, Contacts, Safari, Messages, Music.
Accessibility (optional, no dialog: turn it on in System Settings → Privacy & Security → Device Control and Data Access, called Accessibility before macOS 27, for the app that starts the server):
mail_replyandreply_allput your text above Mail's own quote. Without it, those two refuse and create nothing.doctorand the Health page show whether it is on.Full Disk Access (optional, no dialog: turn it on in System Settings → Privacy & Security → Full Disk Access, for the app that starts the server): Messages content, Photos, Mail's index reads, reminder tags and subtasks, and the fast Notes path. Without it, Notes and some Mail reads use a slower path. The rest return an error or a
coveragenote.
Under stdio, macOS gives each grant to the app that starts the server (Claude Desktop, Terminal, VS Code), so each client needs its own. The signed .app daemon holds one set for all: docs/DAEMON.md.
Load only the apps you use. MACOS_APPS_ADAPTERS_OFF=photos,music registers no tools for those apps, so your client holds fewer tools in its context. Under the daemon, see turn adapters off.
From source (development): use this path to work on the server itself.
git clone https://github.com/elfensky/macos-apps-mcp && cd macos-apps-mcp
uv syncThen point your MCP client at the project's own venv python — deterministic, and it carries the locked PyObjC wheels:
{
"mcpServers": {
"macos-apps": {
"command": "/absolute/path/to/macos-apps-mcp/.venv/bin/python",
"args": ["-m", "macos_apps_mcp"]
}
}
}Why not apple-mcp?
apple-mcp by Dhravya Shah pioneered one MCP server for all Apple apps. It is now archived. It returned full note and email bodies inline. This server returns pointers, fetches bodies only on request, and gates every write by tier. See CREDITS.md.
Something broke? Run doctor and paste its output into a GitHub issue. The report shows process paths, so check them before you post.
Tools
Reads return pointers; results are capped per adapter. Bodies/content are a separate bounded
fetch. Writes/actions are skipped entirely when MACOS_APPS_READ_ONLY is set (see below).
Calendar & Reminders — read/write (EventKit)
Tool | Args | Notes |
|
| list events as pointers |
|
| merged busy intervals + free gaps in the window; no event details |
|
| list reminders as |
| — | containers (id + name) to target writes |
| title, start, end (ISO), calendar, location, notes, |
|
| id, |
|
| title, due, list_name, notes, |
|
| name | new list on the default account; an exact duplicate name is refused |
| id | marks complete; completing a parent lists the subtasks it leaves open under |
| id, | deletes by id and proves it gone; a parent with subtasks is refused unless |
Event and reminder pointers carry folder = the calendar or list id, which
free_busy(calendars=…) and the write tools (calendar=, list_name=) take.
Reminder tags and subtasks (tags, parent = the parent's id) are read from the
Reminders store, read-only, and need Full Disk Access. When that store cannot be read, the
reminders still come back and coverage says why. No public API writes a tag or nests a
reminder, so no tool here does.
A write targets its container by name or Pointer.id; an ambiguous name raises rather than
guessing. Recurrence is an RFC 5545 RRULE: FREQ, INTERVAL, COUNT, UNTIL, BYDAY (with
ordinals such as 2TU or -1FR for monthly and yearly rules), BYMONTHDAY, BYMONTH,
BYYEARDAY and BYSETPOS, e.g. FREQ=MONTHLY;BYDAY=2TU;COUNT=6. A recurring reminder needs a
due date. BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND and WKST are refused by name (EventKit
saves BYWEEKNO but expands only the first date), and so is any value out of range or any
combination RFC 5545 forbids; each part is checked again after the write. A start date that
does not match its rule is accepted — RFC 5545 counts it as the first occurrence — and the
event result says that the first occurrence is an extra one.
Mail — id-first read + draft-and-open (Automation)
Sending is off by default: reads, create_draft, and mail_reply never send — they
open a compose window for you to review. Outbound (send_mail, reply_all,
forward_mail) exists but only runs when the operator opts in via
MACOS_APPS_ALLOW_SEND, and dry_run still defaults to True even then.
Tool | Args | Notes |
| subject-OR-sender substring | inbox matches; id = stable RFC822 message-id, |
| id, mailbox | one message's plaintext, bounded + truncation-marked; |
| subject, from_, to, mailbox, account, since, until, unread, flagged, has_attachments, body, limit | indexed search via Envelope Index (at rest — no Mail launch unless |
| rebuild | builds/refreshes opt-in FTS body index from |
| id, limit (default 100) | whole conversation, oldest-first, includes your sent messages; deduped; over |
| — | every mailbox with total + unread, unread-first; includes Junk/Trash/All Mail; counts live (stored counters go stale) and per distinct message; account names come from Mail (launches it), UUIDs stand in when it's unreachable; On My Mac always named |
| mailbox (a search result's | attachment name/size/downloaded per message; works on Drafts |
| — | inbox mail likely needing your reply, ranked with a |
|
| mail you sent ≥ |
| to, subject, body | opens a draft for review — never sends; returns a locator |
| message_id, mailbox, reply_body, | native threaded reply (sets In-Reply-To/References) that keeps Mail's own quote, your text on top through Accessibility; opens for review — never sends |
| — | list Mail drafts as pointers (id + subject — to recipient) |
| id, | delete one draft by message-id; |
| name ( | creates the folder; missing parents auto-created. No delete counterpart — |
| ids (≤25), from_mailbox, to_mailbox, | file/archive/refile; every message backed up + logged before anything moves, so |
| ids (≤25), mailbox, | soft delete, and the only delete there is — Mail's |
| receipt, | replay a |
| ids (≤25), mailbox, | mark read/unread, flag (+colour). Re-issuing with the opposite value is the undo, so |
|
| report only — per-mailbox redundant-copy counts + worst offenders. Cleanup is the |
|
| gated by |
|
| gated; native threading headers |
|
| gated; original + attachments forwarded intact — no covering-note param (writing the body destroys both, device-verified) |
Messages — content via chat.db (read-only; Full Disk Access)
Tool | Args | Notes |
| — | conversation list (id + name); no content, no FDA needed |
| query, | search message text (decodes |
| contact (phone/email), | recent messages with one person; |
| id | full text of one message by guid |
Notes — NoteStore.sqlite reads + opt-in bodies
Tool | Args | Notes |
| title, snippet or body words |
|
| — | every live note (id + "Account / Folder" + snippet), Recently Deleted excluded |
| ids (≤ 50) | opt-in plaintext hydration → |
| title, body, optional | returns the stable x-coredata id; an unknown/ambiguous folder is refused, not guessed |
| id, title, body | full replace of title+body by id; the stable id is preserved and verified after write |
| id, | moves to Recently Deleted; |
Other read-only context
Tool | Args | Returns |
| name substring | cards (name, org, first phone + email) |
| search string |
|
| — |
|
| photo id | dates, location, place, people, EXIF subset, pixel size, kind; never image bytes or thumbnails |
| — | every open tab (url + title) |
| name substring (empty = all) | the user's Shortcuts; id = stable UUID, |
| — ( | health check / time / permission diagnostics |
| optional | recent write audit entries (newest first) — what macos-apps-mcp changed, with before/after pointers (enough to undo by hand) |
| — | per-tool call counts + the never-used list, for pruning rarely-used tools |
Actions (writes)
Tool | Args | Notes |
| given_name, family_name, organization | |
| name or id, optional | runs a Shortcut; returns a bounded output snippet |
| url | opens in a new tab; bare host → |
| photo id, | writes the edited still (the original when there is no edit) as a new file, name |
Read-only mode
Set MACOS_APPS_READ_ONLY=1 (or true / yes) to register reads only — every write and action
tool is skipped, a safe-deploy guard. (Reads may still open apps / read local stores.)
Turning adapters off
Set MACOS_APPS_ADAPTERS_OFF=photos,music (a comma list of adapter names) to register no tools
for those apps. Under the daemon, the file ~/.local/state/macos-apps-mcp/adapters_off holds the
same list and takes effect after a restart. Details: docs/DAEMON.md.
Dashboard
Under the daemon, http://127.0.0.1:47632 shows the audit trail, Health, the adapter switches,
usage and the Mail backups. Run macos-apps-mcp dashboard to open it with its page key. Details:
docs/DAEMON.md. Both screenshots use invented data.
Cleaning up duplicate mail
Mail accumulates redundant copies of the same message — a UI drag copies rather than moves, Gmail
shows one message under both a label and All Mail, migrations leave copies on two accounts. The
read tools already collapse them, so this is only about what is physically on the server. Ask a
session for mail_duplicates() to see the damage, then clean up in a terminal:
macos-apps-mcp dedupe-mail # preview every mailbox — changes nothing
macos-apps-mcp dedupe-mail --verbose # also list the sets it will NOT touch
macos-apps-mcp dedupe-mail --execute --mailbox=<folder-url> # do one mailbox for realA CLI command, not a tool, for the same reason as allow-send: thousands of deletes against a
30-second-capped serialized worker is hours of work a human starts. It only collapses copies that
are byte-identical (size and date sent) — Mail gives no way to address one specific copy, so
the survivor is whichever one Mail leaves, and identical bytes are what make that safe. Sets that
differ are counted, left alone, and listed under --verbose.
Redundant copies go to Trash, in small batches, each its own mail_undo receipt. Emptying the
Trash is yours to do in Mail.app — nothing here can erase a message.
It is slow: ~1 minute per duplicate set against a real IMAP account (Mail's whose lookup scans
the whole mailbox), so a big folder is hours. Run it in a terminal you can leave, one mailbox at a
time. It is resumable — the plan is recomputed from Mail's index on every run, so interrupting it
costs nothing and re-running just finds less to do. A set Mail fails to delete is reported, not
retried silently.
Outbound (send) mode
Sending is off by default — the server creates drafts and never sends. Turn it on with:
macos-apps-mcp allow-send mail # or: messages / mail,messages / all / off
macos-apps-mcp allow-send # print the current settingThat persists the opt-in and restarts the daemon so it re-registers (registration happens at import, so a restart is unavoidable — reconnect your MCP client afterward). It is a CLI command, not a tool: the gate is your consent, so the model can neither grant itself sending nor restart the server out from under your session.
The same choice is available as MACOS_APPS_ALLOW_SEND in the environment, which is what a
stdio server reads (a set variable always wins over the persisted toggle):
Value | Effect |
unset (default) | no send tools are registered at all |
| Mail outbound only ( |
| named adapters (comma list) |
| every adapter's outbound |
MACOS_APPS_READ_ONLY always wins: with both set, no send tools are registered.
Send tools take dry_run, which defaults to True — deliberately inverted from the
id-addressed deletes. A delete targets an item a read already returned; a send constructs its
recipient, and a wrong recipient is the failure that matters. The dry run makes no call into Mail
at all and reports the resolved envelope; pass dry_run=False to actually send. reply_all is
the one exception: its dry run reads (never sends) the original message's actual to/cc
recipients, because that's exactly the recipient set a caller can't predict.
A successful send_mail / reply_all / forward_mail result (sent: True) means Mail
accepted the message — not that it was delivered. Device-verified: a perfectly-formed message
can sit in Mail's Outbox undelivered for minutes after send returns, and a stranded
recipient-less message can jam the outbox so later, valid sends queue behind it and never leave.
Every result also reports outbox_pending, Mail's current outbox count; when it's greater than
zero the result carries a note explaining that delivery is not confirmed and to check Mail ▸
Outbox.
Run the doctor tool to check whether sending is actually enabled — deployment.outbound lists
every adapter currently send-enabled ([] if none), derived from the same registration logic
above rather than a re-read of the raw env var, so it can never disagree with what got registered;
deployment.outbound_note explains the state in prose.
Under the daemon deployment, setting MACOS_APPS_ALLOW_SEND in an MCP client's config is a
silent no-op: the client's env block reaches the shim, not the long-lived daemon process that
reads the variable at import time, and the shipped LaunchAgent plist ships no
EnvironmentVariables key. This is exactly why allow-send exists — it writes state the daemon
can read (~/.local/state/macos-apps-mcp/allow_send, home-pinned so the shell that writes it and
the launchd process that reads it always agree) and survives reboots, unlike launchctl setenv.
See docs/DAEMON.md ("Outbound (send) mode under the daemon").
Develop
uv sync
uv run pytest # unit tests (mock at the adapter boundary)
uv run pytest -m integration # real macOS / EventKit / TCC — run manually, never in CI
uv run ruff check . # lint (config in pyproject.toml)
uv run ruff format . # format
uv run macos-apps-mcp # run the server (stdio)ruff (lint + format, line-length 88) and pytest gate CI — full workflow in CONTRIBUTING.md.
Prior art & credits
macos-apps-mcp builds on prior work — the Apple Mail MCP it draws from, the EventKit/Photos servers it references, the project that pioneered the unified-Apple-MCP pattern, and FastMCP / PyObjC / the MCP spec it depends on. See CREDITS.md.
Available Tools
68 toolsauditARead-only
Recent write audit entries (newest first) — what macos-apps-mcp changed, with
before/after pointers, enough to reverse a change by hand. since optional ISO
datetime (call now() to ground it) drops older entries; bounded to the last 50.
Each entry carries dry_run (resolved from the tool's default when the caller
omitted it, so a preview reads true) and caller (the MCP client's name and
version, plus session for a shim); caller is reported by the client, never an
identity check. Read-only; no permission (reads a local log at
~/.local/state/macos-apps-mcp).
| Name | Required | Description | Default |
|---|---|---|---|
| since | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/destructiveHint annotations: discloses the 50-entry cap, the on-disk source path (~/.local/state/macos-apps-mcp), that no permission is required, that `dry_run` is resolved from the tool's default rather than the caller's override, and that `caller` is client-reported and not an identity check. These are exactly the caveats an agent needs to interpret results correctly.
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?
Front-loads what the tool returns and the recency ordering before the caveats, and nearly every clause adds information. It is dense and runs long as one paragraph, with the parenthetical asides stacked, which costs a point on structure but not on value.
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 a single optional parameter and an output schema, the description still explains the notable per-entry fields (`dry_run`, `caller`, `session`) an agent could misread, and covers scope, cap, and storage. Nothing needed to call or interpret it 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?
Schema coverage is 0% and the only parameter is an untyped anyOf string, so the description carries the full burden — it does, defining `since` as an optional ISO datetime that drops older entries and recommending `now()` as the grounding source. Without this the agent would have no idea of format or semantics.
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 — 'Recent write audit entries (newest first)' — plus the value proposition (before/after pointers sufficient to reverse a change by hand). No sibling tool in the list does anything comparable, so the agent can distinguish it immediately.
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 clear usage context: use `since` to drop older entries, and explicitly directs the agent to call `now()` to ground a relative time — a concrete routing instruction to a sibling. It also sets an expectation ceiling ('bounded to the last 50'). It does not state when not to use it, which keeps it short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calendarsARead-only
List calendars as pointers (id + name); use a name to target writes. The id
is the folder that events carry. Read-only; needs EventKit (Calendar) access.
See create_event to write.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered, yet the description adds real context: it requires EventKit (Calendar) access, which is an authorization prerequisite an agent needs. It also clarifies the semantic link between `id` and event folders, going beyond the annotations.
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 short sentences, front-loaded with the core action and return shape, followed by the routing hint and the access prerequisite. Every sentence earns its place with no redundancy.
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 is simple (no params, output schema present), and the description covers purpose, return shape, the auth requirement, and the sibling to use for writing. Nothing an agent needs to call it correctly is missing, and return-value detail is appropriately delegated to the output schema.
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?
With zero parameters, the baseline is 4, and the description does add value by defining what the returned `id` means (the folder events carry) rather than only echoing the schema. There are no input parameters to explain, so deeper parameter semantics do not apply.
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 specific verb and resource ('List calendars as pointers'), and immediately clarifies the return shape (id + name). It further distinguishes the resource by explaining that the returned `id` is the `folder` that events carry, so an agent can tell exactly what this tool yields versus sibling event 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?
It gives a concrete usage path: use a name to target writes, and 'See create_event to write,' routing the agent to the relevant sibling. It does not state explicit exclusions or when not to call it, so it falls just short of a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
complete_reminderADestructive
Mark a reminder complete by id. Completing a parent leaves its subtasks open
(Reminders.app hides them under a completed parent); the result lists them under
subtasks. Side effect (completes). Requires EventKit and Full Disk Access:
the subtask check reads the Reminders store first, and when the store cannot be
read the completion is refused and nothing changes. id from reminders.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that a parent's subtasks remain open and are surfaced under `subtasks` in the result, names the required framework and permission (EventKit + Full Disk Access), and describes the failure mode where an unreadable store refuses the completion with no state change. That is exactly the behavioral context the destructiveHint annotation cannot convey.
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?
Front-loads the action in the first clause and packs the subtask caveat, prerequisites, and failure semantics into a short block with no filler. The parenthetical explanation of hidden subtasks earns its place, though the sentence structure is slightly dense.
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?
An output schema exists, yet the description still usefully flags the `subtasks` field, and it covers preconditions and refusal behavior. The only loose end is parameter-level detail for `id`, which the schema does not supply and the description only partially fills.
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 0%, so the lone `id` parameter is undocumented in the schema. The description partially compensates by stating '`id` from reminders', giving the agent the provenance of the value, but it adds nothing about format or validity constraints on that string.
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 ('Mark a reminder complete') plus the keying parameter ('by id'), so the action is unambiguous. It does not explicitly distinguish itself from update_reminder, which could plausibly also flip completion state, leaving a small amount of sibling inference.
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 context is implied rather than stated: the description explains what happens on completion and what prerequisites are needed, but never says when to choose this over update_reminder or delete_reminder. An agent can infer the intent, but the routing decision is left to it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contactsARead-only
Find contacts by name (substring). Returns pointers (id + name/org). Read-only; needs Automation access for Contacts. See create_contact to write.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Consistent with readOnlyHint=true and adds context annotations do not carry: matching is substring-based, results are lightweight pointers rather than full records, and Contacts requires Automation access. It stops short of noting match limits, ordering, or case sensitivity when many substring matches occur.
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 match rule, then the return shape, then the permission and sibling routing. No sentence is 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?
An output schema exists, so return-value explanation is optional and the description's one-line summary is sufficient. Permission requirement and the write alternative are covered; only behavior under many matches (truncation/paging) is left unaddressed for a lookup that can return large result sets.
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 0% (the single `name` property has no description), so the description must compensate, and it does: it tells the agent the value is matched as a substring rather than exactly. Case sensitivity and whether org names are also matched remain unstated.
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 (find), resource (contacts), and match semantics (substring on name), plus the shape of the return (id + name/org pointers). It also names the sibling it is not (create_contact), so an agent can distinguish it without opening any schema.
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?
"Read-only" plus "See create_contact to write" gives an explicit read-vs-write routing rule between the two contact tools. It does not address whether this is the right choice when the agent only knows an email/phone rather than a name, which is a real limitation given name is the sole parameter.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_contactA
Create a contact (given/family name + organization). Side effect (creates); needs Automation access for Contacts.
| Name | Required | Description | Default |
|---|---|---|---|
| given_name | Yes | ||
| family_name | No | ||
| organization | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false, so the safety profile is covered. The description adds useful context beyond annotations by stating the Automation access requirement for Contacts, though it does not mention error behavior, duplicate handling, or rate limits.
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, front-loaded sentences with no wasted words: the action and fields come first, followed by the side-effect and permission note.
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?
An output schema exists, so return values need not be described. For a simple create operation, the description covers the action, fields, side effect, and permission requirement; only duplicate-handling or failure semantics are 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?
Schema description coverage is 0%, so the description must compensate. It names all three parameters (given_name, family_name, organization), which is helpful, but it does not clarify that only `given_name` is required or explain field formats or constraints.
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?
Uses a specific verb and resource ("Create a contact") and names the fields it accepts (given/family name and organization). It does not explicitly distinguish itself from the sibling `contacts` tool, which likely lists contacts, so it falls short of full sibling differentiation.
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 saying it creates a contact and requires Automation access for Contacts. However, it gives no explicit guidance on when not to use it or how it relates to alternatives such as `contacts`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_draftA
Create a Mail draft and OPEN it for you to review and send — it NEVER sends on
its own. to a recipient address. Returns a locator dict ({"created", "subject",
"mailbox", "from", "note"}) — a freshly opened compose window has no stable id
yet, so this says where to find it (Drafts) instead of fabricating one; save it
and drafts() resolves it by its stable message-id. If the create FAILS partway,
Mail may still leave a stray autosaved draft behind (#133 — its autosave is
asynchronous and cannot be suppressed); drafts() + delete_draft() clear it.
A new draft is unthreaded; it is sent from from_address (an address one of
Mail's accounts owns, matched case-insensitively, Name <addr> accepted) or
Mail's default account.
An address no account owns is refused before Mail builds anything — Mail would
otherwise use its default account silently. To answer a message use
mail_reply, which is threaded and sent from the account that received it.
THE AUTOSAVE WINDOW: Mail stamps the Message-ID only when it autosaves the draft,
~10-15 SECONDS after this returns — asynchronously, and nothing can hurry it. So
drafts() called immediately shows nothing. That is normal. Wait for the window,
then drafts() resolves it. Do NOT retry this call because the draft has not
appeared: you get two drafts and the first one still arrives.
Additive (creates a draft; does not send/modify/delete); needs Automation access
for Mail (the ownership read is Automation too).
| Name | Required | Description | Default |
|---|---|---|---|
| to | Yes | ||
| body | No | ||
| subject | No | ||
| from_address | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite annotations already saying this is non-read-only and non-destructive, the description adds substantial behavioral context: it never sends, opens a compose window, may leave a stray autosaved draft on failure, requires Automation access, and refuses unowned sender addresses.
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 core purpose and the never-sends guarantee are front-loaded, and the critical no-retry/autosave warning is prominently placed. It is long and repeats some autosave timing details, but the extra length is largely justified by the tool's non-obvious asynchronous behavior and cleanup path.
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 covers the create flow, return locator behavior, permissions, sender ownership rules, asynchronous autosave timing, partial-failure recovery, and the correct alternative tool. With an output schema present, it does not need to fully document return structure, and it still explains the key locator semantics.
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 0%, so the description must carry parameter meaning. It clearly explains `to` as a recipient address and richly documents `from_address` ownership, case-insensitive matching, `Name <addr>` support, and default-account fallback; `body` and `subject` are not explicitly described but are conventional and partially implied by the return fields.
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: creating a Mail draft that opens for review and never sends by itself. It also distinguishes this from `mail_reply`, which is explicitly named as the threaded alternative for answering 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?
It gives explicit when-to-use guidance versus `mail_reply`, explains the autosave wait window, and warns not to retry because that creates duplicate drafts. It also names `drafts()` and `delete_draft()` for cleanup after a partial failure.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_eventA
Create an event. start/end ISO datetime — naive = local time, call now()
first; recurrence an RRULE with FREQ, INTERVAL, COUNT, UNTIL, BYDAY (ordinals
such as 2TU or -1FR for monthly and yearly), BYMONTHDAY, BYMONTH, BYYEARDAY,
BYSETPOS; BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND and WKST are refused. all_day
takes a DATE
(2026-07-01); a timestamp with a UTC offset is rejected. A start that does not
match its recurrence is accepted (RFC 5545 counts it as the first occurrence) and
the result's summary says so.
alarms are minutes before the start, as in the Google Calendar API. For an all-day
event the offset counts from local midnight: -540 is 09:00 on the day, 900 is
09:00 the day before. On a DST-change day the alert shifts an hour, the same as
Calendar's own alerts. At most 5.
Side effect (creates); needs EventKit (Calendar) access. Target a calendar via
calendar — a calendar name OR a calendar Pointer id (from calendars). An ambiguous
name is refused (with the candidate ids listed), never guessed.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| notes | No | ||
| start | Yes | ||
| title | Yes | ||
| alarms | No | ||
| all_day | No | ||
| calendar | No | ||
| location | No | ||
| recurrence | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and destructiveHint=false, but the description adds substantial behavioral context: it creates an event, requires EventKit/Calendar access, refuses ambiguous calendar names, rejects certain RRULE parts, rejects timestamp offsets for all_day, caps alarms at 5, and explains DST and recurrence-mismatch 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 front-loaded with its core purpose and then packs in necessary edge-case detail. It is dense and somewhat run-on, but nearly every sentence adds useful invocation or validation 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?
Given the tool's complexity, the lack of schema descriptions, and the presence of an output schema, the description is largely complete: it covers creation, auth needs, calendar targeting, recurrence constraints, and alarm semantics. Minor gaps remain around simple fields like notes and location.
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?
With 0% schema description coverage across 9 parameters, the description carries most of the semantic burden. It thoroughly explains the complex parameters start/end, recurrence, all_day, alarms, and calendar, though it does not explicitly mention notes, location, or title beyond their self-evident meanings.
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 specific verb and resource: 'Create an event.' That clearly identifies the operation. It does not explicitly distinguish this tool from siblings such as update_event or events, 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?
The description gives operational guidance such as calling now() first for naive datetimes and targeting a calendar via name or Pointer id. However, it does not explicitly state when to use create_event versus update_event, delete_event, or events. Usage is therefore implied more than fully guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_mailboxA
Create a Mail mailbox (folder) under one account. name may contain "/" to nest
("Projects/2026") — missing parents are created for you. account is a display name
("Personal"), an account UUID, or "On My Mac", and is REQUIRED: a folder has to land
somewhere specific.
Returns {created, mailbox, account, folder, note}. folder is the address token to
pass back verbatim to move_mail/mail_search; it works immediately, and
mail_overview will report Mail's own equivalent spelling of it once the account
syncs — both address the same mailbox. A "%" in the name is rejected (it cannot be
addressed unambiguously). There is no delete counterpart: removing a mailbox is not
scriptable, so do it in Mail. In a Gmail account the new mailbox is a label:
move_mail refuses it at either end (#291), and reads show it empty while Mail's
index does not mark it as a label. Additive (creates a folder; touches no message);
needs Automation access for Mail, plus Full Disk Access to resolve "On My Mac".
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| account | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint=false/destructiveHint=false annotations: it discloses missing-parent auto-creation, the '%' rejection rule, Gmail label behavior and the move_mail refusal (#291), that reads show the new label empty, and the required Automation plus Full Disk Access permissions for 'On My Mac'.
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?
Purpose and the required-account rule are front-loaded, then return shape, token semantics, and caveats. It is dense but nearly every clause carries operational information; the Gmail-label parenthetical is the only passage that verges on over-long.
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?
Despite an output schema, the description still names the return fields and, critically, explains that the returned 'folder' token works immediately while mail_overview reports a different spelling later — a non-obvious detail an agent would otherwise get wrong. Permissions and platform caveats are covered.
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 0% with two required, undescribed string parameters, so the description must carry the load and does: 'name' supports '/' nesting and rejects '%'; 'account' accepts a display name, a UUID, or 'On My Mac'. That is exactly the disambiguation an agent needs to construct a valid call.
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 ('Create a Mail mailbox (folder) under one account') and clarifies the folder concept, distinguishing it from message-creation siblings like create_draft. The scope ('under one account') and nesting semantics are 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?
Gives concrete usage conditions: 'account' is REQUIRED and why, the 'folder' token is what to pass to move_mail/mail_search, and it explicitly closes off the wrong expectation with 'There is no delete counterpart... do it in Mail.' No competing creation tool exists to disambiguate against, so no explicit alternative routing is needed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_noteA
Create a note and return its STABLE x-coredata id (unique in the ecosystem —
immediately usable with note_bodies). title/body are plaintext (escaped, so
markup is inert); folder an existing folder name (across accounts) or omit for the
default folder — an unknown/ambiguous name is refused. Verified after write (#49).
Side effect (creates); needs Automation access for Notes (verify read-back also uses
Full Disk Access, falling back to Automation).
| Name | Required | Description | Default |
|---|---|---|---|
| body | No | ||
| title | Yes | ||
| folder | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations, the description discloses the write side effect, required Automation access for Notes, Full Disk Access for verify read-back with Automation fallback, and that writes are verified after creation. It also states unknown or ambiguous folder names are refused, which is meaningful behavioral context for a 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 purpose and stable-ID return are front-loaded, followed by parameter and behavior details in a compact paragraph. It is appropriately sized, though dense parentheticals and the issue reference '#49' make it slightly less clean than ideal.
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 creation tool with an output schema, the description covers the essential creation behavior, folder constraints, authentication requirements, verification behavior, and uniqueness/return-ID details. An agent has enough context to invoke it correctly and understand the write side effect.
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 0%, so the description must carry parameter meaning. It explains that title/body are plaintext with markup escaped and inert, and gives detailed folder semantics including cross-account lookup, default omission, and refusal of unknown/ambiguous names. The title parameter is only lightly explained beyond being plaintext, keeping this from a 5.
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: create a note, and immediately explains it returns a stable x-coredata id usable with note_bodies. This clearly differentiates creation from sibling tools like notes, notes_all, update_note, and delete_note without requiring the agent to inspect 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?
The description gives clear creation context and details folder selection rules: an existing folder name across accounts or omit for default, with unknown/ambiguous names refused. It does not explicitly compare to update_note or state when not to use it, so it falls short of the explicit when/when-not/alternatives bar for a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_reminderA
Create a reminder. due/start ISO datetime — naive = local time, call now()
first; priority 0–9; recurrence an RRULE with FREQ, INTERVAL, COUNT, UNTIL,
BYDAY (ordinals such as 2TU or -1FR for monthly and yearly), BYMONTHDAY,
BYMONTH, BYYEARDAY, BYSETPOS; BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND and WKST are
refused.
This tool cannot set tags or make a subtask (no public API; read-only via
reminders()).
Side effect (creates); needs EventKit (Reminders) access. Target a list via
list_name — a list name OR a list Pointer id (from reminder_lists). An ambiguous
name is refused (with the candidate ids listed), never guessed.
| Name | Required | Description | Default |
|---|---|---|---|
| due | No | ||
| notes | No | ||
| start | No | ||
| title | Yes | ||
| priority | No | ||
| list_name | No | ||
| recurrence | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only declaring readOnlyHint=false and destructiveHint=false, the description adds the substantive traits: it creates (side effect), requires EventKit/Reminders access, cannot set tags or subtasks due to API limits, and refuses ambiguous list names while listing candidate ids. This is exactly the extra context the annotations cannot carry.
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?
Front-loaded with the action, then parameter rules, then side-effect/constraint notes. Dense but every clause carries information; the recurrence allow/deny list is long but prevents a whole class of failed calls.
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?
Output schema exists so return values need no explanation, and the mutation, permission and targeting behaviors are all covered. The only untouched parameters are title and notes, which are self-evident from the schema.
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 0%, so the description has to carry the load and it does: due/start are ISO datetimes where naive means local time, priority is 0–9, recurrence is an RRULE with an explicit allowed subset (FREQ, INTERVAL, COUNT, UNTIL, BYDAY with ordinals, BYMONTHDAY, BYMONTH, BYYEARDAY, BYSETPOS) and refused parts (BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND, WKST), and list_name accepts a name or Pointer id.
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?
Opens with a specific verb+resource ('Create a reminder') and immediately scopes what is excluded (tags, subtasks). An agent can distinguish it from update_reminder, complete_reminder and create_reminder_list without opening any schema.
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 concrete preconditions for use: call now() first for naive datetimes, target a list via list_name or a Pointer id from reminder_lists, and note that ambiguous names are refused rather than guessed. It does not explicitly state when to use create_reminder vs update_reminder, but the sibling names make that inference safe.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_reminder_listA
Create a reminder list in the default Reminders account. An exact-name duplicate
is refused (it would make list_name= ambiguous). Returns the list pointer (id +
name); use the id as list_name=. Side effect (creates); needs EventKit
(Reminders) access.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint=false annotation, it discloses the mutation side effect explicitly, the exact-name uniqueness rule and why it exists, the return payload (pointer with id and name), and the EventKit permission requirement. That is the full behavioral profile an agent 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 short sentences, front-loaded with the action, then the constraint, then the return value and permission note. No 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?
For a single-parameter creation tool with an output schema already present, the description covers creation scope, duplicate behavior, return shape, and auth dependency. Nothing needed to invoke it correctly 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?
Only one parameter and the schema coverage is 0%, so the description must carry the load; it conveys that the name must be unique and that the returned id is what later tools expect, but it says nothing about naming format, length, or case sensitivity of the duplicate check.
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 ('Create a reminder list') plus the scope ('in the default Reminders account'), which cleanly separates it from create_reminder (a reminder, not a list) and from reminder_lists (read-only listing).
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?
Tells the agent what to do with the result ('use the id as `list_name=`'), which is real chaining guidance, and flags the duplicate-name precondition. It never names an alternative tool or an explicit when-not, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_draftADestructive
Delete one Mail draft by its message-id (from drafts()). dry_run DEFAULTS TO
TRUE — previews the draft that WOULD be deleted (pointer, no mutation); pass
dry_run=false to delete. Destructive but LOCAL — this deletes an unsent draft, it
never sends. Needs Automation access for Mail.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| dry_run | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as destructive and not read-only, and the description adds important context beyond them: dry_run defaults to true and performs a non-mutating preview, while dry_run=false causes deletion. It also clarifies that deletion is local, unsent-draft-only, and requires Automation access for Mail.
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 compact and front-loaded with the core action and scope. The dry_run default is emphasized early, and the final safety note about local deletion and permissions is brief and useful.
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 output schema exists, the description does not need to explain return values. It covers the destructive nature, preview behavior, identifier source, and permission requirement, leaving no important operational gap for an agent calling this 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 0%, so the description must carry parameter meaning. It does: it explains that id comes from drafts() and gives precise semantics for dry_run, including its default and the behavioral difference between true and false.
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: 'Delete one Mail draft by its message-id'. It clearly distinguishes itself from sibling draft tools like create_draft or update_mail_status by naming the exact operation and identifier source.
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 explains how to select the target ('by its message-id (from drafts())') and how dry_run controls preview versus actual deletion. It does not explicitly name alternative tools or when not to use this one, but the operational context is clear enough for correct invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_eventADestructive
Delete a calendar event by id. span REQUIRED if the target is recurring:
'this-event' (only this occurrence) or 'future-events' (this + all later); ignored
for single events. dry_run DEFAULTS TO TRUE — previews the event that WOULD be
deleted (pointer, no mutation); pass dry_run=false to delete.
Destructive; needs EventKit (Calendar) access. id from events.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| span | No | ||
| dry_run | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description adds genuinely new behavior: dry_run defaults to true and performs no mutation, `span` is silently ignored for non-recurring events, and EventKit/Calendar access is required. Those are exactly the surprises that would otherwise cause an accidental deletion.
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?
Front-loaded with the action, then clauses ordered by risk (span, then the dry_run default, then permissions). Every sentence adds a fact; nothing is restated 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?
A destructive mutation tool with an output schema that needn't be explained. The description covers the safety default, the recurrence branch, permissions, and id provenance — the full set of things an agent must know before acting.
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 0% and the schema gives no enum for `span`, so the description fully carries the load: it supplies the accepted values 'this-event' and 'future-events' and their meaning, the null/single-event behavior, and the default-true semantics of `dry_run`. All three parameters are covered with meaning beyond type.
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: 'Delete a calendar event by id.' Among siblings like delete_reminder, delete_note, and delete_draft, the 'calendar event' qualifier makes the target 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?
Explicit conditional rules: `span` is required only for recurring targets and ignored for single events, and `dry_run` defaults to true so the agent knows the default call is a preview. It also routes the agent to `events` for obtaining the id. It doesn't distinguish itself from `update_event` for edge cases like moving a single occurrence, which keeps it short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_noteADestructive
Delete a note by id → Recently Deleted (recoverable ~30 days). Destructive.
Pass expect_title to verify the target before deleting (content-verify first).
dry_run DEFAULTS TO TRUE — previews the note that WOULD be deleted (pointer, no
mutation); pass dry_run=false to delete.
Needs Automation access for Notes. id from notes / notes_all.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| dry_run | No | ||
| expect_title | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it destructive, but the description adds critical details beyond them: the delete is recoverable for about 30 days, dry_run defaults to true and performs no mutation, expect_title verifies the target, and Automation access is required. This is strong behavioral disclosure with no contradiction.
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 dense but carefully front-loaded, starting with the action and effect, then safety checks, dry_run semantics, permissions, and id source. Every sentence adds operational value, and the formatting makes the default dry_run behavior easy to spot.
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 destructive delete operation, three parameters, existing annotations, and an output schema, the description is complete enough for correct invocation. It covers recovery behavior, preview defaults, target verification, auth requirements, and where ids come from.
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 0%, so the description must carry parameter meaning, and it does: id is sourced from notes/notes_all, dry_run defaults to true with preview semantics, and expect_title verifies the target before deletion. All three parameters are explained with behavior beyond their types.
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: "Delete a note by id" and clarifies the effect by noting it moves to Recently Deleted. This clearly separates it from create_note, update_note, and other delete_* siblings by resource.
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 clear operational context: use the id from notes/notes_all, verify with expect_title before deleting, and preview with dry_run because it defaults to true. It does not explicitly name when to avoid this tool versus update_note or other alternatives, so it is not a full 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_reminderADestructive
Delete a reminder by id. dry_run DEFAULTS TO TRUE — previews the reminder that
WOULD be deleted (pointer, no mutation); pass dry_run=false to delete. A parent
with subtasks is refused unless with_subtasks=true, because deleting a parent
deletes its subtasks too. A subtask indented in Reminders in the last few minutes
may not be visible yet.
Destructive; needs EventKit and Full Disk Access (the subtask check reads the
Reminders store). id from reminders.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| dry_run | No | ||
| with_subtasks | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructiveHint annotation it discloses concrete behavioral traits: the default is a non-mutating preview pointer, parent deletion cascades to subtasks and is refused without an explicit flag, EventKit and Full Disk Access are required because the subtask check reads the Reminders store, and a just-indented subtask may not yet be visible. This is exactly the context an agent needs before an irreversible call.
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 critical dry_run default is front-loaded in caps, and each subsequent sentence adds a distinct operational fact. It is dense but nearly every clause earns its place, with only the clipped 'id' from reminders' phrasing reading as slightly terse.
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 destructive three-parameter mutation with an output schema, the description covers safety default, refusal conditions, cascade semantics, permission requirements, and a consistency caveat. Return values need not be explained since an output schema exists.
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 0%, but the description documents all three parameters: id's source ('from reminders'), dry_run's default and effect, and with_subtasks' role in bypassing the parent refusal. Nothing about parameter meaning is left to inference.
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 opening sentence gives a specific verb ('Delete') and resource ('a reminder') scoped by identifier, which cleanly separates it from siblings such as update_reminder and complete_reminder. The following sentences define exactly what deletion means in the parent/subtask case.
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 states clearly when the tool previews versus deletes (dry_run defaults true, pass false to actually delete) and when a parent deletion is permitted (with_subtasks=true). It never explicitly contrasts with alternatives like complete_reminder or update_reminder, but the operational guidance for the tool itself is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
doctorARead-only
Diagnose per-surface macOS permissions + health with exact remediation.
Read-only and prompt-free by default. request=True also triggers permission
prompts (EventKit consent + per-app Automation probes) — use it once to grant.
| Name | Required | Description | Default |
|---|---|---|---|
| request | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare readOnly/destructive, but the description adds the crucial side-effect disclosure that `request=True` triggers EventKit consent dialogs and per-app Automation probes — behavior an agent could not infer from the schema. It does not contradict readOnlyHint (no data is mutated), but it does flag a hidden user-visible effect, which is exactly the kind of context annotations cannot carry.
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 short sentences, front-loaded with the purpose and then the safety-relevant default. Every sentence adds information the agent needs; nothing is redundant with the schema or annotations.
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?
With an output schema present, return values need no explanation, and the description covers the one parameter and the prompt side effect. Minor gap: "per-surface" is never defined, so the agent doesn't know which surfaces/domains are diagnosed.
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 0%, so the description must carry the only parameter — and it does, explaining what `request=True` actually does (permission prompts, EventKit consent, Automation probes) and the recommended cadence ("once to grant"). Without this text the boolean would be opaque.
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 names a specific verb and resource combination ("Diagnose per-surface macOS permissions + health") and adds the value proposition of "exact remediation." It is clearly distinct from the sibling action tools (mail, notes, reminders) and from the lighter `ping`/`usage` utilities, though it never explicitly names those siblings.
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 explicit guidance for the parameter's two modes: default is "Read-only and prompt-free," and `request=True` should be used "once to grant" permissions. What is not covered is when to reach for this tool rather than a sibling diagnostic like `ping`, `usage`, or `audit`.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
draftsARead-only
List Mail drafts, newest mailbox order. Returns {results, truncated?};
truncated means the 25 cap was reached. Each record is a citable pointer (id,
summary, deeplink, folder = "drafts") PLUS discrete subject and to fields, so
picking out one specific draft is a field comparison, not substring-matching the
summary — which collides whenever two drafts share a subject. The id is the RFC822
message-id: pass it to delete_draft, or to send_mail(draft_id=…) to send a
draft the human has approved.
A compose window Mail has not autosaved yet (~10-15s) is absent here — wait, do not
retry the create. Read-only; needs Automation access for Mail.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and non-destructive, but the description adds substantial context beyond them: the 25-record truncation cap and its `truncated` flag, newest-first ordering, the shape of each record, that the id is an RFC822 message-id, the ~10-15s autosave visibility lag with an explicit 'do not retry' instruction, and the Automation access requirement. That is exactly the operational detail annotations cannot express.
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?
Front-loads the action and the return shape, then layers in the identifier contract and the caveat. Dense and mostly earned, though the explanation of why field comparison beats substring-matching on the summary is slightly long-winded for the value it adds.
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?
An output schema exists, yet the description still surfaces the two things an agent must know before calling: the truncation cap and the autosave delay. Combined with the id→delete_draft/send_mail handoff and the permissions note, nothing needed for 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 the baseline is 4 and there is nothing for the description to disambiguate. It correctly spends no words on parameter semantics and instead invests in return-value and identifier meaning.
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?
Opens with a specific verb and resource plus ordering semantics ("List Mail drafts, newest mailbox order"), which immediately distinguishes it from mailbox-wide siblings like mail, mail_search, and mail_overview. It also clarifies the record type (citable pointer with folder = "drafts") so there's no ambiguity about scope.
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 concrete downstream routing: pass the id to delete_draft or send_mail(draft_id=…) for a human-approved draft, and explicitly says to wait rather than retry a create for an un-autosaved compose window. It stops short of naming a sibling to use instead when the agent actually wants to search drafts by content, which is the one remaining gap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
eventsARead-only
List calendar events as pointers. when: today | week | YYYY-MM-DD.
Each result's folder is its calendar's id (from calendars); pass it to
free_busy(calendars=…) or as calendar=. A read cannot tell that a series'
first occurrence is extra (each result holds its own occurrence start); the
create/update result says so. Read-only; needs EventKit (Calendar) access.
| Name | Required | Description | Default |
|---|---|---|---|
| when | No | today |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only, yet the description still adds real context: EventKit (Calendar) permission is required, results are pointers rather than full records, and each result carries its own occurrence start so a series' extra first occurrence is invisible to reads. That last caveat about a known limitation is exactly the kind of behavior an agent cannot infer from structured fields.
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 short sentences, each earning its place, front-loaded with the core action before the chaining and caveat details. The parenthetical about occurrence starts is dense but necessary and kept short.
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?
With an output schema present, return values needn't be enumerated, and the description correctly focuses on the pointer shape and `folder` semantics that matter for chaining. Permission requirements and the read-versus-create asymmetry caveat round it out; only explicit non-use guidance 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?
Schema description coverage is 0%, so the description carries the burden and does: `when` accepts today | week | YYYY-MM-DD, which is effectively an enum the schema lacks. The `folder` output field is also explained for chaining purposes, though the default value is left to 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?
"List calendar events as pointers" gives a clear verb and resource, and the surrounding sibling set (create_event, update_event, delete_event) makes the read-only listing role obvious. "As pointers" is slightly cryptic on its own but is unpacked in the following sentence about the `folder` field.
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 wires the tool into the workflow explicitly: pass each result's `folder` to `free_busy(calendars=…)` or as `calendar=`, which tells the agent when this tool is the prerequisite for others. It does not state exclusions (e.g., use `free_busy` instead when you only need availability), so it stops short of a full when/when-not pair.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_mailA
Write messages out as importable .eml files (Full Disk Access).
Read AT REST — the same on-disk bytes the undo backups copy — so this never
launches Mail and needs no Automation. ids are RFC822 message-ids from a mail
read, comma-separated, max 25. dest_dir must be inside the allowed root
(~/Downloads by default; MACOS_APPS_FILE_ROOT moves it) and is created if needed;
a path outside it is REFUSED. Filenames are derived, never overwritten. A name that
already exists refuses the whole batch before any file is written; a refusal after
a write names the files already written.
.eml is the only format — it is lossless and opens in Mail and everything else,
and mail_body already covers "give me the text".
Returns {results, written, dest_dir, plane}. A message with no local file is
reported per-id as status: "absent" rather than failing the batch.
fidelity: "partial" means the .eml is missing its ATTACHMENT payloads — the body
is complete (#119). It is lossy for archival, not for reading.
Additive: writes new files, never overwrites or modifies mail.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| dest_dir | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses that it reads at rest and never launches Mail or needs Automation, requires Full Disk Access, refuses paths outside the allowed root, derives filenames on a never-overwrite basis, and aborts the whole batch before writing if a name collides. It also explains partial-fidelity attachment loss and per-id 'absent' handling — exactly the behavioral context an agent needs before a write.
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?
Front-loaded with the core action, then constraints, then return shape — a logical order with almost no filler. It is dense and multi-paragraph for a 2-param tool, so slightly heavier than strictly necessary, but each sentence adds operational value.
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?
Covers the failure semantics (batch refusal, per-id absent, partial fidelity) that matter for a batch write, and an output schema already exists so return values are doubly covered. Minor gap: it does not state what happens on a mid-batch I/O error beyond the 'files already written' note, or whether there is rate limiting on Full Disk Access reads.
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 0%, and the description fully compensates: `ids` is documented as comma-separated RFC822 message-ids (from a mail read) capped at 25, and `dest_dir` as being constrained to the allowed root, defaulting to ~/Downloads, relocatable via MACOS_APPS_FILE_ROOT, and auto-created. This is strictly more information than the bare string-typed schema carries.
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 — 'Write messages out as importable .eml files' — and immediately distinguishes itself from the sibling mail_body ('mail_body already covers "give me the text"'). An agent can tell exactly what this produces without opening the schema.
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?
Explicitly routes the text-only case to mail_body and frames this as the archival/export path, plus notes the max-25 batch limit and the allowed-root requirement. It stops short of naming other export siblings (export_photo, save_mail_attachment) as alternatives, so selection against the full sibling set is slightly under-specified.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_photoA
Write one photo out as a still image file (Full Disk Access).
Writes the edited still, the image as Photos shows it; the original when there is
no edit. id is a photo id from photos (the old
<UUID>/L0/001 form is accepted). dest_dir must be inside the allowed root
(~/Downloads by default; MACOS_APPS_FILE_ROOT moves it) and is created if needed;
a path outside it is REFUSED. The filename is derived from the original name plus
the first 8 characters of the id, and an existing file is never overwritten.
Files over 250 MiB are refused.
Reads the library at rest, so it never launches Photos and needs no Automation. A
photo whose file is only in iCloud comes back status: "absent" with a reason:
nothing is downloaded. Videos are refused; a Live Photo exports its still only and
says skipped: "live photo motion". Hidden and Recently Deleted ids are refused.
Returns {id, status: "written", path, bytes, edited, dest_dir}. Additive: writes a new file, never modifies the Photos library.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| dest_dir | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnly=false/destructive=false; the description adds substantial context beyond that: Full Disk Access requirement, no Photos launch or Automation needed, no overwrites, 250 MiB cap, path-root enforcement, and status values for refusal cases. This is exactly the extra behavioral detail the annotations cannot convey.
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?
Front-loaded with the action, then parameters/constraints, then return shape — a logical progression with no filler sentences. It is on the long side, but each constraint (iCloud, videos, Live Photos, hidden) maps to a distinct failure mode an agent must anticipate.
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?
Despite an output schema existing, the description also states the return shape ({id, status, path, bytes, edited, dest_dir}) plus the non-written statuses, and covers permissions, filesystem limits, and library-state edge cases. Nothing an agent needs to invoke it correctly 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?
Schema coverage is 0%, so the description carries the full burden and does: `id` is a Photos photo id with the legacy `<UUID>/L0/001` form accepted, and `dest_dir` must be inside an allowed root (~/Downloads default, MACOS_APPS_FILE_ROOT override), is auto-created, and is REFUSED if outside. Every parameter gets meaning, defaults, and failure semantics.
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?
Opens with a specific verb+resource: 'Write one photo out as a still image file'. It also clarifies the edited-vs-original semantic, which no sibling (photos, photo_info) handles, so an agent can distinguish export from listing/inspection without opening 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?
Rich conditional routing: videos refused, Live Photos export still only, hidden/Recently Deleted refused, iCloud-only photos return 'absent'. It does not explicitly name a sibling alternative (e.g. use photo_info first to verify), but the refusal conditions effectively define when this tool won't work.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
free_busyARead-only
Availability in a window: merged busy intervals + free gaps. start/end are
ISO-8601 datetimes (naive local, e.g. 2026-07-20T09:00:00); calendars optional
Pointer ids (from calendars) to restrict to, else all. Returns {"busy": [...],
"free": [...]} of {start, end} — no event details. Read-only; needs EventKit.
| Name | Required | Description | Default |
|---|---|---|---|
| end | Yes | ||
| start | Yes | ||
| calendars | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds real value beyond that: intervals are merged, no event details are returned, and it 'needs EventKit' (a platform/permission precondition the schema does not express).
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?
Front-loaded with the core purpose, then parameter notes, then return shape and precondition — every clause earns its place. Slightly dense/compressed prose costs it the top mark.
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?
Covers inputs, output shape ('{busy: [...], free: [...]} of {start, end}'), what is deliberately omitted ('no event details'), and the EventKit dependency. Nothing an agent needs to invoke it correctly is missing despite the output schema existing.
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 0%, so the description carries the full burden and does: `start`/`end` are ISO-8601 naive local datetimes with a concrete example, and `calendars` is defined as optional Pointer ids sourced from the `calendars` tool, defaulting to all. That is meaning the schema alone cannot convey.
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+resource ('Availability in a window') and immediately names the two outputs it computes ('merged busy intervals + free gaps'), which distinguishes it from sibling `events` (raw event listing). An agent can tell exactly what it produces without opening the schema.
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 explains the scoping option ('calendars optional Pointer ids... else all') and the read-only nature, which implies 'use this when you want free/busy rather than event details.' But it never explicitly says when to prefer this over `events` or names the alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mailARead-only
Search the Mail inbox by subject OR sender substring. Pointers: id = the stable
RFC822 message-id, summary = subject — sender, deeplink = a message:// URL,
folder = "inbox" (this scans the inbox only) — pass that folder straight to
mail_body. Prefer mail_search, which reaches every mailbox and reports the
account. Returns {results, truncated?} — truncated means the 25-message cap was
reached and there may be more. Read-only; needs Automation access for Mail. Bodies
are never fetched.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only and non-destructive, and the description still adds meaningfully: it requires Automation access for Mail, bodies are never fetched, results are capped at 25 with a `truncated` flag signaling more may exist. It also discloses the inbox-only scan scope, which is a behavioral limit not visible in any structured field.
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?
Front-loaded with the action, then a compact "Pointers:" list mapping field names to meanings, then scope/limit and a sibling recommendation. Every clause carries information, though the pointer enumeration makes it denser than strictly necessary for a one-parameter tool.
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 search tool it covers everything an agent needs: matching semantics, inbox-only scope, output field meanings, the truncation cap, the auth prerequisite, and the routing decision to `mail_search`. An output schema exists, yet the description still clarifies the one field (`truncated`) whose meaning matters operationally.
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 single `query` parameter has 0% schema description coverage, so the description must carry it — and it does, explaining that matching is a subject OR sender substring. It does not specify case sensitivity, whitespace handling, or whether multiple terms are ANDed, which keeps it below a 5.
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 ("Search the Mail inbox") and narrows the matching semantics to subject OR sender substring. It also explicitly separates itself from `mail_search`, which reaches every mailbox, so an agent can pick between the two without opening 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 an explicit preference rule: "Prefer `mail_search`, which reaches every mailbox and reports the account," which is precisely the condition that selects the sibling over this tool. It also tells the caller to forward the returned `folder` value straight to `mail_body`, closing the follow-up loop.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_attachmentsARead-only
List attachments on messages in a Mail mailbox, or on ONE message (Automation).
mailbox: the folder value from a mail_search result passed back VERBATIM (an
opaque imap://<uuid>/<path> token, not a name to retype), or a canonical system
mailbox — "inbox" | "sent" | "drafts" | "trash" | "junk" (resolved via Mail's
unified, cross-account accessors). query: optional
subject substring — an empty/omitted query lists ALL messages in the mailbox
(bounded), unlike mail/get_pointers which rejects an empty query. Use this to
confirm an attachment landed on a DRAFT before it's saved (a freshly opened compose
window has no stable id yet — once saved to Drafts it does, see drafts()).
message_id: address ONE message instead of scanning; with no mailbox the id
resolves on its own (Full Disk Access), and query is then ignored. Prefer it when
you know the message — a mailbox scan stops at 25 records, so the one you meant is
often past the cap. Either mailbox or message_id is required.
Returns {results, truncated?} over
[{id, deeplink, folder, summary, attachments: [{name, size, downloaded}]}].
id/deeplink identify the carrying message and folder names the mailbox read,
so a row is actionable on its own. An unsaved draft has no message-id yet:
its id is "" and it carries no deeplink — it is still listed.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No | ||
| mailbox | No | ||
| message_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and destructiveHint=false, and the description adds meaningful behavioral context beyond them: bounded mailbox scans, truncation, empty-query listing behavior, Full Disk Access resolution for message_id, and the unsaved-draft edge case where id is empty and deeplink is absent.
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 front-loaded and dense with useful distinctions, but it is long and parenthetical-heavy. It also explains the return shape despite an output schema existing, which is somewhat redundant, though the return semantics around actionable rows and unsaved drafts still add value.
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 output schema and read-only annotations, the description is complete enough for correct invocation: it covers all parameters, alternatives, required input combinations, scan limits, and key edge cases. Nothing essential for selecting or calling the tool appears 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?
Schema description coverage is 0%, so the description must compensate, and it does for all three parameters. It explains mailbox as an opaque imap token or canonical system mailbox, query as an optional subject substring with special empty-query behavior, and message_id as a single-message selector that ignores query and can resolve without mailbox.
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 opening sentence uses a specific verb and resource: 'List attachments' on messages in a Mail mailbox or on one message. It distinguishes mailbox scanning from single-message lookup, and references related tools like mail_search, mail/get_pointers, and drafts to disambiguate usage.
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 explicit routing guidance: use mailbox for a folder scan or message_id for one known message, prefer message_id because scans stop at 25 records, query is ignored when message_id resolves on its own, and either mailbox or message_id is required. It also states a concrete use case: confirming an attachment landed on a draft before saving.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_awaiting_replyARead-only
Messages YOU sent more than days ago (1–365, default 3) with no reply, ranked
oldest-first, reason awaiting-reply. Uses real In-Reply-To/References threading. A
group send is cleared once any recipient replies. Each pointer carries
folder = "sent" — ready for mail_body/reply_all; no account (the scan spans
every account, see mail_needs_response). Returns {results, truncated?}; truncated
means the 25 cap was reached. Read-only. Fast path reads Mail's index at rest
(needs Full Disk Access; never launches Mail); without it, degrades to an
AppleScript scan — Automation access is the floor, and that path is SLOW on a
large store.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint annotation: threading via In-Reply-To/References, group sends cleared on any reply, a hard 25-result cap surfaced as `truncated`, and the operational prerequisites (Full Disk Access fast path vs. SLOW AppleScript fallback). This is exactly the context an agent needs before committing.
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?
Front-loaded with the core definition, then scope, then operational caveats — every sentence adds information. It is dense with parentheticals and backticked identifiers, which costs a little readability.
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?
Covers filter semantics, ordering, scope, result cap, output-flag meaning, downstream tool compatibility, and access requirements. Even without relying on the output schema, an agent knows what it will get and what it costs.
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 0%, so the description must carry the load — it supplies the meaning of `days` (sent more than N days ago) plus the 1–365 range and default, none of which the schema encodes. Only a small gap remains (no note on invalid values).
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 resource (messages you sent) with a precise filter (no reply, older than `days`, oldest-first) and even the reason label `awaiting-reply`. An agent can distinguish it from mail_needs_response and mail_search without opening any schema.
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 clarifies the account-spanning scope versus mail_needs_response and says pointers are ready for mail_body/reply_all, which orients the agent in a workflow. It never states an explicit 'use this instead of X when...' exclusion, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_bodiesARead-only
Plaintext bodies for up to 20 message ids in ONE call — the bulk read behind
"catch me up on this thread". Opt-in and bounded: reading a thread stays
mail_search -> mail_thread -> mail_bodies, three calls total, and with
mail_thread(snippets=True) often only two.
Returns {"results": [{"id", "body"}], "missing": [ids]}. An id whose message can't
be read off disk is listed in missing — it is NEVER returned with an empty body,
so "unreadable" is never mistaken for "the sender wrote nothing". Each body is
truncated at the usual per-body budget with an explicit marker; if the batch total
is too large the call REFUSES (output_overflow) rather than dumping — ask for fewer
ids.
Reads Mail's message files at rest: fast, no Mail launch, and it sees messages that arrived seconds ago (unlike the mail_search(body=) FTS index, which only knows what mail_index_bodies last swept). Read-only. Needs Full Disk Access.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond readOnlyHint/destructiveHint=false: discloses that unreadable ids land in `missing` rather than returning empty bodies, that bodies are truncated with an explicit marker, that oversized batches REFUSE with output_overflow, that it reads files at rest without launching Mail, and that Full Disk Access is required. That is a rich behavioral profile; a 5 would need detail on the actual per-body budget size.
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?
Front-loads the verb, resource and batch limit, then layers failure modes and storage semantics in short, scannable clauses. Dense but nearly every sentence earns its place; the parenthetical about 'the sender wrote nothing' and the FTS-index comparison slightly pad an already-long block.
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?
Covers what an agent needs to call correctly and recover from failure: batch cap, truncation, overflow refusal with a remedy ('ask for fewer ids'), missing-id semantics, permission prerequisite, and freshness versus the index. An output schema exists, so the extra return-shape prose is surplus but harmless.
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 0% and the single `ids` array is undocumented in the schema, so the description carries the burden — it supplies the meaningful constraint (up to 20 ids) and defines what happens to invalid/unreadable ids. It does not say what id format is expected (RFC message-id vs Mail's internal id), which leaves one real gap.
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 ('Plaintext bodies for up to 20 message ids in ONE call') with an explicit scope limit and a use-case gloss ('the bulk read behind "catch me up on this thread"'). The batch framing plus the mail_body sibling name differentiates it from the single-message reader without opening either schema.
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?
Prescribes the exact call path (mail_search -> mail_thread -> mail_bodies) and notes the shorter path via mail_thread(snippets=True), plus the opt-in/bounded framing. It also contrasts itself against the mail_search(body=) FTS index, telling the agent which source is fresher.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_bodyARead-only
Full plaintext body of one message by id (bounded + truncation-marked).
id is a message-id from mail/mail_search — or from a note written months ago:
an id resolves ON ITS OWN, so a stored citation still works after the message was
filed or moved. mailbox is OPTIONAL and is the disambiguator: pass the folder
value from the SAME search result back VERBATIM — it is an opaque round-trip token
(imap://<uuid>/<path>), not a folder name to retype — or one of the five canonical
names ("inbox"/"sent"/"drafts"/"trash"/"junk"). With it the read is Automation-only
and an id absent from that mailbox raises; without it the id is resolved through
Mail's index (Full Disk Access) to the same copy every other read cites. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| mailbox | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial behavior beyond the readOnly/destructive annotations: bounded and truncation-marked output, id resolution independent of mailbox, Automation-only path with mailbox, and index/Full Disk Access fallback without it. These details give the agent a clear behavioral model without contradicting the annotations.
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?
Front-loads the purpose and then parameter rules, with no obvious fluff. It is dense and longer than typical, but the length is largely justified by the zero schema coverage; minor tightening is possible.
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?
With an output schema present, the description appropriately focuses on input semantics and behavior. It covers id sourcing, mailbox token handling, error behavior, and access paths, leaving little needed before invocation.
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 0%, so the description carries the full burden and does so: id is a message-id that resolves on its own, and mailbox is an optional disambiguator that must be passed verbatim as an opaque imap:// token or canonical name. It also explains the consequence of including or omitting mailbox.
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?
Opens with a specific verb and resource ('Full plaintext body of one message by id') and adds scope ('bounded + truncation-marked'). It does not explicitly differentiate from sibling body tools such as mail_bodies or message_body, so the one-message-vs-many distinction is left implicit.
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?
Explains where the id comes from (mail/mail_search, stored citations) and the two modes for the optional mailbox parameter, including that an id absent from the mailbox raises. It lacks an explicit comparison to sibling tools, so it stops short of full when-to-use guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_duplicatesARead-only
Where Mail is storing redundant copies of the same message — a REPORT, read-only.
Mail accumulates duplicate rows (a UI drag copies rather than moves, Gmail shows one
message under a label and All Mail, migrations leave copies on two accounts). The
read tools already hide them — mail_search/mail_thread/mail_overview report
result per Message-ID — so this exists to show what is still physically there.
Returns {redundant, mailboxes, worst, cross_account, note}: mailboxes is
{mailbox_url, total, distinct_, redundant} per mailbox worst-first, worst names
individual messages with the most copies ({mailbox_url, id, subject, copies}), and
cross_account counts rows whose Message-ID also exists under another account.
This tool CANNOT delete anything. Cleaning up is macos-apps-mcp dedupe-mail, run
a terminal by the user — thousands of deletes is a job a human starts, not a tool
call. Tell them that command rather than proposing per-message deletes.
Fast and read-only, straight from Mail's index at rest (so it may lag Mail by a few
minutes and never launches Mail). Needs Full Disk Access.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds substantial context beyond the readOnly/destructive annotations: index freshness lag, no Mail launch, Full Disk Access requirement, cross-account counting, output shape, and the inability to delete. These details materially affect correct invocation and user guidance.
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 opening sentence front-loads the purpose and read-only nature, and most follow-up detail is useful. It is somewhat long and repeats read-only information already in annotations, but the density is justified for a report tool with cleanup guidance.
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?
Complete for this tool: it covers purpose, output fields, read-only behavior, freshness, permissions, cross-account semantics, and the correct cleanup path. The output schema exists, but the prose still gives enough context for an agent to use and explain 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 single optional `limit` parameter has 0% schema description coverage and is never mentioned in the description. It is unclear whether `limit` caps mailboxes, worst-message entries, or rows, so the description does not compensate for the missing schema documentation.
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 resource and report action: it shows where Mail physically stores redundant duplicate copies. It also explicitly distinguishes this report from read tools like mail_search/mail_thread/mail_overview, which already hide duplicates.
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?
Explains exactly when to use it: when the agent needs to see remaining physical duplicates that normal read tools hide. It also states what not to do by clarifying this tool cannot delete and directing cleanup to the external dedupe-mail command.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_index_bodiesARead-only
Build/refresh the opt-in FTS body index used by mail_search(body=…). Reads every
.emlx file at rest, .partial ones included (never launches Mail, never writes in
Mail's data). Resumable and size-capped — safe to re-run; a re-run continues where
it left off. rebuild=True re-indexes from scratch. Returns {indexed, skipped,
total_emlx, capped, indexed_this_run}. Read-only for Mail; the one thing it writes
is this server's own FTS sidecar. Needs Full Disk Access (it reads .emlx at rest),
NOT Automation.
indexed_this_run is THIS RUN's progress, NOT coverage: a resumable indexer's own
counters cannot say how much of the store is searchable (a fully-indexed store
re-runs as "14 newly indexed"). mail_search(body=…) is the one place that answers
"is body search usable?", and it does so on the path that needs it — an empty
result.
A .partial.emlx is missing its ATTACHMENTS, not its body, so partials are indexed
like any other message (#119). The residual unsearchable tail is ~0.5%: messages
Mail never stored a text part for.
| Name | Required | Description | Default |
|---|---|---|---|
| rebuild | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description contradicts the readOnlyHint=true annotation: it says the tool builds/refreshes an index and explicitly writes the server's own FTS sidecar. Even though it clarifies that Mail's data is not modified and that Full Disk Access is required, the tool-level readOnly annotation is inconsistent with the disclosed sidecar write.
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 front-loaded and information-dense, but it is long and includes some repetition around resumability and safe re-runs. Most sentences add real value, though the prose could be tightened without losing meaning.
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 covers permissions (Full Disk Access, not Automation), write scope (Mail untouched, FTS sidecar written), resumability and size caps, partial .emlx handling, residual unsearchable tail, and return-shape context. This is highly complete for a complex indexing 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 0%, but the description fully explains the only parameter: rebuild=True re-indexes from scratch, while normal runs resume where they left off. That is exactly the semantic detail an agent needs beyond the bare boolean 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 states a specific verb and resource: build/refresh the opt-in FTS body index used by mail_search(body=…). It clearly scopes what is indexed and how it relates to a sibling consumer tool, leaving little ambiguity about the tool's purpose.
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 explains resumability, safe re-runs, and when rebuild=True applies, and it routes the question 'is body search usable?' to mail_search(body=…). It does not explicitly compare against other index-related siblings such as mail_index_ids, but the operational guidance is otherwise clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_index_idsARead-only
Build/refresh the Message-ID sidecar that enables the sqlite mail plane on
macOS 15 (Sequoia) and earlier (#201). Those systems' Envelope Index never stored
the RFC822 Message-ID (#199); this harvests it headers-only from the .emlx files
at rest into this server's own sidecar — never launches Mail, never writes in
Mail's data. On macOS 26+ the index has the column natively and this build is
unnecessary. Safe to re-run: a re-run harvests only what is missing and retries
messages whose files had not been downloaded yet; rebuild=True starts from
scratch. A full first build reads every message's headers — about a minute per
35k messages on a slow disk. Returns {harvested, mapped, total_ids, coverage,
skipped_no_file, skipped_no_message_id, rows_without_local_store,
high_water_rowid, index_rebuilt}. coverage is the number that matters:
messages it could not map stay uncitable, exactly as they would be on macOS 26
until Mail backfills its own column. Read-only for Mail; needs Full Disk Access
(it reads .emlx at rest), NOT Automation.
| Name | Required | Description | Default |
|---|---|---|---|
| rebuild | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description says it builds/refreshes a sidecar and that rebuild=True starts from scratch, which implies persistent writes to server-side storage. This conflicts with the annotation readOnlyHint=true, even though the description limits read-only behavior to Mail's data specifically.
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 purpose is front-loaded and the information is dense and useful, including auth and performance context. It is somewhat overlong and redundantly lists return fields despite an output schema, but most sentences still carry meaningful operational detail.
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?
Covers the key operational context: macOS applicability, Full Disk Access versus Automation, safety for Mail, re-run semantics, performance expectations, and coverage interpretation. Given the output schema, the remaining return-field explanation is extra rather than 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?
Although the schema provides 0% parameter description coverage, the description fully explains the single rebuild boolean: default re-runs harvest only missing data, while rebuild=True starts from scratch. This adds the exact semantics an agent needs.
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: build/refresh a Message-ID sidecar for the sqlite mail plane on macOS 15 and earlier. It also explains the OS boundary where it is unnecessary, so an agent can distinguish it from related mail-index 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?
Explicitly says when the tool is needed (macOS 15 and earlier without native Message-ID storage) and when it is unnecessary (macOS 26+). It also clarifies re-run behavior and the effect of rebuild=True, giving clear invocation guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_needs_responseARead-only
Inbox messages that likely need your response, ranked with a machine-readable
reason (flagged / unread-direct / unanswered-direct). Heuristic over headers +
message properties — no body is read; keeps direct-addressed, not-yet-replied mail.
Each pointer carries folder = "inbox", so an id from here goes straight into
mail_body/mail_reply with no second lookup. No account: this reads Mail's
unified inbox across every account, so the owning account is genuinely unknown —
use mail_search when you need it. Returns {results, truncated?}; truncated
means the 25 cap was reached. Read-only; needs Automation access for Mail.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Far exceeds what annotations cover: discloses the heuristic basis (headers + message properties, no body read), the 25-result cap and the meaning of truncated, and the Automation permission requirement. These are exactly the behaviors an agent needs before calling, none of them stated by readOnlyHint/destructiveHint.
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?
Front-loaded with purpose and reasons, then constraints, then output shape and permissions — well ordered with no filler. It is dense and slightly crammed (reason codes, folder contract, cap, auth in one block), but every sentence carries operational value.
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 an output schema exists, the description still clarifies the important return semantics (truncated = 25 cap reached) and the reason taxonomy. Combined with permission requirements, the fixed folder contract, and the zero-param rationale, an agent has everything needed to call and interpret it.
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?
With zero parameters the baseline is 4, but the description explains the implicit design decisions that a schema cannot: why there is no account argument (unified inbox, owner genuinely unknown) and the fixed folder='inbox' that makes returned ids directly reusable. That is real added meaning, not schema repetition.
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+resource ('Inbox messages that likely need your response') plus the ranking signal (reason codes flagged/unread-direct/unanswered-direct), and explicitly names a sibling (mail_search) it is not. An agent can distinguish this from mail_awaiting_reply or mail_overview without opening the schema.
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 an explicit routing rule: use mail_search when the owning account matters, since this tool spans the unified inbox so account is unknown. It also states the ids are directly usable in mail_body/mail_reply, removing a lookup step. It does not, however, contrast with the similarly named mail_awaiting_reply sibling, leaving one ambiguous boundary.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_overviewARead-only
Every mailbox with its message total and unread count, unread-first — the triage
entry point ("what's unread where?"). Rows are {account, account_id, mailbox,
folder, total, unread}: account_id is the same uuid every mail Pointer reports as
account, so ONE call here is the whole uuid -> name map; folder is the exact
mailbox url, so a mailbox picked here round-trips into mail_search/mail_body
without going back through name matching. Includes Junk/Trash/All Mail so you can
see what they are rather than having them silently filtered. Counts are computed
live, not read from Mail's own stored counters, which go stale, and each message is
counted ONCE even when it is filed in the same mailbox twice.
Account NAMES are looked up through Mail, so this tool does contact Mail (launching
it if it isn't running); when Mail is unreachable the account UUID stands in and
the counts — which never needed Mail — are still correct. An account Mail answers
but does not list (for example a removed one) shows "(account not in Mail)" as its
account; account_id keeps the uuid. The On My Mac store is
always shown as "On My Mac": Mail never lists it as an account.
Fast and read-only. Needs Full Disk Access for the counts and Automation access for
Mail for the account names.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly/non-destructive annotations, it discloses that the tool contacts and may launch Mail, that counts remain correct without Mail, the fallback UUID-as-name behavior, the '(account not in Mail)' sentinel, the always-shown 'On My Mac' store, live vs. stale counting, double-filing dedupe, and both required permissions (Full Disk Access, Automation). That is unusually rich behavioral context for a read-only 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?
Purpose and the triage use case are front-loaded, and nearly every sentence carries operational information the agent needs (uuid mapping, folder round-trip, permission needs). It is dense and includes a small amount of overlap with the annotations ('Fast and read-only'), which keeps it just below a 5.
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-param read-only tool with an output schema, the description is complete: it covers what is returned, edge cases (unlisted account, On My Mac, unreachable Mail), counting correctness, and permission prerequisites. Nothing an agent needs to call it safely and interpret results 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 is no parameter meaning to add and baseline is 4. The description instead specifies the row shape and field semantics ({account, account_id, mailbox, folder, total, unread}), which is value-add even if it belongs more to output semantics than parameters.
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 opening sentence names the verb, the resource, the scope (every mailbox), and the differentiator ('unread-first'), and frames it as the triage entry point. An agent can tell immediately this is a survey/count tool rather than a search or body-fetch tool.
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 clearly implied with 'triage entry point ("what's unread where?")' and the concrete follow-on workflow into `mail_search`/`mail_body` via the round-tripping `folder` url. It stops short of explicitly distinguishing itself from siblings like `mail_stats` or naming when not to use it, so it is clear context without exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_replyA
Reply to a message, opening a threaded draft for review (Automation).
NEVER sends. message_id: the RFC822 id from a mail read. mailbox is REQUIRED: the
folder value from the SAME search result, passed back VERBATIM (an opaque
imap://<uuid>/<path> token; the five canonical names also work). Mail sets the
threading headers natively; include_quote appends the quoted original. Returns a
locator dict — save the draft to Drafts and drafts() resolves it by a stable
message-id.
THE AUTOSAVE WINDOW: that message-id is stamped only when Mail autosaves the draft,
~10-15 SECONDS after this returns — asynchronously, and nothing can hurry it. So
drafts() called immediately shows nothing; that is normal, not a failed create.
Wait for the window, then drafts() resolves it. Do NOT retry this call
because the draft has not appeared: you get two drafts and the first still arrives.
Note a reply draft cannot be sent with send_mail(draft_id=…) — rebuilding it
would drop the threading headers, so that call refuses and points you at
reply_all(dry_run=False) instead.
| Name | Required | Description | Default |
|---|---|---|---|
| mailbox | Yes | ||
| message_id | Yes | ||
| reply_body | Yes | ||
| include_quote | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=false and destructiveHint=false, but the description adds far more: threading headers are set natively, an async ~10-15 second autosave window applies, and retrying produces duplicate drafts. These are exactly the non-obvious traits an agent cannot infer from structured fields.
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?
Front-loaded and well-sectioned: purpose first, then parameter guidance, then the autosave caveat. It is dense and the autosave paragraph runs long with emphasis formatting, but nearly every sentence carries operationally necessary information, so little is wasted.
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?
An output schema exists, so return values need not be spelled out, yet the description still notes it returns a locator dict and how drafts() resolves it. Combined with the send-path exclusion and the retry hazard, an agent has everything needed to call and chain this 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?
With 0% schema description coverage, the description carries the burden and mostly does: message_id is defined as the RFC822 id from a mail read, and mailbox is explained in detail (REQUIRED, the `folder` value from the same search result, verbatim opaque imap:// token, canonical names also accepted), plus include_quote appends the quoted original. reply_body is left to the parameter name, a minor but real gap.
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 specific verb and resource ('Reply to a message, opening a threaded draft for review') and immediately adds the key differentiator 'NEVER sends'. An agent can distinguish this from create_draft (new draft) or a send operation without inspecting any schema.
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 explicit when-not rules: do NOT retry if the draft does not appear, and the resulting draft cannot be delivered via send_mail(draft_id=…) because that call refuses and redirects to reply_all(dry_run=False). It also names the correct follow-up (save to Drafts, then drafts()) and the required waiting window.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_searchARead-only
Indexed search across ALL mailboxes via Mail's Envelope Index — fast and
read-only. All filters optional and ANDed:
subject/from_/to substrings, mailbox a mailbox NAME exactly as mail_overview
reports it ("Junk E-mail" — case-insensitive substring; the encoded spelling also
works; a name that matches nothing RAISES — it is a typo, not an empty mailbox —
while a stale folder url just returns no results), since/until (epoch seconds on
received date),
unread/flagged. body searches message TEXT via the FTS index and is BEST-EFFORT —
it only sees messages already indexed by mail_index_bodies (run that first;
incomplete coverage is normal). At least one filter required. Returns citable
Pointers, newest first. Falls back to AppleScript inbox search on missing Automation
access / schema drift.
has_attachments means a real DOCUMENT — inline signature/newsletter images are
excluded, so it will not match a mail whose only attachment is a logo. account
takes a display name ("Personal") or a raw account UUID; the UUID form stays pure
sqlite, while a NAME has to be resolved through Mail and therefore LAUNCHES Mail if
it isn't running (an unknown name raises rather than guessing). Every other filter
reads the index at rest and never launches Mail.
Read-only; needs Full Disk Access, plus Automation access for Mail on the
account-name path and the AppleScript fallback.
Each Pointer carries folder (the round-trip mailbox token) and account (the
owning account's uuid — map it to a name with one mail_overview call), so a hit
is complete on its own: no second read to work out where it lives.
Returns {results, truncated?, plane?, coverage?}. truncated means the answer came
back AT limit (25 max) and there may be more — do NOT report such a search as
exhaustive. plane = "applescript-inbox" means the sqlite index was unreachable and
this scanned the INBOX ONLY. coverage explains an empty body= answer: bodies are
only matchable once mail_index_bodies has indexed them.
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | ||
| body | No | ||
| from_ | No | ||
| limit | No | ||
| since | No | ||
| until | No | ||
| unread | No | ||
| account | No | ||
| flagged | No | ||
| mailbox | No | ||
| subject | No | ||
| has_attachments | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds extensive behavior beyond the readOnlyHint and destructiveHint annotations: Full Disk Access and Automation requirements, AppleScript inbox fallback on missing access or schema drift, mailbox typos raising errors, body-index coverage limits, and account-name resolution potentially launching Mail. It also explains result fields such as truncated, plane, and coverage so the agent can interpret partial or degraded outcomes.
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?
Despite being long, the length is justified by the tool's 12 parameters and complex fallback/permission behavior. The purpose and core filters are front-loaded, and the remaining sentences each add operational meaning rather than repeating schema or annotations.
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?
With annotations, an output schema, and 12 undocumented parameters, this description covers the missing context an agent needs to call the tool correctly. It explains permissions, fallback behavior, best-effort body search, error conditions, truncation, and how to interpret the returned coverage and plane fields.
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 0%, so the description carries the full burden and does so thoroughly for all 12 parameters. It defines substring semantics for subject/from_/to, mailbox-name matching rules, epoch-second date filters, unread/flagged flags, body-index best-effort behavior, has_attachments document semantics, account display-name versus UUID behavior, and limit via the 25-max truncation note.
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 specific verb and resource: indexed search across ALL mailboxes via Mail's Envelope Index, fast and read-only. It clearly distinguishes this tool from siblings by naming mail_overview and mail_index_bodies where their roles matter, and by explaining scope such as all mailboxes and optional ANDed filters.
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 explicitly states conditions: at least one filter is required, body search requires mail_index_bodies first and is best-effort, mailbox names must match mail_overview output, and account-name lookups launch Mail while UUID lookups stay pure sqlite. It also tells the agent not to treat a truncated result as exhaustive, which is a usage constraint beyond basic invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_statsARead-only
Mail volume, read ratio and top senders over the last days (Full Disk Access).
Pure Envelope Index — never launches Mail. Counted per DISTINCT message, not per
row: the same message filed twice is one message (raw rows overcount by up to 3.6x
on a real store). account takes a raw account UUID — the account field every
mail Pointer and mail_overview row carries — not a display name.
Returns a compact aggregate: {window_days, since, messages, unread, read_ratio,
flagged, with_attachments, per_day, busiest_day, top_senders[10],
top_mailboxes[10], plane}. Deliberately token-bounded: top-N only, no per-day
series. top_mailboxes carries the decoded name plus folder (the round-trip url)
and the account uuid — map the uuid to a name with one mail_overview call.
Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| days | No | ||
| account | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/destructiveHint, and the description adds genuinely new behavioral facts: it reads the Envelope Index only and never launches Mail, it counts DISTINCT messages (raw rows overcount up to 3.6x), and output is deliberately token-bounded with top-N instead of per-day series. The trailing 'Read-only.' merely repeats the annotation, but the surrounding disclosures are substantive.
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?
Front-loaded with the one-line purpose, then progressively adds constraints and output shape; the deduplication warning and the account-UUID caveat each earn their space. The enumerated return-key list is somewhat verbose given an output schema exists, though it doubles as guidance on what is and isn't included (top-N, no per-day series).
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 two-parameter read-only aggregate with an output schema and clear annotations, nothing material is missing: prerequisite access, counting semantics, parameter format, output shape and the follow-up call to resolve account UUIDs are all covered. An agent could call this correctly without inspecting anything else.
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 0%, so the description carries the burden and largely does: `days` is defined as the lookback window, and `account` is explicitly described as a raw account UUID — the same UUID carried by mail Pointer and mail_overview rows — not a display name. That is exactly the disambiguation an agent needs; only the default values/edge behavior are left to 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?
States a specific resource and metric set ('Mail volume, read ratio and top senders over the last `days`') and frames the scope as an aggregate over the whole store, which cleanly separates it from per-message siblings like mail_search and mail_thread. The parenthetical '(Full Disk Access)' and the 'never launches Mail' clause further pin down what kind of tool this is.
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 trigger context (summary statistics over a day window rather than message listing) and an explicit follow-up path: 'map the uuid to a name with one `mail_overview` call.' It also states the Full Disk Access prerequisite. It stops short of naming an explicit alternative tool and when-not-to-use condition, so it is strong but not complete routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_threadARead-only
Every message in the conversation containing id, oldest-first — the transcript,
including messages YOU sent. Deduped: a message filed in several mailboxes appears
once. Returns {results, truncated?} of citable Pointers. Over limit messages the
OLDEST are dropped (and truncated says so), since a thread is usually read to
reply to it. Unknown id returns no results.
snippets=True adds a short snippet (first ~200 chars of the body) to each
pointer, read off disk in one pass — no Mail launch and no extra calls. Use it to
see WHO SPOKE LAST and roughly about what before deciding which messages are worth
hydrating; then mail_bodies(ids) for the few that are. A message whose body can't
be read carries no snippet key at all (absent, not empty). Leave it off for a
long thread you only need to enumerate.
Fast, read-only, no Mail launch. Needs Full Disk Access.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| limit | No | ||
| snippets | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover safety (readOnly, non-destructive); the description adds substantial context beyond them: dedupe behavior, truncation direction (oldest dropped) and its `truncated` signal, empty results for unknown ids, snippet read off disk with no Mail launch, and the Full Disk Access prerequisite. It even specifies that an unreadable body yields an absent `snippet` key rather than an empty one.
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?
Front-loaded with the core purpose and structured around the snippets decision, so it reads well. Minor redundancy — 'no Mail launch' is asserted twice ('no Mail launch and no extra calls' and 'Fast, read-only, no Mail launch') — keeps it just short of a 5.
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 3-parameter read tool with an output schema, the description covers everything an agent needs: return shape, truncation direction, unknown-id behavior, snippet opt-in cost, and the FDA permission requirement. Nothing material is left to inference.
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 0%, so the description must carry the load — and it does: `id` identifies the conversation, `limit` controls truncation with the oldest messages dropped when exceeded, and `snippets=True` toggles a ~200-char body preview with explicit absent-key semantics. All three parameters gain meaning beyond their bare types.
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: every message in the conversation containing `id`, oldest-first, including messages the user sent, with dedupe across mailboxes. An agent can immediately distinguish this from mail_bodies, mail_body, or mail_search without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the agent: use `snippets=True` to see who spoke last, then `mail_bodies(ids)` for the few worth hydrating; leave snippets off for a long thread you only need to enumerate. Both the when and the when-not are stated alongside the named alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mail_undoADestructive
Undo one recoverable Mail operation by its receipt id (from move_mail's
result, or from audit). A move is undone by moving the messages back to the exact
mailbox each came from — recorded per message before the original ran.
dry_run DEFAULTS TO TRUE: preview which messages would be restored, then pass
dry_run=False. The undo is itself backed up, logged and verified, and returns its
own receipt — so an undo can be undone. A receipt for an operation with no
destination mailbox cannot be replayed; the error names the directory holding the
preserved message bytes for manual re-import.
Undoing a batch moved into a mailbox that already held pre-existing copies of the
same Message-ID moves those copies back too — the by-ID act moves every copy of a
Message-ID, and undo is an ordinary move. A receipt whose targets recorded
unknown (a timeout mid-act) is replayed the same as ok.
A move into a Gmail label folder or a unified mailbox name cannot be replayed; the
error names the source folder and how to restore by hand.
Destructive (it moves mail); needs Automation access for Mail and Full Disk Access.
| Name | Required | Description | Default |
|---|---|---|---|
| dry_run | No | ||
| receipt | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, and the description adds substantial context beyond that: the undo is itself backed up, logged, verified, and yields its own receipt (an undo can be undone); it discloses permissions required (Automation for Mail, Full Disk Access) and multiple failure modes with recovery guidance. This is unusually rich disclosure for a 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?
Front-loaded with the verb and identifier, then proceeds in escalating edge cases. The batch Message-ID caveat is dense but material; a couple of sentences (e.g., the 'unknown' timeout replay) could be tightened, keeping this below a perfect score.
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?
An output schema exists so return shape needn't be described, yet the description still notes that the call returns its own receipt. Combined with the dry-run workflow, permission requirements, and named failure modes, nothing essential for 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?
Schema coverage is 0%, so the description carries the full burden, and it does: 'receipt' is defined via its producers (move_mail result, audit), and 'dry_run' has its default, purpose (preview which messages would be restored), and override instruction spelled out. No ambiguity remains for either 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?
Opens with a specific verb+resource ('Undo one recoverable Mail operation') and names the identifier source ('receipt' from move_mail's result or from audit). An agent can immediately tell this apart from move_mail, trash_mail, and audit.
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?
States exactly where to obtain the receipt, warns that dry_run defaults to true and must be set to False to act, and enumerates the cases where undo cannot be replayed (no destination mailbox, Gmail label folder, unified mailbox name). The routing to move_mail as the producer of the receipt is explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
message_bodyARead-only
Full text of one Message by id (chat.db, read-only). Decodes the attributedBody
typedstream when message.text is NULL (the modern norm); returns "" for a message
with no text. Needs Full Disk Access. id is a message guid from messages_search or
messages_with.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only annotations, the description discloses that it reads chat.db, decodes attributedBody typedstream when message.text is NULL, returns an empty string for a message with no text, and requires Full Disk Access. These are meaningful behavioral and operational details an agent would not get from annotations alone.
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 purpose is front-loaded in the first clause, followed by the decoding edge case, auth requirement, and parameter source. Every sentence adds useful information with no repetition or 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 a single required parameter and an output schema, the description covers the key gaps: parameter provenance, NULL-text decoding behavior, empty-string return, and Full Disk Access. Nothing essential for correctly calling and interpreting this tool 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?
Schema description coverage is 0%, so the description must carry the parameter explanation. It does so by defining `id` as a message guid obtained from messages_search or messages_with, which is sufficient for correct invocation, though it omits format details such as guid shape.
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: retrieve the full text of one Message by id from chat.db. It clearly distinguishes this from messages_search and messages_with by identifying them as the source of the guid rather than the tools that return the body.
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 tells the agent where the `id` comes from, naming messages_search and messages_with as the upstream tools, which implies this is a follow-up lookup. It does not explicitly state when not to use it or name alternatives for retrieving message text, so it stops short of full routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messages_chatsARead-only
List Messages conversations (id + name). No content; sending isn't supported. Read-only; needs Automation access for Messages.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the description needn't restate safety; it instead discloses two non-obvious traits: the response carries no message content, and the tool requires Automation permission to be granted in Messages. It does not mention limits, pagination, or ordering of the returned conversations.
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 short clauses, each carrying distinct information: what it returns, what it does not do, and what permission it needs. Nothing is repeated from the annotations or schema, and the scope statement leads.
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 read-only listing tool with an output schema, the description covers scope, exclusions, and the auth prerequisite. The only remaining gap is volume/ordering behavior (how many conversations come back), which matters for an agent deciding whether to page or narrow the call.
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 the baseline of 4 applies. The description correctly describes the output fields ('id + name'), which is a bonus rather than a substitute for parameter documentation.
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 Messages conversations') and bounds the payload ('id + name'), which is enough to separate it from content-fetching siblings like message_body. It does not name the alternative tools (messages_search, messages_with) explicitly, so it stops short of full sibling differentiation.
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?
'No content; sending isn't supported' sets clear boundaries and implies this is a discovery/enumeration step rather than a search or send operation. It adds the precondition 'needs Automation access for Messages', which is actionable guidance an agent must have before calling.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messages_searchARead-only
Search Messages by text content (chat.db, read-only), newest first. Pointers:
id=message guid, summary=[date] sender: snippet. Needs Full Disk Access (raises a
typed error if not granted). Text-only for now; sending isn't supported.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish readOnlyHint=true and destructiveHint=false, and the description adds genuinely new behavior: newest-first ordering, a hard Full Disk Access requirement with a typed error on failure, and an explicit 'sending isn't supported' limitation. It stops short of covering result caps or pagination, but the extension beyond annotations is substantial.
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 short sentences, all front-loaded: scope and ordering first, then result-shape pointers, then the access prerequisite and the text-only constraint. No filler and nothing buried at the end.
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?
With annotations covering safety, an output schema covering return values, and the description covering the auth prerequisite, ordering, and capability limits, an agent has nearly everything needed to call it correctly. The only real omission is any guidance on the 'limit' parameter or result-size ceilings.
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 0%, so the description carries the burden. 'Search by text content' implies how 'query' is matched, but 'limit' is never mentioned in either the schema or the description, and the return pointer note (id/summary format) explains output rather than inputs.
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 ('Search Messages by text content') plus the backing store (chat.db) and ordering (newest first). It implicitly separates itself from messages_chats and messages_with, but it never names those siblings outright, so an agent must infer the boundary rather than read it.
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 conditions ('Text-only for now; sending isn't supported') and a prerequisite (Full Disk Access), which frames when the tool is applicable. It does not, however, tell the agent when to pick this over messages_with or message_body for similar-looking lookups, leaving that comparison implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
messages_withARead-only
Recent Messages by phone or email (chat.db, read-only), newest-first.
contact a phone number or email; country an optional calling code or 2-letter
region (e.g. '+32' or 'BE') to resolve a national number — default from the Mac's
locale, never +1. Needs Full Disk Access (raises a typed error if not granted).
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| contact | Yes | ||
| country | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint/destructiveHint annotations, the description discloses the data source (chat.db), ordering (newest-first), the Full Disk Access requirement, and the typed error raised when access is missing. It does not cover pagination or rate-limit behavior, but adds meaningful operational context.
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 compact and front-loaded: the resource, source, ordering, contact/country semantics, and access requirement are all presented without filler. Every sentence adds useful 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?
Given an output schema exists, return formatting is not needed. The description covers the key behavioral constraint (Full Disk Access), source and ordering, and two of three parameters. The missing limit semantics and lack of sibling routing guidance are the only notable gaps.
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 0%, so the description must carry parameter meaning. It explains contact as a phone number or email and country as an optional calling code or 2-letter region with a locale-derived default, but it omits the limit parameter entirely, leaving one of three parameters undocumented.
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/resource: recent messages by phone or email, read-only from chat.db, newest-first. It is clear enough to distinguish from general message search, but it does not explicitly name or contrast with siblings such as messages_search or messages_chats.
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 'Recent Messages by phone or email.' The description does not say when this should be used instead of messages_search, messages_chats, or message_body, and it provides no explicit exclusions or routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
move_mailADestructive
Move messages between Mail mailboxes — archive, file, or refile. DESTRUCTIVE but
recoverable: every message's bytes are copied to a backup directory and its source
mailbox is logged BEFORE anything moves, so mail_undo puts the batch back.
dry_run DEFAULTS TO TRUE — the preview reads Mail and reports, per id, whether it
is actually present in from_mailbox. Pass dry_run=False to move.
ids are RFC822 message-ids from a mail read, comma-separated; max 25 per call and
the cap is not overridable. BOTH mailboxes are required and are address tokens.
from_mailbox must be the folder value from the read that produced the ids,
passed back VERBATIM (an opaque imap://<uuid>/<path> token, not a name to
retype); a canonical name there is refused. to_mailbox may also be one of the
canonical "inbox"/"sent"/"drafts"/"trash"/"junk", which files into the SOURCE
message's own account (it names Mail's cross-account accessor, not one mailbox),
so it is refused for an On My Mac source — that store has none of the five. A
Gmail label folder is refused as either end (a move out of a label left a copy
on device, so mail_undo cannot reverse a move into one), and a canonical
to_mailbox is refused when the source account has Gmail label folders. Pass a
folder url from mail_overview when in doubt. To archive, move into a mailbox
named Archive — there is no separate archive tool.
Cross-account moves are supported and leave exactly ONE copy (out of a Gmail label
they do not, which is why a label is refused). Verification is
by-ID (#206): each copy's internal reference must go dead after the move, and the
destination's count of that Message-ID must rise — presence alone can't tell a
landed copy from a pre-existing one. A Message-ID with several copies in the
source gets every one of them moved; ok means every copy left. A per-id
status reports what really happened rather than assuming success. If the call
times out mid-batch, the error names the receipt — re-run the same batch, or
mail_undo it.
Returns {op, receipt, count, succeeded, targets, destination, backup_dir, undo} —
keep receipt to undo the batch. Needs Automation access for Mail,
plus Full Disk Access to locate each message's file for the backup.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| dry_run | No | ||
| to_mailbox | Yes | ||
| from_mailbox | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, and the description aligns with them ('DESTRUCTIVE but recoverable') while adding genuine depth: bytes are backed up and the source logged before anything moves, the 25-id cap is not overridable, cross-account moves leave one copy while label moves are refused, and Automation plus Full Disk Access are required. The only miss is that permission/keychain failure modes beyond the timeout path are not described.
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?
Front-loaded with purpose and destructiveness, and almost every sentence carries an operational constraint that would otherwise cause a failed call. It is nonetheless a dense wall of text with mild redundancy between the Gmail-label-refusal sentence and the later restatement, which costs it the top mark.
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?
Output schema exists so return values need not be explained, yet the description still lists them and tells the agent to keep `receipt` for undo, plus documents per-id `status`, the timeout/receipt recovery path, and the required system permissions. Nothing an agent needs to invoke this safely and correctly 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?
Schema coverage is 0%, so the description must carry the full burden and does: `ids` are RFC822 message-ids, comma-separated, max 25; `dry_run` defaults true; `from_mailbox` must be the verbatim opaque imap:// token from the originating read and a canonical name is refused; `to_mailbox` accepts canonical accessors with a documented On My Mac and Gmail-label refusal. That is far more than the bare types 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?
Opens with a specific verb and resource ('Move messages between Mail mailboxes — archive, file, or refile') and immediately distinguishes itself from siblings by noting 'there is no separate archive tool' and pointing at mail_undo as the reversal path. An agent can tell this apart from trash_mail or delete_draft without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit about when this is the right tool (archiving by moving into an 'Archive' mailbox), about the default preview behavior ('dry_run DEFAULTS TO TRUE … Pass dry_run=False to move'), when to consult mail_overview, and when to re-run vs. call mail_undo after a timeout. Refusal cases are enumerated rather than left to discovery.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
music_controlA
Control Music playback: action in play|pause|playpause|next|previous. Additive, reversible player-state change; needs Automation access for Music. Returns the resulting now-playing state.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, it explicitly discloses that the change is 'additive, reversible player-state change', that macOS Automation permission is required, and that the response is the resulting now-playing state. This is exactly the kind of safety, prerequisite, and side-effect context annotations alone cannot convey, and it is consistent with destructiveHint=false.
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 dense sentences with zero filler: scope and action set first, then side-effect/permission/return semantics. Nothing to trim and nothing front-loaded incorrectly.
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 single-parameter tool with an output schema and non-destructive annotations, the description covers purpose, legal values, side-effect profile, permission prerequisite, and response shape. An agent has everything needed 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?
With 0% schema description coverage and no enum declared in the schema, the description compensates by fully enumerating the legal values for the single `action` parameter. It stops short of explaining each action's edge behavior (e.g. what 'previous' does at track start), which keeps it from a 5.
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 ('Control Music playback') and enumerates the exact action set (play|pause|playpause|next|previous), which cleanly separates it from read-only siblings like now_playing and from playlist/volume tools (play_playlist, set_volume, music_search). An agent can identify what this does without opening the schema.
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 action enumeration implies when each mode applies, and the parenthetical 'needs Automation access for Music' hints at a prerequisite. However, it never routes the agent to alternatives (now_playing for a read-only query, play_playlist for playing a named playlist, set_volume for loudness), nor states when not to use this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
music_searchARead-only
Search the Music library + playlists as pointers. query optional
name/artist/album substring (empty lists all, bounded). Read-only; needs Automation
access for Music. Pointers only (id = persistent ID); no audio plays.
| Name | Required | Description | Default |
|---|---|---|---|
| query | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond readOnlyHint/destructiveHint, the description adds real behavioral context: results are bounded, an Automation permission is required for Music, and the tool returns persistent IDs rather than playing audio. These are exactly the facts that change how an agent calls it.
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 short sentences, each front-loading the most decision-relevant information first (what it searches, how to filter, what it returns). No 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?
An output schema exists so return values need no explanation, and the description still flags the pointer/persistent-ID shape and the permission prerequisite. Nothing an agent needs in order to call this correctly 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?
Schema coverage is 0%, so the description carries the full burden and does: query is optional, matches name/artist/album substrings, and an empty value enumerates all results bounded. That is more than the schema's bare string type communicates.
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 (search) and resource (Music library + playlists) and immediately delimits the output as 'pointers'. The clause 'no audio plays' separates it from playback siblings such as music_control, play_playlist, and now_playing without naming them.
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?
'Empty lists all, bounded' plus 'no audio plays' tells the agent both how to enumerate and when this is the wrong tool for playback. It stops short of explicitly naming music_control as the alternative, which keeps it from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
note_bodiesARead-only
Hydrate plaintext bodies for up to 50 note ids (opt-in; search stays pointer-only). Returns [{"id", "body"}]; unknown ids are silently skipped. Read-only; needs Automation access for Notes. Get ids from notes / notes_all.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the readOnlyHint annotations: discloses the hard cap of 50 ids, that unknown ids are silently skipped (a real failure-mode detail), the return shape, and the Automation-access requirement for Notes. That is precisely the context annotations cannot carry.
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 clauses, no filler. The core action is front-loaded, and the operational caveats (cap, silent skip, permissions, id source) follow in descending order of importance.
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?
An output schema exists so return values need not be described, yet the description still sketches the [{id, body}] payload; combined with the cap, skip behavior, and auth requirement, an agent has everything needed to call this correctly on the first try.
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 0% for the single 'ids' parameter, so the description must compensate — and it does, establishing the max of 50, the silent-skip behavior for unrecognized ids, and the upstream source of valid ids. It stops short of stating format/syntax of an individual id, keeping it at 4.
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 ('hydrate plaintext bodies for note ids') and immediately distinguishes itself from the pointer-only siblings notes / notes_all. An agent can tell exactly what it gets back (plaintext bodies) versus what the list tools return.
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?
Explicitly names where the ids come from ('Get ids from notes / notes_all') and frames the tool as an opt-in second step after pointer-only search. It does not spell out a when-not-to-use case, but the two-step workflow is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
notesARead-only
Search Notes by title, snippet and note body. Returns {results, truncated?, plane?, coverage?}: results are pointers (id + snippet); title/snippet hits come first, body-only hits after. Body words split at spaces and punctuation only, so a word inside unspaced Chinese or Japanese text is found in a title or snippet, never in a body. Read-only. Fast path reads NoteStore.sqlite (needs Full Disk Access) and searches bodies in memory, never on disk, skipping locked notes; without it, degrades to an Automation (Notes) title search, and plane/coverage say so. Automation access is the floor. See notes_all, note_bodies.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond readOnlyHint by disclosing return shape and ordering, CJK tokenization limitations, fast-path NoteStore.sqlite access requiring Full Disk Access, in-memory body search, locked-note skipping, and fallback behavior. This is unusually rich behavioral 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?
Front-loads the purpose and return shape, then moves into access and behavior details. It is dense but mostly earns its place; 'Read-only' duplicates the annotation and 'Automation access is the floor' is slightly cryptic.
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 search tool with an output schema and non-trivial access paths, the description covers return shape, degraded mode, and body-search limitations. It still leaves title-query semantics and sibling choice under-specified, but is largely complete for correct invocation.
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 single parameter title has 0% schema description coverage. The description usefully says search covers title, snippet, and body and explains body tokenization, but it never explicitly defines title as the query string, match type, or exactly how the parameter drives those searches.
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: search Notes by title, snippet, and note body. It names notes_all and note_bodies, but does not explicitly say how this search tool differs from them, so sibling differentiation is only implicit.
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?
Provides useful access context: the fast path requires Full Disk Access, otherwise it degrades to an Automation title search. It also points to notes_all and note_bodies, but never states when to choose this tool over those alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
notes_allARead-only
List the 25 newest notes as pointers (id + "Account / Folder" + snippet), excluding Recently Deleted. Read-only. Fast path reads NoteStore.sqlite (needs Full Disk Access); degrades to Automation (Notes) enumeration without it (very large libraries can hit the osascript timeout, all-or-nothing). See note_bodies.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Well beyond the readOnlyHint annotation it already has: it discloses the full-disk-access requirement for the SQLite fast path, the fallback to Automation enumeration, the osascript timeout risk on very large libraries, and that the fallback is all-or-nothing. This is exactly the operational context an agent needs to interpret partial failure.
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?
Front-loaded with purpose, scope, and exclusions in the first clause, then layered operational detail. It is dense with jargon (NoteStore.sqlite, osascript) but each clause carries distinct information, so little could be cut without losing behavioral signal.
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?
Though an output schema exists, the description still previews the pointer fields, and it covers permissions, degradation, and failure modes for a tool whose behavior varies by environment. Nothing needed to call it correctly or interpret results 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 the baseline is 4. The description correctly describes a parameterless call and adds no misleading guidance about filters or options.
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 with exact scope: 'List the 25 newest notes as pointers (id + Account / Folder + snippet), excluding Recently Deleted.' It also names the field shape returned, so an agent knows exactly what it gets without opening the schema, and it points to the sibling note_bodies for full content.
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 'See note_bodies' pointer plus the pointer-vs-body distinction makes it clear this is the lightweight listing tool, and the fast-path/Automation detail explains environmental selection. It doesn't give an explicit 'use X instead when...' exclusion statement, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
nowARead-only
Current local date, time, timezone, UTC offset, weekday. No permission needed.
Call this FIRST to ground any relative date ("today", "tomorrow", "next Friday") — never guess the date from memory. Every date parameter on the write tools is interpreted in THIS timezone (naive ISO = local time).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, but the description adds meaningful context beyond them: no permission is needed, and the returned timezone governs interpretation of naive ISO date parameters on write tools.
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, front-loaded with the core return values, and then adds the critical usage rule and timezone interpretation note. Every sentence adds useful information without repetition.
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 read-only utility with a clear output schema and read-only annotations, the description is complete. It covers purpose, when to call it, permission behavior, and the downstream timezone semantics that matter for other 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?
The tool has zero input parameters, so there is nothing to document in the schema. The description appropriately focuses on output meaning and timezone semantics rather than inventing parameter guidance.
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 tool returns the current local date, time, timezone, UTC offset, and weekday. This is an unambiguous resource and purpose, and it is readily distinguishable from unrelated siblings such as now_playing.
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 an explicit usage rule: call this FIRST to ground relative dates and never guess from memory. It also explains that date parameters on write tools are interpreted in this timezone, which tells the agent exactly when this tool is required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
now_playingARead-only
Current Music player state + track (name/artist/album/id/position/duration), or {"state": "stopped"}. Read-only; needs Automation access for Music.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, yet the description still adds real context: the exact return payload shape and the stopped-state variant, plus the Automation permission requirement. It stops short of saying what happens when permission is denied (error vs. stopped state), which is the one behavioral ambiguity left.
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 dense sentences with zero filler. The returned fields and the stopped-state fallback are front-loaded, and the permission caveat is appended where it belongs.
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?
An output schema exists, so return values need not be spelled out, yet the description still sketches the payload and the degenerate stopped case, which is the key completeness risk for a state-reader. Only the failure/auth-denied behavior is unaddressed.
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?
Zero parameters, so the baseline of 4 applies; there is nothing about parameter meaning the description could usefully add.
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 names the exact resource (current Music player state plus track fields: name/artist/album/id/position/duration) and even specifies the terminal shape ({"state": "stopped"}). It implicitly but clearly separates itself from the mutating siblings (music_control, play_playlist, set_volume) by being the state reader.
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 — an agent infers it should call this to check what's playing. It gives a prerequisite ("needs Automation access for Music") but never names the sibling control tools or states when to prefer this over them.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
photo_albumsARead-only
List Photos albums as pointers: id = the album uuid, summary = title (n photos), folder = the album's folder path (/ joined) when it sits in a folder.
Returns
{results, truncated?}, at most 100, ordered by folder then title; same-title
albums stay separate. Needs Full Disk Access (osxphotos reads the library at rest).
Read-only; the albums' photos are not listed — search with photos.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/destructiveHint annotations: it discloses the Full Disk Access requirement (osxphotos reads the library at rest), a hard cap of 100 results, the sort order (folder then title), the possible `truncated` flag, and that same-title albums are kept distinct. These are exactly the operational constraints an agent needs before invoking.
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?
Front-loaded with the core purpose and alternatives, then constraints, then the return contract — good ordering with no filler sentences. Minor waste in restating the `{results, truncated?}` return shape, which an output schema already covers.
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, read-only list tool with an output schema, the description supplies everything else that matters: auth prerequisite, result cap, ordering, truncation behavior, and sibling routing. Nothing an agent needs to call it correctly is absent.
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 the baseline is 4 and there is nothing parameter-level to document. The description instead clarifies the semantics of the returned pointer fields, which is supplementary rather than compensating for any schema gap.
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 Photos albums') plus the exact shape of what is returned as pointers (id/summary/folder). It also explicitly distinguishes itself from the `photos` sibling by noting albums' photos are not listed, so an agent can choose between them without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a clear routing rule: this tool enumerates albums, and photo-level search belongs to `photos`. That covers the main alternative, but there is no explicit 'when to prefer this vs. photo_info/export_photo' style guidance or note on when album listing is the wrong entry point.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
photo_infoARead-only
Metadata for one photo by id: id, filename, title, description, kind (photo,
video, live photo), edited, taken/added/modified (ISO-8601), latitude, longitude,
place, persons, camera_make, camera_model, lens, focal_length, aperture,
shutter_speed, iso, width, height. Photo ids come from photos; the old
<UUID>/L0/001 form is accepted too. Reads the Photos library at rest through
osxphotos, so it needs Full Disk Access (not Automation). Read-only; never returns
image bytes, thumbnails or file paths. An unknown or Recently Deleted id raises; a
Hidden one is refused (unhide it in Photos first).
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark it read-only and non-destructive, and the description adds substantial context beyond them: it reads the library at rest via osxphotos, requires Full Disk Access, never returns image data or paths, and documents behavior for unknown, Recently Deleted, and Hidden ids.
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 dense but front-loaded: it leads with the core lookup purpose, then field coverage, id sourcing, permission requirements, and error behavior. Every clause adds actionable information, with no 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 one required parameter, an output schema, and read-only annotations, the description supplies the missing operational context: id provenance, accepted id format, required Full Disk Access, non-return of media bytes, and error conditions. Nothing needed to invoke it correctly appears absent.
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 has 0% description coverage for the single `id` parameter, so the description must compensate. It does: it states the id source ('photos'), accepts the legacy `<UUID>/L0/001` format, and clarifies that unknown or Recently Deleted ids raise.
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: 'Metadata for one photo by id', then enumerates the returned fields. It clearly distinguishes this lookup from sibling media tools by emphasizing it returns metadata only, never image bytes, thumbnails, or file paths.
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 explains where ids come from ('photos'), accepts the legacy `<UUID>/L0/001` form, and gives explicit exclusion/error conditions: unknown or Recently Deleted ids raise, Hidden ids are refused. It also names the required permission, Full Disk Access rather than Automation, which is critical before invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
photosARead-only
Search Photos by one string, matched (case, accent and smart-quote blind)
against original filename, filename, title, description, keywords, place name,
person names and labels. Returns {results, truncated?}: pointers (id = the Photos
uuid, summary = title · filename · date), newest first, at most 25; truncated
means the 25 cap was reached and there may be more. Hidden and Recently Deleted
photos never match. Pass the id to photo_info or export_photo. Reads the library at
rest through osxphotos, so it needs Full Disk Access (not Automation). Read-only;
never returns image bytes or thumbnails.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the readOnlyHint/destructiveHint annotations: discloses the osxphotos library-at-rest mechanism, the Full Disk Access (not Automation) permission requirement, the 25-result cap with a truncated flag, that no image bytes or thumbnails are ever returned, and that hidden/Recently Deleted items are excluded. These are exactly the operational facts an agent needs and none of them are in structured fields.
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?
Dense but zero-waste; the verb+resource leads, then matching semantics, return shape, cap behavior, exclusions, and prerequisites in a logical order. No sentence restates a structured field verbatim.
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?
Covers purpose, query semantics, return shape, truncation, permission prerequisites and downstream chaining. Even though an output schema exists, the inline mention of `{results, truncated?}` and the id/summary field meaning helps the agent plan follow-up calls; nothing material 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?
Schema coverage is 0% for the single required `query` param, so the description must carry the load and does: it defines the match as case-, accent- and smart-quote-blind against original filename, filename, title, description, keywords, place name, person names and labels. That is far more than the bare `{type: string}` schema conveys.
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?
Opens with a specific verb+resource ('Search Photos by one string') and then enumerates exactly which fields are matched, which distinguishes it cleanly from photo_albums (browsing) and photo_info (detail lookup). An agent can select this tool without opening the schema.
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?
Explicitly routes the agent downstream: 'Pass the id to photo_info or export_photo', and states the negative scope that hidden and Recently Deleted photos never match. It doesn't spell out the alternative for browsing albums or say when a different search tool would be preferable, so it falls short of a full when/when-not/alternatives triad.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pingARead-only
Health check — confirms macos-apps-mcp is alive. No permission needed.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds genuinely new operational context — that no permissions are required, meaning an agent can call it without an auth check — which is value beyond the structured fields. It does not add latency/cost notes, but the output schema covers the return value.
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 clauses, front-loaded with the purpose, with the auth reassurance trailing. Every word earns its place and there is no redundancy against the schema or title.
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 trivial liveness probe, annotations plus an output schema mean the description only needs to state purpose and auth requirements, which it does. The one omission is a hint about what a healthy vs unhealthy result looks like, which would help an agent interpret the call — though the output schema largely covers that.
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 the schema carries no semantics to compensate for. Baseline for a parameterless tool is 4, and the description correctly adds nothing that would confuse the empty input shape.
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+resource — a health check that confirms the macos-apps-mcp server is alive — which is unambiguous in isolation. It does not distinguish itself from the potentially overlapping diagnostics siblings such as 'doctor', 'usage', or 'now', so an agent must infer the difference.
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?
'Health check' implies the usage context (verify the server is reachable) and 'no permission needed' signals it is safe to call freely. However, there is no explicit when-to-use guidance nor any pointer to the alternative diagnostic tools like 'doctor' that an agent might otherwise pick.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
play_playlistA
Play a Music playlist by its persistent id (from music_search). Additive, reversible; needs Automation access for Music. Returns the resulting now-playing state.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With readOnlyHint=false and destructiveHint=false already declared, the description adds real value by labeling the action 'additive, reversible' and naming the Automation permission requirement for Music. It also notes the returned now-playing state, going beyond what the annotations state.
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 lines, front-loaded with the action and resource; every clause (id source, reversibility, permission, return value) carries 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 tool with annotations and an output schema, the definition covers the essentials: input source, permission requirement, mutation character, and return. Minor gaps remain around failure modes (e.g., invalid or missing playlist id) and whether playback replaces the current queue.
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 0% for the single 'id' parameter, so the description must compensate. It does clarify that the id is a persistent playlist id obtained from music_search rather than a name or index, but it gives no format or example of that id.
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 ('Play a Music playlist') and identifies the key input as a persistent id sourced from music_search. It separates itself from music_search, though it does not explicitly contrast with the sibling music_control, which also touches playback.
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 phrase '(from music_search)' routes the agent to the right tool for obtaining the id, and the Automation-access prerequisite gives a usage condition. However, there is no explicit when-not guidance or comparison to music_control for generic playback control.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
reminder_listsARead-only
List reminder lists as pointers (id + name); use a name to target writes. The
id is the folder that reminders carry. Read-only; needs EventKit (Reminders)
access. See create_reminder to write.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false; the description adds genuinely new context: it requires EventKit (Reminders) access, i.e., an authorization prerequisite. That is useful beyond what annotations convey, though rate limits and pagination are not covered.
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 compact clauses, front-loaded with what it does and what the output looks like. Every element (pointers, folder mapping, read-only, auth, write alternative) carries information an 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?
An output schema exists, so return-value detail isn't strictly required, yet the description still explains the pointer shape and its relation to reminders. Combined with the auth note and the write-routing hint, nothing essential is missing for a zero-param list 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?
The tool takes zero parameters, so the baseline is 4. The description appropriately uses its space to explain the meaning of the values returned (id/name, and that id equals the reminder 'folder') rather than inventing parameter detail.
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 reminder lists") and even the return shape: "pointers (id + name)". It further disambiguates by explaining 'id' is the 'folder' reminders carry and by naming create_reminder for the write path, so an agent can tell it apart from sibling reminder 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?
Gives a clear usage rule ("use a name to target writes") and routes to the correct alternative ("See create_reminder to write"). It doesn't spell out when-not conditions, but the read-before-write context is explicit enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remindersARead-only
List reminders as pointers in {results, coverage?}. due: today | overdue |
this-week | a list name. Each result may carry folder (its list's id, from
reminder_lists; pass it as list_name=), tags and parent (the parent
reminder's id, for a subtask). Requires EventKit and Full Disk Access (tags and
parent links come from the Reminders store). Tags and subtasks are read-only:
macOS has no public API that writes them, so no tool here can add a tag or nest a
reminder — do that in Reminders.app. If the Reminders store cannot be read, results
still come back and coverage says why tags and parent links are missing.
Read-only. Hydrate none — pointers only.
| Name | Required | Description | Default |
|---|---|---|---|
| due | No | today |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the read-only annotations, the description discloses important behavior: it requires EventKit and Full Disk Access, tags and parent links come from the Reminders store, and tags/subtasks cannot be written by any tool. It also explains fallback behavior via `coverage` when the store cannot be read.
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 dense and front-loads the output shape and `due` semantics. It is somewhat long for a one-parameter read tool, and the final 'Read-only. Hydrate none — pointers only' partly repeats earlier information, but most sentences add useful behavioral context.
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 output schema, the description does not need to explain return values in full, but it still clarifies that results are pointers and may include optional `coverage` details. It covers prerequisites, read-only limitations, and fallback behavior, which is complete for this 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?
With 0% schema description coverage, the description carries the burden for the single `due` parameter and does so by enumerating accepted values. It does not mention the schema's default of `today`, and the parenthetical about passing `folder` as `list_name=` is slightly ambiguous, but the main parameter meaning is clear.
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 specific verb and resource: 'List reminders as pointers.' It also clarifies scope by stating results are pointers only and distinguishes this read operation from the mutation-oriented reminder siblings such as create_reminder and update_reminder.
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 clearly explains the main usage context and enumerates valid `due` filters: today, overdue, this-week, or a list name. It references `reminder_lists` when explaining list ids, but does not explicitly state when to choose this tool versus `reminder_lists` or another reminder tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_shortcutADestructive
Run a Shortcut by name OR its UUID id (from shortcuts — the id is unambiguous
across renames/duplicate names); optional input_text piped in. Returns a pointer
citing the run + a bounded output snippet. dry_run=True resolves the shortcut
and reports what WOULD run without running anything. Side effect (runs arbitrary
automation the user owns, which may reach beyond this machine — a shortcut can
call web services); uses the Shortcuts CLI (no TCC prompt).
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| dry_run | No | ||
| input_text | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag readOnly=false, openWorld=true and destructive=true, yet the description still adds real information: the shortcut is arbitrary user-owned automation that can reach external services, and the run goes through the Shortcuts CLI so no TCC prompt appears. It also discloses the return shape (pointer plus bounded output snippet) and describes dry_run as resolving without executing.
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?
Front-loaded with the action and identifier guidance, and every clause carries signal. It is dense to the point of being parenthetical-heavy ('TCC prompt', the long aside about web services), which costs a little readability.
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?
Covers the side-effect profile, identifier resolution, input piping, dry-run preview, and even the return value despite an output schema existing. For a three-parameter tool that executes arbitrary automation, nothing material 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?
Schema coverage is 0%, so the description carries the full burden and does: `name` accepts either a plain name or a UUID id, `input_text` is optional and piped into the shortcut, and `dry_run=True` resolves the shortcut and reports what would run. All three parameters gain semantics the schema does not provide.
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 ('Run a Shortcut') plus the two accepted identifiers, the optional piped input, and the dry-run mode. It implicitly distinguishes itself from the `shortcuts` sibling, which supplies the id, so an agent knows this is the execution tool rather than the listing tool.
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 clear selection guidance between the two identifier forms ('the id is unambiguous across renames/duplicate names') and a concrete preview path via `dry_run=True`. It does not state outright when not to use it, but the mode guidance is specific enough to steer invocation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
safari_openA
Open a URL in a new Safari tab; adds https:// if no scheme (http/https only). Side effect (opens a tab); needs Automation access for Safari. See safari_tabs.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds meaningful behavior beyond the annotations: it discloses the side effect of opening a tab, the scheme normalization rule (adds `https://` when missing), the restriction to HTTP/HTTPS, and the need for Automation access to Safari.
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 compact sentences, front-loading the primary action and then adding side-effect and permission notes. Every sentence contributes useful 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 simple one-parameter tool with an output schema, the description provides enough context to call it correctly: action, side effect, permission requirement, scheme behavior, and related sibling.
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 0%, so the description must carry the parameter's meaning. It identifies the parameter as a URL and explains important semantics: missing schemes get `https://`, and only HTTP/HTTPS are accepted.
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 precise verb and resource: opening a URL in a new Safari tab. It also distinguishes the tool from the related `safari_tabs` sibling by pointing to it for tab-related operations.
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 tool's intended use is clear from "Open a URL in a new Safari tab," and it references `safari_tabs` as the related alternative. However, it does not explicitly state when to use this tool versus inspecting tabs with `safari_tabs`, nor does it describe exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
safari_tabsARead-only
List open Safari tabs as pointers (url + title). Bounded to 50. Read-only; needs Automation access for Safari. See safari_open to open a URL.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds genuinely useful context beyond that: the 50-tab bound and the Automation-permission requirement for Safari, both of which an agent needs before invoking.
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 short clauses with zero waste; the core action and output shape are front-loaded, with the bound and permission noted after. 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?
With an output schema present, return values needn't be explained further, and the zero-param schema requires no input documentation. Combined with annotations covering safety, the description's additions (bound, auth requirement, sibling routing) make it complete for an agent to call 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?
There are zero input parameters, so the baseline is 4. The description correctly adds no parameter detail and instead documents the output shape (url + title) and result cap, which is appropriate for a no-arg tool.
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 (list) and resource (open Safari tabs), plus the output shape (url + title pointers) and a bound (50). It also distinguishes itself from the sibling safari_open by directing URL-opening there, so an agent can tell the two apart without opening either schema.
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 line 'See safari_open to open a URL' explicitly names the alternative and the condition that selects it, which is clear routing. There is no further elaboration on exclusions (e.g. tab content vs. pointers), so it stops just short of a full when/when-not treatment.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
save_mail_attachmentA
Save ONE attachment to disk (Automation, plus Full Disk Access to resolve a bare message_id).
List them with mail_attachments first, then address one by name or — when
several on the same message share a name, which is ordinary — by its
attachment_id (the id field on the attachment row). An ambiguous name RAISES
and lists the ids rather than picking one.
dest_dir must be inside the allowed root (~/Downloads by default;
MACOS_APPS_FILE_ROOT moves it) and is created if needed; a path outside it is
REFUSED. The filename is DERIVED from the attachment's name — an attachment name
comes from whoever sent the mail, so it is treated as hostile — and an existing
file is never overwritten. Writes are capped at 25 MiB.
mailbox is optional: the folder value from the read that produced message_id,
verbatim. Omitted, the id resolves on its own through the index.
Saving an attachment Mail has not downloaded makes Mail FETCH the message first, so this can take much longer than a read; if the account is offline the file lands empty, and it is then removed and reported as a failure rather than left behind. Returns {saved, name, original_name, bytes, reported_size, was_downloaded, id, folder}. Additive: writes a new file, never modifies mail.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | ||
| mailbox | No | ||
| dest_dir | Yes | ||
| message_id | Yes | ||
| attachment_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare `readOnlyHint=false` and `destructiveHint=false`; the description adds substantial behavioral context: Full Disk Access requirements, allowed `dest_dir` root and refusal outside it, filename sanitisation, no overwrite, 25 MiB cap, Mail fetch delays, and offline cleanup. These details go well beyond the annotations and align with `destructiveHint=false` via the additive-write note.
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 dense but front-loaded: it leads with the action, then addressing, filesystem security, mailbox behavior, fetch caveats, and return fields. Every paragraph provides operational value without filler, which is appropriate for a security-sensitive filesystem write.
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 mutation, sensitive filesystem effects, missing schema parameter descriptions, and available output schema, the description is complete. It covers permissions, path security, collision policy, size limits, failure handling, and return shape, leaving no material gap for correct invocation.
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 0%, so the description must carry parameter meaning—and it does. It defines `name` versus `attachment_id` disambiguation, `dest_dir` root restrictions and creation behavior, `mailbox` as the verbatim folder from the read, and how `message_id` resolves through the index when mailbox is omitted.
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 'Save ONE attachment to disk'—a specific verb and resource—and immediately distinguishes the tool from sibling `mail_attachments` by telling the agent to list attachments first. The capitalised ONE and two addressing methods make the scope precise.
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 an explicit workflow: list with `mail_attachments` first, then address one attachment by `name` or `attachment_id`. It also explains the ambiguous-name failure mode and when `mailbox` is needed, so the agent knows how to select and invoke it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_modeA
Set Music shuffle or repeat: mode in shuffle|repeat, on=true/false (repeat on→all, off→off). Additive, reversible; needs Automation access for Music. Returns the resulting now-playing state.
| Name | Required | Description | Default |
|---|---|---|---|
| on | Yes | ||
| mode | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare this is a non-read-only but non-destructive operation. The description adds useful context beyond that: the change is additive and reversible, it requires Automation access for Music, and it returns the resulting now-playing state.
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 compact and front-loaded, stating the tool's purpose and parameter behavior in two efficient sentences with no wasted text.
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 an output schema exists, the description still summarizes the return state. It also covers both required parameters, authentication needs, and reversibility, leaving no critical gap for an agent invoking this 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 0%, so the description must carry parameter meaning. It specifies the allowed mode values (shuffle|repeat), defines on as true/false, and clarifies that repeat on means all while off means off.
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: setting Music shuffle or repeat mode. It is clearly distinguishable from broader sibling tools like music_control or set_volume because it names the exact Music feature and mode values.
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 the tool applies by naming shuffle and repeat modes, but it does not say when to use this instead of alternatives such as music_control. It gives no explicit exclusions or routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_volumeA
Set the Music app sound volume (0–100). Additive, reversible; needs Automation access for Music. Returns the resulting now-playing state.
| Name | Required | Description | Default |
|---|---|---|---|
| level | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses that the operation is additive and reversible, requires Automation access for Music, and returns the resulting now-playing state. These are meaningful operational details for a write operation and go well beyond readOnlyHint=false and destructiveHint=false.
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 tight sentences that front-load the action and range, then add behavior and return information. Every sentence contributes useful information with no repetition.
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 one-parameter setter that already has an output schema, annotations, and a stated permission requirement, the description is complete enough to invoke correctly. It covers range, side-effect profile, auth, and return state without needing to restate the output schema.
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 0% and the sole parameter has no schema description, so the description must carry the load. It does so by specifying that level is the 0–100 volume range, though it does not state out-of-range handling.
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: setting the Music app sound volume, with an explicit 0–100 range. It is clear enough to distinguish from read-only tools like now_playing, but it does not explicitly differentiate from the broader music_control sibling.
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 by 'Set the Music app sound volume,' so an agent can infer this is the volume-setting tool. However, the description gives no explicit when-to-use guidance versus music_control or now_playing and names no exclusions, leaving sibling selection partly to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shortcutsARead-only
List/search Shortcuts by name (empty lists all). Pointers: id = the shortcut's stable UUID (survives renames), summary = name, deeplink = shortcuts://run-shortcut. Read-only; uses the Shortcuts CLI (no TCC prompt). See run_shortcut to invoke.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and non-destructive behavior. The description adds useful context beyond annotations, notably that it uses the Shortcuts CLI without a TCC prompt and that id survives renames, though it does not discuss failure modes or limits.
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 compact and front-loaded: the primary list/search behavior comes first, followed by useful output pointers and the run_shortcut alternative. Every sentence contributes 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?
Given the simple one-parameter schema, existing output schema, and read-only annotations, the description supplies the remaining context an agent needs: filtering behavior, output field meanings, CLI/no-prompt behavior, and how to invoke a shortcut via the sibling 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 0%, so the description must carry parameter meaning. It does so by explaining that `name` is a search filter and that an empty value lists all shortcuts, which is sufficient for a single optional string parameter, though matching semantics such as substring vs exact are not stated.
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/search Shortcuts by name, with empty meaning list all. It also explicitly distinguishes itself from run_shortcut, which handles invocation rather than listing.
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 clearly explains that passing a name searches/filters and empty lists all, and points to run_shortcut for invoking a shortcut. The alternative is named, though there is no broader when-not guidance or edge-case exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trash_mailADestructive
Move Mail messages to Trash — soft delete, and the ONLY delete there is.
Mail's scripting layer cannot permanently erase a message: delete moves it to the
owning account's Trash, and nothing in the dictionary empties Trash from a script.
Emptying Trash is something the user does in Mail.app. So this is always
recoverable, and there is no permanent-delete tool to ask for.
DESTRUCTIVE but recoverable: every message's bytes are copied to a backup directory
and its source mailbox logged BEFORE anything is deleted, so mail_undo moves the
batch back out of Trash. dry_run DEFAULTS TO TRUE — the preview reports, per id,
whether it is actually present in mailbox. Pass dry_run=False to delete.
ids are RFC822 message-ids from a mail read, comma-separated; max 25 per call and
the cap is not overridable. mailbox is REQUIRED and must be the folder url from
the read that produced the ids, passed back VERBATIM — not one of the canonical
names: Mail files a deleted message in its OWNING account's Trash, and a unified
name ("inbox") cannot say which account that is. A Gmail label folder is refused
(a delete there is not a delete of the message, #287); use the message's
[Gmail]/All Mail folder.
Returns {op, receipt, count, succeeded, targets, destination, backup_dir, undo} —
keep receipt to undo the batch. Each copy is deleted by Mail's internal id and
verified by the account Trash's count rising, or every one of its copies' source
reference going gone within a bounded wait (12 checks, 0.5s apart — up to 5.5s) —
Mail's delete clears the source ASYNCHRONOUSLY, so "gone from the source" alone is
not a signal that can be read straight after the call. A message with several
stored copies gets every one of them trashed. If the call times out mid-batch,
re-run the same batch or
mail_undo the receipt. Needs Automation access for Mail, plus Full Disk Access
to locate each message's file for the backup.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| dry_run | No | ||
| mailbox | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, but the description adds genuinely new behavior: bytes are backed up and source mailboxes logged before deletion, dry_run defaults to true, deletion is verified by Trash-count rise or source-reference loss within a bounded 12x0.5s wait, Mail clears sources asynchronously, and a mid-batch timeout should be re-run or undone. It also states the Automation + Full Disk Access prerequisites — none of which are in the annotations.
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?
Front-loaded with the single most important fact (soft delete, only delete that exists) and organized in a logical order. It runs long for a 3-param tool and repeats the destructive-but-recoverable idea ('soft delete' then 'DESTRUCTIVE but recoverable'), but nearly every sentence carries load-bearing 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 destructive, async-verifying, backup-dependent operation with 0% schema coverage, nothing an agent needs is missing: parameters, permissions, dry-run default, failure/timeout recovery, and the receipt to retain for undo are all present. It even summarizes the return shape, though an output schema already exists.
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 0%, so the description carries the full burden and does: ids are RFC822 message-ids from a mail read, comma-separated, capped at 25 non-overridably; mailbox is required, must be the verbatim folder url from the read that produced the ids, must not be a canonical/unified name, and Gmail label folders are refused; dry_run defaults true and must be set False to actually delete.
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 ('Move Mail messages to Trash') plus a distinguishing qualifier ('soft delete, and the ONLY delete there is'). An agent can immediately tell it apart from move_mail, delete_draft, or delete_note without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly rules out the assumption of a permanent-delete tool, explains that emptying Trash is a user action in Mail.app, names mail_undo as the reversal path, and gives the exact substitution rule for Gmail label folders ('use the message's [Gmail]/All Mail folder'). When-to-use and when-not-to-use are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_eventADestructive
Update an event by id (full replace). start/end ISO — naive = local time.
recurrence an RRULE with FREQ, INTERVAL, COUNT, UNTIL, BYDAY (ordinals such as
2TU or -1FR for monthly and yearly), BYMONTHDAY, BYMONTH, BYYEARDAY, BYSETPOS;
BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND and WKST are refused. all_day takes a
DATE (2026-07-01); a timestamp with a UTC offset
is rejected. A start that does not match its recurrence is accepted (RFC 5545
counts it as the first occurrence) and the result's summary says so.
alarms are minutes before the start, as in the Google Calendar API. For an all-day
event the offset counts from local midnight: -540 is 09:00 on the day, 900 is
09:00 the day before. On a DST-change day the alert shifts an hour, the same as
Calendar's own alerts. At most 5. Omit alarms to keep the event's alarms; []
removes them all.
span REQUIRED if the target is recurring: 'this-event' (only this occurrence) or
'future-events' (this + all later); ignored for single events.
Side effect (full-replace update); needs EventKit (Calendar) access. id from
events.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| end | Yes | ||
| span | No | ||
| notes | No | ||
| start | Yes | ||
| title | Yes | ||
| alarms | No | ||
| all_day | No | ||
| calendar | No | ||
| location | No | ||
| recurrence | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only say readOnly=false/destructive=true; the description adds far more: full-replace side effect, EventKit/Calendar access requirement, a whitelist/blacklist of supported RRULE parts (BYWEEKNO/WKST refused), rejection of offset timestamps for all_day, DST shifting of alarms, a 5-alarm cap, and the fact that a non-matching start is accepted with a note in the summary. This is exactly the extra context the annotations cannot convey.
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?
Front-loads the core operation, then groups constraints by parameter in a roughly scannable order, with every technical caveat (DST, RFC 5545 first-occurrence, alarm cap) being actionable. It is dense and a bit long, but almost nothing is filler; light tightening of the alarm paragraph would help.
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 11-parameter destructive mutation with an output schema (so return values need not be explained), the description covers the hard parts: recurrence grammar, alarm encoding, span requirement, and the full-replace consequence. It is nearly complete, missing only note on how unspecified fields (notes/location/calendar) behave under full replace.
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 0%, so the description carries the burden, and it delivers rich meaning for start/end (naive = local), recurrence (enumerated RRULE parts and ordinals), all_day (DATE vs rejected offset), alarms (minutes-before, all-day midnight math, DST), and span (enum values with semantics). It leaves `title`, `notes`, `location`, and `calendar` undocumented, which is the main remaining gap.
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?
Opens with a specific verb+resource plus a crucial qualifier: 'Update an event by id (full replace).' The parenthetical full-replace semantics immediately distinguish it from create_event and delete_event, and the closing pointer to `events` for the `id` reinforces the sibling relationship.
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 concrete conditional guidance: `span` is REQUIRED for recurring targets and ignored for single events, and omitting `alarms` keeps existing alarms while `[]` removes them. It points to `events` as the source of `id`, but never explicitly contrasts when to reach for update_event versus create_event/delete_event.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_mail_statusADestructive
Mark Mail messages read/unread and flag/unflag them, optionally with a colour.
ids are RFC822 message-ids from a mail read, comma-separated; max 25 per call.
mailbox is OPTIONAL and is the disambiguator: pass the folder value from the
SAME read back VERBATIM (an opaque imap://<uuid>/<path> token) and the whole batch
is addressed directly; omit it and each id is resolved through Mail's index (Full
Disk Access), which also lets one call span several mailboxes.
At least one of read, flagged or flag_color is required. flag_color is a
name — red/orange/yellow/green/blue/purple/grey — and setting one implies flagged.
dry_run defaults to FALSE: this changes two booleans, destroys nothing, and
re-issuing it with the opposite value is the undo — so it does not use the backup
plane that move_mail does. Each message is re-read after the write, so the per-id
results report what actually persisted. Destructive (it modifies stored messages);
needs Automation access for Mail.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| read | No | ||
| dry_run | No | ||
| flagged | No | ||
| mailbox | No | ||
| flag_color | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true, and the description goes well beyond that: it explains that only two booleans change, that nothing is destroyed, that re-issuing the opposite value is the undo, that it skips the backup plane move_mail uses, that messages are re-read so `results` reflect what actually persisted, and that Automation access is required. That is unusually rich disclosure of write semantics and failure/verification behaviour.
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?
Purpose is front-loaded and almost every sentence adds actionable information. The middle paragraph is dense and chains multiple facts per sentence, which makes it harder to scan than a short bulleted structure, but there is no filler to cut.
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 is a batch mutation with 6 parameters, an output schema and annotations; the description covers id format, batching limit, the mailbox disambiguation trade-off, the required-field invariant, colour semantics, undo story, persistence verification and permissions. An agent has everything needed 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 0%, so the description must carry all meaning and it does: `ids` is RFC822 message-ids from a prior read, comma-separated, max 25; `mailbox` is an opaque imap://<uuid>/<path> token taken verbatim; `flag_color` enumerates the allowed names and implies flagged; `dry_run` defaults to false. Every parameter is given semantics the bare schema lacks.
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 first clause names a specific verb pair and resource: 'Mark Mail messages read/unread and flag/unflag them.' The scope (status booleans + optional flag colour) is distinct from siblings like move_mail, trash_mail and mail_search, so an agent can route without opening the schema.
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 states exactly when to pass `mailbox` (copy the `folder` token verbatim from the same read) versus when to omit it (each id resolved through Mail's index, allowing a multi-mailbox batch). It also gives the precondition 'at least one of read, flagged or flag_color is required' and explicitly contrasts itself with move_mail's backup plane.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_noteADestructive
Update a note by id (full-replace title+body); the stable id is preserved and
verified (#49). dry_run DEFAULTS TO TRUE — previews the CURRENT title and body
size against the NEW ones (reads Notes; makes no write); pass dry_run=false to
overwrite. title/body plaintext (escaped). folder must be omitted — update
cannot move a note between folders and refuses a non-None folder loudly.
Side effect (full-replace update); needs Automation access for Notes. id from
notes / notes_all / create_note.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| body | No | ||
| title | Yes | ||
| folder | No | ||
| dry_run | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses that the update is a full replace (existing title/body are destroyed, not merged), that dry_run previews current title and body size with reads only, that Automation access to Notes is required, and that a non-None folder is rejected loudly. These match readOnlyHint=false / destructiveHint=true rather than contradicting them.
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 two-sentence structure is front-loaded and dense with decision-relevant facts — no filler. Minor deductions for the internal issue reference '(#49)', which means nothing to an agent, and for the heavy backtick/parenthetical compression that makes it slightly harder to parse than it needs to be.
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 destructive mutation with an output schema in place, this covers everything an agent needs: id source, must-omit folder, dry_run default and preview semantics, permission prerequisite, and the nature of the side effect. Nothing required to call it correctly 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?
Schema description coverage is 0%, so the description must carry all five parameters — and it does: id (provenance and stability), title/body (plaintext, escaped, full replace), folder (must be omitted or it fails), dry_run (default true plus its exact preview behavior). It fully compensates for the empty schema descriptions.
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 both the verb and resource ('Update a note by id') and immediately qualifies the semantics as a 'full-replace title+body' operation with the id preserved, which distinguishes it from create_note/delete_note and from any partial-update expectation. An agent knows exactly what this call does before opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit routing: 'id from notes / notes_all / create_note', a hard exclusion ('folder must be omitted — update cannot move a note between folders'), and a decision rule for dry_run ('DEFAULTS TO TRUE ... pass dry_run=false to overwrite'). When-to-use, when-not-to, and alternatives are all present rather than inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_reminderADestructive
Update a reminder by id (full replace). due/start ISO (naive = local).
recurrence: RRULE to set ('none' to stop repeating) with FREQ, INTERVAL, COUNT,
UNTIL, BYDAY (ordinals such as 2TU or -1FR for monthly and yearly), BYMONTHDAY,
BYMONTH, BYYEARDAY, BYSETPOS; BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND and WKST are
refused. REQUIRED (rule or 'none')
when the target reminder repeats — omitting it is refused so a rename can't
silently kill the series.
This tool cannot set tags or make a subtask (no public API; read-only via
reminders()).
Side effect (full-replace update); needs EventKit (Reminders) access. id from
reminders.
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | ||
| due | No | ||
| notes | No | ||
| start | No | ||
| title | Yes | ||
| priority | No | ||
| list_name | No | ||
| recurrence | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the destructiveHint=true annotation: it discloses that this is a full-replace update (fields not supplied are lost), that EventKit/Reminders access is required, that the API refuses a missing recurrence on repeating reminders, and that tags/subtask creation are impossible. These are exactly the behavioral facts an agent needs before invoking a destructive mutation.
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?
Front-loads the operation and the full-replace warning, then layers recurrence detail and constraints; every clause carries information. The telegraphic backtick-heavy fragments and mid-sentence line breaks make it slightly harder to parse than a plain prose version.
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 destructive 8-parameter mutation with an output schema (so return values need no explanation), the description covers the destructive semantics, permission prerequisite, id source, and the recurrence edge case that would otherwise cause silent data loss. Remaining gaps around non-critical scalar fields are minor at this complexity.
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?
With 0% schema description coverage the description does the heavy lifting for the risky parameters: ISO format and naive=local for due/start, the full RRULE grammar for recurrence including which clauses are refused, and the source of id. It leaves title, notes, priority and list_name unexplained, so the full-replace effect on omitted fields is not spelled out per 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?
States the specific verb and resource ('Update a reminder by id') and immediately qualifies the semantics with '(full replace)', which separates it from create_reminder, complete_reminder and delete_reminder in the sibling list. An agent knows exactly what operation this performs without opening the schema.
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 concrete when-to guidance (recurrence is REQUIRED when the target repeats, and omission is refused so a rename can't kill the series) and explicit when-not limits (cannot set tags or make a subtask, no public API). It does not name sibling tools as alternatives for those unsupported operations, which is the only thing keeping this from a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
usageARead-only
Per-tool call frequency, for pruning rarely/never-used tools. Returns tools
(each {tool, count, first, last}, busiest first), never_used (registered tools
with zero calls — the pruning list), and total_calls. Read-only; no permission
(reads a local log at ~/.local/state/macos-apps-mcp).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and destructiveHint=false, so the description isn't obligated to re-state safety — but it adds the useful detail that no permission is required and that the data comes from a local log at ~/.local/state/macos-apps-mcp. Minor redundancy in repeating 'Read-only', but the data provenance is real added context.
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?
Front-loaded with purpose, then return shape, then the safety/provenance note — a sensible order and only a few lines. Slightly wasteful in that the field-level return breakdown duplicates the output 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 zero-parameter, read-only reporting tool this covers purpose, data source, and output contents. Nothing an agent needs in order to call it or interpret the result 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?
Zero parameters, so the baseline is 4 and there is nothing to clarify. The description helpfully frames what selectivity the caller gets (busiest-first ordering, never_used bucket) even though that is technically return data rather than input semantics.
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?
Opens with a specific resource and metric ('Per-tool call frequency') plus the intent behind it ('for pruning rarely/never-used tools'). It's distinctive enough that no sibling is confusable, though it never names the potentially adjacent tools (audit, doctor) to draw the boundary 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?
The pruning use case is stated outright, which effectively tells the agent when to reach for this tool. It stops short of exclusions or naming an alternative for adjacent diagnostics questions.
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.
68 tool updates
v0.15.1- First observed
audit - First observed
calendars - First observed
complete_reminder - First observed
contacts - First observed
create_contact - First observed
create_draft - First observed
create_event - First observed
create_mailbox - First observed
create_note - First observed
create_reminder - First observed
create_reminder_list - First observed
delete_draft - First observed
delete_event - First observed
delete_note - First observed
delete_reminder - First observed
doctor - First observed
drafts - First observed
events - First observed
export_mail - First observed
export_photo - First observed
free_busy - First observed
mail - First observed
mail_attachments - First observed
mail_awaiting_reply - First observed
mail_bodies - First observed
mail_body - First observed
mail_duplicates - First observed
mail_index_bodies - First observed
mail_index_ids - First observed
mail_needs_response - First observed
mail_overview - First observed
mail_reply - First observed
mail_search - First observed
mail_stats - First observed
mail_thread - First observed
mail_undo - First observed
message_body - First observed
messages_chats - First observed
messages_search - First observed
messages_with - First observed
move_mail - First observed
music_control - First observed
music_search - First observed
note_bodies - First observed
notes - First observed
notes_all - First observed
now - First observed
now_playing - First observed
photo_albums - First observed
photo_info - First observed
photos - First observed
ping - First observed
play_playlist - First observed
reminder_lists - First observed
reminders - First observed
run_shortcut - First observed
safari_open - First observed
safari_tabs - First observed
save_mail_attachment - First observed
set_mode - First observed
set_volume - First observed
shortcuts - First observed
trash_mail - First observed
update_event - First observed
update_mail_status - First observed
update_note - First observed
update_reminder - First observed
usage
TDQS
Scored across 68 tools
The descriptions are unusually detailed and usually state exactly when to prefer one tool over another, but the Mail surface has many similarly aimed read paths (mail vs mail_search, drafts vs mail_attachments, mail_body vs mail_bodies) and narrow write tools (move_mail vs trash_mail vs delete_draft). Across 68 tools, an agent can still misselect among near-neighbors even though the descriptions try hard to disambiguate.
Write tools mostly follow verb_noun (create_reminder, update_event, delete_note), but read/list tools are usually bare nouns (reminders, events, mail, notes, photos) and some use domain prefixes or noun compounds (mail_search, music_search, photo_info, now_playing). The patterns are readable but not a single predictable convention.
68 tools is a very large surface for one server, even counting the many macOS app domains. Each domain has a plausible subset, but the aggregate set is heavy and granular enough that it burdens tool selection and maintenance; it clearly exceeds the comfortable 3–15 range.
Coverage is extensive in Mail, Reminders, Calendar, Notes, Photos, Messages, Music, and Safari, but there are notable gaps: no send_mail tool despite descriptions referencing it, Contacts has only find/create without update/delete, and several list/container lifecycle operations (reminder lists, calendars, albums) are read/create-only. Agents can often work around these by drafting or using app UI, but the surface is not full lifecycle-complete.
Maintenance
Related MCP Connectors
A MCP server that works with Google Calendar to manage event listing, reading, and updates.
A MCP server that works with Outlook Calendar to manage event listing, reading, and updates.
MCP server for Nylas — read email, calendars, events and contacts, and send email or create events.
One MCP server for all your work accounts: Slack, Teams, Google Chat, Jira, ClickUp, digest, tasks.
Related MCP Servers
- AlicenseBqualityFmaintenanceEnables interaction with Apple apps like Messages, Notes, and Contacts through the MCP protocol to send messages, search, and open app content using natural language.7454 npm3,114MIT
- AlicenseBqualityAmaintenanceEnables AI assistants to interact with Apple Mail through natural language, providing comprehensive email management including reading, searching, composing, organizing, and analyzing emails across all configured accounts. Includes an expert skill system that teaches intelligent email workflows and productivity strategies.28160 PyPI247MIT
- AlicenseNot gradedqualityAmaintenanceProvides native integration with Apple Reminders and Calendar on macOS, enabling full CRUD operations and smart task management through the Model Context Protocol. It allows users to search, create, and organize reminders and calendar events using natural language via the macOS EventKit framework.2,320 npm230MIT
- AlicenseBqualityDmaintenanceA macOS MCP server that provides AI agents with secure access to Calendar, Reminders, Notes, and Health data via native Apple APIs.3023MIT