MCP server that lets AI assistants control Affinity creative suite on macOS via AppleScript
Server has 12 tools with basic descriptions and input schemas using Zod. However, descriptions are minimal (10-50 chars), lack context on WHEN to use each tool, and omit error recovery guidance. Parameters are typed but descriptions are sparse. No output schemas documented. Tools lack idempotency hints and error classification. Naming is verb-prefixed (good), but descriptions do not explain prerequisites, side effects, or dependencies between tools. No tool annotations (readOnlyHint/destructiveHint). Error handling returns raw AppleScript errors without actionable recovery steps.
Click a menu item. Path: ['File','Export','Export…'] for nested menus.
Export current document via File > Export > Export…
List all items in a top-level menu (File, Edit, Pixel, etc.)
List items in a submenu (e.g., File > Export)
Send a key code (Escape=53, Return=36, Delete=51, Tab=48, Left=123, Right=124, Down=125, Up=126)
Send a keystroke to Affinity with optional modifiers
Launch Affinity app if not already running
Descriptions lack context on WHEN to use each tool and prerequisites. E.g., affinity_keystroke and affinity_key_code both send input but differ in mechanism, descriptions do not explain when to choose one over the other.
No output schemas documented. Tools return text responses but LLMs cannot infer structure of returned data (e.g., affinity_status returns window names as comma-separated string, no schema declares this format).
Error handling returns raw AppleScript errors without recovery guidance. E.g., 'AppleScript error: ...' tells LLM nothing about whether to retry, check prerequisites, or ask user. No error classification (retryable vs fatal).
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | 2026-07-28+ | v2 |
Create a new document. fromLastPreset=true skips the dialog.
Open a file in Affinity (image, .af, .psd, .svg, etc.)
Save the current document (Cmd+S) or Save As
Check if Affinity is running and get current state (open documents, windows)
Type text into Affinity (for text fields, dialogs, the text tool, etc.)
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). LLM cannot distinguish safe read-only tools (affinity_status, affinity_get_menus) from destructive ones (affinity_save, affinity_export) without parsing descriptions.
Parameter descriptions are minimal (10-30 chars). E.g., 'menuPath' described as 'Menu path from menu bar to item', does not explain format, nesting depth limits, or how to discover valid menu names.