MCP server bridging Claude/Codex/Cursor to the Drafts app on macOS — create, search, append, and run actions on your drafts by chatting.
Mixed quality across tool definitions. Strengths: all 9 tools have descriptions and input schemas are present with type constraints (enums, required fields). Weaknesses: descriptions are functional but generic (avg ~80 chars, well below the 194 char baseline for A+ tools); parameter descriptions lack actionable detail and format guidance; no output schemas documented; error handling is not visible in the definitions; no evidence of idempotency guidance for write operations; resource composition is poor (create_draft and append_to_draft should return draft UUIDs to enable chaining, but no output schema visible). Tool naming is clear and verb-driven, which is a strength. The server reads from a local macOS Drafts database and interacts with the Drafts app via AppleScript, which limits testability but is reasonable for a platform-specific tool.
Append text to an existing draft
Create a new draft in Drafts app with the specified content, tags, and optional action
Get a list of all drafts with metadata by reading from local Drafts database
Retrieve a draft by its UUID (reads directly from local database)
Open a draft in the Drafts app by UUID or title
Prepend text to an existing draft
Run a Drafts action on specified text
No output schemas documented. LLMs cannot determine what fields to expect from tool calls (e.g., does create_draft return the new draft UUID? does get_draft return content, metadata, both?). This breaks tool chaining, an LLM cannot confidently pass a draft_uuid from create_draft to append_to_draft without seeing the response shape.
Descriptions are brief and lack actionable context (avg ~55 - 80 chars, below the 194 char baseline). Example: 'Append text to an existing draft' does not explain: What constitutes a valid UUID format? Does append modify the draft in place or return a new version? Is this idempotent? Can the append fail if the draft is locked or deleted?
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 61 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 47 | - | v1 |
Open the Drafts search interface with optional filters (opens UI)
Search drafts by text content in the local database
Write operations (create_draft, append_to_draft, prepend_to_draft, run_action) do not document side effects or idempotency. An LLM retrying a failed append could inadvertently append the text twice. Descriptions must state: 'This operation is idempotent, retrying with the same UUID and text is safe' or 'This operation is NOT idempotent, each call appends text. Do not retry without confirmation.'
Parameter descriptions lack format and constraint guidance. Example: uuid parameter ('The UUID of the draft to retrieve') does not specify: What format is a valid UUID? (e.g., RFC 4122? 128-bit hex?) How does the LLM obtain a UUID? (Must it call get_all_drafts first?) Does an invalid UUID return a 404 or a validation error?
open_draft and run_action have optional-only parameters (both uuid and title are optional in open_draft; action and text are required in run_action but text is ambiguous, is it the draft text to operate on, or does the action auto-apply to the open draft?). This ambiguity invites misuse.
No error handling guidance visible. What happens if: create_draft is called with an invalid folder? get_draft is called with a non-existent UUID? append_to_draft fails because the draft is read-only? Descriptions must include recovery paths, e.g., 'If the draft UUID is not found, call get_all_drafts() to list available drafts.'
Tool composition is weak. create_draft, append_to_draft, and prepend_to_draft likely return nothing or generic success/failure messages. If they do not return the draft UUID or updated draft metadata, an LLM cannot chain operations (create a draft, then append to it in one coherent plan), it would need to call get_all_drafts to find the draft UUID after creation.