Skip to content

Latest commit

 

History

History
807 lines (663 loc) · 22.2 KB

File metadata and controls

807 lines (663 loc) · 22.2 KB

mcp-debugger Tool Reference

This document provides a complete reference for all tools available in mcp-debugger, based on real testing conducted on 2025-06-11.

Table of Contents

  1. Session Management
  2. Breakpoint Management
  3. Execution Control
  4. State Inspection

Session Management

create_debug_session

Creates a new debugging session.

Parameters:

  • language (string, required): The programming language to debug. Languages are discovered dynamically from installed adapters. The default fallback languages (when dynamic discovery is unavailable) are "python" and "mock". When all adapters are available, the full list is: "python", "javascript", "rust", "go", "java", "dotnet", "mock". The actual list depends on which @debugmcp/adapter-* packages are discoverable at runtime.
  • name (string, optional): A descriptive name for the debug session. Defaults to "session-<8 chars>" (e.g., "session-a4d1acc8").
  • executablePath (string, optional): Path to the language interpreter/executable (e.g., Python interpreter path).

Response:

{
  "success": true,
  "sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
  "message": "Created python debug session: Test Debug Session"
}

Example:

{
  "language": "python",
  "name": "My Debug Session"
}

Notes:

  • Session IDs are UUIDs in the format xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Sessions start in "created" state
  • When a port parameter is provided in create_debug_session, the server performs an inline attach (creating the session and immediately attaching to a running process on that port)

list_debug_sessions

Lists all active debugging sessions.

Parameters: None (empty object {})

Response:

{
  "success": true,
  "sessions": [
    {
      "id": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
      "name": "Test Debug Session",
      "language": "python",
      "state": "created",
      "createdAt": "2025-06-11T04:53:14.762Z",
      "updatedAt": "2025-06-11T04:53:14.762Z"
    }
  ],
  "count": 1
}

Session States (from SessionState enum):

  • "created": Session created but not started
  • "initializing": Debug session starting up
  • "ready": Session initialized and ready to start debugging
  • "running": Actively debugging (program executing)
  • "paused": Paused at breakpoint or step
  • "stopped": Session stopped (program terminated)
  • "error": Session encountered an error

close_debug_session

Closes an active debugging session.

Parameters:

  • sessionId (string, required): The ID of the debug session to close.

Response:

{
  "success": true,
  "message": "Closed debug session: a4d1acc8-84a8-44fe-a13e-28628c5b33c7"
}

Notes:

  • Sessions may close automatically on errors
  • Closing a non-existent session returns success: false

Breakpoint Management

set_breakpoint

Sets a breakpoint in a source file.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • file (string, required): Path to the source file (absolute or relative to project root).
  • line (number, required): Line number where to set breakpoint (1-indexed).
  • condition (string, optional): Conditional expression for the breakpoint (not verified to work).

Response:

{
  "success": true,
  "breakpointId": "28e06119-619e-43c0-b029-339cec2615df",
  "file": "C:\\path\\to\\debug-mcp-server\\examples\\python_simple_swap\\swap_vars.py",
  "line": 9,
  "verified": false,
  "message": "Breakpoint set at C:\\path\\to\\debug-mcp-server\\examples\\python_simple_swap\\swap_vars.py:9",
  "context": {
    "lineContent": "    a = b  # Bug: loses original value of 'a'",
    "surrounding": [
      { "line": 7, "content": "def swap_variables(a, b):" },
      { "line": 8, "content": "    \"\"\"This function is supposed to swap two variables.\"\"\"" },
      { "line": 9, "content": "    a = b  # Bug: loses original value of 'a'" },
      { "line": 10, "content": "    b = a  # Bug: 'b' gets the new value of 'a', not the original" },
      { "line": 11, "content": "    return a, b" }
    ]
  }
}

Important Notes:

  • Breakpoints show "verified": false until debugging starts
  • The response includes the absolute path even if you provide a relative path
  • Setting breakpoints on non-executable lines (comments, blank lines, declarations) may cause unexpected behavior
  • Executable lines that work well: assignments, function calls, conditionals, returns

