mcpField
E
Electron Driver

Electron Driver

本地服务
github.com浏览器自动化329 周前更新

关于 Electron Driver

Electron Driver 是一个基于 Playwright 的 MCP 服务,让 AI Agent 操作已构建的 Electron 应用,适用于应用测试、调试和无障碍检查。它提供交互、状态读取、多窗口控制,以及在渲染进程和主进程中执行 JavaScript 的工具。

主要功能

  1. 01启动和关闭 Electron 应用
  2. 02点击、输入、拖动及滚动
  3. 03截图并读取控制台日志
  4. 04检查 DOM、ARIA 树和元素状态
  5. 05列出及切换应用窗口
  6. 06在渲染进程或主进程执行 JavaScript

适用场景

  1. 01验证新实现的应用功能
  2. 02进行视觉回归测试
  3. 03通过 ARIA 树开展无障碍检查
  4. 04复现描述中的界面问题

MCP 相关

该 MCP 服务向兼容 MCP 的 Agent 主机提供 38 个 Electron 应用操作与检查工具。README 提及可接入 Claude Code、Claude Desktop、Cursor 等主机。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

electron-driver

npm version license node version

通过 AI Agent 驱动 Electron 应用。 点击、输入、拖动、截屏,在渲染进程或主进程中执行 JavaScript,读取控制台日志,处理多窗口应用,捕获无障碍快照——所有操作都通过一个 MCP(Model Context Protocol)服务完成,该服务可接入 Claude Code、Claude Desktop、Cursor 以及其他兼容 MCP 的 Agent 宿主。

https://github.com/user-attachments/assets/a95500d2-28d2-4ee1-9965-8f7e1ef54caa

基于 Playwright 的实验性 _electron API 构建。适用于任何 Electron 应用——React、Vue、Svelte 或原生应用——只要能指定其编译后的主进程入口即可。

状态: v0.3.0。首次公开发布。包含 38 个工具,覆盖实际工作流。

为什么要开发它

AI Agent 能够推理桌面应用应该如何运行,但无法独立查看或与应用交互。Web 浏览器有大量 Agent 自动化方案,而 Electron 几乎没有。本包填补了这一空白:向 Agent 提供编译后的 Electron 应用路径,它就能像人一样驱动应用。

常见用例:

  • Agent 通过实际运行应用并检查可见结果,验证刚刚实现的功能
  • 重构过程中的视觉回归测试
  • 通过 ARIA 树快照进行无障碍审计
  • 根据自然语言描述复现 Bug
  • 指导子 Agent 反复调整 UI,直到通过规范检查

安装

需要 Node 18+,并且已有构建好的 Electron 应用。

npm install electron-driver

无需单独安装 Playwright 浏览器——_electron 会直接驱动 Electron 二进制文件。

在 Agent 宿主中注册

Claude Code(项目范围)

在仓库根目录创建 .mcp.json:

{
  "mcpServers": {
    "electron-driver": {
      "command": "npx",
      "args": ["electron-driver"]
    }
  }
}
Claude Code(用户范围——适用于每个项目)
claude mcp add electron-driver --scope user -- npx electron-driver
Claude Desktop / Cursor / 其他

在宿主的 MCP 配置中添加条目,指向 npx electron-driver 或 node_modules/electron-driver/index.mjs 的绝对路径。

核心理念

服务一次只管理 一个 Electron 会话。start_app 启动应用,其他所有工具都与其交互,stop_app 则关闭应用。截屏会保存到会话目录中;每次调用 start_app 时都会清空该目录,避免文件堆积或残留过时内容。会话期间,所有工具调用都会记录到 <project>/.electron-driver/driver.log。

错误包含稳定的 code 字段,调用方无需通过正则表达式匹配错误文本,即可按程序逻辑分支处理:

代码含义
NOT_RUNNING工具需要正在运行的会话,但当前没有会话
ALREADY_RUNNING已存在会话时调用了 start_app
TIMEOUT操作超时
NOT_FOUND选择器或文件未匹配到内容
FILE_NOT_FOUND基于路径的输入指向不存在的文件
BAD_ARGUMENT参数未通过验证
UNKNOWN_TOOL无法识别工具名称
ERROR其他所有错误

工具

全部 38 个工具按用途分组。所有基于选择器的工具都支持 Playwright 的完整选择器引擎:CSS、text=、role=、[aria-label=]、:has-text()、作用域(main >> button)等。

生命周期

start_app — 启动应用。接受 main(编译后的主进程入口的绝对路径)、可选的 cwd、args、env、screenshotsDir 和 timeoutMs。返回 { title, url, viewport, screenshotsDir, logFile }。能够检测单实例锁导致的失败,并提供有用提示,而不是返回原始断开连接错误。

stop_app — 正常关闭。会话已经停止时也可安全调用。

info — { title, url, viewport: {width, height, devicePixelRatio}, uptimeMs }。视口信息取自 window.innerWidth/innerHeight。

捕获

screenshot — 全页 PNG。传入 name(不带扩展名)以指定文件名。返回 { path }。

cleanup_screenshots — 清空当前会话的截图目录。

console_logs — 最近的渲染进程控制台消息(log/info/warn/error/ debug/pageerror)以及主进程 stdout/stderr。滚动缓冲区最多保留 1000 条记录。可按 source(renderer/main/all)、type 和 limit 筛选。传入 clear: true 可在读取后清空缓冲区。

交互

click — 点击元素。选项:timeoutMs、button (left/right/middle)、clickCount、force(跳过可操作性 检查)、position(点击元素内的偏移位置)。

type — 对文本输入框执行 fill,替换已有内容。速度快,但 仅适用于真正的输入框。对于编辑器/CodeMirror/contenteditable 元素,请使用 keyboard_type。

keyboard_type — 通过真实的逐字符 keydown 事件输入。传入 focusSelector 可先点击某个元素。如果没有元素获得焦点且未传入焦点选择器,结果中会发出警告。

press — 按下某个键或组合键:"Escape"、"Enter"、"Control+S"、 "Shift+Tab"、"Control+Shift+P"。

press_sequence — keyboard_type 的别名,不带焦点选择器。

hover — 将鼠标悬停在元素上。选项:timeoutMs、force。

drag — 使用真实的 Chromium 输入事件(通过 Playwright 的 CDP 鼠标 管线)从一个点拖动到另一个点。由于这些是可信的浏览器事件,Chromium 的指针 管线会同时生成对应的 PointerEvent,因此 React onPointerDown、原生的 pointerdown 监听器、setPointerCapture、CSS :hover/:active 以及 所有其他指针事件处理方,都会像真实用户执行拖动一样准确地接收到事件。坐标单位为 CSS 像素。传入 detectSelector 后, 驱动程序会测量拖动前后的元素,并在结果中包含 detect.moved ——这是唯一可靠的方式,可捕获被 min/max 限制静默拦截的拖动。

{
  "from": { "x": 275, "y": 400 },
  "to":   { "x": 420, "y": 400 },
  "detectSelector": ".sidebar-resize-handle"
}

如果主要策略未能移动检测目标,驱动程序会自动回退,通过 fiber 属性访问直接调用 React 处理程序,并在 document 和 window 上派发 move/up 事件——涵盖所有已知的 React 分隔器模式。传入 fiberFallback: false 可禁用 此回退机制。结果中会包含 strategy ("pointer-capture" 或 "react-fiber")。

clear_input — 清空输入框或文本区域。

select_option — 按 value、label 或 index 从 <select> 中选择选项。

check — 勾选复选框或单选按钮。选项:timeoutMs、force。

uncheck — 取消勾选复选框。

scroll — 滚动容器(传入 selector)或窗口。支持 绝对位置(x、y)或增量(dx、dy)。

scroll_into_view — 确保元素可见。如果元素已经可见,也可以安全调用。

drop_file — 通过合成 DragEvent 和重建的 File,结合 DataTransfer,模拟将文件拖放到目标上。适用于 通过 Web API(FileReader、File.text() 等)读取文件的应用。不会 填充 file.path ——依赖 webUtils.getPathForFile() 的应用必须使用 eval_main 直接调用自己的 IPC 处理程序。

set_input_files — 测试文件上传界面的正确方式。无需原生对话框,即可将文件设置到 <input type="file"> 上。应用使用真实文件输入框时,这种方式比 drop_file 可靠得多。

等待

wait — 固定暂停指定毫秒数。优先使用其他等待方式。

wait_for_selector — 等待选择器达到指定状态 (attached/detached/visible/hidden)。遵循 timeoutMs。成功时返回 count、box 和 elapsedMs;超时则错误信息中包含 elapsed vs requested。

wait_for — 轮询 JavaScript 谓词(函数体,请使用 return), 直到其返回真值。选项:timeoutMs、pollMs。

检查和读取状态

exists — { exists, count } 快速检查,不会等待。支持完整的选择器引擎。

get_text — 第一个匹配项的文本内容。支持完整的选择器引擎。返回 { exists, text }。

get_attribute — 按名称读取 HTML 属性。返回 { exists, value }。

get_value — 读取 input/textarea/select 的当前值。

get_bbox — 以 CSS 像素为单位的边界框 { x, y, width, height }。在拖动或按偏移量点击前使用。

get_computed_style — 读取一个或多个计算后的 CSS 属性。传入 properties 数组。

elements_list — 列出与选择器匹配的元素及其标签、id、类名、文本片段、边界框和关键属性。非常适合查看“此屏幕上有哪些按钮”。默认上限为 50;可通过 limit 调整。

focused_element — 当前获得焦点的元素及其标签、id、类名、文本和边界框。如果没有有意义的焦点元素,则返回 { focused: false }。

accessibility_snapshot — 将 ARIA 树捕获为 JSON。适用于无障碍审计和按角色查找元素。传入 interestingOnly: false 可包含所有节点。传入 root 可对某个子树进行快照。

多窗口

windows_list — 应用打开的每个 BrowserWindow,包括 id、标题、URL、焦点/可见性/状态标志。

switch_window — 将后续工具调用路由到其他窗口。传入 index 或 titleMatch。

对话框

dialog_handler — 为 JavaScript 对话框(alert/confirm/prompt/beforeunload)安装自动响应器。传入 action: "accept" | "dismiss"、prompt() 的可选 text,以及 once: true(默认值),即可在第一个对话框出现后自动卸载。

求值逃生通道

eval_renderer 和 eval_main 使用相同的约定:传入函数体,使用 return 返回值,支持 async/await,并且可通过局部变量 arg 使用可选的 arg 负载。

eval_renderer — 在渲染器(页面)上下文中求值。

{
  "js": "return document.querySelectorAll(arg.selector).length",
  "arg": { "selector": ".item" }
}

eval_main — 在 Electron 主进程中求值。函数体可接收 electron(完整的 Electron 模块)和 arg。

{
  "js": "return electron.app.getName()"
}
{
  "js": "const w = electron.BrowserWindow.getAllWindows()[0]; w.webContents.send('open-file', arg.path); return true",
  "arg": { "path": "C:/docs/README.md" }
}

对于 DOM 侧无法访问的所有内容,使用 eval_main 作为逃生通道:调用 IPC 处理程序、读取用户路径、控制辅助窗口,以及绕过使用原生对话框的应用中的这些对话框。

选择器速查表

text=Open File              // exact text match
text=/^Save$/               // regex
[aria-label="Settings"]     // ARIA attribute
role=button[name="Close"]   // ARIA role
button:has-text("Save")     // CSS with text predicate
button.primary              // plain CSS
main >> text=Save           // scoped

选择器引擎一致性

所有基于选择器的工具(click、hover、wait_for_selector、get_text、get_attribute、get_value、get_bbox、exists、elements_list、scroll_into_view、select_option、check、uncheck、set_input_files)都使用 Playwright 的完整定位器引擎。Playwright 接受的选择器,这些工具都接受,包括 text=、role= 和 :has-text()。

底层通过 eval_renderer 读取 DOM 的工具(get_computed_style、scroll、focused_element、drop_file)使用原生 document.querySelector,仅支持 CSS。相关工具的说明中会注明这一点。

故障排除

“Electron 进程启动后立即退出。” 已有另一个应用实例正在运行并占用了单实例锁——第二个进程会通过 app.requestSingleInstanceLock() 退出。关闭正在运行的实例(检查任务栏和后台进程),然后重试。

drag 返回了 ok:true,但 detect.moved 为 false。 最常见的原因是目标受到最小值/最大值限制(例如,可调整大小的侧边栏已达到其 MAX_WIDTH)。尝试向相反方向拖动,以确认拖动流程正常。如果确实不是限制导致的,React fiber 回退机制应该会自动捕获——检查结果中的 strategy 字段。如果这样仍返回 moved:false,请使用 eval_renderer 或 eval_main 直接调用应用自身的拖动 API。

type 抛出“Element is not an <input>...” 你操作的是按钮、div 或 contenteditable。请改用带有 focusSelector 的 keyboard_type。

