Skip to main content
Glama
kvm-pilot

kvm-pilot

by DustinTrap

kvm-pilot

Smart hands for your AI agents. A write-capable, multi-plane (KVM + BMC + SSH) MCP server for controlling physical machines — gated, verified, audited.

kvm-pilot lets an agent drive a headless box through POST, firmware, the bootloader, and an OS install with no agent on the target: it works at the pixel level through an IP-KVM (PiKVM, the GL.iNet GLKVM fork GL-RM1 / GL-RM1PE, BliKVM), at the structured-state level through a BMC (Redfish on iDRAC/iLO/OpenBMC, IPMI on BMCs that predate Redfish), at the firmware level through Intel AMT/vPro (a BIOS/POST/GRUB screenshot + power + SOL on a business laptop an HDMI-capture KVM can't see boot on), and over SSH once an OS is up. A pluggable vision subsystem reads a KVM screenshot and tells you what boot phase the machine is in — bios_menu, grub_menu, installer_progress, login_prompt, crash_screen, and so on — and a safety layer gates every destructive operation behind operator opt-ins and per-call approvals.

Vision runs on Claude or any local OpenAI-compatible VLM (LM Studio, Ollama, vLLM, llama.cpp). Point it at a model on your own GPU and the screenshots never leave your network and cost nothing per frame.

How it works

kvm-pilot runs a see → decide → act loop, and the screen is its only sensor: it pulls a screenshot from the KVM, a vision model classifies the boot phase, and kvm-pilot acts back through the KVM's keyboard and power. Because it works at the pixel level, there is no agent on the target — the same loop drives POST, firmware, the bootloader, and an OS install.

kvm-pilot reads a screenshot from the KVM, a vision backend (Claude or a local VLM) classifies the boot phase, and kvm-pilot drives keyboard and power back through the KVM — a closed loop with no agent on the target machine.

A real, unedited run against a GLKVM on the home fleet — an honest preflight, a headless snapshot (watch it wake the on-demand encoder), a gated dry-run power-cycle, and the boot console the agent actually saw:

Live terminal demo: kvm-pilot snapshot runs an honest preflight (worst: CRITICAL, no out-of-band recovery path), wakes the GL on-demand encoder over WebSocket, and saves screen.jpg; kvm-pilot power-cycle --dry-run logs and skips both destructive ATX operations; the final frames show the captured Linux boot console.

Related MCP server: qemu-mcp-server

Quickstart

One install gives you the whole product — the kvm-pilot CLI, the kvm-pilot-mcp MCP server, and the bundled Claude skill — nothing to clone.

pip install kvm-pilot                          # CLI + skill + MCP server + WebSocket events
pip install "kvm-pilot[totp]"                  # + 2FA / TOTP support (pyotp)
kvm-pilot install-skill                        # optional: put the bundled skill where Claude Code loads it

Driving a KVM from an AI agent (MCP)

claude mcp add kvm-pilot -s user \
    -e KVM_PILOT_PROFILE=mykvm -e KVM_PILOT_MCP_READ_ONLY=1 -- \
    kvm-pilot-mcp

KVM_PILOT_MCP_READ_ONLY=1 is the recommended first rung of the trust ladder — the agent can see everything and touch nothing until your hardware is verified. The Getting started guide covers credentials, Claude Desktop JSON config, sample prompts, and climbing the ladder. The server is published to the official MCP registry as io.github.DustinTrap/kvm-pilot, so registry-aware hosts can discover and install it by name. Agents: the repo root carries an llms.txt doc map.

Scripting from Python

from kvm_pilot import KVMClient
from kvm_pilot.vision import ScreenAnalyzer, make_backend

kvm = KVMClient("192.168.8.1", "admin", "secret")

# Classify the current screen with Claude (model auto-resolved at runtime)
analyzer = ScreenAnalyzer(kvm, make_backend("anthropic"))
print(analyzer.classify().phase)

# Or run entirely on a local VLM — nothing leaves your network
local = make_backend("local", base_url="http://127.0.0.1:1234/v1", model="qwen2.5-vl-7b")
analyzer = ScreenAnalyzer(kvm, local)

# Block until the box reaches the GRUB menu, then pick the first entry
analyzer.wait_for_state("grub_menu", timeout=120)
kvm.press_key("Enter")

For the latest unreleased tree:

pip install "kvm-pilot[totp] @ git+https://github.com/DustinTrap/kvm-pilot"

CLI

kvm-pilot info     --host 192.168.8.1 --user admin --ask-passwd   # prompt (no echo)
kvm-pilot capabilities --profile homelab                 # what this driver supports
kvm-pilot snapshot screen.jpg --profile homelab
kvm-pilot --timeout 60 power-cycle --profile homelab --dry-run   # log, don't send
kvm-pilot eject --profile homelab                        # detach virtual media
kvm-pilot events --profile homelab --count 5             # stream device events
kvm-pilot watch grub_menu --profile homelab \
    --backend local --vision-url http://127.0.0.1:1234/v1 --vision-model qwen2.5-vl-7b

The CLI prompts for confirmation before any destructive action (power, virtual media — including uploads — keyboard/mouse injection, GPIO). Use --yes to skip prompts in automation, or --dry-run to log intended actions without sending them — dry-run short-circuits before the prompt, so it never blocks waiting for input. --timeout (HTTP per-request timeout) is a global flag and goes before the subcommand; watch keeps its own --timeout for the vision wait deadline.

Profiles like homelab live in ~/.config/kvm-pilot/config.toml. See docs/cli.md for the full command table (every subcommand, the capability it needs, and its gating), and docs/configuration.md for the config-file format, every KVM_PILOT_* environment variable, and the precedence between flags, env, and profiles.

GLKVM setup note: on GL.iNet firmware the PiKVM REST API is disabled by default and a firmware upgrade can re-disable it — enable it first, per Every /api/* call returns 404.

The tool surface, by plane

The same capability protocols span three actuation planes, so one agent workflow can mix pixels, structured BMC state, and shell access — with every destructive effect gated per class:

Plane

Read

Act (operator-gated)

KVM — pixels & HID (PiKVM · GLKVM · BliKVM)

snapshot · classify_screen · wait_for_state · power_state · logs · list_virtual_media

power · type_text / press_key / send_shortcut / mouse · calibrate_mouse · mount_iso / eject

BMC — structured state (Redfish · IPMI)

info · boot_options · logs (SEL) · sensors (CLI)

power · set_boot_device · SOL console (CLI console)

Firmware — Intel AMT/vPro (spans both planes)

info · snapshot (firmware BIOS/POST/GRUB) · boot_options · power_state

power · set_boot_device · type/mouse · SOL (console) · amt_enable (open SOL/KVM listeners)

SSH — in-band & appliance

ssh_reachable · appliance_status · access_paths

ssh_exec · host_exec (ssh/winrm auto-picked) · wake (WoL) · appliance_reboot

Meta — evidence & intake

capabilities · support_matrix · healthcheck

file_firmware_report

A machine with no KVM and no BMC at all is itself a first-class target: driver = "ssh" plus ssh_host (the machine's own address, #248) stands kvm-pilot on the recovery ladder's in-band rung — every device capability honestly absent, and the healthcheck saying plainly that there is no out-of-band recovery path there.

The canonical per-tool reference — annotations, effect gates, approval lifecycle — is the MCP server README; the CLI covers the full surface in docs/cli.md.

Status & maturity

Status: 1.0, general availability — on the strength of the run ledger, not beyond it. Three device types have run live (GL-RM1PE, Dell R710 over iDRAC6/IPMI, Dell Latitude 5411 over Intel AMT); three of the seven device drivers (redfish, pikvm, blikvm) have only ever run against emulators. See the Hardware-Compatibility list for what has actually been exercised — and please add to it. (The exact version lives in the CHANGELOG.) The core paths have graduated from mocked-only to live-verified: a fleet of GL-RM1PE units has exercised snapshot/healthcheck/logs/power_state/virtual_media/info across two firmware lines — on V1.9.1 the run ledger that ships in the wheel puts info/logs/healthcheck/power_state at ga, snapshot at rc, and virtual_media at beta — derived from real runs, never hand-edited — and a Dell iDRAC6 has exercised the IPMI driver live end-to-end (power, boot-device, sensors, event log, SOL serial console). The paths that can hurt are hardened: transports never re-fire a destructive request, MCP approvals are signed single-use receipts with an audit trail, and every destructive effect — power, HID, media, boot-config, appliance, SSH, external writes — has its own operator opt-in gate. Recent betas added remote boot-device control (Redfish, IPMI, and in-band efibootmgr), Wake-on-LAN, an IPMI driver for BMCs that predate Redfish, a serial (SOL) console, mouse auto-calibration, and headless native-resolution GLKVM snapshots; kvm-pilot test-report turns contributing evidence into one command, and the firmware registry feeds itself (firmware-check auto-files registry updates). Now we need your hardware. PiKVM, BliKVM, other GLKVM models, and Redfish BMCs (iDRAC/iLO/OpenBMC) are the combos the matrix needs most — success or failure, a hardware report takes two minutes and the hourly ingest does the rest. Anything the Hardware-Compatibility list doesn't show as exercised is still unverified: the 1.x line keeps the public API stable, but a rating only moves when a live run moves it; note the remote firmware-flash no-op on GL-RM1PE (#94/#95), and don't point destructive ops at a machine you can't afford to have power-cycled unexpectedly. See Compatibility.

Evidence in, maturity out: live fleet runs, the one-command test-report, and community hardware-report issues feed the run ledger shipped inside the wheel; aggregation per device × firmware × capability with a minimum-sample gate derives the alpha → beta → rc → ga ladder. A failure is a first-class ledger row.

Boot-phase detection

The vision classifier maps each screenshot to a phase — bios_menu, grub_menu, installer_progress, login_prompt, crash_screen, and so on. wait_for_state() polls the screen and blocks until the phase you asked for appears (or a timeout fires), so an unattended install becomes a few waits with actions wired between them:

Timeline of boot phases — POST, bios_menu, grub_menu, installer_progress, installer_complete, login_prompt — with the unattended-install example wiring mount_iso and hard_cycle at the start, wait_for_state on grub_menu then Enter, and wait_for_state on installer_complete; any phase can branch to crash_screen.

Sensing model

Vision is the most expensive way to read a screen — a model call per frame — and most of what it infers (power state, boot phase, liveness, a crash) is also available as a field, an event, or a line of text. The direction of kvm-pilot is to treat classification as a hierarchy: answer from the cheapest signal the device exposes, and fall through to OCR and finally a vision model only when nothing cheaper can.

Sensing hierarchy: structured signals (events, power and LED state, video signal and resolution, Redfish BootProgress, sensors, logs) and serial-console text are preferred; local frame-diff, OCR, and a vision model are the escalating last resort. Colour encodes cost — vision is the only expensive tier.

The PiKVM/GLKVM client already exposes the cheap end — ATX and HID LEDs, video-signal and resolution, on-device OCR (?ocr=true), logs, Prometheus metrics, and a WebSocket event stream. The capability protocols add Logs, BootProgress, Sensors, SerialConsole, Watchdog, and BootConfig as the seam for BMC drivers (Redfish/IPMI), where the boot phase is a structured enum (BootProgress.LastState) and the console is a serial text stream rather than pixels. Different device classes are nearly complementary: capture devices are strong on pixels, BMCs on structured state and serial text.

Safety model

Power-offs, hard resets, virtual-media connect/disconnect and image uploads, keyboard/mouse injection (type_text, press_key, shortcuts, clicks), GPIO, boot-config changes, and Redfish/IPMI resets are classified as destructive and pass through a safety layer:

  • dry-run short-circuits first: it logs the intended call and skips it entirely — the confirm callback is never invoked, so dry runs never prompt or block.

  • confirmation — a callback that can veto any destructive call that would really be sent. The library default allows everything (so plain scripts work); the CLI installs an interactive y/N prompt unless you pass --yes.

Decision flow for a destructive call: if the op is not in DESTRUCTIVE_OPS it executes directly; if it is, dry-run logs and skips it, otherwise a confirm callback can veto it, and only an allowed call is sent to the device.

The destructive set is defined explicitly in kvm_pilot.safety.DESTRUCTIVE_OPS so it is auditable rather than guessed. A vision classification can never trigger a destructive action on its own — you wire that yourself, and the safety layer still applies. On the MCP side each destructive effect class additionally needs an operator opt-in env gate plus a per-call approval backed by a signed single-use receipt — the trust ladder (READ_ONLY → DRY_RUN → per-effect ALLOW_*) is drawn in the MCP server README.

This software controls real hardware and can power-cycle or interrupt a running machine. Read SECURITY.md before exposing a KVM to the internet.

No hard-coded model version

There is no model version string anywhere in the code. The Anthropic backend resolves the newest vision-capable model at runtime via the Models API and caches it; set KVM_PILOT_VISION_MODEL or pass model= to pin one. The local backend uses whatever model you loaded on your server. Bring your own backend, endpoint, and model.

How this differs from other clients

pikvm-lib is a fine general-purpose PiKVM client. kvm-pilot is aimed at a different job:

  • Vision-based boot-phase detection — classify BIOS/GRUB/installer/crash states from screenshots, with blocking wait_for_state loops. This is the core feature and pikvm-lib has no equivalent.

  • Pluggable local or cloud VLM — run inference on your own GPU at zero per-frame cost, or on Claude.

  • A safety layer around destructive operations (dry-run + confirmation).

  • GLKVM-fork awareness — documents the API-enable prerequisite and GL hardware quirks that bite GL-RM1PE users.

  • Stdlib-only client core — the driver/vision code imports only the standard library (the bundled MCP server pulls the mcp SDK; feature extras are opt-in).

If you just want to script power and HID against a stock PiKVM and don't need the vision layer, pikvm-lib may be the simpler choice.

On the BMC side, sushy, DMTF's python-redfish-library, and pyghmi (IPMI) are mature, far more complete BMC management SDKs — if you need account/firmware/network configuration, EventService subscriptions, or hardware-proven maturity, use them. kvm-pilot trades that completeness for one uniform capability surface across device classes (IP-KVMs and BMCs behind the same protocols), the same safety layer gating every destructive call, and the vision loop on devices that have pixels.

Compatibility

Device

Status

GL-RM1PE (Comet PoE)

Primary target — exercised live: read/healthcheck/logs verified on firmware V1.5.1 release2 & V1.9.1 release1; snapshot verified on V1.9.1 (on V1.5.1 it fails with a clear error — undecodable H.264 frame, #107/#151); remote flash a no-op (#94/#95); encoder wedges >1080p (#107)

Dell iDRAC6 — IPMI (PowerEdge R710)

Exercised live: power / boot-device / sensors / event log (SEL) / SOL serial console all verified over ipmitool lanplus (fw 1.95)

Dell Latitude 5411 — Intel AMT/vPro

Exercised live (AMT 14.1.67): WS-Man power / info / single-use boot, remote SOL + KVM enablement, and a 1920×1080 BIOS/POST screenshot over KVM redirection — the firmware screen an HDMI-capture KVM can't see on a laptop. Captures graphical screens only (not legacy VGA text mode)

GL-RM1 (Comet)

Expected to work (same firmware family); untested

PiKVM v3 / v4

Expected to work (upstream API); untested

BliKVM

Expected to work (PiKVM-compatible API); untested

Redfish BMCs (iDRAC7+, iLO, OpenBMC)

Emulator-verified (in-repo emulator + DMTF sushy-tools in CI); live-BMC validation pending (#29)

The GL-RM1PE (read/snapshot paths), a Dell iDRAC6 over IPMI, and a Dell Latitude 5411 over Intel AMT are the combos run live so far — everything else is "expected to work" pending validation. The Hardware-Compatibility list is the authoritative, per-capability record. ATX power control needs the ATX adapter wired to the target's front-panel header: on the GL Comet family (GL-RM1 / GL-RM1PE) that is GL.iNet's separately sold ATX board (GL-ATXPC), while PiKVM v3/v4 kits include the ATX adapter in the box and BliKVM bundles vary by model — check yours. Without ATX wiring, ATX calls return errors from the device. Reports of success or failure on any hardware are exactly what this project needs — please open a hardware report.

Architecture

kvm-pilot is built on a modular, driver-plugin architecture so support can expand to many KVM/BMC devices (PiKVM family, Redfish BMCs, IPMI BMCs, JetKVM, …). Each device implements only the capability protocols its hardware supports; the CLI, safety layer, and vision subsystem stay device-agnostic. A make_driver(kind) registry (mirroring make_backend) builds drivers by name, and a hardware-free FakeDriver lets you exercise the whole loop — capabilities, safety gating, the analyzer — with no device (kvm-pilot capabilities --driver fake). See docs/architecture.md for the design and diagram.

A RedfishDriver (make_driver("redfish")) speaks the DMTF Redfish API to server BMCs — Dell iDRAC, HPE iLO, Supermicro, Lenovo XCC, OpenBMC — in one stdlib-only client. It shows why capabilities are segmented: a BMC's set is complementary to a PiKVM's (strong on structured state — power, boot phase, sensors, logs, virtual media — with no keyboard/mouse/screenshot), and the driver stays portable by following Redfish hypermedia rather than hard-coding vendor ids:

from kvm_pilot.drivers import make_driver

bmc = make_driver("redfish", host="idrac.lan", user="root", passwd="…")
bmc.get_boot_progress()        # 'os_running'  — structured, no screenshot
bmc.read_sensors()["temperatures"]
bmc.power_off(wait=True)       # mapped to the target's actual ResetType, gated

An IpmiDriver (make_driver("ipmi")) covers BMCs that predate Redfish (e.g. Dell iDRAC6) over the system ipmitool: power, boot-device control, sensors, the SEL event log, and an SOL serial console (kvm-pilot console). Both are on the CLI too — kvm-pilot info --driver redfish --host idrac.lan …. Capability-specific subcommands a BMC can't serve (type, snapshot, events) fail cleanly rather than crashing. Add --redfish-auth basic for an endpoint without a SessionService (emulators, or a BMC with session auth disabled).

An AmtDriver (make_driver("amt")) manages Intel AMT/vPro laptops and desktops out-of-band over AMT's three native protocols — WS-Man (power / info / single-use boot), SOL (kvm-pilot console), and KVM redirection — all pure-stdlib. It is the first non-PiKVM driver with Video + HID: snapshot returns a real firmware-level BIOS/POST/GRUB screenshot on a machine whose HDMI a capture-KVM can't see boot on a laptop. SOL and KVM listeners are opened remotely over WS-Man (kvm-pilot amt enable-sol / enable-kvm), no MEBx trip.

Help shape it — this is where you come in

kvm-pilot is built in the open. 1.0 shipped on the evidence of three device types; what it still needs is not code — it's breadth of real hardware. Three of the seven drivers (redfish, pikvm, blikvm) have never run against a physical device, only emulators. Every rating you see is derived from a run ledger that ships inside the wheel, never hand-set, so the matrix only grows when someone runs it on real metal. That someone could be you.

The single most valuable thing you can send: a hardware report. kvm-pilot test-report --profile <name> turns it into one command, it is read-only by default, and an hourly job folds the result into the published compatibility matrix. Failures are as welcome as successes — a driver that returns a confident wrong answer on your BMC is a more useful report than one that works, and it will be treated as a first-class finding, not swept up.

Also genuinely wanted:

  • ⭐ Star the repo if the idea is useful to you. It is the cheapest signal that this problem is worth solving, and it is what brings in the operators whose hardware the matrix still needs.

  • 🐛 Open an issue for anything: a bug, a device that misbehaves, a confusing error, a doc that lied to you. This repo is issue-per-finding — an issue is the unit of record, and "the error message didn't tell me what to do" is a legitimate report.

  • 💬 Tell us what it got wrong. Review the safety model, the approval flow, the tool surface. Push back on the defaults. If an agent did something with your machine that surprised you, that is exactly the feedback that makes this safe for everyone else.

  • 🔌 Ask for your device. Missing driver, unsupported BMC, a KVM we've never heard of? Open a driver request — the plugin architecture exists precisely so that adding one doesn't mean forking the project, and docs/plugin-development.md is the contract.

  • 🛠️ Send a PR. docs/CONTRIBUTING.md has the full pre-PR checklist; good first issues are labelled.

Nothing here phones home. The project has no telemetry that reports itself — every row in the compatibility matrix is there because a human chose to send it. That's the deal, and it's why your report actually matters.

Documentation

Full user and developer docs live in docs/ (architecture, design decisions, the Redfish reference, the troubleshooting & FAQ, contributing, and the security policy). The project wiki is an auto-generated, nicely formatted mirror of that folder, and the repo root carries an llms.txt doc map for AI agents.

License

Apache License 2.0 — see LICENSE and NOTICE. kvm-pilot is independent and not affiliated with or endorsed by the PiKVM project, GL.iNet, or Anthropic; those names are used only for compatibility description.

Available Tools

34 tools
access_pathsA
Read-onlyIdempotent

Which INDEPENDENT recovery paths are live for the device — the lockout view.

Rolls up the REST API, appliance-SSH, target-SSH, out-of-band power, and console-HID paths, each labeled by its failure domain so redundancy is not oversold: several live paths that all ride the same appliance are ONE independent domain. summary.out_of_band_live=false means every path shares the appliance's fate — a fully hung box can't be recovered remotely. summary.out_of_band is live, down (the path exists but management access to its plane failed — restore it) or none (no such path).

Inputs: profile.

amt_enableA
Destructive

Enable an Intel AMT redirection listener over WS-Man (Intel AMT/vPro only). CONFIG MUTATION.

feature='sol' opens the SOL/IDE-R listener (16994); feature='kvm' opens KVM redirection (5900) and sets the RFB password. Gated by the config effect gate + per-invocation approval (typed same-path denials, #234). consent_off=true (KVM only) DISABLES the on-screen user-consent prompt — a surveillance escalation — and additionally requires the dedicated KVM_PILOT_MCP_ALLOW_CONSENT_OFF operator gate (see README.md); leaving it false keeps the prompt.

Inputs: feature (required), confirm, profile, consent_off.

appliance_rebootA
Destructive

Reboot the KVM APPLIANCE (not the target) to clear a wedged encoder. DESTRUCTIVE.

Recovers the RV1126 encoder wedge (the only fix — the stuck threads are unkillable kernel threads). Drops all KVM control for ~60s; the target's power is untouched. Gated by the appliance effect gate + per-invocation approval, with typed same-path denials (#234). There is no out-of-band power to the appliance, so use this deliberately, never in an automated loop.

Inputs: confirm, profile.

appliance_statusA
Read-onlyIdempotent

Read-only diagnostics from the KVM APPLIANCE's own OS over SSH.

Targets the KVM appliance itself (its appliance_ssh channel), NOT the managed target. Reports the 1-minute load and the RV1126 video-pipeline threads in D-state. NOTE: on these units load sits at ~10 even when perfectly idle (the driver parks those threads in D-state), so it is NOT a health signal on its own — use the healthcheck encoder-wedge finding for the real tell.

Inputs: profile.

boot_optionsA
Read-onlyIdempotent

Show the host's current boot override (Redfish BootSourceOverride) — read-only.

Reports enabled (Disabled/Once/Continuous), the normalized target, the mode (UEFI/Legacy, or null if the BMC doesn't expose it), and the allowable targets the BMC advertises — so an actuator knows what set_boot_device values this box will accept before trying one.

Inputs: profile.

calibrate_mouseA
Idempotent

Measure and store this host's mouse commanded→observed correction (#128).

Fixes "clicks where the button should be and misses". Pointer moves only — no clicks, no keystrokes — but it visibly moves the live cursor ~10-30s, so it is gated like HID input (KVM_PILOT_MCP_ALLOW_HID; one approval covers the whole run). Preconditions: live video signal, a static screen, and a visible cursor. Afterwards mouse percent coords apply it transparently (calibrated: true); stored per (host, capture resolution) — a resolution change makes it stale, never applied. Mechanism details: the MCP server README.

Inputs: confirm, profile, tolerance.

capabilitiesA
Read-onlyIdempotent

List the capabilities the target's driver supports (read-only, offline).

Structural — makes no network call and runs no preflight; it answers "which tools/actions can this device serve?" so you can pick the right interface up front (a Redfish BMC has no video; a PiKVM has no BootProgress). Returned in the capability enum's declaration order for stable output. video_scope answers the question video cannot — whether BIOS/POST/GRUB are visible through this interface (an HDMI-capture KVM is blind below the OS on a laptop; AMT/BMC firmware video is not). live_evidence additionally names which device+firmware combos this driver has real-hardware run evidence for — structural support is not live verification; call support_matrix for per-combo evidence and healthcheck for this exact device+firmware.

Inputs: profile.

classify_screenA
Read-onlyIdempotent

Classify the current screen's boot/run phase (read-only).

Uses the server-side vision backend when configured; cheap on-device gates (power-off, no-signal, boot-progress, OCR rules) resolve with no credentials at all. Return shapes:

  • server-side / cheap-gate → a dict with mode="server" + phase fields.

  • no server vision → caller-side fallback, a [json_text, Image] list: classify the image yourself against the system_prompt / phases in the JSON block.

Inputs: hint, profile.

ctrl_alt_deleteA
Destructive

Send Ctrl+Alt+Del to the managed host over the keyboard. DESTRUCTIVE (reboot).

A reboot (or the OS's secure-attention screen) delivered through HID, so it is classified power_soft and needs KVM_PILOT_MCP_ALLOW_POWER — the power tool's gate — never the weaker HID gate. Prefer power(action='reset') when the device has out-of-band power: that is verifiable, this chord is not (a hung host simply ignores it). Returns the typed act outcome; confirm with wait_for_state or snapshot.

Inputs: confirm, profile.

doctrineA
Read-onlyIdempotent

Re-serve the bundled operating doctrine (read-only; offline, no device I/O).

The skill's playbooks ship inside this package; this tool re-serves them so a session that never loaded the skill file — or has long since compacted it away — can re-anchor on the written doctrine instead of a faded memory of it. Call with no topic to list the topics; call with one for that playbook's full text. Read recovery the moment a host goes dark or a snapshot fails, and interfaces before picking how to do an action you haven't done this session.

Inputs: topic.

ejectA
Idempotent

Detach the virtual media presented to the host (inverse of mount_iso). GATED, reversible.

Needs KVM_PILOT_MCP_ALLOW_MEDIA + per-invocation approval. With nothing attached it returns detached=false and says so — not an error. Touches neither power nor the boot order: a host running from the ISO keeps running until it reboots; on BMCs, set_boot_device picks what boots next. Returns the typed act outcome.

Inputs: confirm, profile.

eventsA
Read-onlyIdempotent

Collect typed device events from the kvmd stream (read-only, bounded).

MCP twin of CLI events minus follow mode (#233 — an endless stream doesn't fit the synchronous stdio transport): returns up to count events or duration seconds' worth (capped 30 s), whichever first. logs is the better first diagnostic; events add the live typed stream (atx/msd/streamer state changes) to cross-check a vision wait against.

Inputs: count, profile, duration.

file_firmware_reportA
Idempotent

File the device's firmware-currency report as a GitHub issue when the registry is behind (MCP twin of CLI firmware-check, #189/#190). EXTERNAL WRITE — writes outside the managed device.

The read/reconcile half always runs; registry current → nothing to file, the result says so. Filing is gated as its own external_write effect (KVM_PILOT_MCP_ALLOW_EXTERNAL_WRITE + per-invocation approval); dry_run=true previews the exact issue title/body; a missing or unauthenticated gh is a graceful filed=false reason.

Inputs: repo, source, confirm, dry_run, +1 more.

firmware_checkA
Read-onlyIdempotent

Report the device's firmware currency vs the bundled registry (read-only).

The read half of file_firmware_report (#233): reconciles the device's reported firmware/update state against the registry SSoT and says whether the registry is behind — nothing is filed, no gate is consulted. When registry_behind is true, file_firmware_report contributes the report (gated external write).

Inputs: profile.

healthcheckA
Read-onlyIdempotent

Audit the device's readiness/recovery, security posture, and firmware (#80).

Read-only. Returns per-check findings with a tiered severity; a CRITICAL (e.g. no out-of-band reset path) is what should gate a subsequent destructive op. The most valuable finding is recovery-path — whether a hung guest can be reset at all when the KVM is remote. Served through the preflight cache (#225): stable posture may come from the last assessment, and a firmware change since then adds a firmware-delta finding of what cleared/regressed.

Inputs: profile.

infoA
Read-onlyIdempotent

Identify the device and the system behind it (read-only).

Returns host/driver plus the driver's info block: model, vendor, firmware and hardware detail as the device reports them (a PiKVM/GLKVM describes the appliance; a BMC describes itself and the managed system). Use it to confirm what you are talking to. It says nothing about whether the device is safe to act on (healthcheck), what it can do (capabilities), or the host's power (power_state).

Inputs: profile.

list_virtual_mediaA
Read-onlyIdempotent

Inventory the KVM's virtual-media (MSD) storage (read-only).

Check this BEFORE asking the operator to download or upload an ISO — the image may already be on the device (#127). Returns stored images, the selected image, and attach state (online). host_visible_as (when known, #78) is the device name the TARGET's boot menu shows for truly presented media — match it to pick the right boot entry and to confirm the medium is really inserted. Details: doctrine topic 'interfaces'.

Inputs: profile.

logsA
Read-onlyIdempotent

Return the device/host event log as text (read-only).

seek is seconds of lookback (0 = the whole buffer). This is the go-to diagnostic when video/streamer/encoder or power behaviour looks wrong: the text log names a fault (e.g. a stuck encoder behind a snapshot 503) that a screenshot cannot. Tail-follow is intentionally not exposed — it blocks over the server's synchronous transport.

Inputs: seek, profile.

mount_isoA
Idempotent

Mount an ISO as virtual media on the host. GATED act (media effect gate); reversible.

source is a local path or an http(s):// URL; usb=true attaches as a USB flash drive instead of a CD-ROM. Needs KVM_PILOT_MCP_ALLOW_MEDIA + per-invocation approval. Mounting bumps the frame generation, so a mouse click planned against the pre-mount screen is invalidated.

Inputs: source (required), usb, name, confirm, +1 more.

mouseA
Destructive

Move the mouse (and optionally click) on the host. DESTRUCTIVE (HID input).

A click must carry the observed_frame_ref it was planned against (from a prior snapshot); it is refused — re-snapshot and retry — if the host rebooted/swapped media since, the observation is older than KVM_PILOT_MCP_FRAME_MAX_AGE (60s default, #141), or the ref wasn't issued by this server. Move-only (button omitted) needs no ref. coord_space: percent (0.0-1.0, default — survives resolution changes), pixel, or raw kvmd. Gated by KVM_PILOT_MCP_ALLOW_HID

  • per-invocation approval.

Inputs: x (required), y (required), button, confirm, +3 more.

powerA
Destructive

Change host power state. DESTRUCTIVE.

Gated by the power effect gate + per-invocation approval (elicitation, or confirm=true under standing policy); denials come back through the same path with a typed outcome (#234). The result carries an honest effect report (#168): verified is true/false when the driver has a trustworthy power signal (Redfish PowerState, a wired ATX LED), and null — with the reason and what to do instead — when it doesn't. A power action also invalidates prior snapshot frame refs (generation bump), so a stale mouse click can't land on the post-reboot screen.

Inputs: action (required), confirm, profile.

power_stateA
Read-onlyIdempotent

Report whether the managed host is powered on (read-only).

Returns powered_on (bool) plus, on PiKVM-family devices, atx (the power/HDD LEDs and button states); BMC/AMT drivers answer from the controller's power state. The cheap check after power/wake when their verified came back null, and before deciding whether a dark snapshot means off or asleep. Changes nothing: to change power use power, to wake a sleeping host use wake.

Inputs: profile.

press_keyA
Destructive

Press and release one key on the managed host's console. DESTRUCTIVE (HID).

For a single non-text key: Enter to submit, Escape, F2/F12 at POST, arrows and Tab in firmware menus. For a chord use send_shortcut; for words use type_text; for Ctrl+Alt+Del use ctrl_alt_delete (power gate). Nothing echoes back — snapshot after. Same gating as type_text: KVM_PILOT_MCP_ALLOW_HID + per-invocation approval. Returns the typed act outcome (receipt, or the denial reason).

Inputs: key (required), confirm, profile.

send_shortcutA
Destructive

Send a key chord — comma-separated kvmd key codes, e.g. ControlLeft,AltLeft,Delete or ControlLeft,AltLeft,F2. DESTRUCTIVE.

Gated by effect, not transport: a reboot/power chord (Ctrl+Alt+Del, Magic SysRq) is classified power_soft/power_hard and needs KVM_PILOT_MCP_ALLOW_POWER; an ordinary session chord is hid_control and needs KVM_PILOT_MCP_ALLOW_HID — so a reboot can't slip through the HID gate.

Inputs: keys (required), confirm, profile.

sessionA
Read-onlyIdempotent

Report this server's current operating posture (read-only; offline, no device I/O — answers even when the device is down).

Call this after a context compaction, when resuming a long flow, or before planning act calls: it names the target, dry-run/read-only state, which effect gates are open (by class name only — opening one is operator-only, out of band), the approval posture, any live standing approvals (#192) with their scope and time left, the recent act journal, and the last wait_for_state result for the target. All journal/wait state is in-memory: a server restart empties it (and voids receipts and frame refs), so an empty journal after a restart is expected, not evidence nothing happened. Pair with healthcheck for device health and doctrine for the operating playbooks.

Inputs: profile.

set_boot_deviceA
Destructive

Set the next-boot (or persistent) boot device via BootSourceOverride. CONFIG MUTATION.

Gated by the config effect gate + per-invocation approval; denials come back through the same path with a typed outcome (#234). none clears the override; once=false makes it persistent; uefi=false selects legacy BIOS mode where the target exposes it. A target the BMC doesn't advertise fails fast (call boot_options first to see allowable).

Inputs: device (required), once, uefi, confirm, +1 more.

snapshotA
Read-onlyIdempotent

Capture the current KVM screen (read-only).

Returns [json_text, image]: the JSON carries a frame_ref (host:generation:hash) — pass it back to the mouse tool as observed_frame_ref so an absolute click can be refused if the host rebooted or swapped media since you looked.

It also carries the live signal state (online/resolution/fps/format, #143) and unchanged_since_last_snapshot (#141): a byte-identical frame when the screen should have changed means the pixels are stale/cached — do NOT trust them as ground truth; check signal and logs instead.

Inputs: profile.

ssh_discoverA
Read-onlyIdempotent

Scan a CIDR for hosts with an open SSH port. RISKY — opt-in.

An active network scan: noisy, and only acceptable on networks the user owns or is authorized to probe. Use it ONLY to help find a target whose address the user doesn't know, after they confirm the range — never by default. confirm=true is required to acknowledge the scan.

Inputs: cidr (required), port, confirm.

ssh_execA
Destructive

Run a command on the managed host's OS over SSH. DESTRUCTIVE / in-band.

Gated by its own SSH effect gate (never the HID gate) + per-invocation approval, with typed same-path denials (#234). host overrides the profile/env ssh_host at runtime (e.g. a discovered install-time DHCP address).

Inputs: command (required), host, confirm, profile.

ssh_reachableA
Read-onlyIdempotent

Is the managed host's OS reachable over SSH? (read-only, in-band).

Targets the host behind the KVM (its own ssh_host / KVM_PILOT_SSH_HOST), a different machine from the KVM appliance. Use this to prefer remote recovery before asking a user to physically intervene.

host overrides the profile/env ssh_host at runtime — e.g. an install-time DHCP address the profile can't know until the target boots.

Inputs: host, profile.

support_matrixA
Read-onlyIdempotent

What has actually been exercised on real hardware, per device+firmware+capability (read-only, offline — no device call).

Aggregated from the test-run ledger shipped in the package (the same data behind the wiki Hardware-Compatibility page), with each combo's derived maturity level (#98) joined from the shipped firmware registry. This is EVIDENCE, not a guarantee: a capability listed in never_exercised (or a combo with no row at all) is unverified on that hardware — treat it as mock-only/alpha maturity and confirm destructive steps with the user. status is "fail" when every recorded live attempt failed (e.g. RM1PE V1.5.1 firmware_update, #94/#95). Filters are case-insensitive; product matches as a substring.

Inputs: vendor, product, firmware_version.

type_textA
Destructive

Type a string on the managed host's console over the HID keyboard. DESTRUCTIVE.

For printable text (commands, installer fields, passwords); nothing echoes back and no Enter is appended — press_key('Enter') to submit. Keys that aren't text go through press_key; chords through send_shortcut. Keystrokes land wherever the host's focus is: snapshot first to confirm the screen, and after to see the effect. Needs KVM_PILOT_MCP_ALLOW_HID

  • per-invocation approval (elicitation, or confirm=true under standing policy). Returns the typed act outcome (receipt, or the denial reason).

Inputs: text (required), confirm, profile.

wait_for_stateA
Read-only

Wait (bounded) until the screen reaches a boot/run phase (read-only).

Server-side twin of CLI watch: polls cheap power/signal/boot-progress gates, then server-side vision, until phase (a classify_screen token; unknown tokens fail fast with the valid list) is observed. timeout is seconds, capped server-side at 300 — chain calls for longer waits. Success returns phase/confidence plus a frame_ref to pass to mouse as observed_frame_ref; a timeout returns reached=false with the last observed state (never a hang, never a raised error). With no server-side vision credentials only cheap-gate phases are waitable; others fail fast pointing at classify_screen polling. Holds the driver open up to timeout s. Details: doctrine topic 'interfaces'.

Inputs: phase (required), hint, profile, timeout.

wakeA
Destructive

Send a Wake-on-LAN magic packet to power the host on. POWER (soft).

Gated by the power effect gate + per-invocation approval (typed same-path denials, #234). mac defaults to the profile's mac; broadcast to its wol_broadcast. No KVM driver is contacted — WoL is a broadcast sent from the server's own host onto the target's L2 segment.

Inputs: mac, count, confirm, profile, +1 more.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.9/5.0

    Scored across 34 tools

    Disambiguation4/5

    Tools mostly occupy distinct resource/action slots: power vs wake vs ctrl_alt_delete vs appliance_reboot are clearly separated, and screen/log diagnostics are explained by purpose. Some read-only meta tools (healthcheck/support_matrix/capabilities/session) and logs/events require careful reading, but descriptions provide boundaries.

    Naming Consistency3/5

    All names are snake_case, but the set mixes noun-only names (info, logs, snapshot, power, events) with verb_noun names (set_boot_device, mount_iso, wait_for_state). It remains readable and domain-predictable, though not a single consistent pattern.

    Tool Count2/5

    34 tools is above the 25-tool threshold and a lot for an agent to navigate; while many are specialized safety/diagnostic operations, several meta/diagnostic tools could be consolidated. The scope is broad, but the surface feels heavy.

    Completeness4/5

    Covers identification, health/capabilities, power, boot override, screen/HID, virtual media, SSH, appliance recovery, logs/events, firmware currency, and external report filing. Minor gaps remain (e.g., no firmware update action, no AMT disable, limited appliance lifecycle), but core operational workflows are present.

    Maintenance

    ActivityMaintained
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      C
      maintenance
      MCP server that enables AI to see and control a physical computer via a JetKVM device for screen viewing, mouse/keyboard input, media mounting, and power management.
      21
      MIT
    • F
      license
      A
      quality
      D
      maintenance
      MCP server for controlling Sipeed NanoKVM devices, enabling remote hardware control via keyboard, mouse, power, and screenshots. It allows AI assistants like Claude to manage headless machines at the BIOS level.
      20
      -