Execution Control

start_debugging

Starts debugging a script.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • scriptPath (string, required): Path to the script to debug.
  • args (array of strings, optional): Command line arguments for the script.
  • dapLaunchArgs (object, optional): Standard DAP launch arguments:
    • stopOnEntry (boolean): Stop at first line
    • justMyCode (boolean): Debug only user code
  • adapterLaunchConfig (object, optional): Adapter-specific launch configuration overrides. Use this for language-specific settings that go beyond standard DAP arguments (e.g., mainClass and classpath for Java, buildCommand for Rust).
  • dryRunSpawn (boolean, optional): Test spawn without actually starting

Response:

{
  "success": true,
  "state": "paused",
  "message": "Debugging started for examples/python_simple_swap/swap_vars.py. Current state: paused",
  "data": {
    "message": "Debugging started for examples/python_simple_swap/swap_vars.py. Current state: paused",
    "reason": "breakpoint"
  }
}

Pause Reasons:

  • "breakpoint": Stopped at a breakpoint
  • "step": Stopped after a step operation
  • "entry": Stopped on entry (if configured)

step_over

Steps over the current line, executing it without entering function calls.

Parameters:

  • sessionId (string, required): The ID of the debug session.

Response:

{
  "success": true,
  "state": "paused",
  "message": "Stepped over"
}

step_into

Steps into function calls on the current line.

Parameters:

  • sessionId (string, required): The ID of the debug session.

Response:

{
  "success": true,
  "state": "paused",
  "message": "Stepped into"
}

step_out

Steps out of the current function.

Parameters:

  • sessionId (string, required): The ID of the debug session.

Response:

{
  "success": true,
  "state": "paused",
  "message": "Stepped out"
}

continue_execution

Continues execution until the next breakpoint or program end.

Parameters:

  • sessionId (string, required): The ID of the debug session.

Response:

{
  "success": true,
  "state": "running",
  "message": "Continued execution"
}

Error Response:

{
  "code": -32603,
  "message": "MCP error -32603: Failed to continue execution: Managed session not found: {sessionId}"
}

pause_execution

Pauses a running program. The debugger sends a DAP pause request and returns immediately; the paused state is updated asynchronously when the stopped event arrives.

Parameters:

  • sessionId (string, required): The ID of the debug session.

Response:

{
  "success": true,
  "state": "running",
  "data": {
    "message": "Execution paused"
  }
}

Notes:

  • The "state" field in the response reflects the session state at the moment the pause request is acknowledged, which is still "running". The state transitions to "paused" asynchronously when the stopped event arrives from the debug adapter; poll list_debug_sessions or wait for subsequent tool calls to observe the paused state.
  • The session must be in a "running" state; pausing an already-paused session returns success immediately with "Already paused"
  • After pausing, you can inspect variables, evaluate expressions, and step through code

State Inspection

get_stack_trace

Gets the current call stack.

Parameters:

  • sessionId (string, required): The ID of the debug session.

Response:

{
  "success": true,
  "stackFrames": [
    {
      "id": 3,
      "name": "swap_variables",
      "file": "C:\\path\\to\\debug-mcp-server\\examples\\python_simple_swap\\swap_vars.py",
      "line": 5,
      "column": 1
    },
    {
      "id": 4,
      "name": "main",
      "file": "C:\\path\\to\\debug-mcp-server\\examples\\python_simple_swap\\swap_vars.py",
      "line": 21,
      "column": 1
    },
    {
      "id": 2,
      "name": "<module>",
      "file": "C:\\path\\to\\debug-mcp-server\\examples\\python_simple_swap\\swap_vars.py",
      "line": 30,
      "column": 1
    }
  ],
  "count": 3
}

Notes:

  • Stack frames are ordered from innermost (current) to outermost
  • Frame IDs are used with get_scopes

