Reading needs no key.
Each vendor puts the same facts in different places. rackhands knows where to look and gives every box the same shape: inventory, health rollup, sensors, event log, power, firmware, boot order. You get a table for you, JSON for scripts, and structured tool results for agents.
$ rackhands health
CRITICAL db-01 (Dell, via redfish)
Critical subsystem power supplies — iDRAC rollup
Critical psu PS2 Status — reading 0 W
CRITICAL web-07 (HPE, via redfish)
Warning subsystem Fans — iLO aggregate health
Critical fan Fan 3 — reading 0 %
OK k8s-12 (Lenovo, via redfish)
WARNING x11-bk (Supermicro, via redfish)
Warning voltage VBAT — reading 2.71 V
WARNING lab-x10 (Supermicro, via ipmi (fallback))
Warning temperature PSU2 Temp — reading 117 C
| Dell iDRAC | HPE iLO | Lenovo XCC | Supermicro | |
|---|---|---|---|---|
| Hardware log | LogServices/Sel | LogServices/IML | LogServices/PlatformLog | Managers/1/LogServices/Log1 |
| Health rollup | Oem.Dell.DellSystem *RollupStatus | Oem.Hpe.AggregateHealthStatus | Status.HealthRollup | Status.HealthRollup |
| Sensors | Thermal + Power | Thermal + Power (0 = no threshold) | Sensors collection | Thermal + Power |
| Virtual media | standard InsertMedia | Oem.Hpe InsertVirtualMedia | standard InsertMedia | OEM only on X11 |
Two keys and a signature.
Power, boot override, BMC reset, firmware update and virtual media are off until you open them. Like a deposit box, each one needs both keys:
- The vault key,
--allow power, given when you start rackhands. Over MCP, a class you didn't allow is not even listed as a tool. - The renter's key,
allow: [power], on that box intargets.yaml. A typo in the target name can't reach a box nobody opened. - The register. You type the box's name, or pass
--yes db-01. An agent gets a plan and a single-use token bound to that exact request. It hands the token back only after you say yes. Every plan and execution is written to the audit log.
One box at a time: all and tag: work for reads and are refused for anything dangerous.
PLAN power force-off db-01 (Dell PowerEdge R750, ResetType=ForceOff, currently On) POST /redfish/v1/Systems/System.Embedded.1/Actions/ComputerSystem.Reset via redfish DONE db-01: accepted (HTTP 204)
$ rackhands power db-01 force-off rackhands: operation not allowed: "power" is off; start with --allow power (dangerous operations are disabled by default) exit 3
When Redfish isn't home, IPMI answers.
Give a box both addresses. rackhands asks Redfish first and falls back to IPMI 2.0 (lanplus) when Redfish is unreachable, missing the feature, or answers 404, 501 or 503. It never falls back on a bad password, so a wrong credential is not hidden by trying again on another protocol. Older Supermicro and Dell boards, and cheap boards that only speak IPMI, give the same health, sensors, SEL, FRU inventory and power. Every result says which protocol answered.
$ rackhands --json inventory lab-x10 | jq '{via, fallback_reason}'
{
"via": "ipmi (fallback)",
"fallback_reason": "redfish unreachable (connection refused)"
}
For agents: same binary, rackhands mcp.
Read tools carry readOnlyHint and work out of the box: get_health, get_sensors, get_event_log, get_inventory, get_firmware_inventory, get_boot_config, get_power_state, list_targets. Dangerous tools exist only if you start the server with --allow. Even then, the first call returns a plan and a token. The second call needs that token, and the server's instructions tell the agent to get your yes first. If it reuses the token, changes the action, or waits two minutes, it is refused.
{"mcpServers": {"rackhands": {
"command": "rackhands",
"args": ["mcp"],
"env": {"BMC_PASSWORD": "…"}
}}}
→ power_action {target: "db-01", action: "force-off"}
← {"status": "confirmation_required",
"plan": {…}, "confirm_token": "rh1-…"}
→ power_action {…, confirm_token: "rh1-…"}
← {"status": "done", "result": "accepted (HTTP 204)"}
Tested against a real Redfish service and a real IPMI BMC.
Every push runs the binary against the DMTF Redfish-Mockup-Server. It serves DMTF's own mockup plus Dell R750, HPE DL380, Lenovo SR650 V2 and Supermicro X11 mockups that carry each vendor's quirks. It also runs against OpenIPMI's ipmi_sim over a real lanplus session. CI checks vendor detection, health, logs and sensors, and every refusal path. It checks that a boot override PATCH persists, and that IPMI chassis power goes off and comes back on. It also drives the MCP server over stdio through the full plan → token → done flow.
Install
$ go install github.com/Blackman99/rackhands/cmd/rackhands@latest # or a single static binary for linux / macOS / windows (amd64, arm64): # https://github.com/Blackman99/rackhands/releases/latest $ rackhands --host https://10.20.0.11 --user root health
Read the docs: config file, every command, vendor notes, the safety model, MCP setup and exit codes.
Article: Giving an AI agent your BMCs without the power button · 中文版