What it does
proxmox-mcp is an open-source Model Context Protocol server for Proxmox VE, the open-source virtualization platform. It gives an AI client (Claude Desktop, Claude Code, OpenClaw, Codex CLI, or any MCP host) a structured, gated interface to a Proxmox cluster: inventory VMs and LXC containers, inspect node and storage status, read RRD metrics, trace tasks, manage snapshots and backups, run gated reads and shell commands inside guests, and provision, clone, or destroy resources, all over Proxmox API-token auth.
It is built for homelab and virtualization operators who want to point an agent at their cluster without handing it a root shell. The differentiator is the write-safety model: 96 tools split across four tiers, where reads need nothing, safe writes need confirm: true, and destructive operations need confirm: true + destructive: true + a process-level PROXMOX_ENABLE_DESTRUCTIVE=1 env flag. A hallucinated or careless tool call fails closed, before any HTTP traffic reaches Proxmox.
Proof
A real MCP client config. Drop this into Claude Desktop (claude_desktop_config.json) and the 96 tools appear in the client. Reads work immediately; the destructive env gate stays off until you opt in.
{
"mcpServers": {
"proxmox": {
"command": "npx",
"args": ["-y", "@solomonneas/proxmox-mcp"],
"env": {
"PROXMOX_URL": "https://192.0.2.10:8006",
"PROXMOX_TOKEN_ID": "pve-admin@pam!api-token-1",
"PROXMOX_TOKEN_SECRET": "00000000-0000-0000-0000-000000000000",
"PROXMOX_TLS_INSECURE": "false"
}
}
}
}
Tool list (96 tools, verified against source)
Tier markers below are authoritative: each tool's gate is enforced in code (src/gates.ts + per-tool schema), and WriteGateError fires before any HTTP call when a gate is unmet.
Generated from docs/assets/workflows/proxmox-safety.json with lidless workflow.
| Tool | Tier | Notes |
|---|---|---|
proxmox_status |
1 read | Cluster + node status. |
proxmox_list_containers |
1 read | LXC inventory across all nodes. |
proxmox_list_vms |
1 read | QEMU inventory across all nodes. |
proxmox_get_resource |
1 read | Single container or VM config + status by vmid. |
proxmox_get_vm_config |
1 read | QEMU VM config by vmid. |
proxmox_get_container_config |
1 read | LXC container config by vmid. |
proxmox_validate_qemu_smoke_source |
1 read | Preflight a QEMU VM before live smoke cloning. |
proxmox_audit_permissions |
1 read | Inspect effective permissions across smoke-relevant paths. |
proxmox_recent_tasks |
1 read | Recent UPID task list per node. |
proxmox_list_backups |
1 read | Backup inventory by storage. |
proxmox_resource_usage |
1 read | CPU/mem/disk RRD metrics. |
proxmox_list_templates |
1 read | LXC + VM templates available for cloning + container creation. |
proxmox_list_storage |
1 read | Storage status on one node or all nodes. |
proxmox_list_snapshots |
1 read | Snapshot inventory for one LXC or VM. |
proxmox_guest_network |
1 read | Guest network interfaces and usable IPv4 addresses. |
proxmox_wait_task |
1 read | Poll a UPID until stopped or timeout. |
proxmox_next_vmid |
1 read | Get the next available VMID for provisioning. |
proxmox_list_pool_resources |
1 read | Inspect resources assigned to a Proxmox pool, defaulting to mcp-smoke. |
proxmox_get_task_status |
1 read | Single UPID status lookup. |
proxmox_get_task_log |
1 read | Task log tail for a UPID. |
proxmox_list_storage_content |
1 read | List volumes on a storage: ISOs, templates, disk images, backups. |
proxmox_list_node_services |
1 read | Host systemd service states (pveproxy, pvedaemon, corosync). |
proxmox_list_disks |
1 read | Physical disks with model/size/SMART health/wearout. |
proxmox_list_updates |
1 read | Pending APT updates on a node (needs a Sys.Modify token). |
proxmox_list_firewall_rules |
1 read | Firewall rules at cluster/node/guest scope. |
proxmox_get_firewall_options |
1 read | Firewall enable state + default policy at a scope. |
proxmox_list_storage_config |
1 read | Datacenter storage definitions (id/type/content/nodes). |
proxmox_list_backup_jobs |
1 read | Scheduled vzdump backup jobs. |
proxmox_list_users |
1 read | Access users (userid, realm, enabled state). |
proxmox_list_roles |
1 read | Roles and their privileges. |
proxmox_list_acl |
1 read | ACL entries: who holds which role on which path. |
proxmox_list_pools |
1 read | All resource pools. |
proxmox_list_tokens |
1 read | API tokens for a user. |
proxmox_cluster_status |
1 read | Cluster membership + quorum per node. |
proxmox_ha_status |
1 read | HA manager status: quorum, fencing, resource states. |
proxmox_list_ha_resources |
1 read | HA-managed resources. |
proxmox_list_ha_rules |
1 read | HA rules (PVE 9+ replacement for HA groups). |
proxmox_list_replication |
1 read | Storage replication jobs. |
proxmox_list_sdn_zones |
1 read | SDN zones. |
proxmox_list_sdn_vnets |
1 read | SDN virtual networks. |
proxmox_list_metric_servers |
1 read | External metrics servers (InfluxDB/Graphite). |
proxmox_get_cluster_options |
1 read | Datacenter options (keyboard, MAC prefix, tags). |
proxmox_cluster_log |
1 read | Recent cluster-wide log entries. |
proxmox_read_file |
2 gated guest read | Read a file from inside an LXC or QEMU VM (SSH + cat). Requires confirm: true. |
proxmox_stat_path |
2 gated guest read | Inspect guest path metadata. Requires confirm: true. |
proxmox_list_directory |
2 gated guest read | List one guest directory. Requires confirm: true. |
proxmox_service_status |
2 gated guest read | Read systemd service state inside a guest. Requires confirm: true. |
proxmox_start_resource |
2 safe-write | Boot container or VM. Requires confirm: true. |
proxmox_stop_resource |
2 safe-write | Graceful shutdown. Requires confirm: true. |
proxmox_reboot_resource |
2 safe-write | Reboot in place. Requires confirm: true. |
proxmox_snapshot_resource |
2 safe-write | Create named snapshot. Requires confirm: true. |
proxmox_run_backup |
2 safe-write | Trigger vzdump for a vmid. Requires confirm: true. |
proxmox_create_container |
2 safe-write | Provision new LXC from template (POST /nodes/{node}/lxc). Requires confirm: true. |
proxmox_create_vm |
2 safe-write | Provision new QEMU VM (POST /nodes/{node}/qemu). Requires confirm: true. |
proxmox_clone_resource |
2 safe-write | Clone existing container or VM into a fresh vmid. Requires confirm: true. |
proxmox_exec |
2 safe-write | Run a shell command inside an LXC or QEMU VM. Returns stdout/stderr/exit_code. Requires confirm: true. |
proxmox_write_file |
2 safe-write | Write a text file (with parent dirs) inside an LXC or QEMU VM. Requires confirm: true. |
proxmox_service_start |
2 safe-write | Start a systemd service inside a guest. Requires confirm: true. |
proxmox_service_stop |
2 safe-write | Stop a systemd service inside a guest. Requires confirm: true. |
proxmox_service_restart |
2 safe-write | Restart a systemd service inside a guest. Requires confirm: true. |
proxmox_update_vm_config |
2 safe-write | Edit an existing QEMU VM config (cores/memory/net/etc, PUT .../qemu/{vmid}/config). Requires confirm: true. |
proxmox_update_container_config |
2 safe-write | Edit an existing LXC config (cores/memory/hostname/etc, PUT .../lxc/{vmid}/config). Requires confirm: true. |
proxmox_resize_disk |
2 safe-write | Grow a VM or container disk (PUT .../{type}/{vmid}/resize). Grow-only. Requires confirm: true. |
proxmox_restore_backup |
2 safe-write | Restore a vzdump/PBS archive into a VMID. Overwriting an existing VMID escalates to the destructive gate. Requires confirm: true. |
proxmox_migrate_resource |
2 safe-write | Migrate a VM or container to another node (POST .../migrate). Requires confirm: true. |
proxmox_suspend_resource |
2 safe-write | Suspend/pause a running guest (QEMU can hibernate to disk). Requires confirm: true. |
proxmox_resume_resource |
2 safe-write | Resume a suspended guest. Requires confirm: true. |
proxmox_reset_resource |
2 safe-write | Hard-reset a QEMU VM (reset button; no graceful shutdown). Requires confirm: true. |
proxmox_convert_to_template |
2 safe-write | Convert a stopped guest into a clone template (one-way). Requires confirm: true. |
proxmox_download_url |
2 safe-write | Download an ISO or container template from a URL onto a storage. Requires confirm: true. |
proxmox_cancel_task |
2 safe-write | Stop a running task by UPID (abort a stuck migration/backup). Requires confirm: true. |
proxmox_add_firewall_rule |
2 safe-write | Add a firewall rule at cluster/node/guest scope. Requires confirm: true. |
proxmox_delete_firewall_rule |
2 safe-write | Delete a firewall rule by position at a scope. Requires confirm: true. |
proxmox_set_firewall_enabled |
2 safe-write | Enable/disable the firewall at a scope. Requires confirm: true. |
proxmox_move_disk |
2 safe-write | Relocate a VM disk or container volume to another storage. Requires confirm: true. |
proxmox_create_storage |
2 safe-write | Define a new datacenter storage (dir/nfs/lvm/pbs/etc). Requires confirm: true. |
proxmox_create_backup_job |
2 safe-write | Create a scheduled vzdump backup job. Requires confirm: true. |
proxmox_delete_backup_job |
2 safe-write | Delete a scheduled backup job (archives untouched). Requires confirm: true. |
proxmox_set_acl |
2 safe-write | Grant or revoke a role for a user/token/group on a path. Requires confirm: true. |
proxmox_create_token |
2 safe-write | Create an API token; returns the secret once. Requires confirm: true. |
proxmox_delete_token |
2 safe-write | Revoke an API token. Requires confirm: true. |
proxmox_create_pool |
2 safe-write | Create a resource pool. Requires confirm: true. |
proxmox_update_pool |
2 safe-write | Add/remove guests or storage in a pool. Requires confirm: true. |
proxmox_delete_pool |
2 safe-write | Delete an empty resource pool. Requires confirm: true. |
proxmox_add_ha_resource |
2 safe-write | Place a VM/container under HA management. Requires confirm: true. |
proxmox_delete_ha_resource |
2 safe-write | Remove a guest from HA management. Requires confirm: true. |
proxmox_create_replication |
2 safe-write | Create a storage replication job to another node. Requires confirm: true. |
proxmox_delete_replication |
2 safe-write | Delete a replication job. Requires confirm: true. |
proxmox_rollback_snapshot |
3 destructive | Roll back a resource to a named snapshot. |
proxmox_destroy_resource |
3 destructive | Permanently delete an LXC or VM (DELETE /nodes/{node}/{type}/{vmid}). |
proxmox_cleanup_smoke_resources |
3 destructive | Dry-run or destroy smoke-prefixed LXC/QEMU guests from a smoke pool. |
proxmox_delete_snapshot |
3 destructive | Delete a named snapshot. |
proxmox_force_stop_resource |
3 destructive | Non-graceful hard stop of a running container or VM. |
proxmox_delete_volume |
3 destructive | Permanently delete a storage volume (backup, ISO, template, disk image). |
proxmox_node_power |
3 destructive | Reboot or shut down an entire node, taking down every guest on it. |
proxmox_delete_storage |
3 destructive | Remove a storage definition from the datacenter config. |
Reads (43): open; no flags required.
Gated guest reads (4): guest file/path/directory/service inspection tools require confirm: true because they expose in-guest state through host-backed SSH.
Safe writes (41): require confirm: true. The schema documents the gate on every tool. WriteGateError fires before any HTTP call.
Destructive (8): require confirm: true + destructive: true + env PROXMOX_ENABLE_DESTRUCTIVE=1. All three gates must be satisfied; if any one is missing the tool throws WriteGateError before resolving the resource.
Eight tools are destructive and can delete, hard-stop, or power off resources:
proxmox_destroy_resource,proxmox_cleanup_smoke_resources,proxmox_rollback_snapshot,proxmox_delete_snapshot,proxmox_force_stop_resource,proxmox_delete_volume,proxmox_node_power, andproxmox_delete_storage. They are gated behind thePROXMOX_ENABLE_DESTRUCTIVE=1process env flag and stay inert until you set it. See SECURITY.md and the Safety section.
Quickstart
Install globally or run on demand with npx:
npm install -g @solomonneas/proxmox-mcp
# or, no install:
npx -y @solomonneas/proxmox-mcp
Set the three required credential env vars (scrub real hosts and IPs out of any shared config):
export PROXMOX_URL=https://192.0.2.10:8006
export PROXMOX_TOKEN_ID=pve-admin@pam!api-token-1
export PROXMOX_TOKEN_SECRET=00000000-0000-0000-0000-000000000000
# Optional: skip TLS cert validation for homelab self-signed certs.
# Accepts true/1/yes (case-insensitive). Defaults to false.
export PROXMOX_TLS_INSECURE=false
Wire it into your MCP client (full per-client config in Setup):
# Claude Code
claude mcp add proxmox -s user -- npx -y @solomonneas/proxmox-mcp
Then ask your agent to list your cluster's containers. Reads work with nothing but the three credential vars; write and destructive tiers stay gated until you opt in.
Note: the latest published version is
0.11.0.npx/npm installpins the published release; this repository may track ahead between releases.
Configuration
Set the following env vars. All three credential vars are required.
PROXMOX_URL=https://192.0.2.10:8006
PROXMOX_TOKEN_ID=pve-admin@pam!api-token-1
PROXMOX_TOKEN_SECRET=00000000-0000-0000-0000-000000000000
# Optional: skip TLS cert validation (homelab self-signed certs).
# Accepts true/1/yes (case-insensitive). Defaults to false.
PROXMOX_TLS_INSECURE=false
Trailing slashes on PROXMOX_URL are stripped. The token secret is registered with the redactor on startup and masked from all log + error output.
In-container exec env vars
The proxmox_exec, proxmox_read_file, and proxmox_write_file tools SSH to the Proxmox host (for LXC, via pct exec) or directly to the VM (for QEMU). All are optional; defaults derive from PROXMOX_URL.
| Env var | Default | Purpose |
|---|---|---|
PROXMOX_SSH_HOST |
hostname from PROXMOX_URL |
Proxmox host for pct exec |
PROXMOX_SSH_PORT |
22 |
SSH port |
PROXMOX_SSH_USER |
root |
SSH user on Proxmox host |
PROXMOX_SSH_KEY |
~/.ssh/id_ed25519 |
Key path for Proxmox host SSH |
PROXMOX_VM_SSH_USER |
falls through to PROXMOX_SSH_USER |
Default user for direct VM SSH |
PROXMOX_VM_SSH_KEY |
falls through to PROXMOX_SSH_KEY |
Default key for direct VM SSH |
PROXMOX_SSH_MAX_OUTPUT_BYTES |
1048576 |
Max stdout bytes and max stderr bytes captured per SSH command |
PROXMOX_EXEC_BACKEND |
ssh |
QEMU exec backend: ssh (direct SSH to the VM) or guest-agent (qemu-guest-agent API, no in-guest SSH key needed). LXC always uses pct exec over host SSH. |
Per-VM overrides (read at execute time, no MCP restart needed):
PROXMOX_VM_<vmid>_SSH_HOST- pin a VM's IP (bypasses guest agent)PROXMOX_VM_<vmid>_SSH_USER- per-VM user overridePROXMOX_VM_<vmid>_SSH_KEY- per-VM key override
For QEMU VMs without a per-VM env override, install qemu-guest-agent in the VM and enable it with qm set <vmid> --agent 1 so the IP can be discovered automatically.
Set PROXMOX_EXEC_BACKEND=guest-agent to run QEMU guest commands entirely through the qemu-guest-agent API instead of SSH. This needs no in-guest SSH key and no network path from the MCP host to the VM (traffic goes through the Proxmox API), but the API token needs the VM.GuestAgent.* privileges (Unrestricted for exec, FileRead/FileWrite for file ops). LXC guests always use pct exec over host SSH regardless of this setting.
Waiting for long-running tasks
Provisioning and disk operations (proxmox_create_container, proxmox_create_vm, proxmox_clone_resource, proxmox_run_backup, proxmox_restore_backup, proxmox_migrate_resource, proxmox_resize_disk, proxmox_download_url, proxmox_destroy_resource) return a task UPID immediately. Pass wait: true (with optional wait_timeout seconds, default 120) to block until the task finishes; the result then includes a task object with done, exitstatus, and ok (true only for an OK exit). Without wait, use proxmox_wait_task to poll the UPID yourself.
CLI
The same package ships a read-only control CLI, proxmoxctl (alias proxops), for shells, cron, and CI. It shares the ProxmoxClient core with the MCP server and reads the same env config (PROXMOX_URL, PROXMOX_TOKEN_ID, PROXMOX_TOKEN_SECRET, PROXMOX_TLS_INSECURE). It exposes only read/inventory/audit operations; every lifecycle, snapshot, backup, and exec action stays in the MCP/plugin surface behind the safety gates.
npx @solomonneas/proxmox-mcp@latest status
# or, installed globally:
proxmoxctl status # PVE version + per-node status (exit 1 if a node is offline)
proxmoxctl vms list
proxmoxctl containers list
proxmoxctl vm config 100
proxmoxctl storage list --node pve
proxmoxctl storage content local --node pve --content backup
proxmoxctl disks list --node pve # physical disks + SMART health
proxmoxctl services list --node pve # host systemd services
proxmoxctl firewall rules --scope cluster
proxmoxctl backups list --vmid 100
proxmoxctl snapshots list 100
proxmoxctl audit-permissions
proxmoxctl recent-tasks --limit 20
proxmoxctl task status UPID:pve:...
proxmoxctl vms list --json # raw JSON for piping
Run proxmoxctl help for the full command list. --json emits raw JSON instead of the concise summary. Exit codes: 0 success, 1 runtime error (backend unreachable / call failed, and status when a node is offline), 2 usage error (unknown command/flag or bad value).
Starting the MCP server
proxmoxctl mcp (or the back-compat proxmox-mcp bin) starts the stdio MCP server. If a launcher referenced the file path dist/mcp-server.js directly, it keeps working; new launchers can point at dist/mcp-bin.js (or dist/cli.js mcp). Launchers that use the proxmox-mcp bin name need no change.
Setup
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"proxmox": {
"command": "npx",
"args": ["-y", "@solomonneas/proxmox-mcp"],
"env": {
"PROXMOX_URL": "https://192.0.2.10:8006",
"PROXMOX_TOKEN_ID": "pve-admin@pam!api-token-1",
"PROXMOX_TOKEN_SECRET": "00000000-0000-0000-0000-000000000000",
"PROXMOX_TLS_INSECURE": "false"
}
}
}
}
Claude Code
claude mcp add proxmox -s user -- npx -y @solomonneas/proxmox-mcp
Then export env vars in your shell (~/.bashrc, ~/.zshrc) or pass --env flags.
OpenClaw
Plugin loads automatically once installed. Config goes in your ~/.openclaw/openclaw.json plugins.entries.proxmox (or use the bundled openclaw.plugin.json):
{
"plugins": {
"entries": {
"proxmox": {
"package": "@solomonneas/proxmox-mcp",
"activation": { "onStartup": true }
}
}
}
}
Env vars from ~/.openclaw/workspace/.env are inherited by the plugin.
Codex CLI
~/.codex/config.toml:
[mcp_servers.proxmox]
command = "npx"
args = ["-y", "@solomonneas/proxmox-mcp"]
[mcp_servers.proxmox.env]
PROXMOX_URL = "https://192.0.2.10:8006"
PROXMOX_TOKEN_ID = "pve-admin@pam!api-token-1"
PROXMOX_TOKEN_SECRET = "00000000-0000-0000-0000-000000000000"
PROXMOX_TLS_INSECURE = "false"
Safety
This MCP uses a three-tier write-gating model. The tier is enforced in code, not just documented.
- Tier 1 (reads): open. No confirm flag needed. Status, listings, config inspection, QEMU smoke-source validation, permission audit, usage, recent tasks, backup inventory, template inventory, storage inventory, snapshot inventory, guest network lookup, task wait, next-VMID lookup, task status/log, pool resource audit, storage content listing, node service/disk/update inventory, and firewall rule/option inspection, storage-config and backup-job listing, and access/role/ACL/pool/token inspection, and cluster/HA/SDN/replication observability live here.
- Tier 2 (gated guest reads + safe writes): require an explicit
confirm: truearg. Guest file/path/directory/service inspection, start, stop, reboot, snapshot create, run backup, create container, create VM, clone, VM/container config edit, disk resize, backup restore (to a new VMID), node migration, suspend/resume/reset, convert-to-template, ISO/template download, task cancel, firewall rule add/delete and enable-toggle, disk move, storage creation, backup-job create/delete, ACL grant/revoke, API-token create/delete, pool create/update/delete, HA resource add/remove, replication job create/delete, in-containerexec, in-containerwrite_file, and guest service start/stop/restart live here. A tool call without the confirm flag throwsWriteGateErrorbefore any HTTP traffic. Restoring a backup over an existing VMID escalates to the Tier-3 gate because it wipes the target's disks. - Tier 3 (destructive): require
confirm: true+destructive: true+ the env flagPROXMOX_ENABLE_DESTRUCTIVE=1on the MCP process. Permanent resource deletion, smoke pool cleanup, snapshot rollback/deletion, non-graceful force-stop, storage-volume deletion, storage-definition removal, and node reboot/shutdown live here.
Destructive operations env gate
Tier 3 destructive tools (proxmox_destroy_resource, proxmox_cleanup_smoke_resources, proxmox_rollback_snapshot, proxmox_delete_snapshot, proxmox_force_stop_resource, proxmox_delete_volume, proxmox_node_power, proxmox_delete_storage) require an additional safety gate beyond the per-tool confirm: true + destructive: true args: the env var PROXMOX_ENABLE_DESTRUCTIVE=1 must be set on the MCP process. Without it, the tools throw WriteGateError before any HTTP call is made. proxmox_cleanup_smoke_resources defaults to dry_run: true, which previews targets without the destructive env gate.
This is intentional: destructive ops are rare. The env flag is a coarse "I am actively doing smoke-test cycles" toggle. Leave it unset day to day; flip it only when actively destroying resources is part of the workflow.
API token scope recommendation: start with a read-only token (PVE Datastore.Audit + VM.Audit + Sys.Audit) and verify the read tools work end to end. Grade up to write privileges (VM.PowerMgmt, VM.Snapshot, VM.Backup) only after you have confirmed the redactor is masking your secret in your transcripts and that the model is honoring the confirm gate. Tokens are tied to a PVE user and can be revoked instantly from Datacenter > Permissions > API Tokens.
The PROXMOX_TLS_INSECURE=true toggle exists for homelab self-signed certs. Leave it false in any environment with a real CA-signed cert.
Full security policy, reporting, and in-scope/out-of-scope detail in SECURITY.md.
Live smoke testing
Read-only live smoke:
PROXMOX_ENABLE_LIVE_SMOKE=1 npm run smoke:live
Full scratch CT lifecycle smoke requires a token that can create, start, stop, inspect, and destroy resources in the mcp-smoke pool:
PROXMOX_ENABLE_LIVE_SMOKE=1 \
PROXMOX_SMOKE_CREATE=1 \
PROXMOX_ENABLE_DESTRUCTIVE=1 \
npm run smoke:live
Optional scratch CT backup and snapshot rollback smoke:
PROXMOX_ENABLE_LIVE_SMOKE=1 \
PROXMOX_SMOKE_CREATE=1 \
PROXMOX_SMOKE_BACKUP=1 \
PROXMOX_SMOKE_BACKUP_STORAGE=local \
PROXMOX_SMOKE_SNAPSHOT_ROLLBACK=1 \
PROXMOX_ENABLE_DESTRUCTIVE=1 \
npm run smoke:live
Create a scoped smoke-test role/user/token on the Proxmox host:
PROXMOX_CREATE_SMOKE_TOKEN=1 bash scripts/create-smoke-token.sh
The script creates or updates role McpSmokeRole, pool mcp-smoke, user mcp-smoke@pve, token mcp-smoke@pve!live-smoke, and ACLs for the smoke pool plus local and local-lvm storage. Proxmox prints the token secret once; store it in your private environment and do not commit it.
Proxmox also checks /vms/<vmid> before creating a new CT/VM. For one-off smoke tests, grant the exact next VMID before running the lifecycle smoke:
PROXMOX_CREATE_SMOKE_TOKEN=1 PROXMOX_SMOKE_VMID_GRANT=102 bash scripts/create-smoke-token.sh
npm run smoke:live now attempts that exact VMID grant automatically before creating a scratch CT or QEMU clone when PROXMOX_SSH_HOST, PROXMOX_SSH_USER, and PROXMOX_SSH_KEY are available. Set PROXMOX_SMOKE_SKIP_AUTO_GRANT=1 to disable it.
Optional QEMU clone smoke:
PROXMOX_ENABLE_LIVE_SMOKE=1 \
PROXMOX_ENABLE_DESTRUCTIVE=1 \
PROXMOX_SMOKE_QEMU_SOURCE_VMID=9000 \
npm run smoke:live
This validates the source, full-clones it to a scratch VMID, starts it, waits for guest-agent network data, stops it, and destroys it. Use PROXMOX_SMOKE_QEMU_TARGET_VMID or PROXMOX_SMOKE_QEMU_NAME to override the generated target.
The QEMU source should be a small stopped VM or template with agent: enabled=1, DHCP networking, no PCI/USB passthrough, no raw args, and a modest disk size. Check it first:
# tool: proxmox_validate_qemu_smoke_source { "vmid": 9000 }
Audit smoke-token permissions:
# tool: proxmox_audit_permissions {
# "userid": "mcp-smoke@pve!live-smoke",
# "source_vmid": 103,
# "target_vmid": 102
# }
Optional systemd service smoke:
PROXMOX_ENABLE_LIVE_SMOKE=1 \
PROXMOX_SMOKE_SYSTEMD_VMID=100 \
PROXMOX_SMOKE_SERVICE=basic.target \
npm run smoke:live
To run a live service action as well as status, add PROXMOX_SMOKE_SERVICE_ACTION=start|stop|restart and PROXMOX_SMOKE_SERVICE_ACTION_CONFIRM=1.
Audit or clean leftover smoke resources:
# Read-only pool audit
# tool: proxmox_list_pool_resources { "pool": "mcp-smoke" }
# Dry-run cleanup, only resources named mcp-smoke-* in the pool are targeted
# tool: proxmox_cleanup_smoke_resources {}
# Actual cleanup waits for delete tasks and skips running guests unless force:true
# tool: proxmox_cleanup_smoke_resources { "dry_run": false, "confirm": true, "destructive": true }
Why not the alternatives?
- The Proxmox web UI is the canonical control plane and you should keep it. proxmox-mcp is not a replacement; it is the agent-facing read/operate surface so an AI client can inventory, trace, and operate the cluster in the same loop it is already running, without you driving a browser.
- Hand-rolling Proxmox API calls in your agent works, but the agent has to manage token auth, the redactor, retry, task polling, and (critically) safety on its own. proxmox-mcp ships the token redactor, structured MCP error payloads, and the three-tier write gate so a careless or hallucinated call fails closed instead of deleting a guest.
- A general "run any HTTP request" MCP tool gives a model unbounded access to the Proxmox API with no guardrails. proxmox-mcp is the opposite: a fixed, named tool surface where every state change is gated and every destructive op needs an explicit process-level env flag.
- Terraform / Ansible /
pct+qmare the right tools for declarative, reviewed, repeatable infrastructure. proxmox-mcp is for interactive, agent-driven inspection and operation, not for codifying your cluster.
What proxmox-mcp is not
- It is not a tool for blind automation of destructive operations. The destructive tier exists for deliberate, supervised work (smoke-test cycles, intentional teardown), not for unattended agents. The
PROXMOX_ENABLE_DESTRUCTIVE=1flag is a coarse "I am actively doing this right now" toggle; leave it unset day to day. - It is not a Proxmox cluster manager or orchestrator. It does not schedule, it does not run in the background, and it holds no state of its own. It translates MCP tool calls into Proxmox API calls and SSH commands, and that is all.
- It is not a substitute for least-privilege tokens. The write gate is a guardrail against a misbehaving model, not a substitute for a properly scoped Proxmox API token. Start read-only and grade up. See SECURITY.md.
- It is not stable yet. It is WIP, pre-1.0, and the tool surface can change between minor versions.
Contributing
Bug reports and patches are welcome. See CONTRIBUTING.md for what lands easily, local dev, and the safety rules every change must keep. By participating you agree to the Code of Conduct.
Changelog
See CHANGELOG.md for the release history.
License
MIT. See LICENSE.
No comments yet
Be the first to share your take.