get_scopes

Gets variable scopes for a specific stack frame.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • frameId (number, required): The ID of the stack frame from get_stack_trace.

Response:

{
  "success": true,
  "scopes": [
    {
      "name": "Locals",
      "variablesReference": 5,
      "expensive": false,
      "presentationHint": "locals",
      "source": {}
    },
    {
      "name": "Globals",
      "variablesReference": 6,
      "expensive": false,
      "source": {}
    }
  ]
}

Important:

  • The variablesReference is what you pass to get_variables as the scope parameter
  • This is NOT the same as the frame ID!

get_variables

Gets variables within a scope.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • scope (number, required): The variablesReference number from a scope or variable.

Response:

{
  "success": true,
  "variables": [
    {
      "name": "a",
      "value": "10",
      "type": "int",
      "variablesReference": 0,
      "expandable": false
    },
    {
      "name": "b",
      "value": "20",
      "type": "int",
      "variablesReference": 0,
      "expandable": false
    }
  ],
  "count": 2,
  "variablesReference": 5
}

Variable Properties:

  • variablesReference: 0 for primitive types, >0 for complex objects that can be expanded
  • expandable: Whether the variable has child properties
  • Values are always returned as strings

get_local_variables

Gets local variables by traversing all stack frames and their scopes, then using the language adapter's policy to extract the relevant local variables. This is a convenience tool that collects scopes and variables across all frames (not just the top frame) so that closures and outer-scope locals are included, then returns the filtered result without needing to manually call stack→scopes→variables.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • includeSpecial (boolean, optional): Include special/internal variables like this, __proto__, __builtins__, etc. Default: false.

Response:

{
  "success": true,
  "variables": [
    {
      "name": "x",
      "value": "10",
      "type": "int",
      "variablesReference": 0,
      "expandable": false
    },
    {
      "name": "y",
      "value": "20",
      "type": "int",
      "variablesReference": 0,
      "expandable": false
    }
  ],
  "count": 2,
  "frame": {
    "name": "main",
    "file": "C:\\path\\to\\script.py",
    "line": 31
  },
  "scopeName": "Locals"
}

Example - Python:

// Request
{
  "sessionId": "842ef9bb-037a-4d3c-960c-ad79a63ccfab",
  "includeSpecial": false
}

// Response
{
  "success": true,
  "variables": [
    {"name": "x", "value": "10", "type": "int", "variablesReference": 0, "expandable": false},
    {"name": "y", "value": "20", "type": "int", "variablesReference": 0, "expandable": false}
  ],
  "count": 2,
  "frame": {
    "name": "main",
    "file": "C:\\path\\to\\test-scripts\\python_test_comprehensive.py",
    "line": 31
  },
  "scopeName": "Locals"
}

Example - JavaScript:

// Request
{
  "sessionId": "ec46719a-68d9-4755-9c28-70478e0cde7d",
  "includeSpecial": false
}

// Response
{
  "success": true,
  "variables": [
    {"name": "x", "value": "10", "type": "number", "variablesReference": 0, "expandable": false}
  ],
  "count": 1,
  "frame": {
    "name": "main",
    "file": "c:\\path\\to\\test-scripts\\javascript_test_comprehensive.js",
    "line": 40
  },
  "scopeName": "Local"
}

Edge Cases:

// Empty locals
{
  "success": true,
  "variables": [],
  "count": 0,
  "frame": {"name": "<module>", "file": "script.py", "line": 2},
  "scopeName": "Locals",
  "message": "The Locals scope is empty."
}

// Session not paused
{
  "success": false,
  "error": "Session is not paused",
  "message": "Cannot get local variables. The session must be paused at a breakpoint."
}

Key Advantages:

  • Single Call: Get local variables with one tool call instead of three (stack_trace → scopes → variables)
  • Language-Aware Filtering: Automatically filters out internal/special variables based on language
  • Consistent Format: Returns a consistent structure across Python and JavaScript
  • Smart Defaults: By default, excludes noise like __proto__, this, __builtins__ unless explicitly requested

