power-hmc-mcp-server
The missing MCP server for IBM Power. Lets AI agents (Claude Desktop, LangGraph, watsonx Orchestrate, anything that speaks Model Context Protocol) safely look at — and eventually drive — IBM Power servers through their Hardware Management Console.
Status: Phases A, D, E, and F (agent ergonomics) are complete on
main. Read tools work end-to-end; write tools remain Phase A scaffold until Phase C. Open work: Phase B2 firmware captures, Phase C real mutations. Roadmap:TODO.md.IBM doc alignment: schema-aligned with the IBM Power9/10/11 HMC REST documentation for the core resources used by the MCP surface (
ManagedSystem,LogicalPartition,LogicalPartitionProfile, PCMProcessedMetrics). Per-builder citations live indocs/hmc-compatibility.md. Runtime behavioural compatibility (firmware-specific state strings, header echo behaviour, write job operation names, composite quick endpoint shape, retry tuning) is validated only for the firmware versions listed in that compatibility doc — uncaptured firmware behaviour stays[ASSUMED]/[PLACEHOLDER]until rows land.
Why this exists
If you've tried to plug an LLM agent into IBM Power infrastructure, you've probably noticed there is no off-the-shelf MCP server for the Hardware Management Console. That's the gap this fills.
- For developers: A typed, tested, observable bridge between MCP and HMC REST. You don't have to learn IBM's XML/Atom feeds or session-token dance. Call
list_lpars(...)and get JSON. - For operators: A read-only-by-default control plane with structured logging, correlation IDs that span the HMC boundary, secret redaction, and an audit event on every write attempt.
- For security teams: Writes are off by default. When enabled, every attempt — including denials — emits a
write_auditlog event with a stable schema. The dry-run / authorized split is enforced by the type system, not by convention.
What you get
- 8 read tools that work today against a real HMC: list/get managed systems, list/get LPARs, LPAR status, partition profiles, capacity samples, health check.
- 3 write tools registered behind a flag:
start_lpar,stop_lpar,create_lpar_from_profile— Phase A scaffold; Phase C wires real HMC mutation payloads. - Two transports:
stdio(default; for Claude Desktop / local LangGraph) andstreamable-http(for shared / containerized deployments behind a gateway). - Observability built in: structured JSON logs,
X-Correlation-IDpropagation to the HMC by default,write_auditevents, secret redaction. - Strong defaults: TLS verification on, allowlist available, write tools off, retries conservative on writes.
Quick start
1. Install
git clone https://github.com/TylrDn/power-hmc-mcp-server.git
cd power-hmc-mcp-server
python3.12 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
2. Point it at your HMC
cp .env.example .env
# edit .env: HMC_HOST, HMC_USERNAME, HMC_PASSWORD (and HMC_VERIFY_TLS=false for self-signed labs)
3. Run
python -m power_hmc_mcp.mcp_server
That's it — the server is now waiting on stdio. To verify against a real MCP client without writing one yourself:
python integrations/langgraph/example_list_lpars_stdio.py <managed-system-uuid>
The script spawns the server, lists tools, and calls list_lpars for one managed system. Get the UUID from list_managed_systems first if you don't have one handy.
4. Connect Claude Desktop (optional)
Drop the snippet from examples/claude_desktop_config.json into Claude Desktop's settings (Settings → Developer → Edit Config), replace the CHANGE_ME-… values, restart Claude. You'll see the power-hmc tools available in the conversation.
Mental model
You don't need to know much about IBM Power to use this — but here's the minimum for context. (Full definitions in the glossary.)
- HMC = the appliance that controls one or more IBM Power servers via REST. This server is a thin, opinionated bridge to that REST API.
- Managed system = a Power server. The HMC sees it by UUID.
- LPAR = a virtual machine on a managed system (PowerVM hypervisor's unit of compute).
- MCP = the open protocol your agent speaks. Tools have typed JSON contracts; agents call
list_lparslike a function.
What flows through:
your agent (LangGraph, Claude, …)
│ speaks MCP
▼
power-hmc-mcp-server (this repo) ← the layered bridge
│ speaks HMC REST + correlation header
▼
HMC (HTTPS, port 12443 by default)
│
▼
Power servers / LPARs
The agent never sees raw HMC XML; this server normalizes everything to JSON. Logs on both sides of the HMC boundary share a correlation_id so a request is one search away.
What you can do today
Read (always available)
| Tool | Plain-English purpose | Typical agent prompt |
|---|---|---|
list_managed_systems |
List every Power server this HMC controls. | "Show me every Power server my HMC manages." |
get_managed_system |
Full detail for one Power server (name, state, MTMS, processor pool). | "Tell me about this managed system." |
list_lpars |
List every LPAR (VM) on one Power server. | "List the virtual machines on this managed system." |
get_lpar |
Full LPAR config — processors, memory, partition type, RMC state. | "Give me the full detail for this LPAR." |
get_lpar_status |
Run state in raw and canonical form for one LPAR. | "Is this LPAR running? What state is it in?" |
list_partition_profiles |
Saved configuration profiles for one LPAR. | "What saved configurations exist for this LPAR?" |
get_capacity |
PCM utilization samples for one Power server (mode=summary or metadata). |
"How busy is this server?" |
health_check |
Server up, HMC reachable, session alive — no inventory leak. | "Is the HMC reachable right now?" |
managed_system_id and lpar_id are HMC REST UUIDs (you get them from list_* calls), not partition numbers or hostnames.
JSON contracts vs. firmware behaviour. The JSON shape each read tool returns is stable and enforced by tests/test_contracts.py — keys, types, and route URLs are schema-aligned with the IBM Power9/10/11 HMC REST documentation. Firmware-dependent behaviours (LPAR state strings, correlation header echo, composite quick endpoint shape, write OP names) are documented separately in docs/hmc-compatibility.md. Agents should branch on the normalized fields surfaced in the tool contracts (e.g. canonical_state from get_lpar_status) rather than on raw firmware strings; the canonical fields are exactly what stays stable across firmware levels.
Write (off by default)
start_lpar, stop_lpar, create_lpar_from_profile register only when HMC_ENABLE_WRITE_TOOLS=true. They take an execute=true|false flag (default false); see Write safety in plain English below.
For full inputs/outputs and sample JSON payloads see the agent guide.
Agent-safe output behavior
Phase F adds deterministic response shapes so orchestrators can branch without guessing:
- List tools (
list_managed_systems,list_lpars,list_partition_profiles) return a paginated envelope — not a bare array. Useresult["items"]for entries andresult["summary"]for counts. Pass optionallimit/offsetto paginate; when truncated,summary.next_offsettells you the next page.summary.truncatedis always explicit. - Capacity — use
get_capacity(..., mode="summary")for a small payload;mode="metadata"is already bounded by the HMC query (one sample window per call). - Write denials — every write envelope includes
guardrail_outcome(denied,preview, orauthorized_placeholder) and a deterministicsuggested_next_step. Denied responses also includedenial_reason_code(writes_disabledorexecute_required) so agents can recover without parsing free-form text.
Migration (Phase F — list tool contract change). If your agent still expects a top-level JSON array from list tools, update accessors:
| Before (pre–Phase F) | After (Phase F) |
|---|---|
result[0]["name"] |
result["items"][0]["name"] |
len(result) |
result["summary"]["total_count"] |
| (n/a) | Continue pages with offset=result["summary"]["next_offset"] when truncated is true |
items order matches the HMC Atom feed order for that call (stable for offset pagination within one snapshot; inventory may change between calls).
Details: agent guide: list envelopes and pagination.
Write safety in plain English
The short version: the server cannot accidentally mutate your HMC. Here's the chain of locks, in order, in plain language:
- Off by default. The write tools aren't even registered with MCP unless you set
HMC_ENABLE_WRITE_TOOLS=true. Agents simply cannot call what isn't there. - Dry-run by default. Even after enabling, every write tool defaults to
execute=false. The agent sees a JSON envelope describing what would happen. Nothing leaves the server. - Type-system gate. When the agent passes
execute=true, the server's internal write methods refuse to run unless they receive a special "permission token" (WriteAuthorization). That token can only be created by one specific helper — the one that just ran the dry-run / denial logic. There is no other way to obtain one. (Bothmypyand a runtimeisinstancecheck enforce this.) - Audited every time. Every write attempt — denied, dry-run, or authorized — emits a
write_auditlog event with a stable schema (tool_name,operation,outcome,reason,execute_requested,correlation_id). Denials are not silent. - Boot-time check. If a contributor adds a new write tool but forgets to wire it through the guardrail, the server refuses to start. The mistake is impossible to deploy.
- Phase A is still placeholder. Even on the authorized path, the current code returns
executed=false, placeholder=trueinstead of POSTing to the HMC. Real mutation lands in Phase C, after the IBM payload schemas are validated. Until then, you literally cannot break anything.
For the engineering details, see architecture: write safety model. For the audit schema your SIEM should pin on, see operations: write_audit schema.
Configuration (essentials)
Full reference: operations: configuration reference. Quick essentials:
| Variable | What it does |
|---|---|
HMC_HOST / HMC_PORT / HMC_USERNAME / HMC_PASSWORD |
HMC connection (required). |
HMC_VERIFY_TLS (default true) |
TLS verification. Use HMC_CA_BUNDLE=/path/to/ca.pem for corporate PKI; false only for self-signed labs. |
HMC_ALLOWED_MANAGED_SYSTEMS |
Optional comma-separated UUID allowlist. Reduces blast radius. |
HMC_ENABLE_WRITE_TOOLS (default false) |
Register write tools with MCP. Off ⇒ truly no write surface. |
HMC_REQUIRE_EXECUTE_FLAG (default true) |
Require execute=true to leave dry-run. Keep on. |
HMC_LOG_JSON (default false) |
Single-line JSON logs (preferred for shippers). |
HMC_MCP_TRANSPORT (default stdio) |
stdio or streamable-http. See transports. |
HMC_DEPLOYMENT_MODE (default development) |
development / controlled / production. Documents intent today. |
HMC_API_VERSION_HINT (default unset) |
Optional firmware/API version hint (e.g. V11R1). Logging hint only — surfaced on session_logon_end / session_logoff_end and the startup log line. Does NOT flip firmware-gated behaviour. See operations. |
Connecting an agent
| Agent / host | How |
|---|---|
| Claude Desktop | Use examples/claude_desktop_config.json. Settings → Developer → Edit Config → paste & edit → restart. |
| LangGraph | The MCP server runs as a stdio subprocess; see integrations/langgraph/ for the working example. |
| Custom MCP client (Python) | Stdio: mcp.client.stdio.stdio_client(...). HTTP: mcp.client.streamable_http.streamablehttp_client(...). See transports for full snippets. |
| Org MCP gateway / multi-tenant | Run the server with HMC_MCP_TRANSPORT=streamable-http, bind to loopback, terminate TLS / mTLS / SSO at the gateway. See transports: streamable HTTP. |
Documentation map
- Glossary — every term defined once. Start here if any acronym in this README was unfamiliar.
- Architecture — module map, request walkthrough, write boundary, design rationale, "how to add a tool" recipes.
- Operations — full config reference, log event types,
write_auditschema, exception map, deployment modes, runbook entries. - Transports — stdio vs streamable HTTP, with full client snippets.
- Agent caller guide — what your agent will actually see (sample JSON inputs/outputs and error shapes).
- Roadmap (
TODO.md) — phased plan with[PLACEHOLDER]/[RISK]/[ASSUMPTION]markers. - Release engineering — Codecov, PyPI OIDC, milestones, CI workflows (maintainers).
- Changelog (
CHANGELOG.md) — notable changes per release (0.1.0a0…0.1.0). - Milestone evaluation — team gate between major phases (current: Phase A → B).
- Contributing (
CONTRIBUTING.md) — dev setup, the new-tool recipe, the things not to work around.
Security and design constraints
This server touches live infrastructure. The defaults reflect that:
- Read-only out of the box.
HMC_ENABLE_WRITE_TOOLS=false. No mutation surface until you opt in. - Least privilege. The HMC user behind
HMC_USERNAMEshould have only what the exposed tools need. - No credentials in logs.
RedactingFiltermasks passwords, session tokens, bearer tokens, and HMC<Password>XML. - Resource IDs are validated. UUIDs are checked before they go into HMC URL paths (defense against path traversal).
- TLS verified by default. Disable only for self-signed labs; prefer
HMC_CA_BUNDLEfor corporate-PKI HMCs. - Allowlist available. Set
HMC_ALLOWED_MANAGED_SYSTEMSfor non-prod pilots. - Approval for destructive operations. Write tools today are placeholder-backed; future destructive surfaces (delete, etc.) will require explicit approval flows, not just
execute=true. - Structural write boundary. The dry-run / authorized split is enforced by the type system and module boundaries — see architecture: write safety model.
Status & roadmap
Shipped on main: Phase A foundation (v0.1.0), Phase D transport/deployment (v0.4.0b1), Phase E observability export (OTEL), Phase F agent ergonomics (tool metadata, list envelopes, denial hints).
In progress / open: Phase B2 firmware captures; Phase C write-path execution; Phase G–I per TODO.md.
See TODO.md for the full phased roadmap (A through I) with [RISK], [PLACEHOLDER], and [ASSUMPTION] markers throughout.
License
MIT. See LICENSE.
Metadata
Release files for power-hmc-mcp 0.7.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| power_hmc_mcp-0.7.1.tar.gz | 353.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| power_hmc_mcp-0.7.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 448.6 kB
Release files / power_hmc_mcp-0.7.1.tar.gz
| Download URL | power_hmc_mcp-0.7.1.tar.gz |
|---|---|
| Size | 353.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5f0a68003107e138d2c6fad06480dc20e10c90f3518e0ff62ce7e48cc474a602
|
|
BLAKE2b-256 checksum How to use checksums |
2619b8923924c857c8783caf5e6d373b33bfe8b4089163e796548ef2ca842f00
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 23, 2026.
Transparency logRelease files / power_hmc_mcp-0.7.1-py3-none-any.whl
| Download URL | power_hmc_mcp-0.7.1-py3-none-any.whl |
|---|---|
| Size | 94.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8446b344899e224a9d23143b76122141743ed3a330c7e2771f0d8c85a0dbca6f
|
|
BLAKE2b-256 checksum How to use checksums |
fdcf56cc18af69dfacf36107157377fb84594dc14439c09b262fa7b1807805fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 23, 2026.
Transparency log