Skip to content
Conduit

mcp server

proxmox-mcp

Proxmox VE MCP server for Claude, Codex, and local-model clients. Read-only by default; typed tools, tests, stdio and Streamable HTTP.

nite-crawler/proxmox-mcpcommunitylistedunreviewed

Set up

Runs on your computer. Pick your agent and operating system.

Before you start

  • uv (`curl -LsSf https://astral.sh/uv/install.sh | sh`)
~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "nite-crawler-proxmox-mcp": {
      "command": "uvx",
      "args": [
        "proxmox-ve-mcp"
      ]
    }
  }
}

same format Cursor, GitHub Copilot CLI, Junie, JetBrains AI Assistant, Augment (Auggie CLI), Factory Droid, Kiro, Devin CLI +12

Values in angle brackets are placeholders. Restart Claude Desktop after editing its config.Claude Desktop docs

README

synced Oct 26, 2026

Proxmox VE MCP

CI License: MIT

Manage Proxmox VE through any client that speaks the Model Context Protocol: Claude Desktop, Claude Code, Codex, or an MCP-capable application using a local model. No model API key or model-specific SDK is required by this server.

Inspect clusters, nodes, QEMU virtual machines, LXC containers, storage, snapshots, and tasks. Opt in to starting, shutting down, rebooting, cloning, backing up, and migrating guests. Track operations through Proxmox task IDs.

Read-only by default. Write tools are absent from discovery until enabled. HTTPS certificate verification is enabled; API token secrets are kept out of startup diagnostics and upstream error messages. Both stdio and local Streamable HTTP are supported through the official MCP Python SDK.

Project status

Community release, version 0.2.2. Automated tests exercise the API adapter, MCP discovery and tool calls, a real stdio subprocess, and Streamable HTTP. Proxmox API responses are mocked: a live Proxmox cluster has not yet been validated. Client examples use standard MCP configuration; individual desktop apps have not been manually certified. Please report compatibility results with your PVE/client version. This project is independent of Proxmox Server Solutions GmbH.

Requires Python 3.11+ and network access from the server process to Proxmox VE. Proxmox Backup Server and Datacenter Manager are different APIs and are not supported.

Quick start

Install from source (no PyPI publication is assumed):

git clone https://github.com/nite-crawler/proxmox-mcp.git
cd proxmox-mcp
python3 -m venv .venv
.venv/bin/python -m pip install --require-hashes --only-binary=:all: -r requirements.lock -r requirements-build.lock
.venv/bin/python -m pip install --no-deps --no-build-isolation .
cp .env.example .env
chmod 600 .env

On Windows, use py -m venv .venv and .venv\Scripts\python.exe in the pip commands. Set restrictive file permissions appropriate to your OS. Edit .env locally:

PROXMOX_URL=https://pve.example.com:8006
PROXMOX_TOKEN_ID=mcp@pve!assistant
PROXMOX_TOKEN_SECRET=replace-with-your-token-secret
PROXMOX_READ_ONLY=true
PROXMOX_VERIFY_SSL=true
# PROXMOX_CA_BUNDLE=/absolute/path/to/proxmox-ca.pem

Create a dedicated Proxmox user and a privilege-separated API token under Datacenter → Permissions → API Tokens. Give the user and token the appropriate ACLs; PVEAuditor on / with propagation is a convenient starting point for cluster-wide monitoring, but exposes cluster-wide inventory. Narrow ACL paths if needed. The token's permissions intersect with the user's permissions. See permissions and deployment before enabling writes.

Use your Proxmox CA certificate or a publicly trusted certificate. The CA bundle must be obtained through a trusted channel; do not work around trust errors by disabling verification on production infrastructure.

Check installation without contacting Proxmox:

.venv/bin/proxmox-mcp --version

Claude Desktop

Merge this entry into your Claude Desktop MCP configuration, replacing both absolute paths. Keep credentials in the env file, not in a shared JSON file.

{
  "mcpServers": {
    "proxmox": {
      "command": "/absolute/path/proxmox-mcp/.venv/bin/proxmox-mcp",
      "args": ["--env-file", "/absolute/path/proxmox-mcp/.env"]
    }
  }
}

On Windows, command is the absolute path to .venv\\Scripts\\proxmox-mcp.exe. Restart the client after changing configuration. See the official local MCP connection guide.

Claude Code

claude mcp add --transport stdio proxmox -- /absolute/path/proxmox-mcp/.venv/bin/proxmox-mcp --env-file /absolute/path/proxmox-mcp/.env

