关于 browsing
通过 `use_browser` MCP 工具控制 Chrome 的技能,适用于需要操作现有会话和多个标签页的浏览任务。它会自动保存页面产物,并对疑似凭据内容实施保护。
主要功能
- 01导航并与页面交互
- 02管理标签页和 Chrome 配置
- 03提取页面内容与属性
- 04运行 JavaScript 并截取页面
- 05自动保存页面产物
- 06抑制疑似凭据内容
适用场景
- 01操作已登录的会话
- 02管理运行中浏览器的多个标签页
- 03检查页面内容和浏览器控制台输出
- 04避免捕获含疑似凭据的页面
MCP 相关
通过 `use_browser` MCP 工具使用 DevTools Protocol 控制 Chrome。首次使用时会自动启动 Chrome。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ obra/ superpowers-chrome --skill browsing安装后在 Claude Code 中输入/browsing确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignorechrome-wschrome-ws-lib.jsCOMMANDLINE-USAGE.mdEXAMPLES.mdhost-override.jslib/browser-bridge.jsbrowser-session.jscapture.jscdp-router.jscdp-utils.jschrome-launcher-helpers.jschrome-process.jsconsole-logging.jscookies.jscredential-guard.jsdialogs-render.jsdialogs-router.jsdialogs.jselement-selector.jsevaluation.jsextraction.jsfile-upload.jshtml-diff.jskey-definitions.jskeyboard-input.jsmouse.jsnavigation.jslib/page-scripts/dom-summary.jsmarkdown.js详细介绍
使用 Chrome Direct 浏览
概述
通过 use_browser MCP 工具使用 DevTools 协议控制 Chrome。提供统一接口,并自动启动 Chrome。
声明:“我将使用浏览技能控制 Chrome。”
适用场景
在以下情况下使用:
- 控制已通过身份验证的会话
- 管理正在运行的浏览器中的多个标签页
- Playwright MCP 不可用或功能过多
在以下情况下使用 Playwright MCP:
- 需要全新的浏览器实例
- 生成截图/PDF
- 偏好更高层级的抽象
自动捕获
每次 DOM 操作(navigate、click、type、select、eval、keyboard_press、hover、drag_drop、double_click、right_click、file_upload)都会自动保存:
{prefix}.png— 视口截图{prefix}.md— 以结构化 Markdown 格式呈现的页面内容{prefix}.html— 完整渲染的 DOM{prefix}-console.txt— 浏览器控制台消息
文件会按顺序使用前缀(001-navigate、002-click 等)保存到会话目录。在使用 extract 或 screenshot 操作前,必须先检查这些文件。
**包含凭据的页面:**如果页面显示令牌或密钥(Slack xoxb-/xapp-、GitHub ghp_/github_pat_、1Password ops_/A3- 密钥、otpauth:// 种子,或带有 data-sen-secret 标记的任何元素),该操作不会写入文件,响应只包含元数据,并显示 ⚠️ Page shows credential-shaped content; auto-capture and DOM output suppressed.。extract/eval 输出中的此类值会替换为 [REDACTED credential-shaped],而 screenshot 会拒绝执行。使用凭据代理捕获密钥;仅将 eval 用于不会读取值的查询(例如“令牌字段是否存在?”)。检查范围包括 HTML、渲染后的文本和开放的 shadow roots,但不包括封闭的 shadow roots 或 iframe。设置 SUPERPOWERS_CHROME_ALLOW_CREDENTIAL_CAPTURE=1 可关闭此功能。
use_browser 工具
提供基于操作的单一 MCP 工具。首次使用时会自动启动 Chrome。
参数:
action(必需):要执行的操作selector(可选):用于元素操作的 CSS 或 XPath 选择器payload(可选):特定操作的数据(字符串或对象)timeout(可选):等待操作的超时时间,单位为毫秒(默认值:5000)
活动标签页:每项操作都会在当前 activeTab 上执行。使用 switch_tab 切换标签页。
操作参考
导航
-
navigate:导航至 URL
payload:URL 字符串- 示例:
{action: "navigate", payload: "https://example.com"}
-
await_element:等待元素出现
selector:CSS 选择器timeout:最长等待时间,单位为毫秒- 示例:
{action: "await_element", selector: ".loaded", timeout: 10000}
-
await_text:等待文本出现
payload:要等待的文本- 示例:
{action: "await_text", payload: "Welcome"}
交互
-
click:点击元素
selector:CSS 选择器- 示例:
{action: "click", selector: "button.submit"}
-
type:输入文本
selector:可选 — 先点击以聚焦payload:要输入的文本(\t=Tab,\n=Enter)- 示例:
{action: "type", selector: "#email", payload: "[email protected]"}
-
double_click:双击元素(触发 dblclick 事件)
selector:CSS 选择器- 示例:
{action: "double_click", selector: ".item"}
-
right_click:右键点击元素(触发 contextmenu 事件)
selector:CSS 选择器- 示例:
{action: "right_click", selector: ".row"}
-
select:选择下拉选项
selector:CSS 选择器payload:选项值- 示例:
{action: "select", selector: "select[name=state]", payload: "CA"}
-
keyboard_press:按下特殊按键(Tab、Enter、Escape、方向键、F1-F12)
payload:按键名称(字符串),或{"key": "Tab", "modifiers": {"shift": true, "ctrl": false, "alt": false, "meta": false}}- 示例:
{action: "keyboard_press", payload: "Tab"} - 带修饰键的示例:
{action: "keyboard_press", payload: {"key": "Tab", "modifiers": {"shift": true}}}
鼠标操作(CDP 级别)
这些操作使用 CDP Input.dispatchMouseEvent,可绕过合成事件限制。
-
hover:将鼠标移到元素上方(CSS :hover、工具提示、菜单)
selector:CSS 选择器- 示例:
{action: "hover", selector: ".menu-trigger"}
-
drag_drop:将元素拖到目标位置(通过 CDP 实现原生拖放)
selector:源元素payload:目标选择器或 JSON 坐标{"x":N,"y":N}- 示例:
{action: "drag_drop", selector: ".card", payload: ".column-2"}
-
mouse_move:将鼠标移至指定坐标
payload:JSON{"x":N,"y":N}(可选:使用steps、fromX、fromY实现平滑移动)- 示例:
{action: "mouse_move", payload: "{\"x\":100,\"y\":200}"}
-
scroll:通过鼠标滚轮事件滚动
payload:方向(up/down/left/right)或 JSON{"deltaX":N,"deltaY":N}selector:可选 — 在元素内滚动- 示例:
{action: "scroll", payload: "down"}
文件上传
- file_upload:为 input[type=file] 元素设置文件(无法通过 JavaScript 完成)
selector:文件输入元素payload:文件路径或 JSON{"files":["/path/a.pdf","/path/b.jpg"]}- 示例:
{action: "file_upload", selector: "#upload", payload: "/tmp/doc.pdf"}
提取
-
extract:获取页面内容
payload:格式('markdown'|'text'|'html')selector:可选 — 限定为指定元素- 示例:
{action: "extract", payload: "markdown"} - 示例:
{action: "extract", payload: "text", selector: "h1"}
-
attr:获取元素属性
selector:CSS 选择器payload:属性名称- 示例:
{action: "attr", selector: "a.download", payload: "href"}
-
eval:执行 JavaScript
payload:JavaScript 代码- 示例:
{action: "eval", payload: "document.title"}
导出
- screenshot:截取指定元素的屏幕截图
payload:文件名selector:可选 — 截取指定元素的屏幕截图- 每次 DOM 操作后都会自动截取视口屏幕截图。仅在需要截取特定元素时使用此操作。
- 示例:
{action: "screenshot", payload: "/tmp/chart.png", selector: ".chart"}
标签页管理
-
list_tabs:列出所有打开的标签页
- 示例:
{action: "list_tabs"}
- 示例:
-
new_tab:新建标签页
- 示例:
{action: "new_tab"}
- 示例:
-
close_tab:关闭当前标签页
- 示例:
{action: "close_tab"}
- 示例:
-
switch_tab:切换当前标签页(保持选中,直到再次切换)
payload:标签页索引(数字)、URL 子字符串或标题子字符串- 示例:
{action: "switch_tab", payload: 1}(按索引) - 示例:
{action: "switch_tab", payload: "example.com"}(按 URL 子字符串) - 示例:
{action: "switch_tab", payload: "GitHub"}(按标题子字符串)
浏览器模式控制
-
show_browser:显示浏览器窗口(有头模式)
- 示例:
{action: "show_browser"} - ⚠️ 警告:重启 Chrome,通过 GET 重新加载页面,并丢失 POST 状态
- 示例:
-
hide_browser:切换到无头模式(不可见浏览器)
- 示例:
{action: "hide_browser"} - ⚠️ 警告:重启 Chrome,通过 GET 重新加载页面,并丢失 POST 状态
- 示例:
-
browser_mode:检查当前浏览器模式、端口和配置文件
- 示例:
{action: "browser_mode"} - 返回:
{"headless": true|false, "mode": "headless"|"headed", "running": true|false, "port": 9222, "profile": "name", "profileDir": "/path"}
- 示例:
配置文件管理
-
set_profile:更改 Chrome 配置文件(必须先关闭 Chrome)
- 示例:
{action: "set_profile", "payload": "browser-user"} - ⚠️ 警告:必须先停止 Chrome
- 副作用:将配置文件标记为显式指定,从而选择退出自动消歧(见下文)
- 示例:
-
get_profile:获取当前配置文件名称和目录
- 示例:
{action: "get_profile"} - 返回:
{"profile": "name", "profileDir": "/path"}
- 示例:
默认行为:Chrome 以无头模式启动,使用**「superpowers-chrome」配置文件**,并使用动态分配的端口(范围为 9222-12111)。使用 CHROME_WS_PORT 覆盖端口;使用 CHROME_WS_PROFILE 覆盖配置文件。
多个 MCP 并行运行时的自动消歧:
当两个 MCP 服务在同一主机上以默认配置文件启动时,第一个会占用 superpowers-chrome(端口 9222),后续服务则会自动改用 superpowers-chrome-2(端口 9223)、superpowers-chrome-3 等。每个 MCP 都通过各自的配置文件目录驱动自己的 Chrome;它们不会争用 activeTab。桥接程序通过 ~/.cache/superpowers/browser-profiles/<profile>.mcp.lock 中的锁文件跟踪所有权;失效的锁(对应已退出的 PID)会自动回收。
若要退出消歧,例如,有意在长期运行的 chrome-ws CLI 会话和 MCP 之间共享 Chrome,请显式设置配置文件名称:
- 环境变量:
CHROME_WS_PROFILE=my-profile - 或者,在运行时使用:
{action: "set_profile", payload: "my-profile"}
显式指定的配置文件名称仍会获取锁,但发生冲突时,桥接程序会选择共享而不是消歧——第二个进程会重新连接到第一个进程的 Chrome(原有的重启后重新连接行为)。
Chrome 生命周期(恢复)
-
kill_chrome:结束此 MCP 正在驱动的 Chrome 进程
- 示例:
{action: "kill_chrome"} - 释放 meta.json;下次执行页面操作时会自动重启 Chrome
- 示例:
-
restart_chrome:执行 kill_chrome 并立即启动
- 示例:
{action: "restart_chrome"}
- 示例:
自动重启提示:当桥接程序必须启动新的 Chrome(因为之前的进程已退出或被外部结束,例如在 shell 中执行 kill -9 <pid>)时,重启后的第一条响应会在开头添加:
[Chrome auto-restarted; URL reset to about:blank. Re-navigate to continue.]
请将此视为先前 URL / 标签页状态已丢失的信号——在确认当前页面的任何信息之前,请重新导航。
控制台日志记录
捕获当前标签页的浏览器控制台输出。缓冲区以页面会话的 sessionId 为键,因此即使 close_tab / new_tab 的执行顺序出现异常,也能保留日志。级别:log、info、warn、error。
-
enable_console_logging:开始捕获
- 示例:
{action: "enable_console_logging"}
- 示例:
-
get_console_messages:读取捕获的消息
- 全部消息:
{action: "get_console_messages"} - 从指定时间戳开始(epoch ms):
{action: "get_console_messages", payload: {since: 1716000000000}} - 返回:由
{timestamp, level, text}条目组成的数组
- 全部消息:
-
clear_console_messages:重置缓冲区
- 示例:
{action: "clear_console_messages"}
- 示例:
对话框处理
原生对话框(JS alert/confirm/prompt、beforeunload、HTTP basic-auth、权限提示、设备选择器)会暂停页面。对话框打开时,面向页面的操作(extract、click、eval 等)会返回拒绝信息,其中包含 Page is behind a dialog,并列出可用的 dialog::* 选择器。
如果在 navigate 过程中触发对话框(HTTP basic-auth 中很常见),navigate 本身会抛出异常,错误消息中包含对话框语法——无需单独调用面向页面的操作来发现对话框。
通过点击或输入 dialog::* 选择器来处理对话框:
{action: "click", selector: "dialog::accept"}— 接受 JS alert/confirm/prompt、beforeunload、授予权限{action: "click", selector: "dialog::dismiss"}— 关闭/取消/拒绝{action: "type", selector: "dialog::prompt", payload: "text"},然后接受 — 回复 JS prompt{action: "type", selector: "dialog::username", payload: "alice"}+{action: "type", selector: "dialog::password", payload: "secret"}+{action: "click", selector: "dialog::accept"}— HTTP basic-auth{action: "click", selector: "dialog::device[id=\"<deviceId>\"]"}— 选择 WebUSB/Bluetooth/Serial/HID 设备
切换模式时的重要注意事项:
- 必须重启 Chrome — 无法在运行中的 Chrome 上切换无头/有头模式
- 页面通过 GET 重新加载 — 所有已打开的标签页都会通过 GET 请求重新打开
- POST 状态会丢失 — 表单提交、POST 结果和基于 POST 的导航都会丢失
- 会话状态会丢失 — 所有客户端状态(JavaScript 变量等)都会被清除
- Cookie/身份验证可能会保留 — 使用相同的用户数据目录,因此已登录会话可能仍然有效
适合使用有头模式的场景:
- 调试视觉渲染问题
- 向用户演示浏览器行为
- 测试仅在浏览器可见时才能运行的功能
- 调试在无头模式下无法复现的问题
适合保持无头模式的场景(默认):
- 其他所有情况——速度更快、更简洁、干扰更少
- 在无头模式下截图也能正常工作
- 大多数自动化在两种模式下的运行方式相同
配置文件管理: 配置文件用于存储持久化的浏览器数据(Cookie、localStorage、扩展程序、身份验证会话)。
配置文件位置:
- macOS:
~/Library/Caches/superpowers/browser-profiles/{name}/ - Linux:
~/.cache/superpowers/browser-profiles/{name}/ - Windows:
%LOCALAPPDATA%/superpowers/browser-profiles/{name}/
适合使用独立配置文件的场景:
- 默认配置文件("superpowers-chrome"):常规自动化、共享会话
- 特定 Agent 的配置文件:隔离不同 Agent 的浏览器状态
- 示例:browser-user Agent 使用 "browser-user" 配置文件
- 特定任务的配置文件:使用不同用户上下文进行测试
- 示例:"test-logged-in" 与 "test-logged-out"
配置文件数据在以下情况下仍会保留:
- Chrome 重启后
- 切换模式后(无头 ↔ 有头)
- 系统重启后(数据位于缓存目录中)
使用不同配置文件:
- 如果 Chrome 正在运行,则将其关闭:
await chromeLib.killChrome() - 设置配置文件:
{action: "set_profile", "payload": "my-profile"} - 启动 Chrome:下一次导航/操作将使用新的配置文件
快速入门模式
Navigate and extract:
{action: "navigate", payload: "https://example.com"}
{action: "await_element", selector: "h1"}
{action: "extract", payload: "text", selector: "h1"}
常见模式
填写并提交表单
{action: "navigate", payload: "https://example.com/login"}
{action: "await_element", selector: "input[name=email]"}
{action: "type", selector: "input[name=email]", payload: "[email protected]"}
{action: "type", selector: "input[name=password]", payload: "pass123"}
{action: "keyboard_press", payload: "Enter"}
{action: "await_text", payload: "Welcome"}
使用 keyboard_press 提交表单。
多标签页工作流
{action: "list_tabs"}
{action: "switch_tab", payload: 2}
{action: "click", selector: "a.email"}
{action: "await_element", selector: ".content"}
{action: "extract", payload: "text", selector: ".amount"}
动态内容
{action: "navigate", payload: "https://example.com"}
{action: "type", selector: "input[name=q]", payload: "query"}
{action: "click", selector: "button.search"}
{action: "await_element", selector: ".results"}
{action: "extract", payload: "text", selector: ".result-title"}
获取链接属性
{action: "navigate", payload: "https://example.com"}
{action: "await_element", selector: "a.download"}
{action: "attr", selector: "a.download", payload: "href"}
执行 JavaScript
{action: "eval", payload: "document.querySelectorAll('a').length"}
{action: "eval", payload: "Array.from(document.querySelectorAll('a')).map(a => a.href)"}
调整视口大小(响应式测试)
使用 eval 调整浏览器窗口大小,以测试响应式布局:
{action: "eval", payload: "window.resizeTo(375, 812); 'Resized to mobile'"}
{action: "eval", payload: "window.resizeTo(768, 1024); 'Resized to tablet'"}
{action: "eval", payload: "window.resizeTo(1920, 1080); 'Resized to desktop'"}
注意:此操作调整的是窗口大小,而非设备模拟。它不会改变:
- 设备像素比(视网膜显示屏)
- 触摸事件
- User-Agent 字符串
对于大多数响应式测试,调整窗口大小就足够了。
清除 Cookie
使用 eval 清除 JavaScript 可访问的 Cookie:
{action: "eval", payload: "document.cookie.split(';').forEach(c => { document.cookie = c.trim().split('=')[0] + '=;expires=Thu, 01 Jan 1970 00:00:00 GMT;path=/'; }); 'Cookies cleared'"}
注意:这会清除 JavaScript 可访问的 Cookie,但不会清除:
- httpOnly Cookie(仅限服务器端)
- 来自其他域的 Cookie
对于大多数注销/重置场景,这样就足够了。
滚动页面
{action: "scroll", payload: "down"}
{action: "scroll", payload: "up"}
{action: "scroll", selector: ".container", payload: "{\"deltaX\":0,\"deltaY\":500}"}
使用真实的鼠标滚轮事件(而不是会被机器人检测器标记的 eval + scrollTo)。
提示
交互前务必等待: 导航后不要立即点击或填写内容,页面需要时间加载。
// BAD - might fail if page slow
{action: "navigate", payload: "https://example.com"}
{action: "click", selector: "button"} // May fail!
// GOOD - wait first
{action: "navigate", payload: "https://example.com"}
{action: "await_element", selector: "button"}
{action: "click", selector: "button"}
使用具体的选择器: 避免使用会匹配多个元素的通用选择器。
// BAD - matches first button
{action: "click", selector: "button"}
// GOOD - specific
{action: "click", selector: "button[type=submit]"}
{action: "click", selector: "#login-button"}
提交表单:
在 type 后使用 keyboard_press 按 Enter,或在负载末尾追加 \n。
{action: "type", selector: "#search", payload: "query"}
{action: "keyboard_press", payload: "Enter"}
先检查内容: 提取页面内容,确认选择器无误后再构建工作流。
{action: "extract", payload: "html"}
故障排除
找不到元素:
- 交互前使用
await_element - 使用
'html'格式,通过extract操作验证选择器
超时错误:
- 对于加载缓慢的页面,增大超时时间:
{timeout: 30000} - 等待特定元素,而不是等待文本
当前标签页不正确:
- 使用
list_tabs查看所有打开的标签页 - 使用
switch_tab,并传入 URL 或标题子字符串,以可靠地切换标签页 - 标签页关闭时索引会变化,优先使用基于 URL/标题的切换方式
eval 返回 [object Object]:
- 对于复杂对象,使用
JSON.stringify():{action: "eval", payload: "JSON.stringify({name: 'test'})"} - 对于异步函数:
{action: "eval", payload: "JSON.stringify(await yourAsyncFunction())"}
测试自动化(高级)
点击展开测试自动化指南
构建测试自动化时,有两种方式:
方式 1:使用 use_browser MCP(简单测试)
适用于:单步测试,以及在对话过程中直接由 Claude 控制
{"action": "navigate", "payload": "https://app.com"}
{"action": "click", "selector": "#test-button"}
{"action": "eval", "payload": "JSON.stringify({passed: document.querySelector('.success') !== null})"}
方式 2:chrome-ws CLI(复杂测试)
适用于:多步测试套件、独立自动化脚本
关键要点:chrome-ws 是展示正确使用 Chrome DevTools Protocol 的参考实现。如果 use_browser 未按预期工作,请查看 chrome-ws 如何处理同一操作。
# Example: Automated form testing
./chrome-ws navigate 0 "https://app.com/form"
./chrome-ws fill 0 "#email" "[email protected]"
./chrome-ws click 0 "button[type=submit]"
./chrome-ws wait-text 0 "Success"
use_browser 失败时
- 检查 chrome-ws 源代码 ——其中展示了正确的 CDP 模式
- 使用 chrome-ws 验证 ——通过 CLI 测试相同操作
- 调整模式 ——将可行的 CDP 方法应用到 use_browser
常见的测试自动化模式
- 表单验证:填写表单,检查错误状态
- UI 状态测试:点击元素,验证 DOM 变化
- 性能测试:测量加载时间,采集指标
- 截图对比:采集操作前后的状态
高级用法
如需在 Claude Code 外使用命令行,请参阅 COMMANDLINE-USAGE.md。
如需详细示例,请参阅 EXAMPLES.md。
协议参考
完整的 CDP 文档:https://chromedevtools.github.io/devtools-protocol/