pypi proxmox-ve-mcpstdioMITupdated 7d ago
49 tools ā nodes, QEMU VMs, LXC containers, storage, cluster, snapshots.
What can you do with Proxmox VE?
Proxmox MCP server
Simple Proxmox MCP
MCP server for managing Proxmox VE
49 tools ā nodes, QEMU VMs, LXC containers, storage, cluster, snapshots.
Why this one?
- One image, multi-arch ā
docker run ghcr.io/akmalovaa/proxmox-mcp:latestand you're done - Just env vars ā no config files, no database, no state
- Read-only by default ā destructive ops are gated behind an explicit
PROXMOX_RISK_LEVEL - Tiny codebase ā pure stdio MCP over Proxmoxer, no HTTP server, no auth layer, no extras
- Raw JSON out ā no formatting, no emoji; LLM gets clean data
- Readable failures ā a 403, a dead host or a blocked tier come back as a sentence, not a stack trace
Quick start
Image: ghcr.io/akmalovaa/proxmox-mcp:latest (multi-arch: amd64 + arm64).
1. Export credentials in your shell profile (~/.zprofile, ~/.zshrc or ~/.bashrc):
# base environment:
export PROXMOX_HOST=192.168.1.100
export PROXMOX_USER=root@pam
export PROXMOX_PASSWORD=your-password
# or use token auth (recommended):
export PROXMOX_TOKEN_NAME=mcp
export PROXMOX_TOKEN_VALUE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# optional:
export PROXMOX_RISK_LEVEL=read
Reload: source ~/.zprofile (or restart the shell).
2. Add to ~/.claude/settings.json (Claude Code) or claude_desktop_config.json (Claude Desktop):
{
"mcpServers": {
"proxmox": {
"command": "docker",
"args": ["run", "-i", "--rm",
"-e", "PROXMOX_HOST",
"-e", "PROXMOX_USER",
"-e", "PROXMOX_PASSWORD",
"ghcr.io/akmalovaa/proxmox-mcp:latest"]
}
}
}
or token auth:
{
"mcpServers": {
"proxmox": {
"command": "docker",
"args": ["run", "-i", "--rm",
"-e", "PROXMOX_HOST",
"-e", "PROXMOX_USER",
"-e", "PROXMOX_TOKEN_NAME",
"-e", "PROXMOX_TOKEN_VALUE",
"ghcr.io/akmalovaa/proxmox-mcp:latest"]
}
}
}
docker run -e VAR without a value passes the host variable through ā no secrets in the config file. Restart the client ā 31 read-only Proxmox tools become available (more if you raise PROXMOX_RISK_LEVEL).
For password auth, swap the token vars for PROXMOX_PASSWORD.
Note: Claude Desktop on macOS is launched via launchd and does not inherit
~/.zprofile/~/.zshrc. Either put the exports in~/.zshenv, or fall back to an inline"env": { ... }block in the config.
Configuration
All settings are environment variables ā set them in your shell profile, pass them inline to docker run -e, or declare them in your MCP client's env block.
| Variable | Default | Description |
|---|---|---|
PROXMOX_HOST |
ā | Proxmox host (IP or hostname) |
PROXMOX_USER |
root@pam |
API user |
| Auth | ā | token or password ā see below |
PROXMOX_PORT |
8006 |
API port |
PROXMOX_VERIFY_SSL |
false |
Verify TLS certificate |
PROXMOX_RISK_LEVEL |
read |
read / lifecycle / all |
Authentication: token or password
Pick one. If both are set, the token wins.
Token (recommended) ā create in Proxmox UI: Datacenter ā Permissions ā API Tokens ā Add (uncheck Privilege Separation). Then:
export PROXMOX_TOKEN_NAME=mcp
export PROXMOX_TOKEN_VALUE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Password (fallback):
export PROXMOX_PASSWORD=your-password
Risk levels
PROXMOX_RISK_LEVEL controls which tools exist. Tools above the active level are not registered, so they never appear in the MCP client's tool list:
| Level | Tools | Adds |
|---|---|---|
read (default) |
31 | read-only tools |
lifecycle |
45 | + start / stop / reboot / suspend / clone / migrate / create-snapshot |
all |
49 | + delete-snapshot / rollback-snapshot |
Each elevated call is also re-checked at call time and logged to stderr (ALLOW / DENY + tool + tier).
Tools
Nodes (10)
| Tool | Description |
|---|---|
list_nodes |
List all cluster nodes with status, CPU, memory, uptime |
get_node_status |
Detailed node metrics (CPU, memory, disk, load, kernel) |
get_node_networks |
Network interfaces on a node |
get_node_disks |
Physical disks on a node |
get_node_services |
Proxmox system services and their state |
get_node_updates |
Pending APT package updates |
get_node_rrd_data |
Historical CPU/memory/disk/network metrics (RRD) |
get_node_tasks |
Recent tasks on a node, optionally errors only |
get_task_status |
Status of a specific task by UPID |
get_task_log |
Log output from a task |
QEMU VMs (17)
| Tool | Tier | Description |
|---|---|---|
list_vms |
read | List all VMs, optionally filter by node |
get_vm_status |
read | Current VM status (running/stopped, CPU, memory) |
get_vm_config |
read | VM configuration (hardware, disks, network) |
get_vm_network_interfaces |
read | IP addresses of a running VM (via QEMU guest agent) |
get_vm_rrd_data |
read | Historical CPU/memory/disk/network metrics (RRD) |
list_vm_snapshots |
read | List all snapshots of a VM |
start_vm |
lifecycle | Start a VM |
stop_vm |
lifecycle | Force-stop a VM |
shutdown_vm |
lifecycle | Graceful ACPI shutdown with timeout |
reboot_vm |
lifecycle | Reboot via ACPI |
suspend_vm |
lifecycle | Suspend a VM |
resume_vm |
lifecycle | Resume a suspended VM |
clone_vm |
lifecycle | Full or linked clone |
migrate_vm |
lifecycle | Move a VM to another node, online or offline |
create_vm_snapshot |
lifecycle | Create a snapshot |
delete_vm_snapshot |
all | Delete a snapshot |
rollback_vm_snapshot |
all | Rollback to a snapshot |
LXC Containers (13)
| Tool | Tier | Description |
|---|---|---|
list_containers |
read | List all LXC containers, optionally filter by node |
get_container_status |
read | Current container status |
get_container_config |
read | Container configuration |
get_container_interfaces |
read | IP addresses of a running container |
get_container_rrd_data |
read | Historical CPU/memory/disk/network metrics (RRD) |
list_container_snapshots |
read | List all snapshots |
start_container |
lifecycle | Start a container |
stop_container |
lifecycle | Force-stop a container |
shutdown_container |
lifecycle | Graceful shutdown with timeout |
reboot_container |
lifecycle | Reboot a container |
create_container_snapshot |
lifecycle | Create a snapshot |
delete_container_snapshot |
all | Delete a snapshot |
rollback_container_snapshot |
all | Rollback to a snapshot |
Storage (2)
| Tool | Description |
|---|---|
list_storage |
Storage pools with usage, optionally filter by node |
get_storage_content |
Contents of a storage pool (ISOs, backups, images, templates) |
Cluster (7)
| Tool | Description |
|---|---|
get_cluster_status |
Cluster health, quorum, node membership |
get_cluster_resources |
All resources (VMs, containers, storage, nodes) |
get_cluster_backups |
Configured backup jobs |
get_ha_status |
High-availability resources and their state |
list_pools |
Resource pools |
get_cluster_log |
Cluster-wide event log, newest first |
get_next_vmid |
Next available VM/container ID |
Architecture
src/proxmox_mcp/
āāā server.py # MCPServer instance + entry point
āāā config.py # Pydantic Settings (PROXMOX_ prefix)
āāā client.py # Proxmoxer connection via lifespan
āāā tools/ # nodes, vms, containers, storage, cluster
- Read-only by default ā elevated tools gated by
PROXMOX_RISK_LEVEL - Lazy connection ā the Proxmoxer client is built on first use, once, and shared; the server therefore starts cleanly even when Proxmox is unreachable
- Raw JSON output ā compact, no formatting; LLM consumes data directly
- Normalized errors ā Proxmox and network failures are translated into one
actionable sentence instead of a
requeststraceback
Development
Run standalone (testing)
export PROXMOX_HOST=192.168.1.100
export PROXMOX_USER=root@pam
export PROXMOX_TOKEN_NAME=mcp
export PROXMOX_TOKEN_VALUE=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
docker run -i --rm \
-e PROXMOX_HOST -e PROXMOX_USER \
-e PROXMOX_TOKEN_NAME -e PROXMOX_TOKEN_VALUE \
ghcr.io/akmalovaa/proxmox-mcp:latest
Without Docker (UV)
git clone https://github.com/akmalovaa/proxmox-mcp.git && cd proxmox-mcp && uv sync
MCP client config:
{
"mcpServers": {
"proxmox": {
"command": "uv",
"args": ["run", "--directory", "/path/to/proxmox-mcp", "python", "-m", "proxmox_mcp"],
"env": {
"PROXMOX_HOST": "192.168.1.100",
"PROXMOX_TOKEN_NAME": "mcp",
"PROXMOX_TOKEN_VALUE": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
}
}
}
Build from source
git clone https://github.com/akmalovaa/proxmox-mcp.git
cd proxmox-mcp
docker build -t proxmox-mcp .
The image is multi-stage: uv builds the virtualenv in a throwaway layer, and the
runtime stage carries only Python plus the venv and runs as the unprivileged mcp
user (uid 10001).
Lint, type-check, test
uv sync --locked --group dev
uv run ruff check .
uv run mypy src/
uv run pytest -v
License
MIT
Install
Add Proxmox VE to your client. Pick the one you use.
claude mcp add proxmox-ve-mcp -- uvx proxmox-ve-mcpcodex mcp add proxmox-ve-mcp -- uvx proxmox-ve-mcpamp mcp add proxmox-ve-mcp -- uvx proxmox-ve-mcp{
"mcpServers": {
"proxmox-ve-mcp": {
"command": "uvx",
"args": [
"proxmox-ve-mcp"
]
}
}
}Add to `claude_desktop_config.json`, then restart Claude Desktop.
{
"mcpServers": {
"proxmox-ve-mcp": {
"command": "uvx",
"args": [
"proxmox-ve-mcp"
]
}
}
}Add to `~/.cursor/mcp.json`, or `.cursor/mcp.json` for a single project.
code --add-mcp '{"name":"proxmox-ve-mcp","command":"uvx","args":["proxmox-ve-mcp"]}'Or add the block manually to `.vscode/mcp.json` under `servers`.
{
"mcpServers": {
"proxmox-ve-mcp": {
"command": "uvx",
"args": [
"proxmox-ve-mcp"
]
}
}
}Add to `~/.codeium/windsurf/mcp_config.json`.
{
"mcpServers": {
"proxmox-ve-mcp": {
"command": "uvx",
"args": [
"proxmox-ve-mcp"
]
}
}
}Add to `cline_mcp_settings.json` via the MCP Servers panel.
{
"mcpServers": {
"proxmox-ve-mcp": {
"command": "uvx",
"args": [
"proxmox-ve-mcp"
]
}
}
}Add to `~/.gemini/settings.json`.
{
"mcpServers": {
"proxmox-ve-mcp": {
"type": "local",
"command": "uvx",
"args": [
"proxmox-ve-mcp"
],
"tools": [
"*"
]
}
}
}Add to `~/.copilot/mcp-config.json`, or run `/mcp add` inside the CLI.
{
"context_servers": {
"proxmox-ve-mcp": {
"command": {
"path": "uvx",
"args": [
"proxmox-ve-mcp"
]
}
}
}
}Add to your Zed `settings.json`.
uvx proxmox-ve-mcpRun `goose configure`, choose **Add Extension ā Command-line Extension**, and paste this command.
Score
39 / 100
Incomplete
- Documentation25/25
- Maintenance19/25
- Trust13/20
- Capability0/15
- Install experience12/15
- Documents what it does and how to connect
- Has a resolvable package or endpoint
- Exposes at least one tool, prompt or resource
- README has substantive content
- Includes a code example
- Documents its configuration
- Mentions credentials or security posture
- Last commit 0 days ago
- Has a release history
- Repository is not archived
- Licensed MIT
- Namespace verified in the official MCP registry
- Claimed by its owner
- Published under an organisation
- 0 tool(s) documented
- Provides prompt templates
- Provides resources
- 12 documented install method(s)
- Published to a package registry
- Offers a hosted endpoint ā no local install
Version history
| Versions | Published |
|---|---|
| 2.1.1Latest | Sep 1, 2026 |