使用说明
Desktop Pilot MCP
Native macOS automation for Claude. 30-100x faster than screenshots.
Desktop Pilot是一款MCP服务器,通过Accessibility API、AppleScript和CGEvent,Claude可以直接访问任何macOS应用程序——无屏幕截图、无像素坐标、无视觉模型开销。它读取实际的UI树并对语义元素引用进行操作,就像Playwright在浏览器中的工作方式一样。
Telegram的一个快照需要20毫秒,并返回结构化数据。使用基于屏幕截图的计算机进行相同的操作需要大约3秒,并返回像素。
pilot_snapshot { "app": "Telegram" }
[e1] Window "Saved Messages"
[e2] MenuButton "Main menu"
[e3] Button "All chats (111 unread chats)"
[e7] Button "Code (4 unread chats)"
[e18] TextField "Write a message..."
[e20] Button "Record Voice Message"
pilot_click { "ref": "e18" } // focus the text field
pilot_type { "ref": "e18", "text": "Hello from Claude" }
pilot_click { "ref": "e20" } // send
没有坐标。没有截图。没有猜测。只是参考。
快速入门(2分钟)
npx desktop-pilot-mcp
步骤1。 添加到您的Claude配置并重新启动Claude:
对于 克劳德代码,添加到 ~/.claude.json 在您的项目下 mcpServers:
{
"desktop-pilot": {
"command": "npx",
"args": ["-y", "desktop-pilot-mcp"]
}
}
对于 克劳德桌面,添加到 ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"desktop-pilot": {
"command": "npx",
"args": ["-y", "desktop-pilot-mcp"]
}
}
}
步骤2。 macOS提示时授予辅助功能权限(一次性)。
如果未出现提示: 系统设置>隐私和安全>辅助功能 --添加您的终端应用程序或Claude Desktop。
步骤3。 让Claude与任何应用程序进行交互:
“拍摄Telegram的快照,并向我展示屏幕上的内容”
就是这样,没有API密钥,没有帐户,没有配置文件。
Alternative: build from source
需要Swift 6.0+(Xcode 16+附带)。
git clone https://github.com/VersoXBT/desktop-pilot-mcp.git
cd desktop-pilot-mcp
swift build -c release
然后直接在Claude配置中使用二进制路径:
{
"desktop-pilot": {
"command": "/absolute/path/to/desktop-pilot-mcp/.build/release/desktop-pilot-mcp",
"args": []
}
}
基准测试
对Telegram、Finder和其他macOS应用程序进行测试的真实测量结果:
| 操作 | 电脑使用(截图) | 桌面试点 | 加速 |
|---|---|---|---|
| 快照(读取完整UI树) | ~3000ms | 20ms | 150倍 |
| 快照(查找器,45个元素) | ~3000ms | 78ms | 38x |
| 点击元素 | ~3000ms | ~50ms | 60倍 |
| 读取元素值 | ~3000ms | <1ms | 3000x |
| 按角色查找按钮 | ~3000ms | 4ms | 750倍 |
| 键入文本 | ~4000ms | ~20ms | 200倍 |
| 全流量(点击+键入+发送) | ~14s | ~450ms | 30倍 |
基于屏幕截图的方法(计算机使用等)支付了全屏捕获、视觉模型调用和每次操作的坐标计算的成本。Desktop Pilot直接读取实时UI树并对其进行操作。
运作原理
Desktop Pilot使用四个交互层和一个智能路由器,为每个应用程序和操作选择最快的方法:
+-------------------+
| Smart Router |
| (per-app + per- |
| action routing) |
+--------+----------+
|
+-------+-------+-------+--------+
| | | |
+------+--+ +--+------+ +-----+---+ +--+--------+
|AppleScript| | AX | | CGEvent | |Screenshot |
| Layer | | Layer | | Layer | | Layer |
+----------+ +--------+ +---------+ +-----------+
Priority: 20 Pri: 0 Pri: 40 Pri: 50
Scriptable Universal Raw input Fallback
apps only all apps injection (vision)
第1层--可访问性API (优先级0,通用) 读取任何macOS应用程序的结构化UI树。每个按钮、文本字段、菜单项和标签都显示为具有语义引用ID的节点。这是读取状态、单击和查找元素的主要层。
第2层——AppleScript/系统事件 (优先级20,可编写脚本的应用程序)
使用AppleScript字典(Finder、Safari、Mail、Keynote、Music等)为应用程序编写深度脚本。路由器通过以下方式检测可编写脚本的应用程序 sdef 并在此处自动路由基于脚本的操作。
第3层——CGEvent (优先级40,输入注入) 超高速键盘和鼠标输入,延迟1-5ms。用于键入文本(对于大多数应用程序来说,比AXSetValue更可靠)、键盘快捷键、坐标处的鼠标点击和拖动操作。
第4层——屏幕截图 (优先级50,最后手段) 将屏幕区域或特定元素边界捕获为base64 PNG格式。仅在辅助功能无法看到内容时使用——游戏视口、画布元素、自定义渲染UI。
这 智能路由器 对每个应用程序进行分类(可脚本化、Electron、原生、未知),并为每个操作选择最佳层:
| 操作 | 可脚本化应用程序 | 电子应用程序 | 原生应用程序 |
|---|---|---|---|
| 快照/读取/查找 | 辅助功能 | 辅助功能 | |
| 单击 | 辅助功能 | 辅助功能 | Accessibility |
| 类型 | CGEvent | 可访问性 | CGEvent |
| 脚本 | AppleScript | 辅助功能 | 辅助功能 |
| 菜单 | 辅助功能 | 辅助功能 |
比较
| 功能 | 桌面飞行员 | 计算机使用(内置) | 剧作家MCP | adamrdraw/macos辅助功能MCP | steipete/macos自动机MCP |
|---|---|---|---|---|---|
| 速度 | 20-100ms | 2-5s | 50-200ms | ~200ms | ~500ms |
| macOS原生应用 | 是 | 是 | 否 | 是 | 有 |
| Web应用程序/浏览器 | 是 | 是 | 否 | 否 | |
| 电子应用程序 | 是 | 是 | 部分 | 否 | |
| 辅助功能API | 是 | 否 | 否 | 是 | 不是 |
| AppleScript集成 | 是 | 否 | 否 | 是 | |
| CGEvent(原始输入) | 是 | 否 | 否 | 不 | 否 |
| 屏幕截图回退 | 是 | 是(主要) | 是 | 否 | 否 |
| 智能层路由 | 是 | 否 | 否 | 不 | 否 |
| 语义元素参考 | 是 | 否 | 是 | 基本 | 否 |
| 批处理操作 | 是 | 否 | 否 | 不 | 否 |
| 菜单栏导航 | 是 | 否 | 否 | 通过脚本 | |
| 零依赖 | 是 | N/A | Node.js | Node.js | Node.js |
| 二进制大小 | 427KB | N/A | ~50MB+ | ~30MB+ | ~30MB+ |
工具参考
Desktop Pilot通过MCP协议公开了10个工具。所有工具都使用 pilot_ 前缀。
pilot_snapshot
获取应用程序UI元素树的结构化快照。这是任何交互的起点——它返回每个可见元素,并带有可以传递给其他工具的引用ID。
{ "app": "Telegram" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
app |
string | 否 | 应用程序名称或捆绑包ID。最前面的应用程序省略。 |
maxDepth |
integer | 否 | 要遍历的最大树深度(默认值10)。 |
返回一个元素树,每个元素都有一个 ref (例如。 e1, e2)、角色、标题、值、启用/聚焦状态和边界矩形。
pilot_click
按引用ID单击UI元素。适用于按钮、复选框、菜单项和任何可单击的元素。
{ "ref": "e5" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
ref |
string | 是 | 快照中的元素引用ID。 |
pilot_type
在文本字段、搜索框或任何可编辑元素中键入文本。首先聚焦元素,然后插入文本。
{ "ref": "e18", "text": "Hello from Claude" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
ref |
string | 是 | 快照中的元素引用ID。 |
text |
string | Yes | 要在元素中键入的文本。 |
pilot_read
读取UI元素的当前值、标题、角色和描述。用于检查文本字段内容、复选框状态或标签文本。
{ "ref": "e3" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
ref |
string | 是 | 快照中的元素引用ID。 |
pilot_find
在应用程序的UI树中搜索符合条件的UI元素。当您知道要查找什么时,比完整快照更快。
{ "role": "AXButton", "title": "Save", "app": "Finder" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
role |
string | 否 | 要匹配的AX角色(例如。 AXButton, AXTextField). |
title |
string | 否 | 标题/标签子字符串,不区分大小写。 |
value |
string | 否 | 要匹配的值子字符串。 |
app |
string | 否 | 将搜索限制到此应用程序。最前面省略。 |
pilot_menu
按路径激活菜单栏项。直接遍历应用程序的菜单栏层次结构。
{ "path": "File > Save As...", "app": "TextEdit" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
path |
string | 是 | 菜单路径 > 分离器。 |
app |
string | 否 | 应用程序名称或捆绑包ID。最前面省略。 |
pilot_script
运行针对特定应用程序的AppleScript或JXA(JavaScript for Automation)代码。
{
"app": "Finder",
"code": "tell application \"Finder\" to get name of every window",
"language": "applescript"
}
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
app |
string | 是 | 目标应用程序名称。 |
code |
string | 是 | 要执行的AppleScript或JXA代码。 |
language |
string | 否 | applescript (默认)或 jxa. |
pilot_screenshot
捕获特定元素或全屏的屏幕截图。返回base64 PNG。谨慎使用-- pilot_snapshot 通常更便于理解UI状态。
{ "ref": "e1" }
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
ref |
string | 否 | 元素引用到屏幕截图。省略全屏显示。 |
pilot_batch
在单个MCP往返中按顺序执行多个工具调用。用于减少执行多步骤操作时的延迟。
{
"actions": [
{ "tool": "pilot_click", "params": { "ref": "e18" } },
{ "tool": "pilot_type", "params": { "ref": "e18", "text": "Hello" } },
{ "tool": "pilot_click", "params": { "ref": "e20" } }
]
}
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
actions |
array | 是 | 数组 { tool, params } 对象按顺序执行。 |
pilot_list_apps
列出所有正在运行的macOS应用程序及其名称、捆绑包ID、PID和窗口计数。用于在拍摄快照之前发现可用的应用程序。
{}
无需参数。
建筑
Sources/
DesktopPilot/
Core/
AppRegistry.swift # App discovery via NSWorkspace
ElementStore.swift # Actor-based ref-to-element mapping
Router.swift # Smart per-app, per-action routing
Snapshot.swift # Batch AX tree traversal
Layers/
LayerProtocol.swift # InteractionLayer protocol
AccessibilityLayer.swift # AXUIElement tree reading + actions
AppleScriptLayer.swift # System Events + sdef scripting
CGEventLayer.swift # Raw keyboard/mouse injection
ScreenshotLayer.swift # Screen capture fallback
MCP/
Server.swift # JSON-RPC 2.0 with Content-Length framing
Tools.swift # 10 tool definitions + dispatch
Types.swift # PilotElement, AppSnapshot, AppInfo
Platform/
PlatformProtocol.swift # Cross-platform bridge interface
macOS/
AXBridge.swift # Low-level AXUIElement C API wrapper
Permissions.swift # Accessibility permission management
SystemEvents.swift # AppleScript/JXA execution helper
DesktopPilotCLI/
main.swift # Entry point: permission check + server start
Tests/
DesktopPilotTests/
DesktopPilotTests.swift # 22 tests: types, router, registry, MCP, tools
关键设计决策:
- 零依赖。 整个服务器仅基于苹果框架(ApplicationServices、AppKit、CoreGraphics)构建。没有SwiftNIO,没有Vapor,没有第三方JSON库。这使二进制文件保持在427KB。
- 基于角色的元素存储。 引用是短暂的——它们会在每个快照上重置。这
ElementStoreactor保证跨并发工具调用对AXUIElement到ref映射的线程安全访问。 - 内容长度框架。 MCP服务器使用标准JSON-RPC 2.0协议
Content-Length通过stdin/stdout构建头帧,与MCP规范完全匹配。 - 批量属性读取。 快照生成器使用
AXUIElementCopyMultipleAttributeValues在一次调用中读取6个属性。这就是为什么快照很快。
支持的应用程序
Desktop Pilot适用于任何公开可访问性树的macOS应用程序(实际上是所有这些应用程序):
| 类别 | 示例 | 主层 |
|---|---|---|
| Apple原生 | 查找器、Safari浏览器、邮件、笔记、日历、音乐 | AppleScript+辅助功能 |
| 生产力 | 微软Office、谷歌Chrome、火狐 | 辅助功能 |
| 电子 | VS代码、Discord、Slack、Spotify、信号 | 可访问性 |
| 创意 | Final Cut Pro、Logic Pro、Xcode | AppleScript+辅助功能 |
| 通信 | 电报、iMessage、WhatsApp | 可访问性 |
| 系统 | 系统设置、活动监视器、终端 | 可访问性 |
用例
- 自动化任何macOS工作流程 --文件管理、应用程序配置、跨应用程序的数据输入
- 构建AI代理 运行Claude无法通过web API访问的本地桌面应用程序
- 测试macOS应用程序 通过结构化元素引用而不是脆弱的像素坐标来驱动UI
- 跨应用编排 --从一个应用程序复制数据,处理数据,粘贴到另一个应用中,所有这些都在一个Claude会话中完成
- 可访问性审计 --检查任何应用程序的完整UI树,以验证可访问性合规性
故障排除
“未授予访问权限” 打开“系统设置”>“隐私和安全”>“辅助功能”,然后添加二进制文件或您的终端应用程序。授予后重新启动MCP服务器。
“未能捕获屏幕截图”
在“系统设置”>“隐私和安全”>“屏幕录制”中授予屏幕录制权限。仅适用于 pilot_screenshot.
陈旧参考文献(Unknown ref 'e5')
每次重置参考值 pilot_snapshot 电话。在与元素交互之前,始终拍摄一张新的快照。如果应用程序的UI自上次快照以来发生了变化,则旧的引用无效。
Electron应用程序没有响应 pilot_type
一些Electron应用程序(VS Code、Discord)会吞下原始密钥事件。路由器通过使用辅助功能(AXSetValue)而不是用于Electron应用程序的CGEvent来处理此问题。如果键入仍然失败,请尝试 pilot_script 通过系统事件按键。
空快照
该应用程序可能没有任何打开的窗口,或者可能使用非标准UI框架(游戏、OpenGL/Metal渲染器)。使用 pilot_screenshot 作为自定义渲染内容的后备方案。
发展
# Build debug
swift build
# Build release
swift build -c release
# Run tests
swift test
# Run the server directly
swift run desktop-pilot-mcp
项目被拆分为一个库目标(DesktopPilot)以及可执行目标(DesktopPilotCLI)为了可测试性。所有核心逻辑都存在于图书馆中;CLI是一个精简的入口点。
许可证
麻省理工学院
贡献者
VersoXBT 💻 📖 |
Claude 🤖 💡 |