Language-Specific Behavior:

  • Python: Looks for "Locals" scope, filters out __builtins__, special variables, and internal debugger variables
  • JavaScript: Looks for "Local", "Local:", or "Block:" scopes, filters out this, __proto__, and V8 internals
  • Other Languages: Falls back to generic behavior (first non-global scope)

Notes:

  • Session must be paused at a breakpoint for this tool to work
  • The tool traverses all frames in the call stack and collects scopes/variables from each, then uses the adapter policy to extract relevant locals (the reported frame is still the top frame)
  • When includeSpecial is true, all variables including internals are returned
  • This is especially useful for AI agents that need quick access to current local state

evaluate_expression

Evaluates an expression in the context of the current debug session.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • expression (string, required): The expression to evaluate.
  • frameId (number, optional): Stack frame ID for context. If not provided, automatically uses the current (top) frame.

Response:

{
  "success": true,
  "result": "10",
  "type": "int",
  "variablesReference": 0,
  "presentationHint": {}
}

Example - Simple Variable:

// Request (no frameId needed!)
{
  "sessionId": "d507d6fb-45fc-4295-9dc0-4f44b423c103",
  "expression": "x"
}

// Response
{
  "success": true,
  "result": "10",
  "type": "int",
  "variablesReference": 0
}

Example - Arithmetic Expression:

// Request
{
  "sessionId": "d507d6fb-45fc-4295-9dc0-4f44b423c103",
  "expression": "x + y"
}

// Response
{
  "success": true,
  "result": "30",
  "type": "int",
  "variablesReference": 0
}

Example - Complex Expression:

// Request
{
  "sessionId": "d507d6fb-45fc-4295-9dc0-4f44b423c103",
  "expression": "[i*2 for i in range(5)]"
}

// Response
{
  "success": true,
  "result": "[0, 2, 4, 6, 8]",
  "type": "list",
  "variablesReference": 4  // Can be expanded to see elements
}

Error Handling:

// Request - undefined variable
{
  "sessionId": "d507d6fb-45fc-4295-9dc0-4f44b423c103",
  "expression": "undefined_variable"
}

// Response
{
  "success": false,
  "error": "Name not found: Traceback (most recent call last):\n  File \"<string>\", line 1, in <module>\nNameError: name 'undefined_variable' is not defined\n"
}

Important Notes:

  • Automatic Frame Detection: When frameId is not provided, the tool automatically gets the current frame from the stack trace
  • Side Effects Are Allowed: Expressions CAN modify program state (e.g., x = 100). This is intentional and useful for debugging
  • Session Must Be Paused: The debugger must be stopped at a breakpoint for evaluation to work
  • Results Are Strings: All results are returned as strings, even for numeric types
  • Python Truncation: Python/debugpy automatically truncates collections at 300 items for performance

get_source_context

Gets source code context around a specific line in a file.

Parameters:

  • sessionId (string, required): The ID of the debug session.
  • file (string, required): Path to the source file (absolute or relative to project root).
  • line (number, required): Line number to get context for (1-indexed).
  • linesContext (number, optional): Number of lines before and after to include (default: 5).

Response:

{
  "success": true,
  "file": "C:\\path\\to\\script.py",
  "line": 15,
  "lineContent": "    result = calculate_sum(x, y)",
  "surrounding": [
    { "line": 12, "content": "def main():" },
    { "line": 13, "content": "    x = 10" },
    { "line": 14, "content": "    y = 20" },
    { "line": 15, "content": "    result = calculate_sum(x, y)" },
    { "line": 16, "content": "    print(f\"Result: {result}\")" },
    { "line": 17, "content": "    return result" },
    { "line": 18, "content": "" }
  ],
  "contextLines": 3
}

Example:

{
  "sessionId": "a4d1acc8-84a8-44fe-a13e-28628c5b33c7",
  "file": "test_script.py",
  "line": 25,
  "linesContext": 3
}

