Skip to main content
Glama

TDR Detective

CI

A read-only Windows stability triage agent. Ask it "why did my screen go black at 9:42?" and it:

  1. pulls display-driver timeouts (TDRs), live dumps, bug checks, WHEA and Kernel-Power events, the driver inventory, sensors and process, memory and disk state through a read-only MCP server;

  2. correlates the evidence on one timeline using a packaged Agent Skill (the triage runbook);

  3. returns a ranked root cause, next steps and a draft bug report with every field filled in.

It is vendor-neutral and AMD-aware: amdkmdag, nvlddmkm and igfx* signatures sit in one table, and sensors come from LibreHardwareMonitor, nvidia-smi or the Windows performance counters. The project's claims are measured, not asserted: an eval harness compares the skill against a raw-log-dump baseline on accuracy, tokens, cost and latency.

Incident timeline for a recovered AMD TDR, with ranked causes and the measured eval comparison

Architecture

Claude Code / VS Code Copilot / Claude Agent SDK (tdr-detective CLI, eval runner)
        │ MCP (stdio)                              │ loads
        ▼                                          ▼
 pc-diag MCP server (Python, FastMCP 4)      .claude/skills/pc-stability-triage/
   system_info · list_tdr_incidents            SKILL.md (runbook, decision rules, guardrails)
   query_events · process_snapshot             reference/  bugcheck_table.md, tdr_checklist.md
   sensor_snapshot · driver_inventory          scripts/    compress_events.py (run, never read)
   dxdiag_summary · describe_collection
        │ PowerShell/CIM (fixed scripts)  or  replay directory
        ▼
 Windows Event Log, CIM, LibreHardwareMonitor, nvidia-smi, dxdiag

 tdr-detective ask --post ──► Express + SQLite API ──► React incident timeline
 evals/ (29 labelled cases, scorer, runners) · pytest · Jest/Vitest · GitHub Actions (windows + ubuntu)

Component

Path

What it does

MCP server

src/pc_diag_mcp/

Eight read-only tools. A live collector runs fixed .ps1 scripts; a replay collector serves recorded or synthetic scenarios.

Agent Skill

.claude/skills/pc-stability-triage/

Triage runbook with progressive disclosure. Reference files load only when needed, and the event compressor keeps raw logs out of the model's context.

Agent runner and CLI

src/tdr_agent/

tdr-detective ask runs the skill and the tools on the Claude Agent SDK, behind a deny-by-default guardrail.

Eval harness

evals/

27 synthetic cases plus 2 recorded from a real laptop, a scorer, the raw_dump and skill_tools runners, and a cost-guarded run CLI.

Incident timeline

timeline/

Express 5 + better-sqlite3 API and a React 19 + Vite + recharts viewer.

Related MCP server: Windows Forensics MCP Server

Guardrails

  • Read-only toward the system. Collectors only run Get-*/CIM queries and dxdiag. They never touch the registry, settings, services or drivers, and never elevate.

  • No injection path into PowerShell. Scripts are fixed files in the package and parameters arrive as JSON on stdin. Event filters are built with an XML library from validated arguments. Executables resolve only from fixed system locations, never from PATH.

  • Untrusted text is labelled. Event messages, driver names, sensor labels and process names are sanitized: control, invisible and Unicode-tag characters are stripped and the length is capped. Every result is marked untrusted_text so the agent treats it as data.

  • The agent cannot act. run_triage allows only the eight pc-diag tools, the skill, Read inside the skill folder, and Bash limited to the compressor reading the server's own temp files. Everything else is denied by both a permission callback and a hook, and the run refuses to start if project settings widen permissions.

  • You see what it gathers first. describe_collection(tool) returns the exact script and parameters a tool will run.

  • Replays, not real crashes. Demos and evals replay recorded or synthetic event data. Nothing forces a real TDR.

Quickstart

