[project] name = "mcp-windbg" version = "1.6.0" description = "A Model Context Protocol server providing tools to analyze Windows crash dumps using WinDbg/CDB" readme = "README.md" requires-python = ">=3.10" authors = [{ name = "svnscha", email = "sven.scharmentke@gmail.com" }] maintainers = [{ name = "svnscha", email = "sven.scharmentke@gmail.com" }] keywords = ["windbg", "cdb", "mcp", "llm", "crash-analysis"] license = "MIT" classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "Environment :: Console", "Operating System :: Microsoft :: Windows", "Topic :: Software Development :: Debuggers", "Topic :: Software Development :: Quality Assurance", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.14", ] # Every runtime dependency is capped at the next major. mcp-windbg is an # application, not a library - nothing depends on it, so an upper bound cannot # cause a diamond conflict for anyone, and it is the only thing that stops a # breaking SDK release from landing in fresh installs unannounced. mcp 2.0.0 # did exactly that to 1.0.0 (#76): an unbounded `mcp>=1.28.1` resolved to it and # 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.1.1,<3.0.0", "pydantic>=2.13.4,<3.0.0", "starlette>=1.6.0,<2.0.0", "uvicorn>=0.52.4,<1.0.0", ] [project.urls] Homepage = "https://github.com/svnscha/mcp-windbg" Repository = "https://github.com/svnscha/mcp-windbg" Issues = "https://github.com/svnscha/mcp-windbg/issues" Changelog = "https://github.com/svnscha/mcp-windbg/blob/main/CHANGELOG.md" [project.scripts] mcp-windbg = "mcp_windbg:main" [build-system] requires = ["setuptools>=42", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools.package-data] mcp_windbg = ["prompts/*.prompt.md"] [dependency-groups] dev = [ "pytest>=9.1.1", "pyyaml>=6.0.2", "coverage[toml]>=7.6", "twine>=6.2.0", "jsonschema>=4.26.0", ] # Only scripts/Build-Exe.ps1 needs this, and it pulls in a compiler toolchain's # worth of bootstrap binaries, so it stays out of dev. dist = [ "pyinstaller>=6.22.3", ] [tool.pytest.ini_options] testpaths = ["src/mcp_windbg/tests"] markers = [ "live: scenario needs a live cdb.exe (skips cleanly when absent)", "remote: scenario starts a local cdb remote server (implies live)", "kernel: scenario drives a real kernel target via kd.exe (implies live; needs MCP_WINDBG_KERNEL_CONNECTION)", ] [project.optional-dependencies] test = ["pytest>=9.1.1", "pyyaml>=6.0.2", "coverage[toml]>=7.6"] # Coverage measures the hosted server subprocess (see harness.server_command). # Run with MCP_WINDBG_COVERAGE=1, then `coverage combine` + `coverage report`. [tool.coverage.run] parallel = true branch = true concurrency = ["thread"] source = ["mcp_windbg"] omit = ["*/tests/*"] [tool.coverage.report] show_missing = true exclude_also = [ "if __name__ == .__main__.:", # Defensive guards the MCP layer already enforces before these run. "raise ValueError\\(\"Either dump_path", "raise ValueError\\(\".* mutually exclusive", # cdb.exe is always present for live tests; the not-found path cannot run. "raise CDBError\\(\"Could not find cdb", # Debug-only output and low-level IO error handlers (no fault injection in e2e). "if self.verbose:", "except IOError", "except \\(IOError, ValueError\\)", ]