Notes:

  • Useful for AI agents to understand code structure without reading entire files
  • Returns the requested line content and surrounding context
  • Handles file boundaries gracefully (won't return lines before 1 or after EOF)
  • Uses efficient line reading with LRU caching for performance

Additional Tools

The following tools are also available but are not fully documented with examples here:

  • list_supported_languages: Lists all supported debugging languages with metadata (installed status, display name, default executable). Takes no parameters.
  • attach_to_process: Attaches the debugger to a running process. Parameters include sessionId, processId or connection details, and adapter-specific attach configuration.
  • detach_from_process: Detaches the debugger from an attached process. Parameters include sessionId and optional terminateProcess flag.
  • list_threads: Lists all threads in the debug session. Parameters include sessionId.

Language-Specific Tools

redefine_classes

Hot-swap changed Java classes into a running JVM using JDI VirtualMachine.redefineClasses(). Java only.

Parameters:

  • sessionId (string, required): The debug session ID (must be an active Java session)
  • classesDir (string, required): Absolute path to compiled classes directory (e.g., build/classes/java/main/)
  • sinceTimestamp (number, optional): Unix timestamp in milliseconds. Only redefine .class files modified after this time. 0 or omitted = scan all files.

Response:

{
  "success": true,
  "redefined": ["com.example.Foo", "com.example.Bar"],
  "redefinedCount": 2,
  "skippedNotLoaded": 3,
  "failedCount": 1,
  "failed": [
    { "fqcn": "com.example.Baz", "error": "UnsupportedOperationException: class redefinition failed: attempted to add a method" }
  ],
  "scannedFiles": 6,
  "newestTimestamp": 1711500000000
}

Example — full scan:

{
  "sessionId": "abc-123",
  "classesDir": "/project/build/classes/java/main"
}

Example — incremental scan (pass newestTimestamp from previous call):

{
  "sessionId": "abc-123",
  "classesDir": "/project/build/classes/java/main",
  "sinceTimestamp": 1711500000000
}

Notes:

  • Only works with Java debug sessions (requires JDI support)
  • Classes must already be loaded in the target JVM — unloaded classes are skipped (skippedNotLoaded)
  • Schema changes (adding/removing methods or fields) will fail for individual classes without blocking others
  • The newestTimestamp in the response enables incremental workflows: recompile, then pass it as sinceTimestamp on the next call to only redefine newly modified files
  • The session can be paused or running when calling this tool

Error Handling

Tools can return errors in two formats:

  1. MCP transport errors: Standard JSON-RPC error responses with numeric error codes. These indicate protocol-level failures.
  2. Application-level failures: JSON payloads with { "success": false, "error": "..." }. Most tool failures use this format, where the HTTP/transport layer succeeds but the operation itself failed.

Common Error Codes (MCP transport errors)

  • -32603: Internal error (feature not implemented, session not found, etc.)
  • -32602: Invalid parameters

MCP Error Response Format

{
  "code": -32603,
  "name": "McpError",
  "message": "MCP error -32603: {specific error message}",
  "stack": "{stack trace}"
}

Application-Level Error Format

{
  "success": false,
  "error": "Session is not paused",
  "message": "Cannot get local variables. The session must be paused at a breakpoint."
}

Common Error Scenarios

  1. Session not found: Occurs when a session terminates unexpectedly
  2. Invalid language: Language must be one of the supported languages (discovered dynamically from installed adapters)
  3. File not found: When setting breakpoints in non-existent files
  4. Invalid scope: When passing wrong variablesReference to get_variables

Best Practices

  1. Always check session state before performing operations
  2. Use absolute paths for files to avoid ambiguity
  3. Get scopes before variables - you need the variablesReference
  4. Handle session termination gracefully - sessions can end unexpectedly
  5. Set breakpoints on executable lines - avoid comments and declarations

Last updated: 2026-03-18 based on source code review of mcp-debugger v0.19.0