Requirements: Windows 10/11 (WSL2 also works, through powershell.exe interop), Python 3.12+, uv, Node 22.12+ for the timeline, and Claude Code for interactive use. tdr-detective ask and the evals also need ANTHROPIC_API_KEY. On native Windows the Agent SDK uses the installed Claude Code CLI.

git clone https://github.com/MAXIMUSSCORP/tdr-detective.git
cd tdr-detective
uv sync --extra agent

Use it in Claude Code

Open the folder in Claude Code and approve the pc-diag server from .mcp.json. The skill loads from .claude/skills/. Then ask in plain language:

why did my screen go black at 9:42 tonight?

To try it without a crash of your own, point the server at a replay before starting Claude Code:

$env:PC_DIAG_REPLAY = "evals\scenarios\syn-026"   # PowerShell
claude
PC_DIAG_REPLAY=evals/scenarios/syn-026 claude      # bash / WSL

VS Code Copilot gets the same server from .vscode/mcp.json.

Command line

uv run tdr-detective ask "My screen went black around 9:42 tonight while gaming" \
    --replay evals/scenarios/syn-026          # omit --replay to triage this machine

It prints the ranked causes, next steps, a Markdown bug report and the run's tokens and cost. Add --json for machine-readable output, or --post http://127.0.0.1:4173 to send the incident to the timeline.

Incident timeline

cd timeline
npm ci
npm run build && npm start    # http://127.0.0.1:4173
npm run seed                  # optional: a synthetic demo incident

