Skip to main content
Glama
masridigital

Proxmox MCP broker

by masridigital

Proxmox MCP broker

This repository lets Claude operate a Proxmox VE cluster through the Model Context Protocol (MCP), behind Cloudflare Access, with per-person accountability.

It is a fork of ry-ops/proxmox-mcp-server by ry-ops (MIT license), imported at upstream commit 7276144. The 340 Proxmox tools and their handlers are the upstream code. This fork adds the security layers around them: identity, policy, per-user API tokens, verified TLS, output filters and a hash-chained audit log.

Contents

Related MCP server: proxmox-mcp

Architecture

The system has two parts on two sides of a trust boundary:

  • The Cloudflare Worker (worker/) is the inbound gateway. It speaks MCP to Claude. It holds no Proxmox credential.

  • The broker (this Python package) is the outbound gateway. It runs on an on-premises Windows Server host. It holds the Proxmox API tokens and makes the final policy decision.

Claude (claude.ai, Desktop, Code)
  |
  |  HTTPS, OAuth (Cloudflare Access Managed OAuth, Entra ID with MFA)
  v
Cloudflare MCP Server Portal + Access application (named users only)
  |
  v
Cloudflare Worker  https://<worker-hostname>/mcp
  |  - verifies the Access JWT again (RS256, team keys, issuer, audience)
  |  - JSON-RPC allowlist, size cap, per-user rate limit
  |  - 3 meta-tools: list_tools, describe_tool_input, execute_tool (MCP-STD-02)
  |  - signs an Ed25519 identity assertion for each broker call
  |  - redacts secrets and PHI patterns, labels results as untrusted data
  |
  |  Workers VPC binding, or Access service token, over a Cloudflare Tunnel
  v
cloudflared (Windows service, outbound connections only)
  |
  v
Broker  http://127.0.0.1:<port>   GET /healthz, GET /v1/catalog, POST /v1/execute
  |  - verifies the Access service-token JWT (the caller is the Worker)
  |  - verifies the identity assertion (signature, 60 s life, body hash, replay cache)
  |  - enrollment: user email -> mode (ro, operator, rw) and Proxmox token
  |  - tool policy, strict argument validation, rate limit
  |  - upstream tool handler
  |  - outbound policy: method and path allowlist per mode, deny list, PHI check
  |  - audit: one hash-chained JSON line per event, no argument values
  |
  |  HTTPS, TLS 1.2 or later, CA bundle or SHA-256 certificate pin
  v
Proxmox VE API  https://<proxmox-host>:8006   (one privilege-separated token per person)

The Proxmox API tokens never leave the broker host. Cloudflare holds no Proxmox credential. The broker holds only the public half of the Worker signing key, so a broker compromise cannot forge identities.

Read docs/ARCHITECTURE.md for the full design.

Security model

Each layer fails closed. A later layer does not trust an earlier layer.

Layer

Control

Where

Person

Entra ID login with MFA. Access policy names each user.

Cloudflare Access

Session

Access token 10 min. OAuth session 8 h. Identity assertion 60 s.

Access, Worker

Gateway

JWT verified again, JSON-RPC allowlist, 256 KB cap, rate limit.

worker/

Broker entry

Service-token JWT, Host allowlist, no Origin, 256 KB cap.

proxmox_mcp/transport/http_app.py

Identity

Ed25519 assertion bound to body, method and path. Single use.

proxmox_mcp/transport/identity_assertion.py

Access list

enrollment.json maps each email to one mode and one token.

proxmox_mcp/enrollment.py

Tool policy

Every tool has a tier. Unknown tools are forbidden.

proxmox_mcp/policy.py

Arguments

Strict JSON Schema check. Path values have fixed patterns.

proxmox_mcp/router.py

Outbound

Method and path allowlist per mode. DELETE needs rw. Deny list for tokens, TFA, consoles, guest agent exec.

proxmox_mcp/outbound.py

PHI

Writes that contain PHI patterns are refused. Results are redacted.

proxmox_mcp/phi.py, proxmox_mcp/output.py

Proxmox

One privilege-separated API token per person. Proxmox ACLs limit each token.

Proxmox VE

TLS

Verified chain or SHA-256 pin. No redirects. No proxy settings from the environment.

proxmox_mcp/client.py

Output

Secret fields redacted. 2 MiB cap. Untrusted-data label on every result.

proxmox_mcp/output.py

Audit

Hash-chained JSONL with user, ray ID, tool, method, path, status. Keys and a hash of arguments, never values.

proxmox_mcp/audit.py

Secrets are files, not environment variables. On Windows they are in the broker credentials directory, protected by DPAPI and by an ACL for the service account. On Linux they are systemd credentials.

Read docs/SECURITY.md for the threat model and risk register.

Modes and tool tiers

Each tool has one tier. Each enrolled person has one mode.

Tier

Tools

What it covers

read

140

GET only: inventory, status, configuration, logs, tasks.

operate

16

Reversible guest lifecycle: start, stop, shutdown, reboot, reset, suspend, resume, snapshot create.

admin

80

Guest create, clone, delete, configuration, disks, migration, guest firewall, pools, HA, backup jobs, SDN.

forbidden

104

