Reliable, efficient Mac control for AI agents.
A Model Context Protocol server that lets agents (Claude Code, Codex, scripts, or agents on other machines over SSH) see and drive macOS apps through the accessibility tree. It uses element references, verified actions and settle-aware waits instead of blind coordinate clicks.
An agent reads the UI as compact rows with refs, acts on a ref, and gets back what changed:
> mac_snapshot app="MacMCPTestHost"
app: MacMCPTestHost (com.playbacksoftware.macmcp.testhost) · window "MacMCP Test Host" · focus: e1 · snapshot s1
heading "Order Form"
e1 textfield "Name" = "" [focused]
e5 popup "Size" = "Small"
e6 button "Submit"
text "Nothing submitted yet."
…
> mac_type ref=e1 text="Ada Lovelace"
into e1 textfield "Name": typed 12 characters; field value verified · settled in 369 ms
~ e1 textfield "Name": value "" → "Ada Lovelace"
> mac_click ref=e6
clicked e6 button "Submit" (accessibility press) · settled in 457 ms
+ text "Submitted: Ada Lovelace, Small, toppings: none"
- text "Nothing submitted yet."
- Refs, not guesses. Every action re-resolves its target, hit-tests before clicking, verifies typed text and answers with a diff, so agents rarely need a screenshot.
- Settle-aware. Actions return once the UI goes quiet, and
mac_waitwaits for conditions instead of fixed sleeps. - Permissions that stick. A signed
MacMCP.appLaunchAgent holds the Accessibility and Screen Recording grants, so they survive rebuilds and work for clients started over SSH. - Works over SSH.
ssh my-mac ~/.local/bin/mac-mcpgives a remote agent the same tools. Several sessions can connect; only one drives the GUI at a time. - More than clicks. Menu commands by path, AppleScript in apps you allow, your Shortcuts, OCR for canvases, and
web_*tools for a separate automation Safari. - Safe and self-diagnosing. A per-machine policy, an audit log, deadlines on every call, and
mac-mcp doctorfor problems and their fixes. See Safety.
| Group | Tools |
|---|---|
| See | mac_snapshot, mac_screenshot (with OCR), mac_wait |
| Act | mac_click, mac_type, mac_key, mac_scroll, mac_drag, mac_hover |
| Direct routes | mac_menu, mac_script, mac_shortcut, mac_clipboard |
| Apps and windows | mac_app, mac_window, mac_doctor |
| Web (Safari) | web_navigate, web_read, web_act, web_tabs, web_dialog, web_logs, web_eval |
The tool reference describes each one.
- macOS 26 or later on Apple silicon, and Xcode 26 or later (Swift 6.1+) to build.
- A person logged in at the Mac's console with the screen unlocked while agents work. Screen Sharing is fine.
- For the
web_*tools: Safari 27, with Safari ▸ Settings ▸ Developer ▸ "Allow remote automation and external agents" turned on once. The Developer tab appears after Settings ▸ Advanced ▸ "Show features for web developers". - Any stdio MCP client, such as Claude Code.
scripts/setup-signing.sh # once: a signing certificate in a dedicated keychain
scripts/build.sh # build, sign and install ~/Applications/MacMCP.app and ~/.local/bin/mac-mcp, start the agent
mac-mcp setup # at the Mac, in Terminal: grant the permissions, then add MacMCP to a clientThe CLI is installed in ~/.local/bin; add it to your PATH or use the full path.
macOS ties permission grants to the signing certificate, so MacMCP needs one that stays the same across builds.
setup-signing.sh creates a self-signed one, or imports yours with --import. If your login keychain has exactly one
valid code-signing identity, such as an Apple Development certificate from Xcode, build.sh uses it from a local
Terminal without this step. With several, it stops and lists them; set MAC_MCP_SIGNING_IDENTITY to the SHA-1 of the one
you want. See Signing.
MacMCP needs two grants: Accessibility (shown as "Device Control" on macOS 27) and Screen & System Audio Recording.
mac-mcp setup checks that you're logged in with the screen unlocked and that the agent is running, then takes them one
at a time. It opens the System Settings pane, says what to switch on, and waits until the grant shows up (Return skips
a step). It never clicks or toggles anything and never answers a macOS prompt; that is yours. It ends with the
mac-mcp doctor report and offers to add MacMCP to a client. Without a terminal, or over SSH, it prints the steps,
checks once, and exits nonzero if something is missing. mac-mcp doctor shows the same state at any time.
Connect a client on the Mac itself, or from another machine over SSH:
mac-mcp install --client claude-code # claude-code, claude-desktop, codex, cursor or vscode
mac-mcp install --client codex --remote you@your-mac # a client on another machine, reaching this Mac over SSH
mac-mcp install --client cursor --dry-run # show the change without writing
mac-mcp uninstall --client claude-codeThis adds a server called mac (--name to change it) to the client's user config. Claude Code is registered with
claude mcp add when claude is on your PATH, and Codex with codex mcp add for a new entry. The other configs are
edited in place: only the MacMCP entry changes, the original is copied to
~/Library/Application Support/MacMCP/client-backups/ first (the path is printed; agents can't open that folder), and a
file that doesn't parse is left alone. Quit the client first: clients don't lock their configs, so one that saves its
settings later can undo the change, and mac-mcp stops if it sees the file change underneath it. See
Registering clients. Or by hand:
claude mcp add mac -- ~/.local/bin/mac-mcp
claude mcp add mac -- ssh you@your-mac /Users/you/.local/bin/mac-mcpmac-mcp remote-setup checks this Mac and prints the exact commands for another machine.
For work alongside the person using the Mac, add --background to this client's MCP server arguments (for
example, "args": ["--background"]). This opt-in uses accessibility actions and app-targeted keys without activating
apps or moving the pointer, and captures app windows even when covered. Unsupported input is refused; only the
person can change the client configuration. mac_doctor and tool results show the mode; it is off by default.
On the Mac itself, Claude Code can install the server entry together with a skill for driving macOS (the observe-and-act loop, waits, menus, Save panels, web pages, and when to stop and ask):
/plugin marketplace add Playback-Software/mac-mcp
/plugin install mac-mcp@playback-software
The plugin runs ~/.local/bin/mac-mcp, so install MacMCP first, and remove a mac server you added with
claude mcp add to avoid having two. The plugin is in integrations/claude-code.
Once the client is connected, give it something small and read-only:
Use the mac tools to list the running apps, then snapshot the frontmost window and tell me what's on screen.
Then something that acts:
Open Calculator, work out 17 × 23 and tell me what it shows.
If a call is refused, mac-mcp doctor and the tool's reply say why; Policy and security
covers the defaults.
git pull
scripts/build.sh # builds, swaps the install in and rolls back if the new agent doesn't answer
mac-mcp doctorPermissions carry over while the signing certificate stays the same. build.sh won't replace the agent while another
client holds the GUI lease. See the changelog for what changed between releases.
mac-mcp uninstall --purge # stops the agent, removes its LaunchAgent, ~/Applications/MacMCP.app and its support folder
rm ~/.local/bin/mac-mcp--purge also deletes the approved-policy records from your login keychain (macOS may ask for its password).
Without it, only the LaunchAgent is removed. Neither touches ~/.config/mac-mcp (your policy), ~/Library/Logs/MacMCP
(logs and the audit log) or the signing keychain ~/Library/Keychains/mac-mcp-signing.keychain-db; delete those yourself
if you want them gone. Remove MacMCP from System Settings ▸ Privacy & Security ▸ Accessibility and Screen & System Audio
Recording, and from your MCP client (claude mcp remove mac).
MacMCP lets an AI agent operate your Mac as you. Run it on a Mac, or under an account, where that's acceptable, and read Policy and security before you give it real work.
- Policy.
~/.config/mac-mcp/policy.jsondecides which apps agents may see and drive. By default they can't touch terminals, launchers and automation apps, Shortcuts, Keychain Access, password managers or System Settings, and AppleScript, Shortcuts, page JavaScript and private-network URLs are off until you allow them. A change that loosens the policy applies only after you runmac-mcp policy approvein Terminal, which records it in your login keychain. - Refusals. Agents can't answer macOS security prompts, read password fields or passwords copied from a password
manager, open launchers by side routes (the Dock, Finder, Services,
open=), or touch MacMCP's own files, keychains, SSH keys, credentials or shell startup files. Allowed scripts run behind an Apple-event gate. Screen and web text is marked as untrusted data with a per-response token that page text can't forge. - Audit log. Every call is recorded in
~/Library/Logs/MacMCP/audit.jsonl, with typed text, keys, script source and URL secrets redacted.mac-mcp reportsummarises it. - Person stop. ⌃⇧⌘\ (Control–Shift–Command–backslash) or
mac-mcp pausestops and pauses agents; the menu bar shows who is driving, and onlymac-mcp resumein Terminal resumes them. - Local by design. The socket is owner-only, there is no network listener, and remote access goes through SSH.
Found a way around these? Please report it privately; see SECURITY.md.
Early development: tools and policy keys may still change before 1.0.
| Document | Contents |
|---|---|
| Tools | Tool reference and an example snapshot |
| Architecture | Agent and relay design, protocol layer, web tools, health checks, GUI sharing, signing |
| Policy and security | policy.json options and the security model |
| Benchmarks | Agent task results with Claude Haiku 5.5, and action timings |
| Development and testing | Unit, integration and soak tests, the TestHost app, and the agent task suite |
| Contributing | Building, testing, linting and style |
| Changelog | What changed in each release |
MIT — see LICENSE. Copyright © 2026 Playback Software, LLC.