vConsole MCP:让AI直接看见H5页面调试日志
发布时间:2026/10/26 16:52:36 锦皓数字建站

事情得从上个月调一个 H5 项目说起。客户那边报了个 bug表单在安卓 WebView 里提交后偶发白屏PC 端 Chrome 里怎么操作都复现不了。我连夜把 vConsole 接上在真机上一顿操作日志倒是都出来了可我身边那堆 AI 编程助手全帮不上忙——它们能改代码却看不见浏览器里到底报了啥错。折腾到最后我干脆自己写了套工具把 vConsole 能看到的日志、网络请求、存储信息全部结构化输出再通过 MCP 暴露给 AI让 Claude 这类助手直接看见H5 页面里正在发生什么。这就是今天要聊的 vConsole MCP 项目。这个项目解决的痛点很实在H5 调试链路越来越复杂真机、WebView、小程序内嵌页各有各的环境传统浏览器 devtools 在移动端基本帮不上忙vConsole 是移动端调试的事实标准但它只是把日志显示在页面上AI 看不到。MCP 恰好补上这一环——它定义了 AI 读取外部数据的标准口径。把 vConsole 和 MCP 组合起来等于给 AI 安了一双盯着页面的眼睛。适合谁看天天跟 H5、移动端、内嵌页打交道的开发者以及所有想让 AI 更深度参与 debug 流程的人。1. 项目动机与整体设计思路1.1 H5 调试的典型困境日志看得见摸不着先聊点真实的调试场景。PC 端调试 H5 时F12 打开就能看到 console、network、application 面板信息量很全。但移动端不是这样真机 Safari、安卓 WebView、微信里打开的 H5你没法按 F12。常规套路是接 vConsole页面上悬着一个绿色小按钮点开是一个悬浮面板能看到 console 日志、网络请求、本地存储甚至能手动执行 JS。vConsole 解决的是人怎么看到日志的问题可它没有能力把日志导出成结构化数据给另一个程序用。我自己踩过的坑有一次同事在安卓手机上复现问题vConsole 里清清楚楚显示了一条ReferenceError: xxx is not defined但报错对应的压缩代码只有一行根本看不出是哪个模块出的问题。我让 AI 助手帮忙猜哪里越界了AI 只能根据我的描述推断来回问了七八轮还是没定位到。问题在哪AI 很有能力但它是瞎子。它没有通道直接读取页面上的运行日志只能靠人转述。转述过程会丢失细节尤其是某个变量的实际值、某次请求的真实返回这类信息。这也是 vConsole MCP 最核心的出发点与其让人当传话筒不如直接把 vConsole 捕获的数据流接到 AI 侧。任何 H5不管跑在哪个环境只要页面里有调试信息AI 就能直接读取、筛选、分析甚至反向在页面里执行 JS 验证修复效果。1.2 MCP 到底是什么为什么它适合做调试桥MCP 全称 Model Context Protocol是一个标准化协议解决AI 如何安全、统一地调用外部工具和数据源的问题。可以把它理解成 AI 世界的 USB 接口鼠标、键盘、显示器各自干各自的活USB-C 口统一了物理连接标准插上就能用。MCP Server 就是把某个数据源或能力封装成标准接口AI 客户端比如 Claude Desktop、Cherry Studio、Cline通过这个接口发现工具、调用工具、拿到结果。放在调试 H5 的场景里MCP Server 就是一个日志运输出口它暗中连着远程浏览器的调试端口监听 console 消息、网络请求、页面错误然后暴露给 AI 几个工具查看日志、查看请求、执行 JS、清理缓存。AI 不用知道 CDPChrome DevTools Protocol怎么调用也不用理解 WebSocket 握手细节它只需要知道有个工具叫 get_recent_logs调用一下就能拿到最近 200 条 console 日志。这套抽象非常有价值因为 AI 的上下文窗口有限它需要的是经过筛选、结构化的关键证据而不是冷冰冰的原始事件流。选 MCP 而不是自己写一套私有接口还有一个很现实的原因生态。目前主流 AI 客户端都原生支持 MCP你写一个标准 MCP Server就能同时服务多个工具。我自己就是先在 Claude Desktop 里测通再切到 Cherry Studio 用几乎零成本迁移。1.3 整体架构浏览器 CDP 加 MCP Server 双端协作这个项目整体只有三条链路目标浏览器或 WebView开启远程调试端口。一个 Node.js 进程作为 MCP Server通过 CDP 连上浏览器订阅 console 和 network 事件并缓存到一个环形缓冲结构里。AI 客户端Claude Desktop / Cherry Studio 等通过 MCP 发现工具读取缓存数据按需分析。为什么直接选 CDP而不是去调 vConsole 的插件 API我最初试过 vConsole 的插件机制。vConsole 确实支持自定义插件插件里也能拿到 log 面板的数据但有几个问题一是要改业务代码去初始化插件侵入性太强二是 vConsole 插件拿到的数据格式偏 UI很多内部字段还拿不到三是如果页面加载早期就报错vConsole 本身还没 ready那部分日志就丢了。CDP 是浏览器底层协议页面里不管跑的是不是 vConsoleconsole 消息、网络请求事件都会经过调试端口。从 CDP 拿数据才是真正意义上的任何 H5。我保留 vConsole 的真实价值在于它负责给人类开发者看CDP 通道负责给 AI 看。两者并行互不干扰。但要注意一个坑——如果页面里装了 vConsole它自己也会输出一些日志比如插件初始化的 logCDP 捕获的时候需要按来源过滤不然 AI 会被 vConsole 自身的信息干扰。这个我在 2.3 节会细说。2. 核心细节解析与实操要点2.1 日志数据从哪里来CDP 事件深度解读CDP 是通过 WebSocket 和浏览器调试端口通信的。要监听 H5 页面里 console 日志核心事件是Runtime.consoleAPICalled。每次页面调用console.log、console.error之类的方法浏览器都会把这个事件推到调试端。但事件里的参数不是纯字符串而是一堆RemoteObject比如一个对象会被序列化成{type: object, className: Object, description: {...}}如果你直接把description丢给 AI会丢掉很多细节尤其嵌套对象会被折叠成{...}。所以我在 MCP Server 里做了一个格式化层递归展开 RemoteObject把对象、数组、函数、DOM 节点都转成可读文本。简单对象直接抽preview.properties深层对象调用Runtime.getProperties拿完整属性。函数就输出它的字符串表现形式。DOM 节点则补上标签、id、class 这些信息。这套展开逻辑是整个工具里最容易出 bug 的部分因为实际项目里的日志千奇百怪你永远猜不到用户会在 console 里扔一个什么玩意儿。网络请求的监听靠两组事件Network.requestWillBeSent和Network.responseReceived。前者记录请求 URL、方法、请求头后者记录状态码、响应头、耗时。要做request body和response body的抓取还得额外调用Network.getRequestPostData和Network.getResponseBody。这里有个很关键的性能点不能每个请求都去拉响应体尤其像上传图片、大 JSON 接口响应体可能几百 KB。策略是默认只记录元信息只有当 AI 明确请求查看某个链接的具体响应时才按需去取 body。这是给 AI 省上下文也是最聪明的一步。2.2 MCP Server 的工具设计少而精最重要MCP 工具设计跟写 REST API 完全是两个思路。API 面向人能多做几个接口就多做人不在乎多一次点击。但 MCP 面向 AI工具越多AI 选错工具的概率越大上下文占用也越大。所以我第一版做的时候故意砍掉了很多看起来有用的功能只留了五个工具工具名作用核心参数get_recent_logs获取最近 console 日志limit, level, keywordget_network_requests获取最近网络请求limit, url, statusget_page_info获取当前页面 URL、标题、UA无evaluate_js在页面执行一段 JS 并返回结果expressionclear_debug_data清空本地缓存的日志/请求缓冲无这五个工具撑起了 90% 的调试场景。get_recent_logs是主力AI 遇到问题第一步通常是调它看看有没有红色错误get_network_requests用来排查接口挂了、参数传错、状态码异常这类问题evaluate_js则是让 AI 在页面里做验证比如执行一个表达式看看当前某个全局变量到底是什么值。有一次排查登录态失效问题AI 就是靠 evaluate_js 执行localStorage.getItem(token)发现 token 存的 key 名跟后端对不上一秒钟定位。工具参数也要克制。limit默认给 200上限设 500。为什么因为 AI 的上下文窗口有限一次性塞 200 条日志已经很考验提取能力了再多没意义。我还加了level参数支持error/warn/info/debugAI 可以先只筛 error缩小范围再决定要不要看完整信息。这个分层的设计非常实用你可以让 AI 先看 error如果没发现再看 warn。2.3 数据结构化、去重与上下文控制CDP 原始事件是流式的而且同一个错误经常被多次触发比如 React 严格模式在开发环境下会执行两次渲染导致console.error出现两遍。日志不去重AI 很容易被重复信息带偏。我在缓存时维护了一个指纹机制把消息内容 发生时间(秒级) 日志级别做一次 hash重复消息会累计 count只保留首次出现的时间戳。这样 AI 看到的是同样的错误出现了 12 次而不是 12 条一模一样的记录。还有一个细节过滤 vConsole 自身日志。页面加载 vConsole 时它会打印一些初始化信息通常是[vConsole]开头或者是某个VConsoleclass 的 log。我在get_recent_logs返回之前会先做一次字符串扫描把[vConsole]开头的记录剔除掉但保留[vConsole]之外的报错内容。实测下来这个过滤能减少约 5% 的噪音配合 level 参数后效果更明显。上下文控制的核心思想是给 AI最小充分集。不是把原始日志全部倒出去而是先做裁剪、去重、时间排序再交出去。比如一个 50MB 的日志文件MCP 工具返回的可能是整理后的 2KB 摘要——但保留了错误级别、关键栈帧、重复次数。很多调试场景下AI 拿到这 2KB 就够定位了不够它再按需展开。这个思路跟你在生产环境排查日志的思路是一样的先看错误再看时间窗口最后才看具体堆栈。3. 实操从零搭一套 vConsole MCP debug 链路3.1 环境准备浏览器调试端口怎么开先说最基本的准备工作。你需要一个 Node.js 18 环境一个 Chrome 或 EdgeChromium 内核以及一个支持 MCP 的 AI 客户端。浏览器调试端口是关键CDP 建立在远程调试协议之上浏览器必须以--remote-debugging-port9222参数启动否则调试端口根本不会开。我平时开发 H5 常用的是独立调试用户目录避免和日常浏览器的会话冲突。推荐这么启动浏览器# Windows chrome.exe --remote-debugging-port9222 --user-data-dir/tmp/vconsole-mcp-profile # macOS /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port9222 --user-data-dir/tmp/vconsole-mcp-profile # Linux google-chrome --remote-debugging-port9222 --user-data-dir/tmp/vconsole-mcp-profile--user-data-dir这个参数很重要。不指定的话Chrome 会用默认用户目录如果平时已经开着 Chrome第二个实例启动时会把所有参数转发给已有实例调试端口不会生效。把 user-data-dir 单独指出来等于起了一个完全独立的浏览器实例互不干扰。启动后访问 http://localhost:9222/json能看 JSON 列表就说明调试端口生效了。如果你需要测的是桌面版页面直接用这个 Chrome 窗口打开 target 页面就行。要是测的是手机端可以用 DevTools 的设备模拟模式如果测的是 WebView那就走 4.1 节的远程转发方案。3.2 用 TypeScript 搭一个最小 MCP Server我推荐直接用官方 SDKmodelcontextprotocol/sdk它把协议细节都封装好了你只需要注册工具和处理回调。先建一个 Node 项目mkdir vconsole-mcp-server cd vconsole-mcp-server npm init -y npm install modelcontextprotocol/sdk ws然后建一个index.ts写一个最简骨架import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; import { z } from zod; const server new McpServer({ name: vconsole-mcp, version: 1.0.0 }); server.tool( get_recent_logs, 获取页面最近 console 日志level 可选 error/warn/info/debug, { limit: z.number().default(200), level: z.string().optional(), keyword: z.string().optional() }, async ({ limit, level, keyword }) { // TODO: 从 CDP 缓存里筛选日志 return { content: [{ type: text, text: JSON.stringify([]) }] }; } ); const transport new StdioServerTransport(); await server.connect(transport);一个 MCP Server 其实就是一个 stdio 进程通过标准输入输出和 AI 客户端通信。StdioServerTransport就是把协议消息接到 stdin/stdout 上。注册工具用的server.tool方法参数分别是工具名、描述、参数 schema、执行函数。描述写得越清楚AI 越不容易用错比如日志 time 字段是毫秒级时间戳这类细节都要写进去。3.3 核心难点CDP 数据流接入CDP 连接部分我直接用ws库连浏览器的 WebSocket 端点。先给每个页面 target 建立一个连接然后启用 Runtime 和 Network 域import WebSocket from ws; const targetList await fetch(http://localhost:9222/json).then(res res.json()); const pageTarget targetList.find(t t.type page); const ws new WebSocket(pageTarget.webSocketDebuggerUrl); ws.on(open, () { ws.send(JSON.stringify({ id: 1, method: Runtime.enable })); ws.send(JSON.stringify({ id: 2, method: Network.enable })); ws.send(JSON.stringify({ id: 3, method: Page.enable })); });之后所有 CDP 事件都会以 JSON 消息推过来你要做的就是在ws.on(message)里解析method字段判断是不是Runtime.consoleAPICalled或Network.requestWillBeSent然后走缓存逻辑。console 事件里args是 RemoteObject 数组必须按 2.1 节说的方式展开展开后的纯文本才是 AI 能直接看的东西。网络事件要按requestId把对应的请求和响应拼起来。实际开发里 A 请求发出去可能隔了一会儿响应包事件才到达中间会穿插其他请求的事件。我维护了一个 Mapkey 是 requestIdvalue 是记录对象等到Network.responseReceived到了之后把完整记录推入环形缓冲。这样 AI 看到的请求记录里URL、参数、状态码、耗时都在同一条里结构非常清晰。3.4 挂到 MCP 客户端Claude Desktop 和 Cherry Studio 的配置Server 写好后集成到 AI 客户端是最简单的一步。Claude Desktop 的配置文件在claude_desktop_config.json加一段 mcpServers 配置{ mcpServers: { vconsole-mcp: { command: npx, args: [tsx, /absolute/path/to/vconsole-mcp-server/index.ts] } } }Cherry Studio 这类开源客户端也在设置里提供 MCP 配置入口填法几乎一样。配好后重启客户端AI 助手就能看到所有注册的工具了。怎么确认连上了直接在聊天里让 AI 调用一下工具。比如问它用 get_recent_logs 看看当前页面有没有报错。如果配置没问题它会自动调用工具并在回复里把日志分析结果列出来。第一次跑通这个流程的时候我有点兴奋——那一刻相当于真正让 AI 长出了一双可以盯 H5 页面的眼睛。3.5 一次完整的 debug 实战记录举一个真实跑通的案例。我在本地起了一个 SPA 项目路由跳转到/order后白屏Console 里有这么一条错误Uncaught TypeError: Cannot read properties of undefined (reading map)。传统流程是我自己去 vConsole 面板里翻栈找是哪个组件调用了.map。现在换成 AI 流程。我输入的指令是用 vConsole MCP 查看最近日志定位白屏原因。 AI 自动调用了get_recent_logs拿到 200 条日志发现 error 级别只有这一条然后它追到get_network_requests发现/api/order/list接口返回的data数组是null而页面拿到null后直接.map就崩了。最后它用evaluate_js在页面上执行了一段表达式验证了数据结构确实异常。整个定位过程不到 20 秒以前我能找十分钟。这还不是最爽的部分。最爽的是你能让它在改完代码后自己验证让 AI 执行evaluate_js刷新接口数据再重新调一次get_recent_logs看报错是否消失。这个发现错误 - 定位 - 修复 - 验证的闭环一旦跑通H5 debug 效率直接上一个台阶。当然它不能替代你理解业务逻辑但它能把最耗时的找证据环节压缩到极致。4. 真实使用中的常见坑与排查方法4.1 手机真机 / WebView 环境连不上 CDP 怎么办本地 Chrome 调试没问题但很多人要调的是 Android WebView 里的 H5。安卓 WebView 支持远程调试只是要先在设备上开启开发者选项和 USB 调试然后电脑浏览器打开chrome://inspect找到对应 WebView点击 inspect 会自动开一个调试窗口。这个调试窗口里同样有 CDP 调试端口只是是转发出来的。实际操作里chrome://inspect会自动映射本地端口你可以从 http://localhost:9222/json 看到这些 target前提是你把 chrome://inspect 的 Discover 开起来。麻烦的是 iOS WebView。Safari 的远程调试依赖 macOS 的 Safari 开发者菜单而且 CDP 协议不适用Safari 走的是 WebKit 私有的 Protocol。如果你主要调 iOS务实的替代方案是在页面里内嵌一段轻量 SDK专门把 console 和 fetch 拦截后的数据通过 WebSocket 上报到本地 MCP Server。这个方案不依赖 CDP但侵入性更强而且只对加了 SDK 的页面有效。我给项目留了一个 SDK mode 的扩展开关需要时再切过去。它显然没有 CDP 通用但在 iOS 上是目前最省事的路。还有一个容易忽略的安全点CDP 调试端口没有任何鉴权任何人只要能访问到那个端口就能拿到页面数据、执行 JS。所以远程调试时一定不要暴露公网VPC 内网或者 localhost 就好。4.2 AI 上下文被日志塞爆回答质量断崖式下降这个坑我摔得最重。最初启用 MCP 工具时我把默认 limit 设成 1000结果 AI 收到 1000 条日志后开始疯狂分析日志里无关紧要的 warn甚至把主要内容挤出了上下文窗口。MCP 工具返回值会被完整塞进对话上下文你给它 1000 条日志就等于让它带 1000 条记忆处理新问题效率必然下降。后面我把设计改成分层返回默认只返回等级为 error 和 warn 的最近 50 条AI 觉得不够再显式请求所有日志或某一类日志。这个调整立竿见影AI 的回答质量和速度都有改善。你可以把 MCP 工具设计想象成一个电梯简报自动帮你把核心信息总结好而不是把整座大楼结构图都塞给你。4.3 SPA 路由切换、iframe 嵌套导致日志丢失SPA 路由切换本身不会丢日志因为 CDP 的 console 事件是持续推送的但如果你在页面跳转时刷新了 target 或整个 MCP Server 的缓存之前积累的日志就被清了。所以两个选择一是保持缓存长期不清按时间窗口截取二是监听Page.frameNavigated在导航发生时打一个标记让 AI 知道日志从某条开始是新页面的。我实际用的是后者配合 vConsole 的日志时间戳能比较准确地切分会话。iframe 是个更隐蔽的问题。页面上内嵌了跨域 iframe子 iframe 的 console 日志默认不在主 frame 的 CDP 事件里。要在 CDP 里捕获所有 frame 需要开启Target.setAutoAttach或使用flatten模式。对多数调试场景推荐一个简单办法让用户或 AI 切换到对应 target。http://localhost:9222/json 会把每个 frame 也列为 target从 target 列表里挑出子 iframe用它的 webSocketDebuggerUrl 单独连接。虽然麻烦一点,但不会漏信息。4.4 端口冲突、浏览器实例崩溃与日志量过大的排查开发环境里 9222 端口经常被 Webpack devServer 或 Vite 的旧进程占用。启动浏览器前先确认端口没有被其他进程占用有就用--remote-debugging-port9223换个端口MCP Server 侧把端口配置抽成环境变量改起来不费劲。浏览器实例崩溃的常见诱因是动了--user-data-dir对应的目录权限或者磁盘空间不足。排查方式很直接看终端里浏览器进程是否还活着访问/json是否能正常拉取。值得注意Headless 模式下要加--remote-debugging-port才能调试不加的话数据流也是通的但很多 AI 客户端需要抓截图时就会失灵。日志量过大导致的另一个表现是 MCP Server 内存飞涨。我维护的环形缓冲默认上限是每条日志 20KB、总条数 3000 条超出后最旧的自动丢弃。这样能保证内存占用稳定在几十 MB 级别跑一整天也不会有问题。结合走查的经验谈一点小扩展最后分享一个我实际用出来的体会这个项目的价值不在于替你做决定而在于把散落在各种角落的证据串成一条线。vConsole 负责给人看CDP 负责给机器看MCP 负责把机器看到的翻译给 AI。三个环节缺一个debug 闭环都不完整。个人经验里最建议的一点是给你的 MCP 工具加上clear_debug_data每次 start 一个新调试会话前清一次旧缓存否则 AI 会被历史日志干扰。后续我还计划扩展两件事一是接 performance entries把页面性能指标也暴露给 AI排查白屏、卡顿可以直接看 LCP 和 FCP二是做一个远程日志中心适配让本地方案延伸到线上页面前提是做好脱敏和白名单。这个方向我已经验证过可行性跑通后会再整理一篇更完整的方案出来。在你搭建过程中如果遇到我上面没提到的坑欢迎在评论区分享我们互相补补课。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。