Node.js调试协议桥

通过Chrome DevTools协议(CDP)和Debug Adapter协议(DAP)桥接,实现AI编程工具对运行中Node.js进程的控制和观察。

  • by VitalyOstanin
  • TypeScript
  • 本地部署
  • 2 星标
  • 更新于
在 GitHub 查看 VitalyOstanin/mcp-chrome-debugger-protocol

使用说明

MCP Chrome调试器协议

MCP服务器,允许AI编码工具通过chrome devtools协议(CDP)和轻量级调试适配器协议(DAP)桥控制和观察正在运行的Node.js进程。

使用Claude Code CLI进行测试。

目录

特性

  • 连接/控制:通过端口、WebSocket URL或PID连接到Node.js进程;暂停、继续并逐步执行代码。
  • 断点和日志点:设置/删除经典断点和日志点(带 {expr} 插值)在TS或JS上。
  • 源地图:解析TS↔JS使用自动发现 *.js.map 具有LEAST_UPPER_BOUND偏置,可实现可靠放置。
  • 状态和事件:观察暂停/恢复、自定义日志点点击和基本线程/堆栈检查。
  • 安全插值:表达式 {expr} 被防御性地评估;错误永远不会中断执行(返回 undefined).

高级图表

flowchart LR
  C[MCP client] <--> S[MCP server]
  S --> A["DAP node.js adapter (debug adapter protocol)"]
  A <--> I["CDP (chrome devtools protocol)"]
  I <--> N[node.js app]

工作原理(功能描述)

  • MCP服务器:在模型上下文协议上公开一组调试工具(附加、断点、步进、检查)。
  • DAP桥:服务器使用进程内DAP客户端和直接与CDP通信的自定义Node.js调试适配器。
  • CDP传输:适配器启用CDP域(Runtime, Debugger, Console)并安装一个名为的绑定 __mcpLogPoint.
  • 日志点:日志点只是一个断点,其条件调用 __mcpLogPoint(JSON.stringify(...)) 并返回 false 所以执行永远不会停顿。
  • 事件流:适配器发送自定义DAP事件 mcpLogpointDAP客户端存储命中数据,MCP服务器通过工具和日志记录将其显示出来。

调试器交互(文本方案)

  1. 附加/初始化

    • MCP客户端呼叫 attach;服务器创建适配器并连接到CDP(通过URL/port/PID)。
    • 适配器: Runtime.enable, Debugger.enable, Console.enable那么 Runtime.addBinding 为了 __mcpLogPoint (以及每个执行上下文)。
  2. 设置日志点/断点

    • MCP客户端呼叫 setBreakpoints 相对于TS或JS源路径和坐标(基于1的行/列)。
    • 对于TS输入,服务器通过源映射解析生成的JS位置(或自动发现它们)。
    • 适配器放置CDP断点(Debugger.setBreakpointByUrl 或通过scriptId)。对于日志点,条件评估 {expr} 安全地调用绑定。
  3. 执行并收集

    • 当代码到达站点时,CDP会触发 Runtime.bindingCalled 使用JSON有效载荷。
    • 适配器发出DAP自定义事件 mcpLogpoint 使用原始有效载荷和上下文id。
    • DAP客户端解析/存储命中并发出 logpointHit;MCP服务器通过以下方式公开它 getLogpointHits 以及日志记录。

演示

带有源代码映射的TypeScript演示

可用格式:

需求

  • Node.js>=22(设置在 engines.node).建议用于本地开发:节点24(固定在 .nvmrc).CI对节点22和24运行矩阵。
  • npm>=10(设置在 engines.npm).npm>=11仅对以下情况是必需的 npm publish.

安装

使用Claude MCP CLI进行安装:

claude mcp add --scope user chrome-debugger-protocol npx @vitalyostanin/mcp-chrome-debugger-protocol

范围选项:

  • --scope user:为当前用户安装
  • --scope project:仅为当前项目安装

移除

卸下MCP服务器:

claude mcp remove chrome-debugger-protocol --scope user

范围选项:

  • --scope user:从用户配置中删除
  • --scope project:从项目配置中删除

安全模型

仅在受信任的本地环境(开发人员工作站、IDE、您拥有的CI沙箱)中运行此服务器。它是 不 设计用于坐在公共代理后面或在相互不信任的客户端之间共享。

连接的MCP客户端实际上是目标Node.js进程内的根: evaluate, setBreakpoints 和 condition,和logpoint {expr} 占位符都是按设计在调试对象中执行任意JavaScript的。 attach 拒绝非环回主机,除非 MCP_CDP_ALLOW_REMOTE=1 已设置;当启用该环境变量时,服务器会在启动时打印stderr警告,因此很难错过剩余的覆盖。日志点命中是缓冲的(FIFO,默认情况下最多2000个条目,可通过配置 MCP_LOGPOINT_BUFFER_SIZE)并按需返回——避免在机密/PII上设置日志点。

在Linux上,当服务器以root身份启动时 attach 使用pid调用,从中读取目标的真实uid /proc/<pid>/status 如果进程由另一个用户拥有,则调用被拒绝——当uid 0是调用者时,任何pid的kill(pid,0)都会成功,因此显式uid检查可以阻止SIGUSR1干扰外部用户的守护进程。

看 docs/SECURITY.md 对于完整的威胁模型、信任边界、缓解措施、操作指南和漏洞报告过程。

快速开始

  1. 使用调试器启动Node.js应用程序:

    node --inspect your-app.js
    
  2. 在Claude Code中尝试这个实用的示例提示:

* Connect to the already running Node.js debugger
* Set a logpoint INSIDE the function handler for HTTP endpoint test1 to show only requests with query parameter logme=1. Make sure that logpoint is installed on the executable code.
* Immediately show the logpoint with marker
* Execute requests to http://localhost:3000/test1 with this parameter and without it
* Show the triggered log

提示:使用 attach 连接工具;通过以下方式设置日志点 setBreakpoints (通过断点 logMessage),然后使用以下命令检查命中率 getLogpointHits.

需要目标应用程序吗?该回购在 tests/fixtures/test-app 带着一个 /test1 您可以在其下启动的端点 --inspect 按照上面的提示进行端到端操作。

发展

贡献者的本地工作流程:

npm install
npm run build              # tsc -> dist/
npm run typecheck          # tsc -p tsconfig.json (src + tests)
npm run lint               # eslint .
npm run lint:fix           # eslint . --fix
npm test                   # vitest unit tests
npm run test:coverage      # vitest unit tests with coverage report
npm run test:integration   # vitest integration tests (real Node debugger)
npm run test:all           # unit + integration sequentially
npm run dev                # tsc --watch (incremental compile only)
npm run dev:server         # build + run MCP server (stdio)
npm run dev:test           # launch the test-app fixture under --inspect for manual attach

30秒内完成端到端循环:运行 npm run dev:test 在一个终端中(它在下面启动测试应用程序夹具 --inspect=9229),然后在另一个终端中运行MCP服务器(npm run dev:server)并使用 attach 您的客户提供的工具。

格式化:此项目依赖ESLint plus .editorconfig。没有单独的 prettier 配置。跑 npm run lint:fix (或其别名 npm run format)应用样式修复。如果编辑器插入了冲突的格式,请将其配置为遵从ESLint。

看 代理商.md 了解详细的贡献者规则和项目约定。

环境变量

所有环境变量都是可选的;当没有设置默认值时,服务器会以合理的默认值运行。

变量 类型 默认值 描述
MCP_CDP_ALLOW_REMOTE 1 启用 取消设置 允许 attach 到非环回主机。只有精确值 1 使之成为可能;设置时,启动时会打印stderr警告。看 安全模型.
DAP_VERBOSE 1 / true unset 在stderr和DAP上启用详细适配器诊断 OutputEvents.参见 详细诊断.
MCP_LOGPOINT_BUFFER_SIZE 正整数 2000 日志点命中和调试器事件的FIFO缓冲区大小。非数字或非正值将恢复为默认值。

详细诊断(DAP_Verbose)

集 DAP_VERBOSE=1 (或 DAP_VERBOSE=true)在环境中启用详细的适配器诊断。启用后,服务器会向stderr(和DAP)写入额外的行 OutputEvents on the wire)用于源映射解析、断点放置、CDP回退和重新连接尝试。

不要在生产/共享环境中启用。 详细输出可能包括:

  • 解析的源路径和 *.js.map 项目中的文件名。
  • 用户提供的断点条件和日志点 logMessage 模板逐字逐句。插值值为 {expr} 占位符在调试对象中进行评估,因此不会被适配器回显,但模板文本本身是(例如。 Logpoint set at /abs/path/src/index.ts:42 - Message: "token={process.env.API_KEY}").
  • 潜在的CDP/DAP错误消息,可能引用用户输入。

储备 DAP_VERBOSE=1 用于适配器本身的本地调试。默认(未设置)模式只会发出致命错误。

可用工具

  • 连接: attach, disconnect, restart, terminate
  • 断点: setBreakpoints (支持 logMessage), setBreakpointsBatch (并行设置多个文件的断点,最多4个并发文件), removeBreakpoint, getBreakpoints, setExceptionBreakpoints, breakpointLocations
  • 执行控制: continue, pause, next (跳过), stepIn, stepOut, restartFrame
  • 检查: evaluate, stackTrace, variables, scopes, setVariable, threads, loadedSources, exceptionInfo
  • 监控: getLogpointHits, clearLogpointHits, getDebuggerEvents, clearDebuggerEvents, getDebuggerState
  • 源地图: resolveOriginalPosition, resolveGeneratedPosition

日志点

  • 放置:通过以下方式创建日志点 setBreakpoints 通过提供断点条目 logMessage 现场。
  • 插值:使用 {expr} 内部占位符 logMessage在目标上下文中安全地计算表达式;错误被接受并屈服 undefined.
  • 传输:日志点通过CDP实现 Runtime.addBinding 并通过以下方式捕获 Runtime.bindingCalled --不使用控制台输出前缀。
  • 有效载荷:每次命中都会产生一个结构化的有效载荷,由 getLogpointHits.

