Freezes the server into a single self-contained `mcp-windbg.exe` with
PyInstaller,
for users who want nothing to do with a Python toolchain. `cdb.exe`
stays a
prerequisite.
**What the build does.** `scripts/Build-Exe.ps1` builds it, `-Verify`
runs the
scenarios against it, and `MCP_WINDBG_SERVER_EXE` re-points the e2e
harness at a
built binary so the whole suite runs with the same assertions and a
different
launcher. A new `exe` job does both on every PR.
**Signed release asset.** The exe is signed and attached to each release
with a
`SHA256SUMS` taken from the signed binary, since signing rewrites the PE
and a
digest from before it would match nothing anyone can download. The
signature is
verified before the asset is attached.
**Identity.** Version resource generated from `pyproject.toml`, plus an
icon and a
`Comments` field stating the binary is signed by Liasoft GmbH, which
sponsors the
certificate. Windows shows the certificate subject as the verified
publisher, so
without that note the author and the signer read as two unrelated names.
**Why signing uses a self-hosted runner.** The signing service requires
one. Two
rules keep that safe on a public repository, and both must hold if the
job is ever
changed: it stays out of reach of `pull_request`, `pull_request_target`
and
`issue_comment`, which would run a fork's code on it, and it never
checks out the
repository. It declares `permissions: {}`, takes its endpoint from a
secret, and
waits for approval in a `signing` environment.
**Verified.** 29 scenarios pass against the binary (2 kernel skips, no
target).
Signing exercised end to end with a rehearsal run, which builds, signs
and
attaches while publishing nothing: `osslsigncode verify` reports
`Succeeded`,
signer `O=Liasoft GmbH`, RFC3161 countersigned.
**Not yet exercised.** Nothing launches the signed binary, so a
post-sign smoke
step is worth adding.
Out of scope: winget.
Separate the MCP server, four debugging skills, and crash-analyst agent into independently installable plugins. Document installation and migration, support existing MCP connections, and validate every marketplace version.
Makes `check-version-consistency.ps1` a gate instead of a post-mortem.
It ran from the publish build - which is *after* release-please has
created the tag and the GitHub release. It reported problems that had
already shipped, and the only way to correct one was to cut a second
release. CLAUDE.md described this as "caught, but late".
It now runs as a `preflight` job that `release-please` depends on, so a
release that is not internally consistent never gets a tag.
## What is asserted
All seven version sources must carry the same version:
| Source | Kept in step by |
| :----- | :-------------- |
| `pyproject.toml` | release-please, natively |
| `server.json` top level and `packages[*]` | two `extra-files` entries
|
| `.release-please-manifest.json` | release-please, natively |
| `plugins/mcp-windbg/.claude-plugin/plugin.json` | `extra-files` |
| `.claude-plugin/marketplace.json` | `extra-files` |
| the `uvx` pin in the plugin `.mcp.json` | `extra-files` |
Plus: `CHANGELOG.md`s top heading names that version, **and has an entry
under it**.
## Two assertions added while promoting it
- **`.release-please-manifest.json`** was unchecked. It is the version
release-please computes the *next* release from, so drift there silently
misprices the following release rather than the current one.
- **A bare heading**. `## [1.2.0]` with nothing beneath it matched the
version comparison perfectly and published empty release notes. The
`release-notes` job could only emit a warning about it, after the
release existed.
## Why only release merges are checked
On an ordinary push `CHANGELOG.md` correctly carries `## [Unreleased]`,
which would fail the version comparison on every single commit. The job
therefore reads the head commit subject and only enforces on
`chore(develop): release ...`. Verified against real subjects:
```
CHECK <- chore(develop): release 1.2.0 (#91)
SKIP <- fix(plugin): stop the agent hard-coding (#92)
SKIP <- chore(main): release 1.2.0 (#89)
```
## Verification
Three states, exit codes checked directly rather than through a pipe:
| State | Expected | Got |
| :---- | :------- | :-- |
| Today`s tree, `## [Unreleased]` on top | fail | exit 1, names the
mismatch |
| Simulated 1.2.0 release, all seven sources bumped | pass | exit 0 |
| 1.2.0 heading with an empty body | fail | exit 1, names the empty
section |
The script still runs from the publish build as well, which is what
guards a `publish-mcp.yml` started by hand.
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.
## Summary
Onboards a MkDocs (Material) documentation site, mirroring the
dap-dbgeng setup, and migrates the GitHub wiki into it (trimmed to the
essentials: getting started, use cases, and a lookup reference).
## What's included
**Site infrastructure**
- `mkdocs.yml` - Material theme, VS Code blue palette, light/dark
toggle, the same markdown extensions and nav structure as dap-dbgeng.
- `requirements-docs.txt` - pinned `mkdocs` / `mkdocs-material` /
`pymdown-extensions`.
- `docs/assets/` - `extra.css` (brand color + mermaid styling) and the
self-contained `mermaid.js` loader.
**Pipeline**
- `.github/workflows/pages.yml` - builds with `mkdocs build --strict`
and deploys to GitHub Pages on pushes to `main` that touch docs.
**Content (migrated + trimmed from the wiki)**
- `index.md`, `getting-started.md`
- Use cases: `scenarios/` - analyze a crash dump, debug a remote target,
triage multiple dumps
- Reference: `reference/` - command-line options, tools, client
configuration
- `troubleshooting.md`
**Agent / authoring setup**
- Migrated `AGENTS.md` -> `CLAUDE.md` (concise, dap-dbgeng style).
- Added `.claude/rules/markdown.md` and
`.claude/rules/documentation.md`, plus `scripts/Format-Docs.ps1` to
enforce the typography rules (plain hyphens, no emojis).
**Housekeeping**
- README documentation links now point at the new site.
- `.gitignore` ignores `/site/`.
## Verification
- `mkdocs build --strict` - clean, all internal links resolve.
- `scripts/Format-Docs.ps1 -Check` - passes repo-wide (also fixed a
stray dash + emoji in CHANGELOG).
## One manual step
GitHub Pages is not enabled on the repo yet. After merge, set **Settings
-> Pages -> Build and deployment -> Source = GitHub Actions** (one time)
so `pages.yml` can publish to `https://svnscha.github.io/mcp-windbg/`.
Happy to enable it via API if you'd prefer.
## Notes / decisions
- Use-case pages chosen to match the product: crash dump, remote target,
triage. The wiki's separate per-client install pages are consolidated
into `reference/clients.md`.
- The wiki repo (`mcp-windbg.wiki`) is left untouched; we can archive or
redirect it once this is live.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
## [0.10.0] - 2025-10-10
**What's New in This Release**
This release focuses on making mcp-windbg more reliable, faster, and
easier to use for everyone - from beginners to advanced users.
### New Features
**Core**
- Live debugging session support via `open_windbg_remote` and
`close_windbg_remote`
- Extended dump file support for `.mdmp` and `.hdmp` formats
- Microsoft Store WinDbg CDB compatibility
**Devops**
- Set up continuous integration that automatically tests the code with
Python versions 3.10 through 3.14
- Added automatic dependency updates to keep everything secure and
up-to-date
- Streamlined the release process so new versions reach users faster
**Development**
- Switched to `uv` - a lightning-fast Python package manager that's
10-100x faster than pip
- Development setup is now much quicker with commands like `uv sync` and
`uv run`
- More reliable builds with locked dependency versions
**Documentation**
- Added comprehensive debugging instructions for AI assistants
([`AGENTS.md`](AGENTS.md))
- Created structured templates to help analyze crash dumps more
effectively
([`.github/prompts/dump-triage.prompt.md`](.github/prompts/dump-triage.prompt.md))
- All documentation is now available in the [repository
Wiki](https://github.com/svnscha/mcp-windbg/wiki) for easy access
- Simplified the main [`README.md`](README.md) to focus on getting
started quickly
- Added this structured [`CHANGELOG.md`](CHANGELOG.md) to track all
project changes
### Improvements
**Performance Boost**: Build times are significantly faster thanks to
the new tooling
**Enhanced Security**: Automatic scanning and updates keep dependencies
secure
### 🤝 Community Contributions
Special thanks to [@sooknarine](https://github.com/sooknarine) for these
valuable contributions:
- [Find local dumps with other common extensions
#6](https://github.com/svnscha/mcp-windbg/pull/6) - Now finds more crash
dump files automatically
- [Add support for remote debugging
#10](https://github.com/svnscha/mcp-windbg/pull/10) - Connect to live
debugging sessions