The Debug MCP Server provides support for Go debugging through Delve (dlv), Go's native debugger with DAP (Debug Adapter Protocol) support. This document explains how to use the Go debugging capabilities.
Before using the Go debugging features, ensure you have:
- Go 1.18 or higher installed from go.dev/dl
- Delve 0.17.0+ installed with DAP support:
go install github.com/go-delve/delve/cmd/dlv@latest
Verify your installation:
go version # Should show 1.18 or higher
dlv version # Should show Delve version
dlv dap --help # Should show DAP help (confirms DAP support)First, create a Go debug session:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="create_debug_session",
arguments={
"language": "go",
"name": "My Go Debug Session"
}
)
This returns a session ID that you'll use for all subsequent debugging commands.
Before debugging, compile your Go program with debug symbols:
go build -gcflags="all=-N -l" -o myprogram main.goThe -gcflags="all=-N -l" flags disable optimizations and inlining, which are required for accurate debugging.
Set breakpoints in your code before starting execution:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="set_breakpoint",
arguments={
"sessionId": "your-session-id",
"file": "/path/to/your/main.go",
"line": 15
}
)
You can also set conditional breakpoints:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="set_breakpoint",
arguments={
"sessionId": "your-session-id",
"file": "/path/to/your/main.go",
"line": 20,
"condition": "x > 10"
}
)
Start debugging your Go program. You can use different launch modes:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="start_debugging",
arguments={
"sessionId": "your-session-id",
"scriptPath": "/path/to/your/main.go",
"dapLaunchArgs": {
"mode": "debug",
"program": "/path/to/your/main.go",
"stopOnEntry": false
}
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="start_debugging",
arguments={
"sessionId": "your-session-id",
"scriptPath": "/path/to/your/compiled/binary",
"dapLaunchArgs": {
"mode": "exec",
"program": "/path/to/your/compiled/binary"
}
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="start_debugging",
arguments={
"sessionId": "your-session-id",
"scriptPath": "/path/to/your/test/directory",
"dapLaunchArgs": {
"mode": "test",
"program": "/path/to/your/test/directory"
}
}
)
When execution pauses at a breakpoint, you can:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="step_over",
arguments={
"sessionId": "your-session-id"
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="step_into",
arguments={
"sessionId": "your-session-id"
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="step_out",
arguments={
"sessionId": "your-session-id"
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="continue_execution",
arguments={
"sessionId": "your-session-id"
}
)
When paused, you can examine the program's state:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="get_local_variables",
arguments={
"sessionId": "your-session-id"
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="get_stack_trace",
arguments={
"sessionId": "your-session-id"
}
)
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="evaluate_expression",
arguments={
"sessionId": "your-session-id",
"expression": "x + y * 2"
}
)
When finished debugging, close the session:
use_mcp_tool(
server_name="debug-mcp-server",
tool_name="close_debug_session",
arguments={
"sessionId": "your-session-id"
}
)
Delve supports several launch modes:
debug: Compile and debug a main packagetest: Compile and debug a test binaryexec: Debug a pre-compiled binaryreplay: Replay a recorded tracecore: Debug a core dump
Go programs use goroutines for concurrency. Delve natively handles goroutines, and the MCP tools reflect this:
- Stack traces show the goroutine context for each frame
- Internal runtime and testing frames (paths containing
/runtime/or/testing/) are filtered out by default (useincludeInternals: trueinget_stack_traceto see them) - Variable inspection works within the current goroutine's stack frame
Note: The MCP tools do not expose goroutine-specific commands (listing goroutines, switching between goroutines, or setting goroutine-scoped breakpoints). These are Delve-internal capabilities not surfaced through the MCP tool interface.
The Go adapter supports exception breakpoints with two built-in filters: panic (break on panic, enabled by default) and fatal (break on fatal errors, enabled by default). These are declared in the adapter's capabilities and sent to Delve during session configuration. Custom exception breakpoint configuration can also be provided via dapLaunchArgs.
- Always build with debug flags: Use
-gcflags="all=-N -l"to disable optimizations - Absolute paths: Use absolute paths for file references in breakpoints
- Internal frame filtering: Frames from Go runtime/testing paths are filtered by default for cleaner stack traces
- Stop on entry: Delve has a quirk with "unknown goroutine 1" --
stopOnEntry=falseis a global session-manager default (not Go-specific), but the Go adapter policy also enforces this default to avoid Delve's goroutine issue when the user has not explicitly specifiedstopOnEntry - Variable inspection: Delve's DAP output automatically dereferences pointers, and represents slices with length/capacity and maps as key-value pairs
- Test debugging: Use
mode: "test"to debug Go test functions
Here's a complete example debugging a simple Go program:
// main.go
package main
import "fmt"
func main() {
x := 10
y := 20
sum := add(x, y)
fmt.Printf("Sum: %d\n", sum)
}
func add(a, b int) int {
return a + b
}-
Build with debug symbols:
go build -gcflags="all=-N -l" -o myprogram main.go -
Create debug session with
language: "go" -
Set breakpoint at line 7 (inside
main) -
Start debugging with
mode: "exec"andprogram: "./myprogram" -
Step through the code and inspect variables
- Ensure Delve is installed:
go install github.com/go-delve/delve/cmd/dlv@latest - Check that
dlvis in your PATH:which dlv - Verify DAP support:
dlv dap --help
- Ensure Go 1.18+ is installed:
go version - Check that
gois in your PATH:which go
- Ensure you built with
-gcflags="all=-N -l" - Use absolute paths for file references
- Check that the line number corresponds to an executable statement
- This is a Delve quirk when
stopOnEntry=true - The adapter defaults
stopOnEntry=falseto avoid this - If you need to stop on entry, the error is harmless and execution continues