SuperAPI AI Directory

debug-mcp-stdio

Coding & development

View repository

Updated 10-15 11:04

About this skill

stdio MCP breakpoint debugging (VS Code Attach + MCP Inspector + Node --inspect)

Goal

Enable the user to reliably hit breakpoints in VS Code, debug an MCP Server running via stdio (usually started by npx @modelcontextprotocol/inspector ... ), and have a clear troubleshooting path when encountering issues like port conflicts, missing sourcemaps, or gray breakpoints.

Quick Start (shortest usage)

You already have a build output (for example build/internal/index.js or dist/index.js), and you want to set breakpoints for a stdio MCP Server:

  • Make sure sourcemaps are enabled(you should see a .map file next to the build output)
  • In the MCP project root, .vscode/launch.json add an attach configuration
  • In VS Code, first start this Attach debugging
  • Run in the terminal (the port must match launch.json):
npx -y @modelcontextprotocol/inspector node --inspect=9229 build/internal/index.js

If you find that "breakpoints are not hit / breakpoints are gray", first change it to:

npx -y @modelcontextprotocol/inspector node --inspect-brk=9229 build/internal/index.js

How it works (plain language)

  • Node's --inspect: it opens a "debug port" on the local machine (by default this is 9229), and VS Code can connect to control breakpoints/stepping.
  • MCP Inspector: it is like a "temporary MCP client + UI"; it starts your server and talks to it via stdio .
  • sourcemap: maps the "built JS" back to "your TS source code", so that breakpoints you set in TS are accurate.

Output format (always give the user this template)

Please output the following 3 sections (all must be copy-pasteable):

【1) VS Code Attach 配置(launch.json 片段)】
<给出一个完整 configuration 对象,提醒用户追加到 configurations 数组里;明确 port/outFiles 需要匹配>

【2) 启动命令(Inspector + Node --inspect)】
- 默认版:<一条命令>
- 稳定版(首行暂停):<一条命令>
- 换端口版(如果 9229 占用):<一条命令>

【3) 排障清单(从最可能到最少见)】
1. ...
2. ...
3. ...

Key constraints (to avoid "it looks right but just does not work")

  • Ports must match:launch.json 's port == --inspect=PORT 's PORT.
  • Attach first, then start the process: for the first attempt, it is recommended to use --inspect-brk, to avoid "starting too fast and missing the breakpoint".
  • Debugging the build output requires sourcemaps: otherwise you can only debug in the compiled JS, and TS breakpoints will most likely be inaccurate.

Overall process (follow step by step)

flowchart TD
  A[确认入口与输出目录<br/>build/ dist/ 内的 index.js] --> B[确认 sourcemap 已生成<br/>能找到 *.map]
  B --> C[追加 launch.json 的 attach 配置<br/>port/outFiles 对齐]
  C --> D[VS Code 先启动 Attach<br/>处于 waiting]
  D --> E[运行 inspector 命令启动 server<br/>建议用 --inspect-brk]
  E --> F{断点命中?}
  F -- 是 --> G[开始调试:单步/变量/调用栈]
  F -- 否 --> H[按清单排查:端口/路径/outFiles/map/拼写错误]
  H --> D

Step 0: Confirm the entry point and output directory (to avoid writing the path wrong)

First, determine "which js file do I actually need to run":

ls -la build dist 2>/dev/null

Common entry points:

  • build/internal/index.js(note: many people write it as internel, this is a spelling trap)
  • build/index.js
  • dist/index.js

Step 1: Enable sourcemaps (the prerequisite for "directly debugging the build output")

1.1 TypeScript(tsconfig)

If you have a TS project,tsconfig.json must at least contain:

{
  "compilerOptions": {
    "sourceMap": true,
    "inlineSources": true
  }
}

1.2 Bundler/build tool (choose the one you use)

The core principle is one sentence:The build output must include .map。

  • tsup: configure sourcemap: true
  • esbuild: add to the command or configuration sourcemap: true(or --sourcemap)
  • rollup:output.sourcemap: true
  • webpack: set an appropriate devtool(for example source-map)
  • tsc direct output: confirm that under outDir there is .js.map

Self-check (you should be able to see .map):

find build dist -maxdepth 4 -name "*.map" -print 2>/dev/null | head

