macOS自动化服务

Desktop Pilot MCP是一个通过Accessibility API、AppleScript和CGEvent实现macOS应用自动化的服务,无需截图即可直接操作UI元素,速度比传统方法快30-100倍。

  • by VersoXBT
  • Swift
  • 本地部署
  • 12 星标
  • 更新于
在 GitHub 查看 VersoXBT/desktop-pilot-mcp

使用说明

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。
  • 基于角色的元素存储。 引用是短暂的——它们会在每个快照上重置。这 ElementStore actor保证跨并发工具调用对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

🤖 💡