Never available: users, tokens, ACLs, TFA, passwords, consoles, guest agent exec and files, cloud-init user data, host power and network, host disks, cluster firewall, certificates, storage definitions, notification endpoints.

Mode

Tiers

Tools

ro

read

140

operator

read, operate

156

rw

read, operate, admin

236 when MCP_ALLOW_ADMIN_TOOLS=1, else 156

The default for every new person is ro. Admin tools stay off until the operator sets MCP_ALLOW_ADMIN_TOOLS=1 on the broker. MCP_TOOL_DENY and MCP_TOOL_ALLOW can restrict the set more. They cannot add a tool.

Compliance gate

This build is designed for HIPAA Security Rule and SOC 2 audits.

Go-live gate. Protected health information (PHI) can pass through Cloudflare and Anthropic. Do not connect a system that holds PHI until a Business Associate Agreement (BAA) is signed with both Cloudflare and Anthropic.

The tools that read guest content are forbidden, and PHI patterns are redacted and refused on writes. These controls reduce exposure. They do not replace the BAA.

Read docs/COMPLIANCE.md for the control map and the evidence that an auditor collects.

Configuration

The broker reads its settings from environment variables and its secrets from the credentials directory. .env.example lists every setting with a safe example value. Do not put a token or a password in .env.

The credentials directory contains:

File

Content

enrollment.json

The access list: email, mode, Proxmox user ID, name of the token file.

pve-token-<name>

One line: <user>@<realm>!<token-name>=<secret>. One file per person.

worker-identity.pub

The Worker's Ed25519 public key (PEM).

Example enrollment.json:

{
  "users": {
    "alice@example.com": {
      "mode": "ro",
      "proxmox_userid": "mcp-alice@pve",
      "token_credential": "pve-token-alice"
    }
  }
}

Read docs/RUNBOOK.md to install the broker, enroll a person, rotate a token, and stop the service in an emergency.

Local development

You can run the upstream stdio server on a workstation, against a lab cluster:

uv venv -p 3.12 .venv
uv pip install -p .venv -e . pytest pytest-asyncio ruff
export PROXMOX_HOST=pve.example.internal
export PROXMOX_TLS_FINGERPRINT=<sha256-of-the-proxmox-certificate>
export PROXMOX_USER=dev@pve PROXMOX_TOKEN_NAME=mcp
read -rs PROXMOX_TOKEN_VALUE && export PROXMOX_TOKEN_VALUE
.venv/bin/proxmox-mcp-server

The stdio server runs as the local identity. Its mode is MCP_LOCAL_MODE (default ro). Use a lab token with few privileges. Do not use stdio mode on the broker host.

Tests

.venv/bin/pytest -q --no-cov
.venv/bin/ruff check proxmox_mcp tests

The tests run offline. The end-to-end tests (tests/test_e2e_*.py) start the real broker application with a temporary credentials directory and drive it as the Worker does. They execute every tool as ro, operator and rw, and check that:

  • the decision agrees with the tool tier;

  • a denied call never reaches Proxmox;

  • an allowed call reaches Proxmox only with the caller's own token, and makes the same Proxmox calls as the upstream handler (tests/fixtures/upstream_calls.json);

  • each result has the untrusted-data label, and secrets and PHI are redacted;

  • the audit log has one line for each side, and the hash chain is intact.

tests/test_e2e_tls.py uses a real local TLS server with a pinned self-signed certificate. With a wrong pin, no request byte reaches the server.

Documents

Document

Content

docs/ARCHITECTURE.md

Components, data path, trust boundaries.

docs/SECURITY.md

Threat model and risk register.

docs/COMPLIANCE.md

HIPAA and SOC 2 control map with evidence.

docs/RUNBOOK.md

Installation, operation, incident response.

worker/README.md

The Cloudflare Worker.

USAGE.md

How Claude finds and runs tools.

CHANGELOG.md

Changes by version.

Changes from upstream

  • The tool handlers are unchanged, with one fix: analyze_schedule uses GET, as the Proxmox API defines it.

  • Removed: password and ticket authentication, PROXMOX_VERIFY_SSL, one shared token for all users, and the stdio container as a deployment.

  • Added: the broker HTTP API, identity assertions, enrollment, tool tiers, outbound policy, PHI filter, output redaction, the audit log and the worker/ gateway.

  • setup.sh and test-connection.sh no longer write or use secrets. They point to the runbook.

  • PROXMOX_READ_ONLY=true still works. It is a kill switch for all writes on top of the modes.

Credits and license

The Proxmox tools, their schemas and their handlers are the work of ry-ops in proxmox-mcp-server. Thank you.

MIT license. See LICENSE. The copyright notice of ry-ops stays in LICENSE and applies to the upstream code and to this fork.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables LLM agents to monitor and manage a Proxmox VE cluster, including cluster status, VM/container lifecycle, and node actions via MCP tools.
    8
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude to manage a Proxmox VE host through natural language, including guest lifecycle, snapshots, host status monitoring, and shell execution via a companion bridge.
    24 npm
    1
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables Claude to manage a Proxmox cluster through chat: inventory, power control, configuration changes, VM/container creation and cloning, snapshots, network/firewall/cluster visibility, guest command execution, and file writes via the QEMU Guest Agent.
    24 npm
    MIT