放置日志点的请求示例:

{
  "name": "setBreakpoints",
  "arguments": {
    "source": { "path": "/abs/path/to/project/tests/fixtures/test-app/src/index.ts" },
    "breakpoints": [
      { "line": 96, "column": 1, "logMessage": "fib={fibResult} sum={breakpointResult}" }
    ]
  }
}

例子 getLogpointHits 响应内容(简化):

{
  "success": true,
  "data": {
    "hits": [
      {
        "timestamp": "2025-08-12T12:34:56.789Z",
        "executionContextId": 1,
        "message": "fib=5 sum=15",
        "payloadRaw": "{\"message\":\"fib=5 sum=15\",\"vars\":{\"fibResult\":5,\"breakpointResult\":15},\"time\":1734000000000}",
        "payload": {
          "message": "fib=5 sum=15",
          "vars": { "fibResult": 5, "breakpointResult": 15 },
          "time": 1734000000000
        },
        "level": "info"
      }
    ],
    "totalCount": 1
  }
}

笔记:

  • payload.vars 包含“配对”表达式→ “为所有人” {expr} 在 logMessage.
  • 为了可靠地放置日志点,请使用真正可执行的行和正确的列(基于1)。

TypeScript断点和源映射

使用TypeScript源代码的两种推荐方法:

  1. TS‑first断点和日志点(推荐)
  • 直接在TS文件路径上设置断点/日志点——适配器会自动解析源映射。
{
  "name": "setBreakpoints",
  "arguments": {
    "source": { "path": "/abs/path/to/project/tests/fixtures/test-app/src/index.ts" },
    "breakpoints": [
      { "line": 96, "column": 1, "logMessage": "fib={fibResult} sum={breakpointResult}" }
    ]
  }
}
  1. 自动解析生成的位置(回退)
  • 如果需要显式映射,请调用 resolveGeneratedPosition 无需手动传递地图路径,只需提供 originalSourcePath。服务器自动发现以下地图 dist|build|out|lib 相对于项目根和TS文件。
{
  "name": "resolveGeneratedPosition",
  "arguments": {
    "originalSource": "src/index.ts",
    "originalSourcePath": "/abs/path/to/project/tests/fixtures/test-app/src/index.ts",
    "originalLine": 96,
    "originalColumn": 1
  }
}

笔记:

  • 当 originalSourcePath 如果提供,服务器会自动在项目的构建目录中以及TS文件位置附近搜索映射——否 sourceMapPaths 需要。
  • 集成脚本 scripts/mcp-logpoint-check.mjs 遵循TS优先流,并验证对数点插值在TS线上有效;它还确保了Node检查器端口 9229 完成后免费。

故障排除

  • 项目根检测:对于自动源映射发现,服务器会查找最近的 package.json 从提供的TS路径向上扫描 dist, build, out,以及 lib。确保您的构建能够发出 *.js.map 到其中一个文件夹。
  • 如果找不到地图:通过 originalSourcePath 到 resolveGeneratedPosition,或从项目根目录运行MCP服务器,以便当前工作目录的回退扫描成功。
  • 坐标:所有MCP/DAP坐标都是基于1的线和列。使用 column >= 1 设置断点/日志点时。
  • 日志点命中:如果您没有看到任何命中,请将日志点移动到实际可执行的行(例如,处理程序中的赋值或表达式),或触发执行该行的端点/函数。在TS测试应用程序中,可靠的线路包括 index.ts:96 (响应对象)和 index.ts:92 (the processor.processData() 地区)。
  • WebSocket连接:您可以通过 attach 和 { "url": "ws://127.0.0.1:<port>/<id>" },或通过以下方式启用正在运行的进程 attach 和 { "processId": <pid> } (发送 SIGUSR1).
  • PID连接端口发现:使用时 attach 和 processId,服务器自动发现检查器端口 port 此路径的参数被忽略。在Linux上,它试图通过以下方式检测激活 strace否则,它将进行民意调查 http://127.0.0.1:<port>/json/version 跨公共端口(9229..9250),如果找不到任何内容,则回退到9229。

建筑

详细流程

sequenceDiagram
  autonumber
  participant C as Client
  participant S as Server
  participant A as Adapter
  participant I as CDP
  participant N as App

  C->>S: attach
  S->>A: start
  A->>I: connect
  A->>I: Runtime.enable
  A->>I: Debugger.enable
  A->>I: Console.enable
  A->>I: Runtime.addBinding (__mcpLogPoint)

  Note over C,S: set logpoint
  C->>S: setBreakpoints
  S->>A: setBreakpoints
  A->>I: setBreakpointByUrl

  Note over N,S: execute and collect
  N->>I: hits line
  I-->>A: bindingCalled (__mcpLogPoint)
  A-->>S: event mcpLogpoint
  C->>S: getLogpointHits
  S-->>C: hits list

项目创建

这个项目是由我的专业知识设计的,并使用人工智能辅助编码实现。

支持

如果你觉得这个项目有用,可以考虑支持它的开发: 捐款