Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/), and this
## [1.2.0] - 2026-06-04

### Added
- **`/debug` Agent Skill** — bundled companion skill at `skills/debug/` that encodes the systematic debugging workflow for AI agents. The skill is automatically copied into each configured harness's personal skills directory (e.g. `~/.copilot/skills/debug/`) when DebugMCP is registered, and can be invoked with `/debug` in supporting agents.
- **`/really-debug` Agent Skill** — bundled companion skill at `skills/really-debug/` that encodes the systematic debugging workflow for AI agents. The skill is automatically copied into each configured harness's personal skills directory (e.g. `~/.copilot/skills/really-debug/`) when DebugMCP is registered, and can be invoked with `/really-debug` in supporting agents. (Named `really-debug` rather than `debug` to avoid shadowing built-in `/debug` commands in some harnesses such as GitHub Copilot Chat.)
- **Robust test debugging via the VS Code Testing API** — `start_debugging` with a `testName` now discovers and launches the target test through the VS Code Testing API, producing reliable breakpoint hits across pytest, Jest/Vitest, Java, .NET, Go, and other Testing-API-integrated runners.

## [1.0.8] - 2025-03-14
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Let AI agents debug your code inside VS Code - set breakpoints, step through exe

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![VS Code](https://img.shields.io/badge/VS%20Code-1.104.0+-blue.svg)](https://code.visualstudio.com/)
[![Version](https://img.shields.io/badge/version-2.0.0-green.svg)](https://github.com/microsoft/DebugMCP)
[![Version](https://img.shields.io/badge/version-2.0.1-green.svg)](https://github.com/microsoft/DebugMCP)
[![VS Marketplace](https://img.shields.io/badge/VS%20Marketplace-Install-blue.svg)](https://marketplace.visualstudio.com/items?itemName=ozzafar.debugmcpextension)

> ⭐ **If you find DebugMCP useful, please [star the repo on GitHub](https://github.com/microsoft/DebugMCP)!** It helps others discover the project and motivates continued development.
Expand All @@ -19,7 +19,7 @@ Let AI agents debug your code inside VS Code - set breakpoints, step through exe

## ✨ What's New in 2.0.0

- **`/debug` Agent Skill** — DebugMCP now ships a companion [Agent Skill](./skills/debug/SKILL.md) that is auto-installed into each configured harness's personal skills directory (e.g. `~/.copilot/skills/debug/`). Invoke it with `/debug` in supporting agents to load the systematic debugging workflow and trigger DebugMCP tools with the right context.
- **`/really-debug` Agent Skill** — DebugMCP now ships a companion [Agent Skill](./skills/really-debug/SKILL.md) that is auto-installed into each configured harness's personal skills directory (e.g. `~/.copilot/skills/really-debug/`). Invoke it with `/really-debug` in supporting agents to load the systematic debugging workflow and trigger DebugMCP tools with the right context.
- **Robust debugging via the VS Code Testing API** — `start_debugging` with a `testName` now uses the VS Code Testing API to discover and launch the test, replacing the previous best-effort path. This works reliably across language test runners that integrate with the Testing API (pytest, Jest/Vitest, Java, .NET, Go, etc.) and produces consistent breakpoint hits inside individual test cases.

## 🚀 Quick Install
Expand Down Expand Up @@ -67,7 +67,7 @@ DebugMCP is an MCP server that gives AI coding agents full control over the VS C
> **Note:** The MCP server intentionally exposes **tools only** — no procedural
> instructions, no documentation resources. Workflow guidance (when to debug, how to
> structure a root-cause investigation, language-specific quirks) lives in the companion
> [DebugMCP Agent Skill](./skills/debug/SKILL.md) so it can be loaded into an
> [DebugMCP Agent Skill](./skills/really-debug/SKILL.md) so it can be loaded into an
> agent's prompt context independently of the MCP capability surface.

### 🎯 Debugging Best Practices
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/debugMCPServer.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ AI Agent (MCP Client)

`DebugMCPServer` exposes **tools only**. Procedural workflow guidance (when to debug,
how to structure a root-cause investigation, language-specific quirks) lives in the
companion Agent Skill at `skills/debug/SKILL.md`, not in tool descriptions or MCP
companion Agent Skill at `skills/really-debug/SKILL.md`, not in tool descriptions or MCP
resources. This separation matches modern agent ecosystems where MCP servers provide
*capabilities* and skills provide *procedural knowledge* an agent loads as context.

Expand All @@ -58,7 +58,7 @@ Each request creates a new stateless `StreamableHTTPServerTransport` instance th
- Class definition: `src/debugMCPServer.ts`
- Tool registration: `setupTools()` method (uses `McpServer.registerTool()`)
- Server startup: `start()` method (creates express app with `/mcp` route)
- Agent Skill (companion, not part of the MCP surface): `skills/debug/SKILL.md`
- Agent Skill (companion, not part of the MCP surface): `skills/really-debug/SKILL.md`

## Exposed Tools

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "debugmcpextension",
"displayName": "DebugMCP",
"description": "Let AI agents debug your code inside VS Code — breakpoints, step-through execution, variable inspection, and expression evaluation. Automatically exposes itself as an MCP (Model Context Protocol) server for seamless integration with AI assistants.",
"version": "2.0.0",
"version": "2.0.1",
"publisher": "ozzafar",
"author": {
"name": "Oz Zafar",
Expand Down
63 changes: 63 additions & 0 deletions skills/really-debug/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# DebugMCP Skill

This folder is a self-contained **Agent Skill** that teaches an AI agent how to use the
DebugMCP MCP server effectively. It follows the Anthropic-style Skills convention: a
`SKILL.md` entry point with YAML frontmatter, plus bundled reference docs.

## Why this is separate from the MCP server

The DebugMCP MCP server exposes only **tools** (with brief, behavioral descriptions).
All workflow guidance — when to debug, how to structure a root-cause investigation,
which breakpoints to set, language-specific quirks — lives in this skill, not in tool
descriptions.

This separation matches modern agent ecosystems where:
- **MCP servers** = capabilities (tools, resources, prompts)
- **Skills** = procedural knowledge an agent loads as context

## Contents

```
skills/debugmcp/
├── SKILL.md # Entry point + workflow + root cause framework
├── README.md # This file
└── references/
└── troubleshooting/
├── python.md
├── javascript.md
├── java.md
├── csharp.md
├── cpp.md
└── go.md
```

## Installation

How you install a skill depends on your agent runtime. Common patterns:

- **Anthropic / Claude API with the Skills feature** — point the runtime at this folder
(or vendor the folder into your project) and the agent will read `SKILL.md` and load
references on demand.
- **Claude Code** — drop this folder under your project's configured skills directory.
- **Cursor / Cline / other clients without native skills support** — copy the contents
of `SKILL.md` into a project rule / system prompt, and keep the `references/` files
available for the agent to read on request.

Refer to your client's documentation for the exact path / mechanism.

## Tool naming

The `allowed-tools` list in `SKILL.md` uses the raw tool names registered by the
DebugMCP MCP server (`start_debugging`, `add_breakpoint`, etc.). Some runtimes namespace
MCP tools (e.g. `mcp__debugmcp__start_debugging`). Adapt the list to whatever convention
your runtime uses, or omit `allowed-tools` if the runtime doesn't honor it.

## Prerequisites

You also need:

1. The DebugMCP VS Code extension installed and running (it starts an MCP server on
`http://127.0.0.1:3001/mcp` by default).
2. The language extension for whatever you're debugging (Python, C# Dev Kit, Java
Extension Pack, etc. — see the per-language reference for specifics).
3. Your AI agent runtime configured to connect to that MCP endpoint.
239 changes: 239 additions & 0 deletions skills/really-debug/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
---
name: really-debug
description: Drive an interactive VS Code debugger to investigate bugs, failing tests, wrong/null variable values, unexpected runtime behavior, and other "it doesn't work" reports. Use this skill whenever speculation about runtime behavior would be cheaper to *verify* by stepping through the code than to reason about. Pairs with the DebugMCP MCP server, which exposes the underlying breakpoint / step / inspect tools.
license: MIT
allowed-tools:
- add_breakpoint
- remove_breakpoint
- clear_all_breakpoints
- list_breakpoints
- start_debugging
- stop_debugging
- restart_debugging
- step_over
- step_into
- step_out
- continue_execution
- get_variables_values
- evaluate_expression
---

# DebugMCP — Interactive Debugging Skill

This skill teaches an agent how to use the DebugMCP MCP server effectively. The MCP server
itself exposes only tools (with brief, behavioral descriptions); the *workflow*, *root cause
analysis framework*, and *language-specific guidance* live here.

> The `allowed-tools` list above uses the tool names registered by the DebugMCP MCP server.
> Some runtimes namespace MCP tools (e.g. `mcp__debugmcp__start_debugging`); adapt as needed.

---

## When to invoke this skill

Reach for this skill whenever you would otherwise *guess* at runtime behavior:

- Any reported bug, failing test, exception, or unexpected output.
- A variable holds an unexpected `null` / `undefined` / wrong type / wrong value.
- A function returns something the caller didn't expect.
- A code path executes (or fails to execute) when you didn't predict it would.
- You're about to read a large amount of code "trying to figure out what happens at runtime."

If you can step through the code in a few tool calls, do that instead of speculating.

---

## Core workflow

1. **Set a starting breakpoint.** Use `add_breakpoint` with the file path and the exact
line content you want to pause on (line content matching is more robust than line
numbers — it survives small edits). Place it at the earliest point that's still
relevant to the suspected issue.
2. **Optionally add strategic breakpoints.** Decision points, error-handling branches,
data boundaries (where input enters, where output is produced).
3. **Start the session.** Call `start_debugging` with the source file path. For a single
test, pass `testName`; the server routes through VS Code's Testing API so test runners
like `dotnet test` / `pytest` / `jest` work correctly. The call returns when the
program either hits a breakpoint (`stopped`) or runs to completion without pausing
(`terminated`).
4. **Navigate and inspect.** Use `step_over`, `step_into`, `step_out`, `continue_execution`
to move through code. Use `get_variables_values` to see local/global state and
`evaluate_expression` to test hypotheses live (call methods, read properties, run
list comprehensions, etc.).
5. **Find the root cause** (see framework below). Don't stop at the first wrong thing
you see — trace it back to *why*.
6. **Clean up.** Call `clear_all_breakpoints` when you're done so you don't pollute the
next session, and `stop_debugging` if the session is still active.

---

## 🚨 Root cause analysis framework

### Never stop at symptoms — always find the root cause

When you encounter an issue during debugging (null variable, unexpected value, thrown
error, wrong branch taken), apply this systematic approach.

#### Symptom vs root cause

- **Symptom:** what you observed is wrong (e.g. "variable `user` is null").
- **Root cause:** *why* the symptom occurred (e.g. "`user` is null because `getUserById()`
returned null because the DB query failed because the connection string in
`appsettings.json` points at the wrong host").

#### Investigation process

1. **Identify the symptom.** What exactly is wrong? Which line, which variable, which
thrown exception? Record the current state.
2. **Ask "why?"** Why is this value wrong? Why did this function return this? Why did
this condition evaluate this way?
3. **Trace backwards.** Set a breakpoint *before* the symptom, restart, and step
forward to watch where the wrong state first appears.
4. **Repeat until you reach the origin.** Keep asking "why" until you hit a fundamental
cause — usually where data enters the system, a config is read, or an assumption
is first violated.

#### ⚠️ Warning signs you're stopping too early

- You found a `null` / `undefined` variable but didn't check why it's that way.
- You see an error but didn't trace where it originates.
- You identified "bad data" but didn't find why the data is bad.
- You found a failing condition but didn't check why it fails.

#### ✅ Signs you've found the root cause

- You can explain the complete chain from root cause → symptom.
- Fixing this one thing would prevent the symptom from occurring.
- The issue is at a fundamental level (data input, configuration, logic invariant).
- You understand not just *what* is wrong but *why* it's wrong.

---

## Practical examples

### Example 1 — Null variable
❌ **Symptom-only:** "The `user` object is null on line 45."
✅ **Root cause:** "`user` is null because `getUserById()` returned null because the DB
query failed because the connection string is incorrect in the configuration file."

**Investigation:**
1. `user` is null → set breakpoint in `getUserById()`.
2. `getUserById()` returns null → set breakpoint inside the function.
3. DB query fails → check connection parameters.
4. Connection string wrong → root cause identified.

### Example 2 — Function exits early
❌ **Symptom-only:** "`processOrder()` exits early due to invalid payment status."
✅ **Root cause:** "`processOrder()` exits early because payment validation fails when
the payment service doesn't receive the required `currency` field, which wasn't
included in the request due to a missing form field in the UI."

**Investigation:**
1. Function exits early → breakpoint at validation check.
2. Payment status invalid → debug payment validation logic.
3. `currency` missing → trace back to request formation.
4. UI form missing `currency` field → root cause identified.

### Example 3 — Unexpected value
❌ **Symptom-only:** "Calculation result is `NaN`."
✅ **Root cause:** "The result is `NaN` because one input is a string instead of a
number, because `parseFloat()` fails when the input contains currency symbols that
weren't stripped by the sanitization function."

**Investigation:**
1. Result is `NaN` → check input parameters.
2. Parameter is a string → find where conversion should happen.
3. `parseFloat()` fails → check what's being parsed.
4. Currency symbols not stripped → root cause identified.

---

## Root cause investigation checklist

Before ending the debug session, confirm you can answer:

- [ ] What is the immediate symptom?
- [ ] What function / code caused this symptom?
- [ ] What input or condition caused that function to behave incorrectly?
- [ ] Where did that input or condition originate?
- [ ] Can I trace this back further to a more fundamental cause?
- [ ] If I fix this root cause, will it prevent the symptom from occurring?

---

## Breakpoint strategy

- **Start broad, then narrow.** Begin at the entry point of the suspect function. As
you isolate the issue, add tighter breakpoints around the problematic region.
- **Match line content, not numbers.** `add_breakpoint` takes the exact line text so
breakpoints survive small edits and refactors.
- **Don't overuse breakpoints.** A handful of well-placed pauses beats dozens of noisy
ones. After each session, `clear_all_breakpoints` to start fresh.
- **For test debugging,** pass `testName` to `start_debugging`. The server routes through
VS Code's Testing API so test runners (`dotnet test`, `pytest`, `jest`, etc.) are
driven correctly and the debugger attaches to the child test-host process.

---

## Tool-call patterns

### Investigating a bug in `calculate.py`
```text
add_breakpoint fileFullPath=/repo/src/calculate.py lineContent="result = parse(raw)"
start_debugging fileFullPath=/repo/src/calculate.py workingDirectory=/repo
# session pauses on the breakpoint
get_variables_values scope=local
evaluate_expression expression="type(raw).__name__"
step_into
# … iterate until root cause found …
clear_all_breakpoints
```

### Debugging a single xUnit test in C#
```text
add_breakpoint fileFullPath=C:\Repo\Calculator.Tests\CalculatorTests.cs lineContent="Assert.Equal(5, _calc.Add(2, 3));"
start_debugging fileFullPath=C:\Repo\Calculator.Tests\CalculatorTests.cs workingDirectory=C:\Repo testName=Add_ReturnsSum
# pauses inside the test
step_into
get_variables_values
```

### Verifying a fix without re-launching VS Code
```text
restart_debugging
# session restarts with the same configuration; breakpoints persist
continue_execution
```

---

## Language-specific guidance

Load the relevant reference file for the language you're debugging:

- **Python** → `references/troubleshooting/python.md`
- **JavaScript / TypeScript** → `references/troubleshooting/javascript.md`
- **Java** → `references/troubleshooting/java.md`
- **C#** → `references/troubleshooting/csharp.md`
- **C++** → `references/troubleshooting/cpp.md`
- **Go** → `references/troubleshooting/go.md`

Each reference covers prerequisites (which VS Code extension to install), framework-specific
configuration (e.g. enabling `pytest` test discovery, building `.NET` projects before
launch), and common pitfalls.

---

## Things to avoid

- ❌ **Speculating about runtime values when you could just inspect them.** That's what
`get_variables_values` and `evaluate_expression` are for.
- ❌ **Calling `start_debugging` without first setting a breakpoint.** The program will
run to completion and you'll learn nothing.
- ❌ **Stopping at the first wrong value you find.** That's a symptom. Trace it back.
- ❌ **Leaving breakpoints set across sessions.** Future runs will pause in unexpected
places. Always `clear_all_breakpoints` when done.
- ❌ **Awaiting interactive input when the program reads stdin.** DebugMCP drives the
VS Code debugger; if the program blocks on stdin, no tool call can unblock it. Pick
a code path that doesn't require interactive input, or pre-supply input via the
launch config / fixture.
Loading
Loading