See Claude Code MCP documentation.

Codex

Add to ~/.codex/config.toml, or a trusted project's .codex/config.toml:

[mcp_servers.proxmox]
command = "/absolute/path/proxmox-mcp/.venv/bin/proxmox-mcp"
args = ["--env-file", "/absolute/path/proxmox-mcp/.env"]

Or register with the CLI:

codex mcp add proxmox -- /absolute/path/proxmox-mcp/.venv/bin/proxmox-mcp --env-file /absolute/path/proxmox-mcp/.env

See official Codex MCP documentation.

Local models and other clients

Configure the same command and arguments in an MCP-capable host, or connect to the local HTTP endpoint below. A bare model inference endpoint (including an Ollama API by itself) is not an MCP client: its host application must discover tools, dispatch tool calls, and return the results to the model.

examples/list_nodes.py is a minimal model-independent Python client that launches this server, performs the MCP handshake, discovers tools, and calls list_nodes:

.venv/bin/python examples/list_nodes.py --env-file /absolute/path/proxmox-mcp/.env

Streamable HTTP

Generate a separate bearer token locally, store it as PROXMOX_HTTP_TOKEN in your protected env file, and configure your MCP client to send Authorization: Bearer <that-token>. Never reuse the Proxmox API token secret. Generate a token with:

python3 -c 'import secrets; print(secrets.token_urlsafe(32))'
.venv/bin/proxmox-mcp --env-file .env --transport streamable-http --port 8000

Connect your MCP client to http://127.0.0.1:8000/mcp. HTTP is deliberately bound to IPv4 loopback and uses SDK Host/Origin validation. Every HTTP method requires one valid bearer header; missing/invalid credentials return 401 before MCP processing. HTTP startup fails without a token. The token is a shared credential, not OAuth or per-user authorization: all authenticated clients share the configured Proxmox identity. Rotate it by replacing the env value, restarting, and updating clients. Do not expose the plain HTTP endpoint remotely. A remote deployment needs TLS, appropriate client identity/authorization, and a separate gateway threat model. Legacy HTTP+SSE transport is not provided. stdio does not require an HTTP token.

Available tools

Every successful result has a data field. Read results are filtered through operator-configurable field allowlists; omitted fields must not be treated as unset. Failures become MCP tool errors (isError: true), without raw upstream bodies.

ModeTools
Read-only (default, 14 tools)get_version, get_cluster_status, list_resources, list_nodes, get_node_status, list_storage, list_storage_content, list_guests, get_guest_status, get_guest_config, list_snapshots, list_tasks, get_task_status, get_next_vmid
Sensitive-output opt-ins (independent)get_guest_config_raw with PROXMOX_ALLOW_RAW_CONFIG=true; get_task_log with PROXMOX_ALLOW_TASK_LOGS=true
Write-enabled (7 additional tools)start_guest, shutdown_guest, reboot_guest, clone_guest, create_snapshot, backup_guest, migrate_guest
Destructive opt-in (3 additional tools)stop_guest, delete_snapshot, rollback_snapshot

To expose normal write tools, set PROXMOX_READ_ONLY=false and restart the server. To additionally expose forced stop and snapshot removal/rollback, also set PROXMOX_ALLOW_DESTRUCTIVE=true. These switches are operator configuration, never tool arguments. They do not grant Proxmox permissions. Graceful shutdown, reboot, migration, and some backup modes can still cause downtime in ordinary write mode. MCP annotations describe impact; client-side approval behavior varies by host.

Use guest_type="qemu" for VMs and guest_type="lxc" for containers. Provisioning is supported through clone_guest from an existing guest or template. This release does not expose arbitrary API requests, shell execution, guest deletion, guest configuration updates, or VM creation from scratch.

Writes returning a UPID:... string are asynchronous submissions, not successful completion. Call get_task_status with the source node and that UPID until status is stopped, then check exitstatus == "OK". Use get_task_log for diagnostics when task-log access is enabled. A timeout does not prove a write failed; check list_tasks before retrying. The server intentionally never retries writes automatically.

Example requests to your assistant:

  • “List my VMs and containers and summarize their current state.”
  • “Show storage capacity on pve1 and recent failed tasks.”
  • “Clone template 9000 to VM 101, then monitor the clone task.”
  • “Create a before-upgrade snapshot of VM 101 and confirm the task completed.”

Configuration

Environment variables override values in an explicitly supplied --env-file. The server never implicitly loads a .env from the working directory.