If you cannot find any .map, do not rush to debug breakpoints: turn on sourcemaps and rebuild once.

Step 2: In .vscode/launch.json Add attach configuration (most important)

In the root directory of the MCP project, add/modify .vscode/launch.json, and add the following as a new configuration(do not overwrite your existing configuration).

You usually only need to change two places:

  • port: the debug port you plan to use (default 9229)
  • outFiles: whether your output directory is build/ or dist/
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Attach: MCP stdio (Node Inspector)",
      "type": "node",
      "request": "attach",
      "port": 9229,
      "protocol": "inspector",
      "restart": true,
      "timeout": 30000,
      "sourceMaps": true,
      "smartStep": true,
      "skipFiles": ["<node_internals>/**", "**/node_modules/**"],
      "cwd": "${workspaceFolder}",
      "outFiles": [
        "${workspaceFolder}/build/**/*.js",
        "${workspaceFolder}/dist/**/*.js"
      ]
    }
  ]
}

Step 3: Start Attach debugging in VS Code

  • Open the Run and Debug panel
  • Select Attach: MCP stdio (Node Inspector)
  • Click Run (or press F5)

At this point VS Code will enter the "waiting for connection" state.

Step 4: Run the Inspector command to start the server (stdio mode)

4.1 Most commonly used (recommended)

npx -y @modelcontextprotocol/inspector node --inspect=9229 build/internal/index.js

4.2 More stable for first-time debugging (recommended to use it first)

--inspect-brk will make Node pause on the first line, ensuring that after attach succeeds you continue execution:

npx -y @modelcontextprotocol/inspector node --inspect-brk=9229 build/internal/index.js

4.3 If you use pnpm / yarn

pnpm dlx @modelcontextprotocol/inspector node --inspect=9229 build/internal/index.js
yarn dlx @modelcontextprotocol/inspector node --inspect=9229 build/internal/index.js

Step 5: Common issues (troubleshoot in this order)

5.1 Port is occupied (9229 is unavailable)

Symptom:

  • The terminal reports the port is occupied
  • or VS Code attach fails/connects to the wrong process

Check (commonly used on macOS / Linux):

lsof -nP -iTCP:9229 -sTCP:LISTEN

Handling (choose one of two):

  • Change the port: for example, change it to 9230
    • Change the launch.json of port to 9230
    • Also change the command to --inspect=9230(or --inspect-brk=9230)
  • Kill the process occupying the port: confirm it is the process you want to terminate before killing it

5.2 Breakpoints are gray / do not stop (most common)

Prioritize these three things:

  • Use --inspect-brk to stabilize first: make the process pause on the first line
  • Confirm that .map actually exists: the output directory must contain *.map
  • Confirm that outFiles covers your output directory: for example, if you are actually in build/, it must include ${workspaceFolder}/build/**/*.js

Additional checkpoints (if you see one, it means sourcemap is working):

  • Build artifact .js has something like this at the end //# sourceMappingURL=xxx.js.map
  • VS Code's Call Stack can show your source paths, rather than a bunch of minified JS

5.3 Inspector can start, but the server exits immediately

Possible reasons:

  • The entry file path is wrong (build/internel/index.js vs build/internal/index.js this kind of spelling is most common)
  • The server reports an error on startup and exits directly (check the terminal output)

First do two minimal actions:

node -p "require('fs').existsSync('build/internal/index.js')"
node --inspect-brk=9229 build/internal/index.js

If the second one can run, it means the problem is more likely in the inspector command or the arguments you pass.

Examples (examples)

Example 1: Standard build artifact debugging (build output)

npx -y @modelcontextprotocol/inspector node --inspect-brk=9229 build/internal/index.js

Example 2: Port conflict, switch to 9230

  1. launch.json Change port to 9230
  2. Command:
npx -y @modelcontextprotocol/inspector node --inspect-brk=9230 build/internal/index.js

Fallback strategy (when you do not want to / cannot adjust the build artifacts)

If you cannot get sourcemap working for now (or bundling is too complex), you can first debug by "running the source code directly in development mode" (provided your project allows starting this way).

For example, use tsx:

npx -y tsx --inspect-brk=9229 src/index.ts

This approach does not use the inspector; it is suitable for first confirming that the "breakpoint/logic/flow" itself is fine, and then going back to complete the sourcemap debugging chain for the build artifacts.