MCP server for IBM Power HMC partition and capacity operations
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file power_hmc_mcp-0.6.2.tar.gz.
File metadata
- Download URL: power_hmc_mcp-0.6.2.tar.gz
- Upload date:
- Size: 341.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d91d14dafe6fc622dce4a5342d9b260d8b64866e0ea2458819f8d270530acb36
|
|
| MD5 |
a0f952f6281d4a8708aca65ed8df351d
|
|
| BLAKE2b-256 |
5567737618474fd01b5d8e26c75799bfd64d817f828b6d19f6eed4805a54c186
|
Provenance
The following attestation bundles were made for power_hmc_mcp-0.6.2.tar.gz:
Publisher:
release.yml on TylrDn/power-hmc-mcp-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
power_hmc_mcp-0.6.2.tar.gz -
Subject digest:
d91d14dafe6fc622dce4a5342d9b260d8b64866e0ea2458819f8d270530acb36 - Sigstore transparency entry: 1615360052
- Sigstore integration time:
-
Permalink:
TylrDn/power-hmc-mcp-server@33ad23c86c82e02a111f6b050bdbc4e16df42bd7 -
Branch / Tag:
refs/tags/v0.6.2 - Owner: https://github.com/TylrDn
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@33ad23c86c82e02a111f6b050bdbc4e16df42bd7 -
Trigger Event:
push
-
Statement type:
File details
Details for the file power_hmc_mcp-0.6.2-py3-none-any.whl.
File metadata
- Download URL: power_hmc_mcp-0.6.2-py3-none-any.whl
- Upload date:
- Size: 89.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b4f6dc158acca152844da70cf5bbb2f639faeb22506f8131717aabc40324e169
|
|
| MD5 |
00da7b52b62dee933cc3e18067633f62
|
|
| BLAKE2b-256 |
8d739df9b24b43759718a3de6a4e5588021c1bf56bf2f46360cdc8a3ff257c25
|
Provenance
The following attestation bundles were made for power_hmc_mcp-0.6.2-py3-none-any.whl:
Publisher:
release.yml on TylrDn/power-hmc-mcp-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
power_hmc_mcp-0.6.2-py3-none-any.whl -
Subject digest:
b4f6dc158acca152844da70cf5bbb2f639faeb22506f8131717aabc40324e169 - Sigstore transparency entry: 1615360060
- Sigstore integration time:
-
Permalink:
TylrDn/power-hmc-mcp-server@33ad23c86c82e02a111f6b050bdbc4e16df42bd7 -
Branch / Tag:
refs/tags/v0.6.2 - Owner: https://github.com/TylrDn
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@33ad23c86c82e02a111f6b050bdbc4e16df42bd7 -
Trigger Event:
push
-
Statement type: