浏览器自动化
Spark Work 浏览器自动化:Playwright managed MCP 负责网页流程,spark_browser 内置 MCP 提供应用内可见窗口、本地 HTML 调试、console/network 和 profile 登录态。
Spark Work 有两条互不替代的浏览器能力:managedplaywrightMCP 负责成熟网页自动化, 内置spark_browserMCP 负责应用内可见独立窗口、本地 HTML 调试、持久脚本、profile 登录态以及 console / network 观察。前者是外挂 Playwright 自己拉起的浏览器,后者是主进程里真实可见的 Electron 窗口。
1. 两套能力的真实分界
Agent Runtime
├─ stdio MCP "playwright"(managed,自动注册并启用)
│ └─ Playwright 自启动 Chromium / 系统 Chrome / Edge
└─ stdio MCP "spark_browser"(内置脚本 + 主进程 bridge)
└─ Electron BrowserWindow(应用内可见)
▲ HTTP 127.0.0.1:<随机端口>,每次调用带 sessionId 校验
- playwright:MCP 记录是
scope=managed、name=playwright, 默认enabled=1,默认 headful。工具名是mcp__playwright__browser_*。 - spark_browser:工具名是
mcp__spark_browser__*,共 17 个; 只有桌面端注入了 bridge provider 才会挂载。 - 旧的 CDP 9223 嵌入式视图已经移除:协议里的
cdpEndpoint字段保留为兼容输入, 正常注册时传null,Playwright 不再复用 Electron 窗口。
2. Playwright MCP
注册逻辑集中在apps/desktop/src/main/services/PlaywrightMcpRegistration.ts, 它是这份 configJson 的唯一来源(设置页的「重置配置」也走它)。构造出的 MCP 配置形如:
{
type: "stdio",
command: "<内置独立 Node 运行时>",
args: [
"<@playwright/mcp 的 cli.js>",
// 仅在用系统浏览器时追加:--browser chrome | --browser msedge
// 仅在 headless 模式追加:--headless
// 兼容参数(当前不传):--cdp-endpoint=<url>
],
env: { PLAYWRIGHT_BROWSERS_PATH: "<内置 Chromium 目录>" } // 命中内置 Chromium 时才注入
}
注册是幂等的,重复注册会保留你手动切换过的enabled状态。
2.1 默认暴露的工具
注册时没有传--caps,所以拿到的是@playwright/mcp的默认能力集 (core automation + tab 管理),共 24 个工具:
browser_navigate browser_navigate_back browser_snapshot browser_find
browser_click browser_type browser_press_key browser_hover
browser_select_option browser_fill_form browser_drag browser_drop
browser_file_upload browser_handle_dialog browser_wait_for browser_resize
browser_evaluate browser_run_code_unsafe browser_take_screenshot browser_console_messages
browser_network_requests browser_network_request browser_tabs browser_close
cookie / localStorage / sessionStorage / route / tracing / video / PDF / 断言类工具属于可选能力, 需要启动时加对应的--caps才会出现,当前注册没有开启。
内置技能builtin:browser-use把工作方式写成了硬约束:先 browser_navigate再browser_snapshot,基于 snapshot 返回的 ref=N操作(element="ref=3"),不要写 CSS 选择器;每步动作后重新 snapshot;结束时调browser_close释放资源。
3. 设置页与 Chromium 修复
入口是设置 → 浏览器自动化(左侧「系统」分组)。页面标题就是「浏览器自动化」, 包含四行:
| 行 | 文案与操作 |
|---|---|
@playwright/mcp | 显示「已安装 <版本>」或「未安装」;按钮是「安装 MCP」/「重新安装」,内部执行 pnpm add @playwright/mcp playwright(工作目录 apps/desktop) |
| Chromium 浏览器 | 徽标为「Chromium 已就绪」/「使用系统浏览器」/「Chromium 未下载」;按钮为「下载浏览器」/「重新下载」,带下载进度 |
| 运行模式 | headful / headless 分段开关;headful 显示 Playwright 自启动浏览器,headless 后台运行 |
| 应用内可见浏览器窗口 | 说明「Agent 会通过内置 spark_browser MCP 工具按需打开」;按钮「重置配置」重建 MCP configJson |
右上角还有「重新检查」与「MCP 已启用 / 启用 MCP」开关。安装 Chromium 使用的命令是:打包版执行内置 Node + 打包后的cli.js install chromium;开发版执行 pnpm exec playwright install chromium(Windows 上是pnpm.cmd), 超时 5 分钟。
3.1 浏览器来源与优先级
Playwright 用哪个浏览器是自动判定的,优先级固定:
- 随应用下载的 Chromium:开发态
apps/desktop/browsers/,打包态<userData>/browsers或resources/browsers;命中时通过PLAYWRIGHT_BROWSERS_PATH指给子进程。 - Playwright 自己的缓存(
~/.cache/ms-playwright等):命中时不覆盖 环境变量,交给 Playwright 自动发现。 - 系统 Chrome / Edge:作为最后兜底,注册时追加
--browser chrome或--browser msedge。 - 都没有时状态为
none,设置页提示「未检测到可用浏览器,可点击右侧按钮手动下载约 150MB 的 Chromium」。
不要给--browser传chromium——该参数只接受chrome/ firefox/webkit/msedge;用内置 Chromium 时是不传这个参数、靠PLAYWRIGHT_BROWSERS_PATH路由的。
4. spark_browser:17 个工具
| 工具 | 关键参数 | 行为 |
|---|---|---|
open | url(必填)·show(默认 true)·profileId· reuse | 打开可见窗口;支持 http/https/file/data URL;reuse=true时复用同 profile 的已有窗口 |
navigate | url(必填)·windowId | 让已有窗口跳转 |
eval | code(必填)·windowId | 执行一次 JS,返回 JSON 可序列化结果;DOM 节点要自己 stringify |
inject_script | code(必填)·scriptId·windowId | 持久注入,后续导航会自动重跑 |
remove_script | scriptId(必填)·windowId | 移除持久脚本 |
screenshot | windowId | 返回 PNG dataUrl 与当前 url / title |
get_url/get_title | windowId | 读取当前地址与标题(包含用户手动导航后的状态) |
list_windows | 无 | 列出窗口的 profile、可见性、url/title、脚本数、网络规则数、console 缓冲条数 |
close | windowId | 关窗并清掉该窗口的脚本、网络规则与事件缓冲;profile 存储保留 |
console_start | windowId | 开始捕获 log / warn / error |
console_events/console_clear | windowId·sinceSeq | 增量读取(用sinceSeq轮询)或清空 |
network_set_rules | rules[],每条match(URL 子串或正则)+action(必填) | action 支持record/block/redirect(redirectUrl)/set_headers(headers) |
network_events/network_clear | windowId·sinceSeq/ruleIds | 增量读取请求/完成/错误事件,或清理全部/指定规则 |
clear_profile | profileId·scope(cookies / cache / localStorage / indexedDB / all) | 清空该 profile 的持久数据,会让页面退出登录 |
windowId全部可省略,省略时作用于第一个打开的窗口。mock_response这个 action 虽然在 schema 里,但当前构建不支持响应体改写,调用会返回NETWORK_RULE_UNSUPPORTED。
4.1 profile、缓冲与桥接
- profile:不传
profileId时用共享的default分区,登录态、cookie、localStorage、IndexedDB、缓存跨轮次跨重启保留。每个自定义profileId都是全新的空分区(站点全部未登录),只适合确实需要干净环境时用,并且要按用途起 稳定名字(如clean-test),不要按任务临时造名字。分区名形如persist:spark-browser:<profileId>,profileId只允许[a-zA-Z0-9_.-]且不超过 80 字符。 - 窗口:1280×820、标题
Spark Work Browser,默认可见。 - 事件缓冲:console 与 network 各自是环形缓冲,最多保留 500 条,用
sinceSeq增量拉取,别指望能翻很久以前的历史。 - 桥接:
spark_browserMCP 子进程本身很薄,只把调用代理到主进程的BrowserBridgeServer(监听 127.0.0.1 的随机端口)。每次请求都要带当前 sessionId, 不在允许集合里的请求直接 403;请求体上限 256 KB。
5. 另一条线:用户手动用的浏览器面板
除了 Agent 驱动的两个 MCP,应用里还有一个给用户自己用的浏览器面板(多标签、地址栏、视口预设、开发者 工具)与「在独立窗口中打开」。其中「选择元素加入会话」开关会把页面上拾取到的元素 以引用形式(页面 URL + CSS 选择器 + 元素摘要)加到输入框,发给 Agent 后它可以直接用 spark_browser 定位该元素。这条链路由 BrowserPanelWindowService与BrowserChrome/ useElementPicker实现,面板与独立窗口共用同一套 chrome,与 spark_browser的自动化窗口是两套窗口。已知限制:元素拾取只覆盖主 frame, 跨域 iframe 里的点击不会被捕获。
6. 怎么选
| 任务 | 推荐 | 原因 |
|---|---|---|
| 稳定点击 / 填表 / 表单流程 | playwright | snapshot 的 ref 定位比 CSS 选择器稳,且自带等待 |
| 批量采集、E2E 式验证 | playwright | 可browser_evaluate批量取数、可多标签、可上传文件 |
| 需要用户看得见、可共享的窗口 | spark_browser | 就在应用内的 BrowserWindow 里 |
本地file://HTML 调试 | spark_browser | 可直接开本地文件,配合 console 捕获与截图 |
| 持久注入脚本、复登录态 profile | spark_browser | inject_script跨导航重跑,profile 分区持久 |
| 观察 / 阻断 / 重定向 / 改请求头 | spark_browser | 主进程 webRequest 级规则 + 事件流 |
两者互补:一边被阻断时就换另一边,并说明原因——注入的 system prompt 就是这么要求的。
7. 安全模型与远程限制
spark_browser的页面保持sandbox: true、nodeIntegration: false、contextIsolation: true、webSecurity: true,页面里没有 Node / Electron API。Agent 的能力来自主进程受控的 eval、webRequest、截图、console 与 profile 工具。- bridge 只绑定 127.0.0.1 且要 sessionId 校验,外部进程无法直接调用。
- 远程连接默认不能用内置浏览器:远程连接能力里的
useInternalBrowser(界面文案「使用内置浏览器窗口」)默认关闭;只要当前会话绑定的远程 连接没开启它,spark_browser整套 MCP 都不会注入。 - URL 白名单:只允许
http/https/file/data,其它字符串会被当成域名补https://。 - 任务结束应主动清理:
network_clear、console_clear、remove_script、close。clear_profile只在确实要清登录态时用,清default会抹掉用户所有登录,必须先确认。
8. 故障排查
| 现象 | 排查 |
|---|---|
看不到mcp__playwright__browser_*工具 | 到设置 → 浏览器自动化确认 MCP 已安装且「MCP 已启用」;只是 disabled 时在这里启用即可,不要重启进程;然后刷新会话。 |
| 启动报浏览器可执行文件缺失 / 版本不匹配 | 先复用系统 Chrome / Edge 或已有 Chromium;都没有时再下载。恢复策略是任务驱动的:应用或会话启动时不会自动下载。 |
| 需要手动下载 Chromium | 设置 → 浏览器自动化点「下载浏览器」(约 150MB)。命令行等价物:pnpm exec playwright install chromium。 |
| 下载卡住 / 404 | 切国内镜像,只对当前 shell 生效、不要写进全局配置:npm config set registry https://registry.npmmirror.com与 export PLAYWRIGHT_DOWNLOAD_HOST=https://npmmirror.com/mirrors/playwright,再执行 install。 |
spark_browser没有打开窗口 | 确认是桌面本机会话;如果是远程会话,需要在远程连接能力里开启「使用内置浏览器窗口」。 |
mock_response报 unsupported | 当前构建只支持 record / block / redirect / set_headers,响应体 mock 未实现。 |
| 每次都要重新登录 | 多半是给open传了新的profileId。省略该参数才会用带登录态的共享default分区。 |
| console 事件读不全 | 先确认已调过console_start;缓冲上限 500 条,需要增量请用 sinceSeq。 |
速查表
| 项目 | 内容 |
|---|---|
| Playwright MCP | managed scope,name=playwright,默认 enabled、默认 headful |
| Playwright 默认工具 | 24 个 mcp__playwright__browser_*(未开启 --caps);内置技能 builtin:browser-use 要求“先 snapshot 再按 ref 操作” |
| spark_browser 工具 | 17 个:open/navigate/eval/inject_script/remove_script/screenshot/get_url/get_title/list_windows/close/console_start/console_events/console_clear/network_set_rules/network_events/network_clear/clear_profile |
| 浏览器优先级 | 内置 Chromium → Playwright 缓存(~/.cache/ms-playwright) → 系统 Chrome/Edge → none |
| 手动装 Chromium | 设置 → 浏览器自动化 →「下载浏览器」(约 150MB);命令行 pnpm exec playwright install chromium |
| spark_browser profile | 省略 profileId 用共享 default 分区(保留登录态);自定义 profileId 是空分区 |
| 事件缓冲 | console / network 各保留最多 500 条,用 sinceSeq 增量读取 |
| 远程开关 | 远程连接能力 useInternalBrowser(默认 false) |
上手清单:用 spark_browser 调试本地 HTML 页面
打开本地文件、抓 console 错误并截图
- 让 Agent 用 mcp__spark_browser__open 打开 file:///绝对路径/demo.html(省略 profileId 用共享登录态)
- 调用 mcp__spark_browser__console_start 开始捕获日志
- 调用 mcp__spark_browser__get_url / get_title 确认实际加载的页面
- 调用 mcp__spark_browser__console_events 读取 error / warn(用 sinceSeq 增量轮询)
- 调用 mcp__spark_browser__screenshot 拿 PNG 并定位布局问题
- 结束时依次 console_clear、network_clear、remove_script、close 清理
常见问题
Playwright 和 spark_browser 是替代关系吗?
不是。Playwright MCP 负责成熟网页自动化(ref 定位、等待、多标签、文件上传),spark_browser 负责应用内可见窗口、本地 file:// 调试、持久脚本、profile 登录态和 console/network 观察。一边不可用就换另一边。
还能使用 CDP 9223 嵌入式视图吗?
不能。旧视图已移除,cdpEndpoint 只作为兼容输入保留,正常注册传 null;Playwright 会自己拉起浏览器,应用内可见窗口由 spark_browser 提供。
spark_browser 会给网页 Node 权限吗?
不会。窗口以 sandbox、nodeIntegration=false、contextIsolation=true、webSecurity=true 创建,页面没有 Node/Electron API。
Chromium 没下载会自动安装吗?
不会。应用或会话启动时不会触发下载;只有任务真的需要浏览器且没有可用浏览器时才会按需下载(约 150MB),你也可以在 设置 → 浏览器自动化 手动下载。
远程连接里能用内置浏览器吗?
默认不能。远程连接能力项 useInternalBrowser(「使用内置浏览器窗口」)默认关闭,未开启时该会话连 spark_browser MCP 都不会注入。
为什么 Agent 每次都要重新登录网站?
通常是因为 open 时传了新的 profileId。每个自定义 profileId 都是空分区;省略 profileId 才会使用带用户登录态的共享 default 分区。