Skip to content

Releases: DustinTrap/kvm-pilot

v0.1.0b8 — docs, visuals & brand overhaul

Choose a tag to compare

@DustinTrap DustinTrap released this 15 Jul 01:14
bb95843

Beta 8 — the docs, visuals & brand overhaul (#209). No runtime code changes; this release exists so the refreshed README (the PyPI page), corrected claims, and the new brand reach every published surface.

One line, everywhere: Smart hands for your AI agents — write-capable, multi-plane (KVM + BMC + SSH) MCP server: gated, verified, audited.

Added

  • Brand: the >_ kvm-pilot terminal-prompt wordmark (dark-mode-aware SVG), favicon, and a 1280×640 social card in the docs' house palette
  • Live demo GIF in the README — a real, unedited GLKVM run: honest preflight, headless snapshot waking the on-demand encoder, gated dry-run power-cycle, and the captured boot console (re-recordable via the committed docs/assets/demo.tape)
  • Five diagrams for the hardest concepts: trust ladder, two-machines, snapshot pipeline, evidence→maturity ledger, approval/receipt lifecycle
  • docs/troubleshooting.md — canonical symptom-first fixes + FAQ (on the wiki sidebar)
  • Root llms.txt — an agent-discoverable doc map (llmstxt.org)
  • Docs guard tests — README version literals must match __about__.py; SKILL.md's tool list must two-way match the registered MCP surface

Changed / fixed

  • README restructured (logo, badges, copy-paste claude mcp add quickstart on the READ_ONLY first rung, tool-surface-by-plane table, version-agnostic status); GLKVM API warning demoted to a setup note
  • Honesty fix: snapshot is verified on RM1PE V1.9.1 only (V1.5.1 fails with an undecodable H.264 frame, #107/#151) — the compat table said otherwise; added the live-verified Dell iDRAC6 (IPMI) row
  • SKILL.md now lists all 29 MCP tools; the stale "nothing reboots the appliance" claims corrected; MCP README gains the missing boot_options/set_boot_device/wake rows + ALLOW_CONFIG env entry
  • architecture.md brought to the present tense (driver split, BootConfig, Redfish/IPMI drivers landed)
  • RESUME.md removed from tracking (published internal fleet details); orphaned docs/mcp-tools.svg removed

Full details in the CHANGELOG.

🤖 Generated with Claude Code

v0.1.0b7 — IPMI driver + serial console (SOL)

Choose a tag to compare

@DustinTrap DustinTrap released this 14 Jul 23:57
06fba4d

Beta 7 — IPMI. A full IPMI 2.0 driver for pre-Redfish BMCs (Dell iDRAC6, older HPE iLO, Supermicro), validated end-to-end against a live Dell iDRAC6 (R710).

Added

  • IPMI driver (#62). --driver ipmi via ipmitool -I lanplus (password through the IPMI_PASSWORD env, never argv). Power / SystemInfo / BootConfig / Sensors / Logs — so power / boot-device / sensors / logs work with no new CLI/MCP code. IPMI completeness ≈ Redfish minus VirtualMedia.
  • IPMI serial console / SOL (#208). SerialConsole (serial_read/serial_write over a PTY-backed ipmitool sol activate) + a kvm-pilot console command for an interactive text console (exit with ~.). Gated ipmi.serial_console (HID_INPUT). Text-only — drives Linux/ESXi serial installers, not the Windows GUI installer.

Fixed

  • IPMI get_info model now comes from FRU Board Product with vendor placeholders skipped, so a Dell R710 reports PowerEdge R710 (not the localhost iDRAC hostname Dell puts in Product Name).
  • Healthcheck now labels the IPMI driver ipmi@… (was mislabeled pikvm@…).

Testing / validation

  • Cross-checked against an independent OpenIPMI ipmi_sim BMC (tests/integration/test_ipmi_external.py) — the IPMI analogue of the sushy-tools Redfish cross-check.
  • Live-validated against a real Dell iDRAC6 (R710): power off/on/reset (verified state flips), boot-device round-trips, 105 sensors, SEL, info (14/0); SOL captured the full BIOS boot; F11 over SOL opened the BIOS Boot Manager (bidirectional drive).

Install: pip install --pre kvm-pilot

v0.1.0b6 — remote boot-control + Wake-on-LAN

Choose a tag to compare

@DustinTrap DustinTrap released this 14 Jul 16:02
74cb41e

Beta 6 — remote boot-control + Wake-on-LAN (epic #200), matured on simulators (in-repo Redfish emulator + independent sushy-tools) ahead of real BMC validation.

  • Wake-on-LAN (#199): wol.py core, kvm-pilot wake + wake MCP tool, HostConfig.mac; power on falls back to WoL when the KVM has no wired ATX. Hardware-validated (woke a real host in 52 s).
  • Redfish boot-device (#28/#201): BOOT_CONFIG capability, boot-device CLI (one-time/persistent, UEFI/legacy) + boot_options/set_boot_device MCP; feature-detects allowable targets + auto-retries without mode on iLO4/iDRAC7.
  • In-band boot (#150): boot-device --via ssh sets UEFI BootNext via efibootmgr.

~75 new tests; boot-device cross-checked against sushy-tools. Real HPE iLO / Dell iDRAC validation pending (#29) — code is simulator-tested only. Install: pip install --pre kvm-pilot.

Full notes: CHANGELOG.

v0.1.0b5 — calibration fixes from the first live fleet run

Choose a tag to compare

@DustinTrap DustinTrap released this 13 Jul 20:35
14a6f67

Beta 5 — b4's mouse auto-calibration went to real hardware (GL-RM1PE ×2, V1.9.1) hours after release. The algorithm validated live — held-out residual 0.0106 of the screen (~17px at 1600×900) on a RHEL/GDM host, correction applied and visually confirmed — and the run surfaced two functional bugs, both fixed here. If you installed b4, upgrade: calibrations recorded no resolution, and on GL's on-demand streamer the correction was never applied via the CLI path. Details in the CHANGELOG.

v0.1.0b4 — mouse auto-calibration

Pre-release

Choose a tag to compare

@DustinTrap DustinTrap released this 13 Jul 20:02
3231906

Beta 4 — mouse auto-calibration.

Fixes the oldest live-hardware complaint (#128): the agent clicks where the button should be and misses. kvm-pilot now measures each host's real commanded→observed mouse mapping and corrects for it transparently.

Highlights

  • calibrate-mouse (CLI) / calibrate_mouse (MCP). Parks the cursor, commands a 5-point grid, locates the observed cursor by frame differencing, least-squares fits a per-axis scale+offset, and verifies a held-out point within --tolerance (default 0.02 of the screen). One detail that matters: the baseline cursor's departure mark is identified from the data — the blob that recurs across every frame — never assumed to sit at the commanded park corner, because the distortion being measured decides where the parked cursor really landed. Failures are actionable, never partial stores: non-static screens, invisible cursors, implausible fits, and non-linear pointer acceleration each get named with a remedy.
  • Transparent application. The correction is stored per (host, capture resolution) — a resolution change makes it stale and it is never applied. Percent-space mouse moves and clicks (MCP and CLI) route through it automatically and report calibrated: true/false; pixel/raw coordinates mean "exactly here" and are never adjusted.
  • pip install 'kvm-pilot[calibrate]' brings Pillow for snapshot decoding; the command ships in base and errors actionably without it. The detection/fit math is stdlib and fully tested with synthetic frames — no hardware, no Pillow needed in CI.
  • Safety: pointer moves only, but gated like HID input (KVM_PILOT_MCP_ALLOW_HID + one approval covers the whole ~10–30s run, on a static screen).

Also

  • docs/cli.md again satisfies its "every command must appear here" contract (adds the missing keep-awake, recover-hid, appliance, paths rows found by the #194 review).
  • First release expected to publish automatically to the official MCP registry as io.github.DustinTrap/kvm-pilot (#197) — b3's job taught us the publisher assets use Go arch names, descriptions cap at 100 chars, and the namespace + PyPI mcp-name: marker are case-sensitive. All fixed here.

Install: pip install --pre kvm-pilot · Getting started · Full details in the CHANGELOG.

v0.1.0b3 — externally visible contracts

Choose a tag to compare

@DustinTrap DustinTrap released this 13 Jul 19:07
69ca0e6

Beta 3 — the externally visible contracts release.

kvm-pilot's safety internals (effect-class gates, signed single-use approval receipts, typed outcomes, audit trail) were already ahead of the MCP ecosystem. b3 makes them legible from the outside — the contracts agent hosts actually build policy on. Distilled from the 2026-07-13 competitive gap analysis (#194).

Highlights

  • Per-tool MCP annotations (#195). Every tool now declares all four hints (readOnly / destructive / idempotent / openWorld) explicitly, and a regression test fails CI if a tool ever ships without them. Clients auto-approve, parallelize, and render confirmation UI off these bits — and the spec defaults treat an unannotated tool as maximally dangerous and internet-reaching, which misrepresented our LAN-only surface. Notable precision fixes: mount_iso/eject/file_firmware_report are reversible writes, not destructive ops (their MEDIA / EXTERNAL_WRITE gates and approvals are unchanged); classify_screen/wait_for_state are flagged open-world because the server-side vision backend may be a cloud VLM — with a local VLM nothing leaves your network.
  • KVM_PILOT_MCP_READ_ONLY=1 (#196). A true least-privilege launch posture, enforced by three independent layers: destructive tools are not registered at all, every effect gate is force-closed regardless of ALLOW_*, and every driver is built with a deny-all confirm — so a registration bypass fails closed instead of mutating (tool filtering alone is not enforcement). The documented trust ladder for a new fleet: READ_ONLYDRY_RUN → per-effect ALLOW_*, one gate at a time.
  • Official MCP registry (#197). The server publishes as io.github.dustintrap/kvm-pilot — this release carries the ownership marker and the release pipeline now keeps the registry listing in step with PyPI automatically.

Also

  • The getting-started guide now starts new users on the read-only rung and closes the loop: kvm-pilot test-report + a two-minute hardware report is how a device+firmware combo earns its row in the Hardware-Compatibility matrix. Success or failure both count.
  • README links on PyPI are absolute again (#193).

Install: pip install --pre kvm-pilot · Getting started · Full details in the CHANGELOG.

v0.1.0b2 — beta 2: the reliability + evidence-harness release

Choose a tag to compare

@DustinTrap DustinTrap released this 12 Jul 14:39
e835ebb

Beta 2 — the reliability + evidence-harness release. Two hardening
batches in one: the transports can no longer double-fire a destructive action,
MCP approvals became signed single-use receipts with an audit trail, GLKVM
snapshots work headless at native resolution, evidence learned to carry the
conditions it was observed under — and kvm-pilot test-report turns the whole
per-device intake into one command. Everything in this release is
unit/emulator-verified; the first live fleet run of the new paths is the next
milestone (the harness exists precisely to record it honestly). 18 issues
closed.

Added

  • kvm-pilot test-report (#99) — the live-test harness: probes the
    device's capabilities and appends one evidence row to the run ledger
    (--ledger > $KVM_PILOT_TEST_LEDGER > ~/.config/kvm-pilot/test_runs.jsonl;
    never the installed package data). Read-only probes (info, snapshot —
    stamped with the #156 conditions on pass AND fail — healthcheck, logs,
    power_state) run every invocation; destructive probes run only via
    --include virtual_media,power,firmware_update with a recorded --attest
    operator statement, still routed through the normal safety gates. Pass =
    assertion + observed effect (power must flip the read-back and restore;
    media must report online and the eject must land; a flash passes only via
    the driver's #94 verified-state contract) — an unobserved effect records an
    honest FAIL. Fake-driver runs (and --synthetic) record
    source="synthetic", which never promotes maturity; there is no flag to
    force real.

  • The generated wiki Hardware-Compatibility page now carries a Maturity
    column
    — the #98-derived level per (device, firmware) read from the shipped
    registry ( when no live-derived rating exists), completing #103.

  • New GLKVM quirk firmware-flash-webui-only (#177): the GL web console is
    the only known-good RM1PE upgrade path (V1.5.1→V1.9.1 live-verified); the
    /api/upgrade/* flash was observed to no-op (#94/#95) and no API-driven
    flash has ever been verified on any release. firmware-update output now
    steers to the web console on affected devices (it never blocks — the driver
    already reports a no-op flash honestly), and
    firmware-update/driver-features/firmware-registry docs carry the guidance.

  • GLKVM headless JPEG snapshot at native resolution (#187): when the
    snapshot bytes fail the JPEG guard (H.264 at native/high res, #107) and the
    firmware exposes params.video_format (V1.9.1+), the driver flips the
    encoder to MJPEG (POST /api/streamer/set_params?video_format=1), retries,
    and restores the prior format — no EDID change, no H.264 decoder, no
    browser. Inside streamer_warm() the flip is held for the whole block and
    restored once at exit. Composes with the #142 offline-streamer recovery
    (offline → warm → H.264 → flip). V1.5.1 doesn't expose the switch and keeps
    the honest SnapshotFormatError (upgrade via the web UI, #177). Mechanism
    live-proven on V1.9.1; the auto-path is emulator-verified and awaits its
    first live ledger row. New quirk snapshot-h264-at-native-res.

  • A firmware change now invalidates the device assessment: preflight
    remembers the firmware each device was last assessed at, forces the stable
    checks to re-run live when it differs (out-of-band web-UI flashes included),
    and emits a firmware-delta finding diffing what cleared / regressed /
    stayed open (#180).

  • Run-ledger capability rows can now record the conditions a result was
    observed under
    (conditions: {resolution, encoder_format, snapshot_cached, jpeg_sink_clients}) — the axes that actually decide a GL snapshot outcome —
    and the support-matrix rollup surfaces them as pass_conditions /
    fail_conditions, so field reports at different operating points reconcile
    from data instead of reading as contradictions. Optional; pre-existing rows
    and derived maturity are unaffected (#156).

  • CI docs-parity guard: build_wiki.py --check fails when a docs/*.md page is
    not registered in the wiki PAGES allowlist, so a new page can no longer
    silently go unpublished; the MCP README tool table gained the missing
    access_paths row (#175).

Added (MCP)

  • Signed, expiring, single-use approval receipts + audit trail for the
    destructive act tools (#72): every approval mints an HMAC-signed receipt
    bound to the exact invocation (host, tool, effect, args-hash, dry-run,
    approver), re-verified immediately before dispatch and consumed on use —
    a bound field changing after approval, an expired receipt
    (KVM_PILOT_MCP_RECEIPT_TTL, default 60 s), or a replay fails closed as a
    denial-shaped result. Approved results carry receipt: {id, state} and a
    real approval.expires. Every destructive-invocation terminal (approved,
    denied, consumed, expired, mismatched, replayed, dispatch-exception) emits
    one JSON audit record on the kvm_pilot.mcp.audit logger.

  • New file_firmware_report tool — the MCP twin of CLI firmware-check's
    auto-filing (#189), completing the registry telemetry loop for agent
    sessions. Filing a GitHub issue is a new external-write effect class
    with its own operator gate (KVM_PILOT_MCP_ALLOW_EXTERNAL_WRITE, off by
    default) plus the usual per-invocation approval; the shared helper moved to
    firmware_registry.file_firmware_report (#190).

Changed

  • The healthcheck's support-evidence finding now labels ledger history as
    recorded (vs this run's own tested-now probes), renders the #156
    conditions each result was observed under, and flags condition-blind
    snapshot passes ("verified only under unknown resolution/encoder") instead
    of overclaiming a bare verified (n=N) — the honesty regression that gave
    #180 its false confidence (#180).

Changed (MCP)

  • Act results now carry a typed outcome field (approved / denied /
    cancelled / not_confirmed / gate_closed / invalidated) so agents
    branch on data instead of matching the human-facing denied_reason strings —
    a cancelled elicitation (benign, retryable) is now typed apart from an
    explicit denial. The KVM_PILOT_MCP_ELICIT=off escape-hatch hint moved from
    every client-side denial to a one-time hint after ≥2 consecutive
    client-side approval kills on the same host — a security trade-off shouldn't
    be advertised on a one-off mis-click (#149).
  • The power tool now returns a structured result instead of a sentence: it
    bumps the frame generation (a stale mouse click can no longer anchor to a
    pre-reboot snapshot within the reboot window) and verifies the effect via
    the driver's trustworthy signal — Redfish PowerState or a wired ATX LED —
    reporting verified: true/false with the observed state, or an honest
    verified: null + the reason and remedy when no trustworthy signal exists
    (GL units: ATX sensing lies; verify visually) (#168).

Fixed

  • The transports no longer auto-retry a 409/503 that answers a state-changing
    request
    — re-firing a POST whose 409/503 arrived after the device began
    acting (e.g. a BMC perturbed by the ComputerSystem.Reset it just accepted)
    could double-fire a destructive action. Reads (GET/HEAD) keep the bounded
    retry; the #164 breaker semantics are unchanged; the Redfish driver's own
    at-target reconciliation now sees the surfaced error instead of being
    pre-empted by a transport re-POST (#167).

  • A JSON endpoint answering with a non-JSON body (e.g. truncated at the
    content boundary) now raises a typed ProtocolError with a redacted preview
    instead of leaking raw bytes into dict-expecting callers as an opaque
    AttributeError; an empty 2xx body returns None (#170).

  • Redfish mount_iso now verifies the medium actually landed (polls the
    VirtualMedia slot for Inserted=true, raising MediaOfflineError on a
    silent no-op — the #78 trap, Redfish edition; verify=False opts out), and
    a mid-flight 401 re-auth DELETEs the old session before re-login so a
    spurious 401 can't strand a live session slot on session-capped BMCs; a
    login that yields no session URI now logs the future leak (#169).

  • The MCP effect gate now fails closed for an effect class with no
    registered enable-flag instead of silently borrowing the CONFIG gate;
    APPLIANCE_RESET is now explicitly mapped to
    KVM_PILOT_MCP_ALLOW_APPLIANCE (#190).


Install: pip install --pre kvm-pilot
Full diff: v0.1.0b1...v0.1.0b2

v0.1.0b1 — first beta: the telemetry-loop release

Choose a tag to compare

@DustinTrap DustinTrap released this 11 Jul 12:48
6c26274

First beta — the telemetry-loop release. The registry telemetry loop now closes itself, and the ingest side can no longer spam on malformed input. The beta label follows the support matrix: the GL-RM1PE on V1.9.1 has its core capabilities at beta maturity in the run ledger that ships in the wheel; most other device+capability combos remain unverified, and the Hardware-Compatibility list stays the source of truth. Broader hardware testing is now the ask — PiKVM, BliKVM, other GLKVM models, and Redfish BMCs especially.

Added

  • firmware-check auto-files the "Latest known release" report as a firmware-report issue (via the gh CLI) when the registry SSoT is behind the device-reported latest — the emission side of the telemetry loop was fully manual and produced almost no reports (#189). On by default; --no-file-report opts out, --dry-run previews the exact issue body, --source/--date/--repo override the details. Deduplicated against existing reports and validated with the same rules the ingest applies.
  • firmware_registry.render_issue_form() — the inverse of parse_issue_form, so auto-filed bodies round-trip through the ingest parser (#189).
  • reconcile() carries the registry entry's source (release channel URL) into the suggested submission, so known devices auto-file with no extra input.

Changed

  • The hourly firmware-ingest workflow parks invalid submissions: one ❌ comment + the ingest-error label (remove the label after fixing the body to re-queue). Previously a malformed firmware-report issue was re-commented every hour forever (#188).
  • Status/maturity messaging updated across the README (PyPI page), getting-started, bundled skill, and MCP README; trove classifier bumped to Development Status :: 4 - Beta.

Install: pip install --pre kvm-pilot (beta is a pre-release; a bare install still picks up nothing).

v0.1.0a14 — interface router

Pre-release

Choose a tag to compare

@DustinTrap DustinTrap released this 08 Jul 13:49
dae6827

The interface-router release (alpha; pip install --pre kvm-pilot).

Adds an adaptive interface router that picks the fastest interface which will actually produce the result — per device, benchmarked, and self-tuning from real use — across a KVM control plane (in-process/MCP/browser) and an in-band OS plane (SSH / WinRM remote-PowerShell).

  • kvm-pilot benchmark — per-command latency + capability scorecard across interfaces
  • kvm-pilot route <cmd> / kvm-pilot host-exec <cmd> — seamless interface selection + in-band execution
  • SSH + WinRM interfaces (WinRM = dep-free PowerShell-over-SSH); persistent SSH (~10× via ControlMaster); dep-free SSH password auth (SSH_ASKPASS)
  • Online learning — the scorecard self-tunes from every call

Grounded in live benchmarks across the GL fleet + real Linux hosts (#181, #179, #182, #183). Full changelog: CHANGELOG.md.

🤖 Generated with Claude Code

v0.1.0a13 — the headless-vision release

Choose a tag to compare

@DustinTrap DustinTrap released this 08 Jul 03:22
103c9dc

The headless-vision release. GL's video encoder is on-demand — it runs only while a video client is connected — so a headless snapshot/classify/watch (the flagship AI-agent case) used to 503 forever on an idle unit. This release makes it work, grounded in a full live reliability sweep of the GL-RM1PE fleet (.11/.20 V1.9.1, .39 V1.5.1; findings in #176).

Per the support matrix this line stays alpha: only GL-RM1PE is live-validated (V1.9.1 reaches beta-grade there), while the other drivers remain emulator-only.

Added

  • Headless snapshot now works on idle GL units (#142) — on a streamer: null 503 the driver registers a stream client over kvmd /api/ws, waits for the encoder (~1.5s), and retries. Verified live: recovers a valid JPEG on RM1PE V1.9.1; on V1.5.1 it emits H.264, honestly surfaced (#107), not a false success.
  • GLKVMDriver.streamer_warm() keep-alive (#142) — holds the stream client open in a background thread so every snapshot in the block is instant (~0.1s vs ~5s cold), no vision/LLM. watch and MCP wait_for_state use it.
  • websocket-client promoted to a base dependency — headless GL snapshot needs it; events now works out of the box (kvm-pilot[ws] kept as a no-op alias).
  • GLKVM quirk snapshot-needs-video-client; driver-features (#171) + reusable hardware test plan (#172) docs, published to the wiki.

Fixed

  • snapshot 503 no longer misdiagnoses an idle streamer as a wedged encoder (#173) — and the matching video-signal healthcheck remediation.
  • power/power-cycle on unwired ATX returns a clear CapabilityError instead of an opaque HTTP 500 (#174).

Full changelog: see CHANGELOG.md. Install: pip install --pre kvm-pilot.