# macos-mcp > The macOS MCP server: give your AI agent a Mac. One signed, notarized Swift binary that exposes accessibility-first UI automation (every action read back and verified), screenshots + OCR + find-on-screen, native apps, files, AppleScript recipes, Apple's own Safari MCP server (re-exported verbatim), a real iPhone through the iPhone Mirroring window (OCR-located, tapped in the phone's own device points), and disposable macOS VMs an agent may destroy (`macos-mcp vm`, single host today; the multi-host hub is in development). Permission profiles, one-shot confirmation tokens for destructive tools, an audit log, no telemetry. MIT. Apple Silicon, macOS 15+. Site: https://macos-mcp.com/ Source: https://github.com/Ark0N/macos-mcp Install: `curl -fsSL https://macos-mcp.sh | sh` (verifies checksum + Apple signature), then `macos-mcp install --client claude-code|claude-desktop|cursor|vscode|codex`. Current version: 0.2.0. This is the full tool list for macos-mcp v0.2.0: 44 tools, 24 on by default. The short version of this file, with the project's key facts and limits, is at https://macos-mcp.com/llms.txt. ## How to read this - Every tool returns structured JSON in `structuredContent`; every failure carries a stable `code` from the table at the end, never prose alone. - Names in parentheses are the tool's **required** arguments. Optional arguments, types and defaults are in the full tables at https://macos-mcp.com/docs/tools/ and in https://github.com/Ark0N/macos-mcp/blob/main/docs/tool-schemas.json. - `(read-only)` and `(destructive)` are the two annotations the dispatcher enforces. Under the `standard` profile a destructive call first returns `confirmation_required` with a one-shot token bound to that exact call. - Tool names and argument shapes are public API: a removal needs a deprecation notice one minor version ahead. ## Tools ### `ui` — Accessibility-first UI automation (on by default) macOS permission required: Accessibility. - `ui_snapshot()` *(read-only)* — Accessibility snapshot of an app's UI: a tree of {id, role, title, value, frame, actions} with stable element ids the other ui_* tools take. - `ui_click(id)` — Click an element by id. - `ui_type(id, text)` — Type text into an element by id. - `ui_scroll(id)` — Scroll an element by id. - `ui_drag()` — Drag from one place to another with the pointer held down — reorder rows, move sliders, drop a file on a target. - `ui_shortcut(keys)` — Send a keyboard shortcut such as "cmd+s", "cmd+shift+p" or "f5". - `app_launch(app)` — Launch an app by name, bundle id, or absolute path, and wait until it reports ready. - `app_quit()` *(destructive)* — Quit an app and confirm it actually exited. - `window_manage(action)` — Move, resize, minimize, unminimize, raise, or close a window — each verified by reading the window state back. - `wait()` *(read-only)* — Wait a fixed time, or poll until a condition holds: an app running or gone, an element id resolving or not. ### `screen` — Screenshots, OCR and find-on-screen (on by default) macOS permission required: Screen Recording. - `screenshot()` *(read-only)* — Capture a display, a window, or a rect as PNG (returned as image content; structuredContent carries dimensions and the captured region in screen points). - `ocr()` *(read-only)* — Read the text on a display, in a window, or inside a rect (Vision, accurate mode). - `screen_find(text)` *(read-only)* — Find text on screen and get clickable coordinates: OCR plus fuzzy matching, tolerant of small misreads. ### `system` — Shell, AppleScript recipes, clipboard, open, Spotlight (on by default) macOS permission required: none (Automation per app for recipes). - `shell(command)` — Run a shell command with /bin/zsh -c. - `applescript_recipes()` *(read-only)* — The catalog of vetted AppleScript recipes: id, description, and the parameters each one takes. - `applescript_run_recipe(recipe)` — Run a recipe from the catalog by id with typed params. - `applescript_eval(source)` *(destructive)* — Evaluate raw AppleScript or JXA source. - `clipboard_read()` *(read-only)* — Read the clipboard with type awareness. - `clipboard_write()` — Replace the clipboard with exactly one of: text, a base64 PNG, or file paths. - `open(target)` — Open a file or URL with its default app, or a specific app by bundle id / .app path. - `spotlight_search(query)` *(read-only)* — Spotlight (mdfind) search. ### `files` — Trash and Finder tags — never a hard delete (on by default) macOS permission required: none. - `trash(path)` *(destructive)* — Move a file or folder to the Trash — recoverable by design; this server never hard-deletes. - `tags(path)` — Read a file's Finder tags; pass `set` to replace them (empty array clears). ### `apps` — Calendar, Reminders, Contacts (gated) macOS permission required: Calendars / Reminders / Contacts (prompted on first use). - `calendar_list()` *(read-only)* — The user's event calendars: id and title. - `calendar_search()` *(read-only)* — Events in a date window (default: the coming 7 days), optionally filtered by text across title, calendar and location. - `reminders_list()` *(read-only)* — Reminders, incomplete by default, optionally narrowed to one list. - `reminders_search(text)` *(read-only)* — Reminders whose title or notes contain the text (case-insensitive), incomplete by default. - `contacts_search(name)` *(read-only)* — Contacts matching a name, with phones, emails and organization. ### `intents` — Shortcuts and App Intents (gated) macOS permission required: none (Shortcuts may prompt per shortcut). - `intents_list()` *(read-only)* — List the shortcuts installed on this Mac (name + identifier). - `intents_run(name)` — Run a shortcut by name or identifier and return its output. ### `web` — Browser control: Apple's Safari MCP where available, AppleScript fallback elsewhere (gated) macOS permission required: Automation for Safari (fallback) or Safari remote automation (Apple MCP). - `web_navigate(url)` — Open an http(s) URL in Safari (AppleScript fallback — used when Apple's Safari MCP isn't available). - `web_current_tab()` *(read-only)* — URL and title of Safari's frontmost tab (AppleScript fallback). - `web_page_text()` *(read-only)* — Rendered text of Safari's frontmost tab (AppleScript fallback) — the page as read, not its HTML. - `web_tabs()` *(read-only)* — Every tab of Safari's front window with its 1-based index, URL, title and whether it is current (AppleScript fallback). - `web_select_tab(index)` — Make a tab of Safari's front window current, by the 1-based index from web_tabs (AppleScript fallback). ### `ios` — Control a mirrored iPhone in device points — read, tap, swipe, type, navigate (gated) macOS permission required: Screen Recording + Accessibility. - `iphone_status()` *(read-only)* — Is a mirrored iPhone readable right now, and if not, what to do about it. - `iphone_screenshot()` *(read-only)* — Capture the mirrored iPhone's screen as PNG — cropped to the phone itself, never the surrounding window or its letterbox bars. - `iphone_find(text)` *(read-only)* — Find text on the mirrored iPhone and get coordinates in the phone's own space: OCR plus fuzzy matching, tolerant of small misreads. - `iphone_tap(x, y)` *(destructive)* — Tap the mirrored iPhone at a point in **device points** — the space iphone_find returns, which survives a window resize. - `iphone_swipe(from, to)` *(destructive)* — Swipe or scroll the mirrored iPhone between two points in **device points**. - `iphone_type(text)` *(destructive)* — Type text into whatever has keyboard focus on the mirrored iPhone. - `iphone_key(key)` *(destructive)* — Press one of iPhone Mirroring's navigation keys. - `iphone_resume()` *(destructive)* — Press the `Resume` control iPhone Mirroring shows when it has paused itself, then report what the window did about it. ### `server` — Meta (on by default) macOS permission required: none. - `enable_toolset(toolset)` — Enable a gated toolset — its tools join the tool list at once and a list_changed notification follows. ## Error codes Wire-stable: a rename needs a deprecation entry. - `permission_missing` — A required TCC grant is missing. **What to do:** `fix` holds the exact System Settings deep-link; grant it and restart the client. - `element_not_found` — An id, app or key did not resolve. **What to do:** `nearest_matches` lists what *is* there — often ids visible right now. Re-snapshot and retry. - `invalid_argument` — A value failed semantic validation the schema can't express — unknown recipe param, enum violation, type mismatch. **What to do:** `param` names the offender; `expected` says what would have been accepted. Fix the argument, don't retry blind. - `refused` — A hard line. The server will not do this. **What to do:** `reason` says why, `alternative` points at the legitimate route. Do not retry. - `action_unverified` — It ran, reported success, and nothing changed. **What to do:** `expected` vs `actual` show the gap. Re-snapshot: the UI is not where you thought. - `timeout` — The operation outlived its budget. **What to do:** Retry with a longer timeout, or check the app is responding. - `confirmation_required` — A destructive action needs a confirm token. **What to do:** Re-issue with the `token` once the human has approved. - `upstream_unavailable` — A mounted upstream (Safari/Xcode MCP) is down. **What to do:** `enable_hint` names the setting to switch on. - `machine_unreachable` — Fleet: the target machine is not answering. **What to do:** Check `last_seen`; the agent may be offline. - `host_at_capacity` — Fleet: the host is at its macOS-VM ceiling (2 per Apple Silicon host — a kernel quota). **What to do:** Schedule the clone on another host; more RAM will not help. - `lease_held` — Fleet: another client holds the machine. **What to do:** `expires` says when it frees. ## More - [Full tool reference with argument tables](https://macos-mcp.com/docs/tools/) - [Safety model](https://macos-mcp.com/docs/safety/) - [Short version of this file](https://macos-mcp.com/llms.txt)