feat: ship a Claude Code plugin and host a marketplace for it (#88)

Installing mcp-windbg into Claude Code meant a `pip install` plus a
hand-written server registration with an env var. It becomes two lines:

```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```

This repo hosts the marketplace itself, so there is no second repository
to keep in step.

## Why there is no install step at all

The plugin launches the server with `uvx`, pinned to the matching
release, so uv fetches it from PyPI on first use. That is what makes the
two lines *complete* rather than the last two of five. `server.json`
already declared `runtimeHint: uvx`, so this is how the package
presented itself anyway.

## What ships

- The ten tools, through the plugin's `.mcp.json`.
- **`/mcp-windbg:analyze-dump`** - crash-dump triage that separates fact
from inference and calls out missing symbols rather than reading meaning
into `module+0x1234`.
- **`/mcp-windbg:debug-remote`** - attaching to a user-mode debug
server, and the part that is easy to get wrong by hand: saying plainly
whether the target was left running or frozen.
- **`/mcp-windbg:kernel-debug`** - driving a live kernel target,
including the `g` / `wait_for_break` / `send_ctrl_break` handling from
1.1.0, and closing with `resume: true` so nobody leaves a machine
halted.
- **`/mcp-windbg:windbg-doctor`** - the first thing to run when nothing
works: checks platform, CDB, uv, the `uvx` round trip, and symbols, then
reports what to fix rather than one failure at a time.
- **`crash-analyst`** agent - hand it a dump and a question and it
investigates on its own, returning a verdict, the evidence behind it,
what it ruled out, and what to do next. Its `tools:` list uses the
scoped `mcp__plugin_mcp-windbg_mcp-windbg__*` names.
- A [reference
page](https://github.com/svnscha/mcp-windbg/blob/feat/claude-plugin/docs/reference/plugin.md)
in the docs site, plus plugin sections in the README, getting-started,
and client configuration.

Always-on cost is about 400 tokens; a skill or the agent costs more only
when it fires.

## Symbols are configured, without overriding yours

The plugin sets `_NT_SYMBOL_PATH` as a **default**, not a value:

```json
"_NT_SYMBOL_PATH": "${_NT_SYMBOL_PATH:-SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols}"
```

Claude Code's `.mcp.json` expansion supports `${VAR:-default}`, so an
existing value wins and a symbol path someone tuned themselves is never
overwritten. Without this the out-of-the-box experience is a stack of
`module+0x1234` offsets, which is exactly the case where triage is
guesswork.

## One thing that cannot be declared

**Windows-only.** There is no manifest field for a platform constraint,
so installing on macOS or Linux loads the plugin and the server then
fails to find a debugger. Stated in the plugin README, the marketplace
description, and the reference page; `windbg-doctor` catches it at the
first check and stops there.

## Version drift, closed

release-please now bumps the plugin manifest, the marketplace entry, and
the `uvx` pin along with `pyproject.toml` and `server.json`, and
`check-version-consistency.ps1` checks all three. That is the guard that
a silently-broken `extra-files` entry does not ship - the exact failure
caught by hand during the 1.1.0 release.

The `uvx` pin survives the bump because release-please's `generic-json`
updater does a substring replace against its version regex rather than
overwriting the whole value, so `mcp-windbg@1.1.0` becomes
`mcp-windbg@1.2.0` and not a bare `1.2.0`.

## A bug fixed on the way

`check-version-consistency.ps1` looped with `foreach ($error in
$errors)`. `$error` is a **read-only PowerShell automatic variable**, so
the first time it had a mismatch to report it threw `Cannot overwrite
variable Error` instead of naming the files. The build still failed, so
this was never dangerous - just useless exactly when you needed it.
Verified both ways now: it names the mismatching file, and still exits
1.

## Dependencies

Floors raised to current releases with the major caps unchanged: `mcp`
2.1.1, `starlette` 1.6.0, `uvicorn` 0.52.4, and `pymdown-extensions`
11.0.2 for the docs build. `uv.lock` is regenerated; it had been
stranded at 1.0.1 since the 1.1.0 release, because release-please has no
updater for it. A `uv lock --check` step in CI would catch that drift
and is worth a follow-up.

## Verification

- `claude plugin validate` passes for both the marketplace manifest and
the plugin manifest.
- Full suite green against the upgraded dependencies: 99 passed, 2
skipped (the kernel scenarios, no target attached). Live CDB scenarios
ran.
- `validate-server-schema.py` passes; `uv lock --check` reports the lock
in sync.
- The `.mcp.json` snippet on the reference page is asserted to parse and
to equal the real file, after it shipped with a single-backslash
`C:\Symbols` that did neither.
- The earlier end-to-end check (`claude plugin marketplace add` ->
`install` -> `details`, and a headless session seeing the tools through
`uvx` with nothing pre-installed) was run when the plugin had two skills
and no agent, so it predates the current surface.

## Note

You already have a `svnscha` marketplace pointing at
`svnscha/claude-plugins`. This adds a second, repo-local one. If you
would rather have the plugin listed there instead, say so - the plugin
directory moves as-is and only the marketplace manifest changes.
This commit is contained in:
Sven Scharmentke
2026-08-27 20:08:07 +02:00
committed by GitHub
parent fdc3b98270
commit 90457306fe
21 changed files with 1194 additions and 421 deletions
+25
View File
@@ -0,0 +1,25 @@
{
"name": "mcp-windbg",
"owner": {
"name": "Sven Scharmentke",
"url": "https://github.com/svnscha"
},
"description": "Windows crash dump analysis and live WinDbg debugging for Claude Code.",
"plugins": [
{
"name": "mcp-windbg",
"source": "./plugins/mcp-windbg",
"description": "Analyze Windows crash dumps and drive live user-mode or kernel debugging through WinDbg/CDB. Windows only; needs CDB and uv.",
"version": "1.1.0",
"author": {
"name": "Sven Scharmentke",
"url": "https://github.com/svnscha"
},
"homepage": "https://svnscha.github.io/mcp-windbg/",
"repository": "https://github.com/svnscha/mcp-windbg",
"license": "MIT",
"keywords": ["debugging", "windbg", "cdb", "kd", "crash-dump", "kernel", "windows"],
"category": "development"
}
]
}
+41
View File
@@ -5,6 +5,47 @@ All notable changes to the MCP Server for WinDbg Crash Analysis project will be
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- **A Claude Code plugin, and a marketplace to serve it from this repo** - installing is now two
lines with no `pip install` and no MCP configuration to hand-edit:
```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```
The plugin launches the server with `uvx`, which fetches the pinned version from PyPI on first
use, so the only prerequisites are Windows, CDB, and uv.
It ships the ten tools, four skills - `analyze-dump`, `debug-remote`, `kernel-debug`, and
`windbg-doctor` for diagnosing a machine that cannot debug - and a `crash-analyst` agent that
investigates a dump on its own and returns a verdict with its evidence, what it ruled out, and
what to do next. Always-on context cost is about 400 tokens; a skill or agent costs more only
when it fires.
Symbols work out of the box: the plugin supplies the Microsoft symbol server as a *default* for
`_NT_SYMBOL_PATH`, and an existing value wins over it, so a symbol path you tuned yourself is
never overwritten.
### Changed
- **Dependency floors raised to current releases** - `mcp` 2.1.1, `starlette` 1.6.0, `uvicorn`
0.52.4, and `pymdown-extensions` 11.0.2 for the docs build. The major-version caps are
unchanged, and `uv.lock` is regenerated to match; it had been left at 1.0.1 since the 1.1.0
release, because release-please has no updater for it.
### Fixed
- **The version-consistency check reports mismatches instead of crashing on them** - it looped
with `foreach ($error in $errors)`, and `$error` is a read-only PowerShell automatic variable,
so the moment it had something to report it threw "Cannot overwrite variable Error" and lost
the diagnostic. The build still failed, but never said which files disagreed. It now also
covers the plugin manifest, the marketplace entry, and the server version pinned in the
plugin's `.mcp.json`.
## [1.1.0] - 2026-08-22
### Changed
+16 -2
View File
@@ -70,7 +70,21 @@ Parameters, timeouts, and the built-in triage prompts are in the [tools referenc
> [!TIP]
> In enterprise environments, MCP server usage might be restricted by organizational policies. Check with your IT team about AI tool usage and ensure you have the necessary permissions before proceeding.
**Install**
**Claude Code - install the plugin.** This is the shortest path: no `pip install`, no MCP
config to edit. It brings the ten tools, four skills (`analyze-dump`, `debug-remote`,
`kernel-debug`, `windbg-doctor`) and a `crash-analyst` agent that investigates a dump on its own
and reports back.
```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```
The plugin launches the server with [uv](https://docs.astral.sh/uv/)'s `uvx`, which fetches the
pinned version from PyPI on first use. See the [plugin
README](plugins/mcp-windbg/README.md) for symbols setup and how to run it without uv.
**Any other client - install the package**
```bash
pip install mcp-windbg
@@ -78,7 +92,7 @@ pip install mcp-windbg
**Configure your client.** The two most common setups are below; see the [client configuration guide](https://svnscha.github.io/mcp-windbg/reference/clients/) for Claude Desktop, Copilot CLI, Autohand Code, HTTP, and from-source.
Claude Code - register the server from the command line:
Claude Code - if you did not use the plugin above, register the server directly:
```bash
claude mcp add mcp-windbg -s user -e _NT_SYMBOL_PATH="SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols" -- python -m mcp_windbg
+9 -4
View File
@@ -5,12 +5,17 @@ GitHub Copilot. Other clients work the same way once the server is configured, s
[Client configuration](reference/clients.md).
!!! tip "Using Claude Code?"
Skip the VS Code steps - register the server with one command and jump straight to
[Analyze your first dump](#4-analyze-your-first-dump):
Skip the VS Code steps and install the [plugin](reference/plugin.md) instead. There is no
`pip install` and nothing to configure - symbols included:
```bash
claude mcp add mcp-windbg -s user -e _NT_SYMBOL_PATH="SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols" -- python -m mcp_windbg
```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```
Then jump to [Analyze your first dump](#4-analyze-your-first-dump), or just run
`/mcp-windbg:analyze-dump`. You still need the prerequisites in step 1, plus
[uv](https://docs.astral.sh/uv/).
## 1. Check the prerequisites
+23
View File
@@ -13,6 +13,29 @@ server. Adjust the path or add more locations as needed. For running from a chec
## Claude Code
### The plugin (recommended)
The [plugin](https://github.com/svnscha/mcp-windbg/tree/main/plugins/mcp-windbg) is the shortest
path. It needs no `pip install` and no MCP configuration:
```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```
Alongside the ten tools you get four skills - `/mcp-windbg:analyze-dump`,
`/mcp-windbg:debug-remote`, `/mcp-windbg:kernel-debug`, and `/mcp-windbg:windbg-doctor` for
diagnosing a setup that will not work - plus a `crash-analyst` agent that investigates a dump on
its own and reports a verdict with its evidence. The plugin runs the server with `uvx`, so it needs
[uv](https://docs.astral.sh/uv/) on `PATH`; it pins the server version so the plugin and the
server it drives stay in step.
Symbols work out of the box: the plugin supplies the Microsoft symbol server as a **default**
for `_NT_SYMBOL_PATH`. If you already have that variable set, your value wins and the default is
ignored, so a symbol path you tuned yourself is never overwritten.
### Registering the server directly
Register the server with `claude mcp add`. The `-s user` scope makes it available in every
project; drop it to scope the server to the current project only. Everything after `--` is
the command Claude Code runs:
+2
View File
@@ -7,6 +7,8 @@ The precise, lookup-style reference for `mcp-windbg`.
- **[Tools](tools.md)** - the MCP tools the server exposes, their parameters, and the
WinDbg commands that come up most often.
- **[Prompts](prompts.md)** - the built-in `dump-triage`, `remote-triage`, and `kernel-triage` prompts.
- **[Claude Code plugin](plugin.md)** - the one-command install for Claude Code, and the
skills and agent it brings with it.
- **[Client configuration](clients.md)** - configuration snippets for VS Code, Claude
Desktop, and GitHub Copilot CLI, plus pip and from-source installs.
+124
View File
@@ -0,0 +1,124 @@
# Claude Code plugin
The plugin is the shortest way to use mcp-windbg from Claude Code. It brings the
[tools](tools.md), a set of skills, and an agent, and it needs no `pip install` and no MCP
configuration.
## Install
```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```
The first line registers this repository as a plugin marketplace; the second installs the plugin
from it. Restart Claude Code if the tools do not appear straight away.
## What you get
All ten [tools](tools.md), plus:
| Skill | What it does |
| :---- | :----------- |
| `/mcp-windbg:analyze-dump` | Triage a crash dump - exception, faulting frame, and what the evidence supports |
| `/mcp-windbg:debug-remote` | Attach to a running process through a WinDbg debug server |
| `/mcp-windbg:kernel-debug` | Drive a live kernel target, including resuming it and waiting for a break |
| `/mcp-windbg:windbg-doctor` | Check whether this machine can debug at all, and what to fix |
And one agent:
- **`crash-analyst`** investigates a dump on its own and reports back a verdict, the evidence
behind it, what it ruled out, and what to do next. Use it when a dump needs more than a first
look, or to keep a long analysis out of your main conversation.
Ask for it by name: *"use the crash-analyst agent on C:\dumps\app.dmp"*.
## Requirements
- **Windows.** The server drives `cdb.exe` and `kd.exe`. A plugin manifest has no field for
declaring a platform, so this is not enforced at install time - on macOS or Linux the plugin
loads and the server then fails to find a debugger.
- **Debugging Tools for Windows**, for `cdb.exe`. Install [WinDbg](https://aka.ms/windbg) from the
Microsoft Store, or the Windows SDK.
- **[uv](https://docs.astral.sh/uv/)**, which provides `uvx`. This is the one prerequisite the
plugin cannot supply for you: `winget install astral-sh.uv`.
Run `/mcp-windbg:windbg-doctor` if you are unsure - it checks all three and tells you what is
missing.
## How it runs the server
The plugin does not require the package to be installed. It launches the server with `uvx`,
pinned to the release that matches the plugin version:
```json title="plugins/mcp-windbg/.mcp.json"
{
"mcpServers": {
"mcp-windbg": {
"command": "uvx",
"args": ["mcp-windbg@1.1.0"],
"env": {
"_NT_SYMBOL_PATH": "${_NT_SYMBOL_PATH:-SRV*C:\\Symbols*https://msdl.microsoft.com/download/symbols}"
}
}
}
}
```
`uvx` fetches that version from PyPI on first use and caches it. Pinning keeps the plugin and the
server it drives in step, so a plugin update is what moves the server version.
## Symbols
Symbols work out of the box. The `${VAR:-default}` form above means:
- **No `_NT_SYMBOL_PATH` set** - the plugin supplies the Microsoft symbol server, caching to
`C:\Symbols`.
- **`_NT_SYMBOL_PATH` already set** - your value wins and the default is ignored. A symbol path
you tuned yourself is never overwritten.
To use your own, set it in the environment before starting Claude Code:
```powershell
setx _NT_SYMBOL_PATH "SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols;C:\my\pdbs"
```
`setx` only affects new processes, so restart the terminal. Check what the server actually
received with `/mcp`.
Without symbols, stacks resolve to `module+0x1234` and any analysis built on them is guesswork -
which is why the plugin defaults to something that works rather than to nothing.
## Passing other options
The [command-line options](cli.md) are set in the plugin's `.mcp.json` `args`. To add one - a
custom `--cdb-path`, a `--filter-script`, a longer `--timeout` - edit that file in the installed
plugin, or install the server directly instead (see
[Client configuration](clients.md#registering-the-server-directly)), which gives you full control
of the command line at the cost of the bundled skills and agent.
Note that editing the installed copy is overwritten when the plugin updates.
## Updating and removing
```
/plugin marketplace update mcp-windbg
/plugin update mcp-windbg@mcp-windbg
```
To remove it:
```
/plugin uninstall mcp-windbg@mcp-windbg
/plugin marketplace remove mcp-windbg
```
## Not using uv
Install the package yourself and register the server directly. You lose the skills and the agent,
but the tools are identical:
```powershell
pip install mcp-windbg
claude mcp add mcp-windbg -s user -e _NT_SYMBOL_PATH="SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols" -- python -m mcp_windbg
```
+1
View File
@@ -89,6 +89,7 @@ nav:
- Command-line options: reference/cli.md
- Tools: reference/tools.md
- Prompts: reference/prompts.md
- Claude Code plugin: reference/plugin.md
- Client configuration: reference/clients.md
- Troubleshooting: troubleshooting.md
- Development: development.md
@@ -0,0 +1,13 @@
{
"name": "mcp-windbg",
"description": "Analyze Windows crash dumps and drive live user-mode or kernel debugging through WinDbg/CDB.",
"version": "1.1.0",
"author": {
"name": "Sven Scharmentke",
"url": "https://github.com/svnscha"
},
"homepage": "https://svnscha.github.io/mcp-windbg/",
"repository": "https://github.com/svnscha/mcp-windbg",
"license": "MIT",
"keywords": ["debugging", "windbg", "cdb", "kd", "crash-dump", "kernel", "windows"]
}
+13
View File
@@ -0,0 +1,13 @@
{
"mcpServers": {
"mcp-windbg": {
"command": "uvx",
"args": [
"mcp-windbg@1.1.0"
],
"env": {
"_NT_SYMBOL_PATH": "${_NT_SYMBOL_PATH:-SRV*C:\\Symbols*https://msdl.microsoft.com/download/symbols}"
}
}
}
}
+98
View File
@@ -0,0 +1,98 @@
# mcp-windbg plugin
Windows crash dump analysis and live WinDbg debugging, inside Claude Code.
```
/plugin marketplace add svnscha/mcp-windbg
/plugin install mcp-windbg@mcp-windbg
```
That is the whole installation. There is no `pip install` step and no MCP config
to edit - the plugin launches the server with `uvx`, which fetches the pinned
version from PyPI on first use.
## What you get
Ten tools for driving `cdb.exe` and `kd.exe`:
| | |
| :-- | :-- |
| `list_dumps` | find crash dumps in a directory |
| `open_cdb_dump` | open a `.dmp` and triage it |
| `open_cdb_remote` | attach to a user-mode debug server |
| `open_kd_session` | attach to a kernel target (KDNET, pipe, serial) |
| `run_cdb_command` / `run_kd_command` | run any debugger command |
| `send_ctrl_break` / `wait_for_break` | halt a running target, or wait for it to stop |
| `close_cdb_session` / `close_kd_session` | release the target |
Four skills:
- **`/mcp-windbg:analyze-dump`** - triage a crash dump: exception, faulting frame,
and what the evidence does and does not support.
- **`/mcp-windbg:debug-remote`** - attach to a running process through a WinDbg
debug server and work out a hang or a live fault.
- **`/mcp-windbg:kernel-debug`** - drive a live kernel target, including resuming
the machine and waiting for a bugcheck or breakpoint.
- **`/mcp-windbg:windbg-doctor`** - check that this machine can debug at all
(CDB, uv, symbols) and explain what to fix. Start here when something fails.
And an agent:
- **`crash-analyst`** - hand it a dump and a question and it investigates on its
own, then reports a verdict with the evidence behind it, what it ruled out, and
what to do next. Worth using when a dump needs more than a first look, or when
you want the analysis kept out of your main conversation.
## Requirements
- **Windows.** The server drives `cdb.exe`/`kd.exe`, which are Windows-only.
There is no way to express that in a plugin manifest, so it is stated here:
installing on macOS or Linux will load the plugin, and the server will fail to
find a debugger.
- **CDB.** Install [WinDbg](https://aka.ms/windbg) from the Microsoft Store, or
the Windows SDK's Debugging Tools for Windows. The server finds it in the
usual locations; override with `--cdb-path` / `--kd-path` if yours is
elsewhere.
- **[uv](https://docs.astral.sh/uv/)**, which provides `uvx`. This is the one thing you must
install yourself; everything else the plugin handles. `winget install astral-sh.uv`, or see
[Not using uv](#not-using-uv) for the alternative.
## Symbols
Symbols are configured out of the box: if you have no `_NT_SYMBOL_PATH`, the plugin points the
debugger at the Microsoft symbol server and caches to `C:\Symbols`.
If you already have `_NT_SYMBOL_PATH` set, **yours wins** - the plugin only supplies a default,
so a symbol path you tuned yourself is never overwritten.
To use your own, set it in your environment before starting Claude Code:
```powershell
setx _NT_SYMBOL_PATH "SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols;C:\my\pdbs"
```
Restart the terminal afterwards - `setx` only affects new processes. To check what the server
actually received, run `/mcp` in Claude Code and inspect the `mcp-windbg` server.
Without symbols a stack is a list of `module+0x1234` offsets and triage is guesswork, which is
why this defaults to something that works rather than to nothing.
## Not using uv
The plugin pins the server version so the plugin and the server it drives stay
in lockstep. To run it a different way, install the package yourself and point
the config at it - edit `.mcp.json` in the installed plugin, or skip the plugin
and register the server directly:
```powershell
pip install mcp-windbg
claude mcp add mcp-windbg -s user -e _NT_SYMBOL_PATH="SRV*C:\Symbols*https://msdl.microsoft.com/download/symbols" -- python -m mcp_windbg
```
You lose the bundled skills that way, but the tools are identical.
## Links
- [Documentation](https://svnscha.github.io/mcp-windbg/)
- [Tool reference](https://svnscha.github.io/mcp-windbg/reference/tools/)
- [Issues](https://github.com/svnscha/mcp-windbg/issues)
@@ -0,0 +1,55 @@
---
name: crash-analyst
description: Deep-dive a Windows crash dump and return a written verdict. Use when a dump needs more than a first look - several hypotheses to rule out, many frames or threads to walk, or a conclusion someone will act on. Give it the dump path and the question.
tools: mcp__plugin_mcp-windbg_mcp-windbg__list_dumps, mcp__plugin_mcp-windbg_mcp-windbg__open_cdb_dump, mcp__plugin_mcp-windbg_mcp-windbg__run_cdb_command, mcp__plugin_mcp-windbg_mcp-windbg__close_cdb_session, Read, Grep, Glob
---
# Crash analyst
You investigate one Windows crash dump and report what actually went wrong. You
are working on someone else's behalf, and they see only your final message, so
it has to stand alone.
## How to work
Open the dump with `open_cdb_dump` and keep the `session_id`. Start with
`!analyze -v`, then follow the evidence rather than a fixed checklist. Typical
lines of enquiry:
- the exception record and context: `.exr -1`, `.ecxr`, `r`
- the stack, in more depth than a first look: `k`, `kb`, `kv`, `!uniqstack`
- whether the faulting module has symbols at all: `lm`, `lmvm <module>`
- the data the crash implicates: `dt`, `dx`, `db`/`dd`/`dps`, `!address`
- heap and handle state when the exception points that way: `!heap -p -a <addr>`,
`!handle`
Close the session with `close_cdb_session` when you are done.
## Standards
**Distinguish what the dump proves from what you infer.** "RCX is null at the
faulting instruction" is a fact. "This is a use-after-free" is a hypothesis.
Label them differently and say what would confirm the hypothesis.
**Rule things out explicitly.** If you considered stack corruption and the stack
is intact, say so. A reader who knows what you eliminated trusts what you kept.
**Treat missing symbols as a finding, not a result.** If the faulting module
resolves only to `module+0x1234`, say the analysis is limited by symbols and
name what would be needed, instead of inventing meaning from offsets.
**Do not pad.** If the dump only shows where the process died and not why, that
is the answer. Say what further data would settle it - a full-memory dump, a
repro under the debugger, `!analyze -v -hang` on a hang.
## Your final message
Structure it as:
1. **Verdict** - one or two sentences: what failed and why.
2. **Evidence** - the specific commands and output that support the verdict.
3. **Ruled out** - what you checked that turned out not to be the cause.
4. **Next steps** - what to do about it, or what to collect if unresolved.
Include the exact debugger commands you ran, so the reader can reproduce the
path you took.
@@ -0,0 +1,47 @@
---
name: analyze-dump
description: Triage a Windows crash dump - identify the exception, the faulting frame, and what to look at next. Use when the user points at a .dmp file or asks why a Windows process crashed.
---
# Analyze a Windows crash dump
Work through a `.dmp` file with the `mcp-windbg` tools and report what actually
crashed, not just what the debugger printed.
## Getting a dump path
If the user gave a path, use it. If not, call `list_dumps` to show what is in
the local crash dump directory and ask which one. Do not guess.
## Triage
1. `open_cdb_dump` with the path. Pass `include_stack_trace: true`; add
`include_modules` or `include_threads` only if the question calls for them.
Keep the returned `session_id` for every follow-up call.
2. `run_cdb_command` with `!analyze -v`. This is the single most informative
command and belongs in every triage.
3. Follow the evidence with further `run_cdb_command` calls. Useful next steps:
- `k` / `kb` for the call stack with arguments
- `lm` to see whether the faulting module has symbols
- `.exr -1`, `.ecxr` for the exception record and context
- `dt`, `dx`, `db`/`dd` to inspect the data the crash implicates
4. `close_cdb_session` when you are done.
## Reporting
Lead with the answer: what failed, where, and why, in the first two sentences.
Then support it - exception code and its meaning, the faulting frame, and the
specific evidence that points there.
Two things worth being explicit about:
- **Say when symbols are missing.** A stack full of `module+0x1234` is a
symbol problem, not an analysis result. Say so rather than reading meaning
into offsets, and mention `_NT_SYMBOL_PATH`.
- **Separate fact from inference.** "The access violation is at a null `this`
pointer" is a fact from the register state. "This is probably a use-after-free"
is a hypothesis - label it as one and say what would confirm it.
If the dump does not support a conclusion, say that. An honest "this dump only
shows the crash point, not the cause, and here is what would" is more useful
than a confident guess.
@@ -0,0 +1,59 @@
---
name: debug-remote
description: Attach to a running Windows process through a WinDbg debug server and inspect it live. Use when the user wants to debug a process on another machine, or one already under a .server session, rather than a crash dump.
---
# Debug a live user-mode process
Attach to an existing WinDbg/CDB **debug server** with the `mcp-windbg` tools.
This is user-mode only - for a kernel target use `/mcp-windbg:kernel-debug`.
## The other end
Someone must already be hosting the target. In WinDbg or CDB on that machine:
```
.server tcp:port=5005
```
If they have not, say so rather than guessing a connection string - there is
nothing to attach to yet.
## Connecting
`open_cdb_remote` with the connection string:
- TCP: `tcp:Port=5005,Server=hostname`
- Named pipe: `npipe:Pipe=pipename,Server=hostname`
The target is running when you attach, so the session may not be at a prompt.
`send_ctrl_break` halts it when you need it stopped.
## Working the target
`run_cdb_command` with the `session_id`:
- `~*k` for every thread's stack - the usual first move on a hang
- `!locks`, `!cs -l` for lock contention
- `lm`, `!peb` for what is loaded and how it started
- `bp`, `g`, `wait_for_break` to catch a code path in the act
- `.dump /ma <path>` to capture a dump for offline analysis
## Letting it run again
Attaching to a live process freezes it while broken in, and a frozen process is
usually worse than an unanalyzed one:
- `g` resumes and returns immediately; the target produces no output until it
stops again.
- `wait_for_break` blocks until it stops on its own.
- Any ordinary command breaks in automatically first.
`close_cdb_session` when finished. Say plainly whether the target was left
running or halted, so nobody discovers a frozen process an hour later.
## Reporting
For a hang, the answer is usually the relationship between threads, not a single
stack: which thread holds what, and which are waiting on it. Say that explicitly
rather than pasting `~*k` and leaving the reader to work it out.
@@ -0,0 +1,55 @@
---
name: kernel-debug
description: Attach to a live Windows kernel target over KDNET, a named pipe, or serial and drive it. Use when the user wants to debug a kernel, a driver, or a bugchecking VM.
---
# Debug a live Windows kernel target
Drive a kernel target with the `mcp-windbg` kd tools. A kernel session halts the
whole machine while it is broken in, so treat the target's running state as
something you are responsible for.
## Connecting
`open_kd_session` with the `-k` connection string:
- KDNET: `net:port=50000,key=1.2.3.4`
- Named pipe: `com:pipe,port=\.\pipe\com_1,baud=115200,reconnect`
- Serial: `com:port=COM1,baud=115200`
Ask for the string rather than guessing it. The session arrives already broken
in, so you can issue commands immediately.
## Working the target
`run_kd_command` with the `session_id`. Common ground:
- `vertarget`, `!pcr`, `lm m nt` to confirm what you are attached to
- `!process 0 0`, `!thread`, `!irp` for OS state
- `bp <module>!<symbol>` to set a breakpoint
- `!analyze -v` after a bugcheck
## Letting the machine run
This is where a kernel session differs from a dump, and where it is easy to
leave a machine frozen:
- `g` resumes the target and returns immediately. It does not wait, and it does
not produce output until the target stops again.
- `wait_for_break` blocks until the target stops on its own - a bugcheck, a
breakpoint, a manual break - and returns what the debugger printed.
- `send_ctrl_break` halts a running target now.
- Any ordinary command issued while the target runs breaks in automatically
first, and the reason it stopped leads that command's output.
A typical loop: set a breakpoint, `g`, tell the user to trigger the code path,
then `wait_for_break`.
## Finishing
`close_kd_session` with `resume: true` (the default) so the machine runs again.
Only pass `resume: false` when the user explicitly wants it left halted, and say
plainly that the machine will stay frozen until a debugger releases it.
If you set breakpoints, clear them with `bc *` before closing unless the user
wants them kept.
@@ -0,0 +1,53 @@
---
name: windbg-doctor
description: Check that this machine can actually debug - CDB present, uv available, symbols configured - and explain how to fix whatever is missing. Use when mcp-windbg tools fail, when a session will not open, or before a first debugging session.
---
# Check the debugging setup
Diagnose why mcp-windbg is not working, or confirm it will before someone
relies on it. Report findings together at the end, not one command at a time.
## Checks
Run these with Bash and interpret the results.
**1. Platform.** `uname -s` or `$env:OS`. The server drives `cdb.exe`/`kd.exe`
and is Windows-only. On anything else, stop here and say so - nothing later will
help.
**2. CDB.** Look in the places the server itself searches:
```
C:\Program Files (x86)\Windows Kits\10\Debuggers\x64\cdb.exe
%LOCALAPPDATA%\Microsoft\WindowsApps\cdbX64.exe
```
Missing means WinDbg is not installed. Point at
[aka.ms/windbg](https://aka.ms/windbg) (Microsoft Store) or the Windows SDK's
Debugging Tools for Windows. If it is installed somewhere unusual, the server
takes `--cdb-path` / `--kd-path`.
**3. uv.** `uv --version`. The plugin launches the server with `uvx`, so a
missing uv means the MCP server never starts and every tool fails at once.
`winget install astral-sh.uv`.
**4. The server itself.** `uvx mcp-windbg --help`. This proves the whole chain -
uv resolves the package from PyPI and the entry point runs. A failure here with
uv present usually means no network, or a proxy blocking PyPI.
**5. Symbols.** Check `_NT_SYMBOL_PATH`. The plugin defaults it to the Microsoft
symbol server, so an empty value in the *shell* is not a problem by itself -
what matters is what the server received. Report the effective value and note
that without symbols, stacks resolve only to `module+0x1234` and any analysis
built on them is guesswork.
**6. Tools reachable.** If the MCP server is up, `list_dumps` returning anything
at all - including "no dumps found" - proves the round trip works.
## Reporting
A short table: check, result, and what to do about it. Lead with the first thing
that is actually broken, since later checks often fail only as a consequence of
it. If everything passes, say so in one line and name the CDB path and effective
symbol path you found, so the user knows what they are running against.
+3 -3
View File
@@ -30,10 +30,10 @@ classifiers = [
# died at import before the server started. A cap turns that into a Dependabot
# PR that fails CI instead of an install everyone has to work around by hand.
dependencies = [
"mcp>=2.0.0,<3.0.0",
"mcp>=2.1.1,<3.0.0",
"pydantic>=2.13.4,<3.0.0",
"starlette>=1.3.1,<2.0.0",
"uvicorn>=0.51.0,<1.0.0",
"starlette>=1.6.0,<2.0.0",
"uvicorn>=0.52.4,<1.0.0",
]
[project.urls]
+25 -2
View File
@@ -7,8 +7,31 @@
"package-name": "mcp-windbg",
"skip-changelog": true,
"extra-files": [
{ "type": "json", "path": "server.json", "jsonpath": "$.version" },
{ "type": "json", "path": "server.json", "jsonpath": "$.packages[*].version" }
{
"type": "json",
"path": "server.json",
"jsonpath": "$.version"
},
{
"type": "json",
"path": "server.json",
"jsonpath": "$.packages[*].version"
},
{
"type": "json",
"path": "plugins/mcp-windbg/.claude-plugin/plugin.json",
"jsonpath": "$.version"
},
{
"type": "json",
"path": ".claude-plugin/marketplace.json",
"jsonpath": "$.plugins[*].version"
},
{
"type": "json",
"path": "plugins/mcp-windbg/.mcp.json",
"jsonpath": "$.mcpServers['mcp-windbg'].args[0]"
}
]
}
}
+1 -1
View File
@@ -5,4 +5,4 @@
# Mermaid diagrams use a small self-contained loader (docs/assets/mermaid.js).
mkdocs>=1.6.1
mkdocs-material>=9.7.7
pymdown-extensions>=11.0.1
pymdown-extensions>=11.0.2
+27 -2
View File
@@ -55,8 +55,31 @@ try {
$CHANGELOG_VERSION = $changelogMatch.Matches[0].Groups[1].Value
Write-Host "INFO: CHANGELOG.md version: $CHANGELOG_VERSION" -ForegroundColor Green
# Extract versions from the Claude plugin + marketplace manifests. These are
# kept in step by release-please extra-files entries; checking them here is
# what catches an entry that silently stopped matching.
$PLUGIN_VERSION = (Get-Content "plugins/mcp-windbg/.claude-plugin/plugin.json" -Raw | ConvertFrom-Json).version
$MARKETPLACE_VERSION = (Get-Content ".claude-plugin/marketplace.json" -Raw | ConvertFrom-Json).plugins[0].version
$mcpArgs = (Get-Content "plugins/mcp-windbg/.mcp.json" -Raw | ConvertFrom-Json).mcpServers.'mcp-windbg'.args
$PINNED_VERSION = ($mcpArgs[0] -split '@')[-1]
Write-Host "INFO: plugin.json version: $PLUGIN_VERSION" -ForegroundColor Green
Write-Host "INFO: marketplace.json plugin version: $MARKETPLACE_VERSION" -ForegroundColor Green
Write-Host "INFO: plugin .mcp.json pinned server: $PINNED_VERSION" -ForegroundColor Green
# Check if all versions match
$errors = @()
if ($PYPROJECT_VERSION -ne $PLUGIN_VERSION) {
$errors += "Version mismatch: pyproject.toml ($PYPROJECT_VERSION) != plugin.json ($PLUGIN_VERSION)"
}
if ($PYPROJECT_VERSION -ne $MARKETPLACE_VERSION) {
$errors += "Version mismatch: pyproject.toml ($PYPROJECT_VERSION) != marketplace.json ($MARKETPLACE_VERSION)"
}
if ($PYPROJECT_VERSION -ne $PINNED_VERSION) {
$errors += "Version mismatch: pyproject.toml ($PYPROJECT_VERSION) != plugin .mcp.json pin ($PINNED_VERSION)"
}
if ($PYPROJECT_VERSION -ne $SERVER_VERSION) {
$errors += "Version mismatch: pyproject.toml ($PYPROJECT_VERSION) != server.json ($SERVER_VERSION)"
@@ -71,8 +94,10 @@ try {
}
if ($errors.Count -gt 0) {
foreach ($error in $errors) {
Write-Host "ERROR: $error" -ForegroundColor Red
# Not $error: that is a read-only PowerShell automatic variable, and
# assigning it threw before any mismatch could be reported.
foreach ($mismatch in $errors) {
Write-Host "ERROR: $mismatch" -ForegroundColor Red
}
exit 1
}
Generated
+504 -407
View File
File diff suppressed because it is too large Load Diff