Chrome-devtools-mcp:闭环Agent的自我验证
一、背景:AI 会写代码,但看不见自己的产物
用 AI 写代码(前端/后端)有一个长期的尴尬:它能生成几千行 Vue/Java/Python,却无法通过浏览器确认是否符合要求。
这就是缺口的本质:Agent 需要一个可以自己调用的浏览器。
二、选型:为什么不自己写,而用官方 MCP
有三条路:
| 方案 | 形态 | 代价 | 适合 |
|---|---|---|---|
| Playwright | 库 / MCP | 本体 ~50 MB + 浏览器 ~300 MB | 稳定的端到端测试、跨浏览器 |
| 自己写 CDP 驱动 | 脚本 | 零依赖,但功能要自己长 | 轻量验证("打开看一眼") |
| chrome-devtools-mcp | MCP server | 13.6 MB,复用本机 Chrome | Agent 的日常排查 |
三条都试过。先自己写了一个零依赖的 CDP 驱动(约 120 行,只用 Node 内置的 fetch / WebSocket),它解决了"截图 + 量像素差异",但控制台和网络这两个最关键的证据它拿不到------因为那需要订阅 CDP 事件流并缓存消息,工作量和收益不成比例。
而 chrome-devtools-mcp 是 Google Chrome 团队官方维护的 MCP server,把这些能力都做成了工具。它复用本机已装的 Chrome,不需要再下载一个浏览器。
结论 :轻量验证继续用自己那 120 行;深度排查交给官方 MCP。两者互补,不冲突。
三、它给 Agent 的是什么:30 个工具
连接后,工具以 mcp__chrome__<tool> 的形式出现------和原生工具一样可直接调用。30 个工具分七类:
| 类别 | 工具 | 对 Agent 的意义 |
|---|---|---|
| 输入自动化 | click fill fill_form hover drag type_text press_key upload_file handle_dialog |
真的能操作页面:提交表单、走完整交互流程 |
| 导航 | new_page navigate_page list_pages select_page close_page wait_for |
多标签页、wait_for 文本出现(抗 flaky 的关键) |
| 调试 | take_snapshot evaluate_script take_screenshot list_console_messages get_console_message get_css_styles lighthouse_audit screencast_* |
无障碍快照 + 控制台 + CSS 级联 + Lighthouse |
| 网络 | list_network_requests get_network_request |
请求清单、状态码、请求头、响应体(含 Cookie) |
| 性能 | performance_start_trace performance_stop_trace performance_analyze_insight |
Core Web Vitals(LCP / INP / CLS)与瓶颈洞察 |
| 模拟 | emulate resize_page |
暗色模式、CPU/网络限速、地理位置、移动端视口 |
| 内存 | 14 个堆快照工具 | 内存泄漏:支配树、保留路径、重复字符串(需 --memoryDebugging=true) |
其中真正改变工作方式的是这三个
1. list_console_messages ------ 把"猜"变成"读"
以前页面出问题,Agent 只能列一堆可能原因让你去试。现在它直接告诉你第几行报了什么错。
2. take_snapshot ------ 给 Agent 的"结构化页面"
它不是截图,而是无障碍树的文本快照 ,每个可交互元素带一个 uid。这是给模型看的格式:token 消耗远低于截图,而且元素定位是稳定的(不像坐标会随布局变化)。
它的工具描述里写得很直白:"Always use the latest snapshot. Prefer taking a snapshot over taking a screenshot."
3. list_network_requests ------ 接口层的唯一真相
"接口通了吗"不该靠猜。这一条列出来,状态码、请求头、响应体一清二楚。
四、接入:DSH 的 MCP 配置
安装只需要一步:
bash
npm install --global chrome-devtools-mcp
DSH 的 MCP 由 @deepseek-ai/dsh-mcp-client 提供(随 DSH 自带,不需要额外安装),配置文件是 profile 的 patch 层:
~/.dsh/profiles/desktop/cordis.patch.yml
它接受一个 YAML 数组,每条是一个 loader patch entry。追加这一条:
yaml
- insert:
- id: mcp-chrome-devtools
name: "@deepseek-ai/dsh-mcp-client"
config:
serverName: chrome
transport: stdio
command: "D:\\Installed\\Nodejs\\node.exe"
args:
- "C:\\Users\\xxx\\AppData\\Roaming\\npm\\node_modules\\chrome-devtools-mcp\\build\\src\\bin\\chrome-devtools-mcp.js"
- "--headless=true"
- "--userDataDir=D:\\ZHUWEI\\AppData\\.tmp\\chrome-devtools-mcp-profile"
- "--executablePath=C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
- "--performanceCrux=false"
- "--usageStatistics=false"
# 首次接通期用 true:连接失败会让该插件激活报错、错误可见;harness 仍能启动
# (app-boot 允许可选 MCP 配置项失败)。确认稳定后可改回 false。
failOnStartupError: true
字段含义:
| 字段 | 说明 |
|---|---|
serverName |
namespace,工具名变成 mcp__chrome__*。只能 [A-Za-z0-9_-]{1,32},同一作用域内唯一 |
transport |
stdio(本地程序)或 streamable-http(远端服务) |
command |
必须是绝对路径 |
args |
传给 server 的旗标与路径 |
failOnStartupError |
false:连不上只表现为"工具缺失",不阻塞 DSH 启动 |
五、成果:上线十分钟抓到两个真实缺陷
配置验证通过后,立刻拿它扫了一遍自己的页面。它当场报出两条此前完全不知道的消息:
msgid=1 [issue] A form field element should have an id or name attribute (count: 2)
msgid=2 [error] Failed to load resource: the server responded with a status of 404 (Not Found)
reqid=16 GET http://localhost:4173/favicon.ico [404]
顺着 get_console_message 拿到的 violatingNodeId: 4, 5,定位到两个表单控件(一个复选框、一个选择器)既没有 id 也没有 name。
这两条都不影响功能,但:
favicon.ico的 404 是每个访客的控制台都会出现的瑕疵;- 表单控件缺
id/name会影响浏览器自动填充,也是无障碍审计会扣分的地方。
关键在于"发现成本" :在这之前,要发现它们必须手动打开 DevTools、切到 Console 面板、自己看。而现在 Agent 每次验证都会顺带看到------这类问题再也不会默默攒着。
六、最后
- 只有 Chromium 系。要测 Safari / Firefox,得用 Playwright。
- 不是测试框架。它给的是"操作与证据",不含断言、重试、报告。要写稳定的端到端测试,仍应使用 Playwright Test 之类。
- 无法替人判断"好不好看" 。它能证明"渲染在动、数值在变、布局正确、控制台干净",不能证明"设计得好"。汇报时必须说清是脚本测的,不能暗示"看过了"。
- 需要重启 DSH 生效 。profile 的 patch 层是 Loader 自己读的入口清单,只在启动或下次组合时判定------当前会话拿不到新工具。
- 此后可以添加一个skill。通过skill让ai使用chrome-devtools-mcp工具验证结果,避免每次给ai用文字描述。
还有一条跨方案的盲区,与具体工具无关:
WebGL 默认
preserveDrawingBuffer: false。 此时用drawImage(webglCanvas)读回的是已被清空的缓冲区 ------量出来"画面完全没动"是假阴性 ,比漏报更危险(会得出与事实相反的结论)。任何浏览器自动化工具都有这个盲区,包括本文这个。读回全空白时必须报"无法测量",绝不要报"没动"。
愿你我都能在各自的领域里不断成长,勇敢追求梦想,同时也保持对世界的好奇与善意!