Safari browser automation MCP server that bridges tool calls to a Safari extension via WebSocket, enabling tab management, navigation, page reading, element interaction, and browser automation.
MCPSafari defines 23 tools with explicit schemas and descriptions. Naming follows verb_noun convention (tabs_context, close_tab, click, type_text). Descriptions are present but terse (10-100 chars), below the 50-200 char LLM-optimized baseline. Schemas use proper JSON Schema with types and enums (e.g., navigate action enum). Tool annotations (readOnlyHint, destructiveHint) are correctly applied. Major gaps: parameter descriptions are sparse or missing (e.g., click's 'x', 'y' lack descriptions; form_input's 'fields' object lacks value type guidance). Output schemas are not documented, LLMs cannot predict response structure. Error handling is absent from visible code. Composition is strong (tools chain well via UIDs and tabId), but parameter validation rules and recovery guidance are missing.
Click element by UID, selector, text, or x/y coordinates.
Close a tab by ID.
Drag element from source to target.
Find elements by selector, text, or ARIA role. Returns UIDs.
Batch fill form fields. React-compatible.
Handle browser dialogs (alert, confirm, prompt).
Hover over element by UID or selector.
Output schemas not documented. LLMs cannot predict response structure (e.g., what fields does tabs_context return? Is it {tabs: [{id, url, title}]} or {id, url, title}[]?). This forces agents to guess and wastes tokens on trial-and-error.
Parameter descriptions are sparse or missing. 'click' tool has x, y parameters with no descriptions (what units? pixels? relative to viewport?). 'form_input' fields parameter lacks guidance on value type or format. LLMs cannot infer intent from names alone.
No error handling or recovery guidance visible in code. If a click fails (element not found, stale UID), what should the LLM do? Retry? Call snapshot first? No guidance forces agents to guess or fail silently.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 55 | <=2025-11-25 | v2 |
Execute arbitrary JavaScript in the page context.
Go to URL or back/forward/reload.
Press keyboard key (Enter, Escape, ArrowDown, etc.).
Read console messages (log, warn, error, info, debug).
Read network requests (XHR and fetch).
Page content as text, html, or snapshot.
Resize the browser window.
Take a screenshot of the current tab.
Scroll page or element.
Select dropdown option by value or label.
Pin a tab as default context for future calls.
Accessibility tree with element UIDs for interaction tools. UIDs change between snapshots.
List open tabs with IDs, URLs, titles.
Open a new tab.
Type into element. Supports clearFirst and submitKey (e.g. Enter).
Wait for element or condition.
Tool 'javascript_tool' is generic and risky. Name does not convey intent (execute_javascript? run_script?). No description of what code can/cannot do, no sandbox limits, no injection protection guidance. Agents may pass untrusted code.
Mutually exclusive parameters not documented. 'click' accepts uid, selector, text, or x/y, but which takes precedence if multiple are provided? 'find' accepts selector, text, or role, are they OR or AND? Undocumented dependencies cause silent misuse.