The MCP server component that exposes VS Code debugging capabilities to AI agents via the Model Context Protocol. This is the main entry point for all external AI agent communication.
AI coding agents need a standardized way to control debuggers programmatically. MCP provides this standard, and DebugMCPServer implements it using the official @modelcontextprotocol/sdk with Streamable HTTP transport over an express HTTP server.
- Initialize and manage the MCP server lifecycle (using
McpServerfrom@modelcontextprotocol/sdk) - Register debugging tools that AI agents can invoke
- Register documentation resources for agent guidance
- Delegate all debugging operations to
DebuggingHandler - Manage Streamable HTTP transport via
StreamableHTTPServerTransporton configurable port (default: 3001)
AI Agent (MCP Client)
│
▼ HTTP POST /mcp
┌───────────────────┐
│ DebugMCPServer │ ◄── You are here
│ (express + HTTP) │
└───────────────────┘
│
▼ Delegates to
┌───────────────────┐
│ DebuggingHandler │
└───────────────────┘
The MCP endpoint uses a fixed port, but every open VS Code window activates the extension. To avoid debugging the wrong workspace when several windows are open:
- Every window starts a loopback
ControlServer(src/controlServer.ts) that runs debug operations against its ownDebuggingHandler, and advertises its workspace folders (plus control port + token) in a shared file registry (src/utils/workspaceRegistry.ts). - One window wins the public MCP port and becomes the router. Its per-MCP-session
handler is a
RoutingDebuggingHandler(src/routingDebuggingHandler.ts) that resolves the target window from the request'sworkingDirectory/fileFullPathand forwards the operation to that window'sControlServer. The target is cached per session so hint-less follow-ups (step/continue/inspect) reach the same window. If the router window closes, a worker window takes over the port on retry.
DebugMCPServer builds one handler per MCP session via a handler factory, which is
what lets concurrent agent sessions drive debuggers in different repos simultaneously.
DebugMCPServer exposes tools for debugger capabilities. Detailed procedural guidance
(when to debug, how to structure a root-cause investigation, language-specific quirks) lives
in the companion Agent Skill at skills/debug-live/SKILL.md, which AgentConfigurationManager
installs into the standard personal skills directories (~/.agents/skills/, and
~/.copilot/skills/ when present) so skills-compatible harnesses load it on demand. This
separation matches modern agent ecosystems where MCP servers provide capabilities and
skills provide procedural knowledge an agent loads as context.
Tool descriptions are intentionally terse and behavioral — they describe what the tool does, not when or how to use it in a multi-step workflow.
The server instructions (passed to the McpServer constructor and returned to the client
at initialize) and the start_debugging tool description both point agents at the
debug-live skill for the full step-through workflow, so the pointer is visible even before
the skill activates.
Uses stateless HTTP POST requests for MCP communication. The express server exposes:
POST /mcp— Handles all MCP protocol messages (JSON-RPC over HTTP)
Each request creates a new stateless StreamableHTTPServerTransport instance that is closed when the HTTP response closes. The server returns JSON-RPC error responses (not HTML pages) for malformed payloads or unsupported methods to keep client behavior predictable.
Every layer that a tool call passes through is time-bounded so a wedged debug adapter or an unresponsive worker window can never leave an MCP request pending forever (which surfaces to clients as "Request timed out" and makes the whole server look stuck). The bounds are nested innermost-first so the most specific error wins:
- DAP request (
DebuggingExecutor.dapRequest) caps eachcustomRequest(stackTrace/scopes/variables/evaluate). - Router → worker forward (
RoutingDebuggingHandler) caps the loopback round-trip to a worker window'sControlServer(timeoutInSeconds + 15s). - Tool boundary (
DebugMCPServer.runTool) is the final backstop around every tool invocation (timeoutInSeconds + 30s), guaranteeing the client always gets a prompt response.
- Class definition:
src/debugMCPServer.ts - Tool registration:
setupTools()method (usesMcpServer.registerTool()) - Server startup / router election:
start()method (returns whether this window owns the port) - Per-window control server:
src/controlServer.ts - Cross-window routing handler:
src/routingDebuggingHandler.ts - Shared window registry:
src/utils/workspaceRegistry.ts - Agent Skill (procedural workflow):
skills/debug-live/SKILL.md
| Tool | Description |
|---|---|
start_debugging |
Start a debug session |
stop_debugging |
Stop current session |
step_over/into/out |
Stepping commands |
continue_execution |
Continue to next breakpoint |
pause_execution |
Interrupt a running program (no breakpoint needed) |
restart_debugging |
Restart session |
add/remove_breakpoint |
Breakpoint management |
clear_all_breakpoints |
Remove all breakpoints |
list_breakpoints |
List active breakpoints |
get_variables_values |
Inspect variable values |
evaluate_expression |
Evaluate expressions |
debugmcp.serverPort: Port number (default: 3001)debugmcp.timeoutInSeconds: Operation timeout (default: 180)