VariableDefaultPurpose
PROXMOX_URLRequiredHTTPS origin, e.g. https://pve.example.com:8006; /api2/json suffix accepted
PROXMOX_TOKEN_IDRequiredFull ID, e.g. mcp@pve!assistant
PROXMOX_TOKEN_SECRETRequiredAPI token secret; at least 16 printable ASCII characters, no whitespace
PROXMOX_VERIFY_SSLtrueCertificate and hostname verification
PROXMOX_CA_BUNDLESystem trustPEM CA bundle path
PROXMOX_TIMEOUT30HTTP timeout in seconds, greater than 0 and at most 300
PROXMOX_OPERATION_TIMEOUT30Total operation/HTTP-request deadline in seconds, including slow response streams (0–300, exclusive of 0)
PROXMOX_MAX_RESPONSE_BYTES4194304Maximum upstream response size; enforced while streaming (1 KiB–128 MiB)
PROXMOX_MAX_REQUEST_BYTES1048576Maximum MCP HTTP request body (1 KiB–4 MiB)
PROXMOX_MAX_CONCURRENT_REQUESTS8Concurrent HTTP requests and concurrent tool API calls per server instance (1–64); excess work is rejected
PROXMOX_HTTP_TOKENUnsetRequired for HTTP; separate random bearer token, 32–256 URL-safe characters
PROXMOX_ALLOW_RAW_CONFIGfalseExpose full guest configuration tool, with known secret fields redacted
PROXMOX_ALLOW_TASK_LOGSfalseExpose task-log tool; logs may contain arbitrary sensitive text
PROXMOX_OUTPUT_FIELDSBuilt-in allowlistsJSON object replacing selected output views' field lists; see output policy
PROXMOX_READ_ONLYtrueOmit write tools and block writes in the API client
PROXMOX_ALLOW_DESTRUCTIVEfalseEnable force-stop, snapshot delete and rollback; requires writes enabled

Ambient HTTP proxy variables are ignored to keep API tokens on the configured direct connection. Redirects are not followed. Logs go to stderr so stdout remains valid MCP traffic. Freeform descriptions/notes and unlisted fields are omitted by default. Known secret keys and configured credential values are redacted recursively. Allowlisted names, statuses, and opted-in raw data can still contain arbitrary sensitive text; only connect clients you trust with your inventory.

Write audit events are emitted at WARNING level even with default settings. Capture stderr and configure retention in your MCP host or service manager. Use --log-level INFO for additional diagnostics; see audit semantics and limitations.

Responses exceeding the byte limit fail without returning partial data. Compressed upstream responses are rejected (the client requests Accept-Encoding: identity) to avoid decompression-based memory exhaustion. Busy HTTP requests return 429; busy stdio tool calls return a tool error. Limits are shared across sessions of one server instance; separately launched processes have separate budgets.

Docker (stdio)

docker build -t proxmox-mcp .
docker run --rm -i --env-file .env proxmox-mcp

Use -i, not -t, to preserve stdio framing. The image runs as a non-root user. The final image excludes pip and its bootstrap files; update dependencies by rebuilding the image, not by installing packages inside a running container. If using a CA bundle, mount it read-only and point PROXMOX_CA_BUNDLE at its container path. Host loopback addresses and paths are not automatically available inside containers. HTTP inside Docker is not exposed by this image.

Development

.venv/bin/python -m pip install --require-hashes --only-binary=:all: -r requirements-dev.lock
.venv/bin/python -m pip install --no-deps --no-build-isolation -e .
.venv/bin/ruff check .
.venv/bin/ruff format --check .
.venv/bin/mypy
.venv/bin/pytest
.venv/bin/python -m build --no-isolation
.venv/bin/pip-audit --require-hashes -r requirements.lock

Tests use synthetic credentials and mocked Proxmox transport; they never require or target a live cluster. Coverage includes branches and enforces a 90% minimum. CI runs the test suite on Python 3.11–3.14 and checks packaging, lint, types, and dependency vulnerabilities. Container CI reports all OS/Python vulnerabilities and blocks HIGH/CRITICAL findings with available fixes; unfixed findings remain in the downloadable report for review. Scheduled weekly CI refreshes the scans. uv.lock and hashed exports pin runtime, development, and build dependencies; the Docker base is digest-pinned and Dependabot proposes weekly updates. See lockfile maintenance. The SDK is bounded to the tested 1.x maintenance line; upgrading to 2.x requires a separate compatibility review.

See CONTRIBUTING.md, SECURITY.md, architecture, and the live validation checklist. The project is distributed under the MIT license.

↑↓ navigate openesc close