mirror of
https://github.com/svnscha/mcp-windbg.git
synced 2026-10-16 20:32:50 +08:00
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:
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
```
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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]
|
||||
|
||||
@@ -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]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user