This release is a pre-release and may not be stable for production use.
AXPilot
The MCP server for macOS. AXPilot lets any AI agent see and operate the apps on your Mac, through the macOS Accessibility API first and screenshots second, with safety controls that are on by default.
A real recording on macOS 26: Claude Code (left) drives TextEdit (right) through AXPilot. Sped up in places; the speed is shown on screen.
Project status: alpha. The first alpha, 0.1.0a1, is on PyPI:
uv tool install axpilot, then three commands to connect it. It is verified on macOS 26 on Apple silicon; macOS 14 and 15 and Intel Macs are not tested yet. Expect breaking changes until 1.0. See the roadmap.
Why AXPilot
- Sees the UI the way macOS does. A compact text snapshot of the accessibility tree gives every
button, field, list and menu a short ref (
e1,e2, …), so agents act on elements instead of guessing pixels. Text-only and local models work; vision is optional. - Acts reliably. Each action tries the most robust strategy first (an Accessibility action), falls back to synthetic mouse and keyboard events, and returns a diff of what changed.
- Scripts that outlive the session. Ask for a script and
locateturns the elements an agent used into stable locators (the AXIdentifier first, then role and name), each checked to match exactly one element, plus a ready-to-run Python script. - Safe by default. Scripting is off, destructive actions need your confirmation, password managers and the Privacy & Security settings are off limits, secure fields are never read, and there is no telemetry.
- Works with any MCP client or agent framework. Standard MCP over stdio or Streamable HTTP: Claude Desktop, Claude Code, Cursor, VS Code, Codex CLI, Gemini CLI, OpenAI Agents SDK, LangGraph, Pydantic AI and more.
- Permissions that just work. A tiny frozen
AXPilot.applauncher holds the macOS permissions, so you grant Accessibility once, to AXPilot, and every client can use it, across updates.
Electron apps too: VS Code
A real recording on macOS 26 with AXPilot 0.1.0a1. Claude Code first drove a throwaway VS Code through AXPilot (light theme, Auto Save, a new file, an extension search); here a script built from AXPilot's locators replays that setup on a fresh VS Code, in real time.
Features
The feature set planned for 1.0. Every tool below is implemented and tested against the simulated desktop. On a real Mac (macOS 26), the perception and input tools are verified, including dropdowns, menus and dialogs; the app, system, scripting and browser tools, the kill switch and the on-screen indicator are not yet. The tool reference documents each one.
| Area | What you get |
|---|---|
| Perception | Accessibility snapshots with refs, element search, element inspection, stable locators for automation scripts, diffs after every action, screenshots with a screenshot_id for coordinate mapping, Vision OCR, app/window/display lists |
| Actions | Click, type (layout-independent), keyboard shortcuts (layout-aware), scroll, drag, set values, raw AX actions, menu-bar commands by path, forms, apps, windows, opening files and URLs |
| Safety | Profiles and toolsets, app and window deny-lists, Terminal rule, secure-field protection, confirmations, rate limit, audit log, yield-to-user, kill switch, client pairing |
| Integrations | Any MCP client; tested framework examples; an Agent Skill; a computer profile for vision-first loops; a Windows-MCP naming profile |
How it works
MCP clients and agent frameworks
(Claude, Cursor, VS Code, Codex, OpenAI Agents SDK, LangGraph, …)
│ spawn `axpilot stdio` │ Streamable HTTP (`axpilot http`)
▼ │ 127.0.0.1 + bearer token
┌────────────────┐ Unix socket (0600) │
│ axpilot bridge │──────────────┐ │
│ (no perms) │ ▼ ▼
└────────────────┘ ┌──────────────────────────────────────────┐
│ AXPilot.app: tiny frozen launcher │
│ └─ Python host (child process) │
│ ├ MCP server: tools and schemas │
│ ├ Policy and safety layer │
│ └ Engine: Accessibility, input, │
│ ScreenCaptureKit, Vision OCR │
└──────────────────────────────────────────┘
macOS permissions (Accessibility, Screen Recording) → AXPilot.app
Spike S1 confirmed
this design on macOS 26 (Apple silicon): the permission prompts name AXPilot, and one grant covers
every client. Direct mode (axpilot stdio --direct) runs everything in one process instead;
macOS then attributes permissions to whichever app started the server (your terminal, Claude, Cursor, …).
Install
Requirements: macOS 14 Sonoma or later, Apple silicon or Intel.
From PyPI (alpha)
You need uv (or pipx).
uv tool install axpilot # or: pipx install axpilot
axpilot setup # installs ~/Applications/AXPilot.app and its runtime
axpilot connect claude-desktop # or claude-code, cursor, vscode, … (see --list)
axpilot doctor # checks the installation
Restart your MCP client, then ask it to use AXPilot ("take a snapshot of Finder"):
- The first time a client connects, AXPilot asks you whether to allow it. Allow it.
- The first tool call makes macOS ask whether AXPilot may control your computer. Open System Settings, switch on AXPilot under Accessibility, and ask again; no restart is needed.
- Screenshots and OCR also need Screen Recording for AXPilot. macOS applies that grant only
after AXPilot restarts: run
killall AXPilot, then restart your MCP client.
Details and other channels: docs/install.md. Permissions explained: docs/permissions.md.
From source (contributors)
You need uv and the Xcode Command Line Tools (xcode-select --install), which build the launcher.
git clone https://github.com/vansh3503/Mac-Mcp.git axpilot
cd axpilot
uv sync
launcher/build.sh # builds launcher/build/AXPilot.app
uv run axpilot setup --dev-source . # installs ~/Applications/AXPilot.app and its runtime
uv run axpilot connect claude-desktop # or claude-code, cursor, vscode, … (see --list)
uv run axpilot doctor # checks the installation
A launcher you build yourself has a different code signature from the published one, so macOS asks for the permissions again when you switch between the two.
Other ways to run it, without the launcher:
uv run axpilot stdio --engine fake # the simulated desktop (any OS, no permissions needed)
uv run axpilot stdio --direct # direct mode: grant Accessibility to the app that starts it
axpilot stdio speaks MCP on stdin/stdout, so it waits for a client. To poke at it by hand, use
the MCP Inspector:
npx @modelcontextprotocol/inspector uv run axpilot stdio --engine fake.
Connect a client
Installed from PyPI
axpilot connect <client> writes the config for you (with a backup). The snippets it writes:
Claude Desktop, Cursor (~/.cursor/mcp.json) and most other clients:
{ "mcpServers": { "axpilot": { "command": "axpilot", "args": ["stdio"] } } }
(Claude Desktop needs the absolute path of axpilot, e.g. /Users/you/.local/bin/axpilot.)
Claude Code:
claude mcp add axpilot -- axpilot stdio
VS Code (.vscode/mcp.json in a workspace, or your user mcp.json):
{ "servers": { "axpilot": { "type": "stdio", "command": "axpilot", "args": ["stdio"] } } }
More clients (Windsurf, Zed, Codex CLI, Gemini CLI, LM Studio, Goose, Cline, Continue): docs/clients.md.
From a source checkout
In the clone, uv run axpilot connect <client> writes the client's config for you (with a
backup), pointing it at the checkout's axpilot by absolute path. Restart the client afterwards.
For direct mode, or to write the config by hand, see
docs/clients.md.
Use it from an agent framework
Anything that speaks MCP works. Two examples (APIs as of writing; one for each of eleven
frameworks is in examples/frameworks/):
OpenAI Agents SDK
from agents import Agent, Runner
from agents.mcp import MCPServerStdio
async with MCPServerStdio(params={"command": "axpilot", "args": ["stdio"]}, cache_tools_list=True) as mac:
agent = Agent(
name="Mac operator",
instructions="Call snapshot before acting, act on element refs, and verify the result.",
mcp_servers=[mac],
)
result = await Runner.run(agent, "Open Notes and create a note titled 'Groceries'")
LangChain / LangGraph
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
client = MultiServerMCPClient({"axpilot": {"command": "axpilot", "args": ["stdio"], "transport": "stdio"}})
agent = create_agent("<your-model>", await client.get_tools())
More frameworks: docs/frameworks.md.
Tools
The 1.0 tool surface, implemented. Profiles pick a starting set: minimal (10 tools, for small or
local models), standard (default), full, and computer (one vision-first computer tool). A
windows-mcp naming exposes the same tools under Windows-MCP's names and parameters.
| Toolset | Tools | Default |
|---|---|---|
observe |
snapshot, screenshot, find, explore, read, inspect, locate, ocr, list_apps, list_windows, list_displays, wait_for, status |
on (read-only) |
input |
click, type_text, press_keys, scroll, drag, move_mouse, set_value, select_option, perform_action, select_menu, fill_form, handle_dialog |
on |
apps |
app, window, open |
on |
system |
clipboard, notify, spotlight_search, system_info, system_control, processes |
clipboard on |
scripting |
shell, applescript, shortcuts, defaults |
off |
browser |
browser_tabs, browser_read, browser_eval_js |
off |
computer |
computer |
computer profile only |
Every tool has an input and output schema, MCP annotations (readOnlyHint, destructiveHint, …)
and stable error codes such as STALE_REF, BLOCKED_BY_POLICY or USER_ACTIVE. Full reference,
generated from the code: docs/tools.md.
Safety defaults
| Control | Default |
|---|---|
| Profile | standard; scripting and browser toolsets off |
| Confirmations | Required for destructive actions (shell, AppleScript, JS eval, running a shortcut, force quit, defaults write, process kill), showing the exact command |
| App deny-list | Keychain Access, Passwords, 1Password, Bitwarden, LastPass, Dashlane, KeePassXC |
| Window deny-list | The Privacy & Security pane of System Settings |
| Terminal rule | Typing into Terminal, iTerm2, Ghostty, Warp and similar apps is blocked unless the shell tool is enabled |
| Secure fields | Values never returned; typing refused unless allow_secure_fields = true |
| Rate limit | 120 input actions per minute |
| Yield to user | On: input pauses while you are using the mouse or keyboard |
| Audit log | ~/Library/Logs/AXPilot/audit.jsonl, arguments redacted |
| Client pairing | The host asks once per client app before it may connect |
| Kill switch, indicator | ⌃⌥⌘. stops the agent (press again to resume); a frame and pill show while it acts (implemented, not yet run on a Mac) |
| Telemetry | None |
Screen content is untrusted input for an agent. Read the
security model before enabling
scripting or browser. To report a vulnerability, see SECURITY.md.
How AXPilot compares
AXPilot is the macOS counterpart of Windows-MCP, with a tool surface (and an optional naming profile) that lets Windows-MCP prompts carry over. Other good projects in this space include MacOS-MCP (Python + PyObjC, the closest peer), Peekaboo (Swift), mcp-server-macos-use (Swift) and cua-driver. AXPilot's focus:
- Permissions that survive updates: a frozen launcher holds the grant for every client.
- Safety and privacy as the headline: no telemetry, pairing, kill switch, confirmations, audit.
- Spec-first MCP: schemas, annotations, structured output, deterministic tool order, stateless handles.
- Integration kit and evals: framework examples tested in CI, an Agent Skill, published eval results.
Roadmap
About 12 weeks to 1.0: v0.1 alpha (engine and core tools in direct mode; 0.1.0a1 is out),
v0.2 beta (launcher, host app, safety), v0.3 public preview (one-line installer, connect for
12 clients, MCP Registry), v0.9 (full toolsets, OCR, frameworks, evals), then v1.0. Details and the open questions are in the
project plan; decisions are recorded as
ADRs.
Contributing
Contributions are welcome, and most of the code (server, policy, perception) runs and is tested on Linux. Start with CONTRIBUTING.md; AI coding agents should read AGENTS.md. Please follow the Code of Conduct.
License
Acknowledgements
AXPilot is inspired by Windows-MCP by CursorTouch, whose tool design and install experience set the bar for desktop MCP servers. Thanks also to the authors of PyObjC, the MCP Python SDK and the projects listed above.
Thanks to Zeel Thakkar, who helped ship the 0.1.0a1 release to PyPI and is working on automating Electron apps with AXPilot, starting with the VS Code demo above.
"Mac" and "macOS" are trademarks of Apple Inc. Claude and Claude Code are trademarks of Anthropic. Other product and framework names mentioned here (such as Cursor, VS Code, LangChain and CrewAI) are trademarks of their respective owners and are used only to describe compatibility. AXPilot is an independent project and is not affiliated with or endorsed by any of them.
The demo video's voiceover was made with ElevenLabs and its music comes from the HeyGen audio library.
Metadata
Release files for axpilot 0.1.0a2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| axpilot-0.1.0a2.tar.gz | 985.3 kB | With provenance | Details for axpilot-0.1.0a2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| axpilot-0.1.0a2-py3-none-macosx_14_0_universal2.whl | Python 3 | none | macOS 14.0+ universal2 (ARM64, x86-64) | Details for axpilot-0.1.0a2-py3-none-macosx_14_0_universal2.whl |
Total release size: 1.7 MB
Release files / axpilot-0.1.0a2.tar.gz
| Download URL | axpilot-0.1.0a2.tar.gz |
|---|---|
| Size | 985.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a35fd2641e50addc4189be6e7e1507585cc89f7ee8e6be946dfdd3aa313573b8
|
|
BLAKE2b-256 checksum How to use checksums |
6ca193fb6ce015974715b95c99b9e38700a7a3157b656135699724febc695335
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logRelease files / axpilot-0.1.0a2-py3-none-macosx_14_0_universal2.whl
| Download URL | axpilot-0.1.0a2-py3-none-macosx_14_0_universal2.whl |
|---|---|
| Size | 721.6 kB |
| Tags | Python 3 macOS 14.0+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
529bd9ab9af9e818526d7a34b39952b790cde91293ef9735ab9eef0ca22bfa5b
|
|
BLAKE2b-256 checksum How to use checksums |
20a65325852aa1312e94368e6800a9e4ff1c8a386583e5c9e8c6e1c186de8163
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logSecurity for axpilot 0.1.0a2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for axpilot-0.1.0a2.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.