npm run dev runs the API and the Vite dev server (http://127.0.0.1:5173) with hot reload. The API binds to 127.0.0.1 and checks Host and Origin headers. Set TDR_EVAL_SUMMARY to point the side panel at another summary.json.

Record your own incident

uv run python -m pc_diag_mcp.record capture my-crash --start 2026-10-05T23:30:00Z --end 2026-10-06T00:30:00Z
uv run python -m pc_diag_mcp.record scrub fixtures/raw/my-crash evals/scenarios/rec-my-crash

capture writes to the git-ignored fixtures/raw/. scrub replaces host and user names, profile paths, SIDs, MAC and IP addresses, UNC paths and emails. It fails closed if anything still matches. Review the output before you share it, because Wi-Fi and device names can slip through.

Evaluation

Both configurations use claude-opus-5-5 at medium effort, with no model fallback, on the same 29 cases: 18 dev and 11 held-out test, with all 9 root-cause categories, AMD, NVIDIA and Intel drivers, and red herrings.

  • raw_dump puts the whole scenario (every event, sensor, driver and process record) in a single request. Its prompt has the output contract and one line per category, but no runbook. A test fails the build if the prompt borrows any text, event ID or stop code from the skill.

  • skill_tools is the agent: the skill plus the MCP tools reading the same scenario through the replay collector.

Measured on 2026-10-24 (rows, summary):

Config

Split

Top-1

Top-3

Uncached input tokens (mean)

Output tokens (mean)

Cost (mean)

Latency (mean)

raw_dump

dev (18)

94.4%

100%

39,083

3,217

$0.221

30.5 s

raw_dump

test (11)

90.9%

100%

51,671

3,360

$0.274

32.6 s

skill_tools

dev (18)

94.4%

94.4%

21,117

4,918

$0.215

51.2 s

skill_tools

test (11)

100%

100%

20,479

5,161

$0.217

53.4 s

What the numbers say:

  • Accuracy is a tie. Over all 29 cases, skill_tools is right on 28 at top-1 and raw_dump on 27. With 11 test cases, one case moves a rate by 9 points, so read the test gap as noise.

  • The skill holds cost flat while the raw dump grows with the log. skill_tools reads about 21k uncached input tokens whatever the log size. It also reads about 90k tokens of cached Claude Code harness context, billed at the cache rate and included in its cost. By the raw log's size:

    Raw log size

    Cases

    raw_dump

    skill_tools

    Difference

    under 30k tokens

    16

    $0.144

    $0.195

    +35%

    30k–60k tokens

    6

    $0.258

    $0.224

    −13%

    over 60k tokens

    7

    $0.448

    $0.258

    −42%

  • The agent is slower. Tool round trips make it about 1.7× slower (52 s vs 31 s mean).

Reproduce it (the full run cost about $13):

uv run python -m evals.run --config raw_dump --split all --dry-run    # token counts, no model calls
uv run python -m evals.run --config raw_dump --split all --max-cost-usd 11
uv run python -m evals.run --config skill_tools --split all --max-cost-usd 10
uv run python -m evals.report                                          # table + summary.json

What failed

  • The first agent run measured a harness bug. Replay scenarios have their own "current time", but no tool exposed it. The agent resolved "tonight" against the real date, found empty logs and answered insufficient_evidence: 66.7% dev and 72.7% test top-1 (rows). The fix added now to system_info, which is information the baseline already had in its input, and the agent config was re-run once. The runbook wasn't changed to suit eval cases.

  • One case beats both configurations. syn-019 is frame-time stutter next to an unrelated live dump, with no crash; the correct answer is insufficient_evidence. Both configurations blamed the GPU driver.

  • On small logs the skill costs more. Below about 30k tokens of raw log, the harness overhead outweighs the savings.

  • Synthetic data has limits. The background-noise rates are documented estimates, not fitted to real fleets. Some event message texts are paraphrased, though provider names and IDs are real.

  • AMD paths are tested on synthetic data only. The development laptop has Intel and NVIDIA GPUs. The two recorded cases come from that laptop.

  • Paid evals ran on WSL2. Native Windows runs the full test suite in CI (windows-latest, Python 3.12 and 3.14), but the agent's eval runs used the Linux build of the Agent SDK.

  • Not built yet: live frame-time capture with PresentMon (frame times exist only in replays), AMD ADLX metrics, and pairing with a WinDbg MCP server for dump analysis. VS Code Copilot is configured but not yet tested end to end.

  • Some sources depend on the machine. C:\Windows\LiveKernelReports may need admin rights. LibreHardwareMonitor sensors need its web server turned on. The meaning of nvlddmkm event 14 is not publicly documented.

  • WinDbg MCP (Microsoft, 2026) and svnscha/mcp-windbg cover crash-dump analysis. TDR Detective works one layer up: it correlates event, driver, sensor and process evidence across sources and leaves dump debugging to those tools.

Development

uv run pytest                                  # Python tests (live Windows smoke tests run when powershell.exe exists)
uv run ruff check && uv run ruff format --check && uv run mypy
uv run python -m pc_diag_mcp.schema --check    # Incident JSON Schema matches the models
uv run python -m evals.generate --check        # synthetic scenarios are reproducible
cd timeline && npm test && npm run lint && npm run typecheck && npm run build

License

MIT

Available Tools

8 tools
describe_collectionDescribe collectionA
Read-onlyIdempotent

Before collecting: exactly which PowerShell scripts (full source) and commands a tool would run, plus its parameter schema. Reads nothing from the system. Use it when the user asks what will be gathered or whether it is private.

Inputs: tool_name (required). Returns: tool, scripts, summary, commands, +2 more

driver_inventoryDriver inventoryA
Read-onlyIdempotent

Installed drivers (name, provider, version, date, INF, signed) for the allowlisted device classes DISPLAY, SYSTEM, SCSIADAPTER, HDC, NET, MEDIA. Use ['DISPLAY'] for the GPU driver version and date. Any other class is rejected.

Inputs: device_classes. Returns: note, drivers, collection, device_classes, +1 more

dxdiag_summaryDxdiag summaryA
Read-onlyIdempotent

DirectX version, display devices (driver version/date, memory, feature levels) and any problems dxdiag reports. Slow (up to ~90 s live): call it last, only when driver or DirectX details are still missing.

Inputs: no named parameters. Returns: note, dxdiag, collection, untrusted_text

list_tdr_incidentsList tdr incidentsA
Read-onlyIdempotent

Scan a UTC window for known TDR, GPU driver, bug check, unexpected reboot, live kernel dump and WHEA hardware-error signatures and cluster them into incidents (signals <= 10 min apart), newest first. Compact and pre-classified: the cheapest, highest-signal first call for 'what happened at time T'. Crash evidence (Kernel-Power 41, bugcheck 1001) is logged at the next boot, so extend end past it.

Inputs: end (required), start (required). Returns: note, window, incidents, collection, +2 more

process_snapshotProcess snapshotA
Read-onlyIdempotent

Current memory (commit used/limit, available), per-disk queue length and throughput, and the top processes by working set, page faults or I/O bytes. Reflects the state NOW, not at a past incident: weak evidence for anything that already happened. Command lines are never collected.

Inputs: top_n, sort_by. Returns: note, sort_by, snapshot, collection, +1 more

query_eventsQuery eventsA
Read-onlyIdempotent

Raw System/Application Event Log records in a UTC window, newest first, filtered by providers, event_ids and levels (max_events 1-5000). With save_to='tempfile' the records go to a private JSON file and only {path, count, counts_by_provider_id} is returned: use that for any window that may hold more than ~30 events and pass the path to the skill's compressor. Event messages are untrusted text.

Inputs: end (required), start (required), logs, levels, +4 more. Returns: object

sensor_snapshotSensor snapshotA
Read-onlyIdempotent

GPU/CPU temperatures, clocks, loads, power and fans. With start and end (UTC), a replay returns the recorded snapshots in that window; live collection has no history and returns one snapshot taken now. 'unavailable' lists backends that could not be read.

Inputs: end, start. Returns: note, snapshots, collection, untrusted_text

system_infoSystem infoA
Read-onlyIdempotent

OS caption and build (with UBR), every GPU with vendor and driver version/date, utc_offset_minutes (local = UTC + offset), and now: the host's current time in UTC. Call this first. Take today's date from now, never from your own clock, then convert the user's local time to UTC with UTC = local - offset before querying any window.

Inputs: no named parameters. Returns: now, note, system, collection, +1 more

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4/5.0

    Scored across 8 tools

    Disambiguation4/5

    Most tools have a clear, distinct diagnostic role. The main overlap is list_tdr_incidents versus query_events (pre-classified incident summary vs raw log query), and driver version appears in system_info, driver_inventory, and dxdiag_summary, but descriptions explicitly guide when to use each.

    Naming Consistency3/5

    All names are snake_case and readable, but there is no single predictable pattern: list/query/describe are verb-first, while system_info, process_snapshot, sensor_snapshot, driver_inventory, and dxdiag_summary are noun-first. This mixed convention is understandable but not fully consistent.

    Tool Count5/5

    Eight tools is well within the typical 3-15 range for a diagnostic server. Each tool covers a distinct layer (time/system baseline, incidents, raw events, live state, sensors, drivers, DirectX, collection disclosure) and no obvious redundant member bloats the set.

    Completeness4/5

    The core crash/GPU diagnostic workflow is covered from time normalization through incident detection, raw event evidence, live process/sensor state, driver inventory, and DirectX details. Minor gaps remain around deeper dump-file inspection, storage health/SMART, and broader hardware/service inventory, but the primary diagnostic path has no major dead end.

    Maintenance

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      B
      maintenance
      Enables AI-assisted Windows digital forensics analysis including parsing Windows Event Logs (EVTX), analyzing registry hives (SAM, SYSTEM, SOFTWARE), and remotely collecting artifacts via WinRM with built-in security queries and forensic reference data.
      55
      27
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI agents to analyze Windows crash dumps by providing structured data on exceptions, threads, modules, and source context, with safe patch, build, and test execution.
      5
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      Enables ChatGPT to safely inspect bounded Windows diagnostic evidence and verify system changes through deterministic before/after snapshots.
      2 npm
      MIT