click 在一个明显存在的元素上超时。 有东西挡住了它——模态框背景、工具提示或提示消息。先使用 exists 确认数量,然后尝试 force: true,或者使用 eval_renderer 检查 getComputedStyle(el).pointerEvents。

看不到原生对话框。 Playwright 无法看到操作系统级别的文件选择器、保存对话框或系统警告。请使用 eval_main 调用 UI 按钮使用的同一个 IPC 处理程序。对于 JavaScript 对话框(alert/confirm/prompt),请使用 dialog_handler 自动响应。

开发构建与编译后的应用。 此工具驱动的是构建后的应用,而不是开发服务器的输出。运行构建命令后再调用 start_app;源代码更改后,请重新构建并重启会话。

一次只能运行一个会话。 会话正在运行时调用 start_app 会返回 ALREADY_RUNNING。请先调用 stop_app。

日志。 会话处于活动状态时,每次工具调用都会记录到 <project>/.electron-driver/driver.log。调试 Agent 卡住的原因时,这些日志很有用。

截图位置。 默认位置为 <project>/.electron-driver/screenshots, 其中 <project> 是最近的、包含 .git 或 package.json 的目录。可通过 start_app 中的 screenshotsDir 覆盖。

安全

此服务可让已连接的 Agent 完全控制 Electron 应用,包括在主进程中执行任意代码(通过 eval_main)。 Electron 主进程拥有不受限制的 Node.js 访问权限——文件系统、网络、子进程,等等。这是有意为之:正是这一点让驱动程序能够强大到足以驱动真实应用。

这对你意味着:

  • 仅通过 stdio 使用(默认方式)。绝不要通过 HTTP、WebSocket 或任何网络传输方式暴露此服务。stdio 会将其绑定到启动它的进程——你本地的 Claude Code 或 Claude Desktop 会话。
  • 信任该 Agent。 调用这些工具的 Agent 可以通过 eval_main 在你的机器上执行任何操作。只连接你信任的 Agent。
  • 不要在多租户环境中使用。 这是面向单个用户的本地工具,并非为共享服务器、包含不可信输入的 CI 流水线,或调用方可能具有恶意的任何环境而设计。
  • drop_file 和 set_input_files 会读取本地文件,并将其内容传递给渲染进程。文件路径应来自可信来源。

如果你使用 Claude Code 运行此工具,其风险等级与授予 Claude Code 终端访问权限相同(你已经授予了)。此驱动程序不会增加任何超出终端中 eval 能力范围的新功能——它只是让 Agent 使用起来更方便。

已知限制

  • Playwright 的 _electron 命名空间在上游官方仍处于实验阶段。 在速度较慢的机器上偶尔会出现启动超时;通常重试即可解决。
  • 主要在 Windows 上开发。Mac 和 Linux 应该也能正常运行——Playwright 会处理这些平台——但测试覆盖较少。欢迎提交错误报告。
  • switch_window 会将后续调用路由到所选窗口,但控制台日志缓冲区的数据来自初始窗口。多窗口控制台捕获计划列入 v0.4。
  • drop_file 不会填充 file.path。使用 webUtils.getPathForFile() 的应用必须通过自己的 IPC 使用 eval_main。
  • 目前尚无内置的网络请求捕获功能——计划列入 v0.4。

实现说明

供感兴趣或希望参与贡献的人参考:

  • 使用单个 Electron 会话,由 MCP 服务进程持有。
  • 每次 start_app 时都会清除屏幕截图——这是有意为之。
  • 控制台日志会捕获到一个最多容纳 1000 条记录的滚动缓冲区中。
  • 每次工具调用都会记录日志;错误会带有稳定的 code 字段。
  • 错误消息会重写为归因于驱动工具,而非底层 Playwright 方法。
  • 单实例锁检测以“启动后 5s 内进程断开连接”为判断依据,这正是实际故障的表现形式。
  • 求值代码会用异步立即调用函数表达式包装,因此 return 和 await 均可使用。
  • arg 负载会在服务端进行强制转换(对字符串执行 JSON 解析),以兼容会将 arg 字段转换为字符串的 MCP 客户端。
  • 状态消息使用 stderr;stdout 保留用于 MCP 协议帧。

贡献

欢迎提交问题和 PR。可在本地运行:

cd electron-driver
npm install
node index.mjs  # stdio MCP server

服务器会向 stderr 输出就绪提示,并在 stdin 上等待 MCP 帧。通过任意 MCP 客户端,对真实的 Electron 应用进行测试。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。