MCP server for reading macOS accessibility trees and interacting with UI elements
screenread-mcp defines 5 tools with complete JSON schemas and reasonable descriptions (avg 120 chars). All tools are read-only and well-scoped. However, descriptions lack LLM-optimization guidance (e.g., when to use screenread_snapshot vs screenread_clickable), parameter descriptions are minimal or missing (e.g., 'depth' lacks guidance on performance tradeoffs), and output schemas are not documented. Error handling is present but generic ('Error: <error>'). No tool annotations (readOnlyHint, etc.). Naming is clear and verb-prefixed (screenread_*), but the screenread_ prefix is redundant across all tools.
List interactive elements (buttons, links, text fields) with their click coordinates. Returns a table with role, label, center x/y, and state.
Search for visible text across all open windows. Plain text substring match (no regex). Returns matches with window context.
List all open windows on macOS. Returns one line per window: 'AppName [PID] - Window Title'.
Read the accessibility tree of a macOS window or application. With no parameters, reads the frontmost (active) app. Returns structured text of all UI elements.
Watch an app for UI changes over a duration. Polls the accessibility tree at an interval and reports additions, removals, and value/state changes.
Output schemas not documented. LLMs cannot plan downstream calls or extract structured data without knowing what fields to expect (e.g., screenread_snapshot returns 'tree' or 'timedOut' or 'empty', but the response structure is not declared in the tool definition).
Parameter descriptions are minimal or missing context. 'depth' lacks guidance on performance/timeout tradeoffs; 'roles' and 'ignore' lack examples of valid AX role names; 'interval' lacks guidance on polling overhead. LLMs cannot infer constraints from names alone.
Tool descriptions lack selection guidance. screenread_snapshot and screenread_clickable both read UI elements but serve different purposes (full tree vs interactive elements only). Descriptions do not explain when to use each, forcing LLMs to guess.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | F | 48 | 2026-07-28+ | v2 |
Error responses are generic ('Error: <error>') and do not guide recovery. No distinction between retryable errors (timeout), user-fixable errors (invalid app name), or fatal errors (accessibility denied). LLMs cannot determine next steps.
No tool annotations (readOnlyHint, idempotentHint). All tools are read-only and safe to retry, but this is not declared in the tool definition. Clients cannot optimize caching or retry logic without explicit hints.