AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
Proxmox 가상 환경 VM·컨테이너·스토리지·클러스터 자원 관리 MCP 서버
MCP server for managing Proxmox Virtual Environment VMs, containers, storage, and cluster resources
개발 도구Python · ShellGitHub @ry-ops직접 설치운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
설치형 프로젝트는 배포 도메인 없이도 확인할 수 있습니다. 개인 저장소는 GitHub 로그인으로, 조직 저장소는 위의 저장소 확인 파일로 직접 확인해 주세요.
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Talk to your Proxmox cluster. A Model Context Protocol server that gives Claude, or any MCP client, the whole Proxmox VE API : 339 tools across VMs, containers, storage, clustering, Ceph, SDN and more.README 전문 보기 ↗vm_agent_exec → vm_agent_exec_status) and read back the exit code and output.PROXMOX_READ_ONLY=true refuses every write inside the server, and 149 read-only tools keep working.PVEAuditor role for monitoring.uv from a clone, or the multi-arch image on ghcr.io.agent-card.json lists every tool in 14 skill categories, for agent-to-agent discovery.deploy_fortigate_vm builds a FortiGate-VM from Fortinet's KVM image, with WAN/LAN NICs on the bridges and VLANs you choose. deploy_cloud_vms builds cluster-ready VMs from a cloud image, with your SSH key and a static IP each, ready for k3s-mcp-server's create_cluster.Once it's connected, just ask:
"Can you list all VMs in my Proxmox cluster?" "What's the status of VM 100 on node pve1?" "Create a snapshot called 'backup-2025' for VM 100 on pve1." "Show me the storage usage on all nodes." "List all running tasks in the cluster." "Clone VM 9000 to a new VM called web-02 and start it." "Run
df -hinside VM 120 using the guest agent and show me the output." "Make three Ubuntu VMs on pve1 at 192.168.1.181–183 with my SSH key, ready for a K3s cluster."
There are more worked examples in USAGE.md.
httpx, the MCP SDK) turns each tool call into a request to the Proxmox VE REST API over HTTPS on port 8006, authenticated with an API token or a password.| Area | Tools | Highlights |
|---|---|---|
| Nodes | 38 | Status, config, DNS/hosts/time, network interfaces, services, APT updates, syslog, power |
| QEMU VMs | 46 | Lifecycle, create/clone/delete, config, snapshots, migration, disk resize/move, RRD metrics, guest agent (vm_agent_exec, vm_agent_exec_status), VNC proxy |
| LXC containers | 28 | Lifecycle, create/clone/delete, config, snapshots, migration, resize |
| Storage & backup | 14 | Storage definitions, content and volumes, URL downloads, vzdump backup and restore |
| Cluster | 37 | Status, resources, options, log, tasks, HA resources/groups, replication, backup jobs |
| Access control | 33 | Users, API tokens, groups, roles, ACLs, realms |
| Firewall | 31 | Cluster and node rules, security groups, aliases, IP sets, macros, logs (per-VM and per-container rules are in the guest modules) |
| Disks | 17 | SMART, wipe, GPT init, LVM, LVM-thin, ZFS, directory storage |
| Ceph | 33 | Status, OSDs, monitors, managers, MDS, pools, flags, CRUSH |
| ACME & certificates | 17 | ACME accounts and plugins, node certificate ordering, custom certs |
| SDN | 16 | Zones, VNets, subnets, apply |
| Notifications | 23 | Gotify, sendmail, SMTP and webhook endpoints, matchers |
| Pools | 5 | Resource pool CRUD |
| Appliances | 2 | deploy_fortigate_vm: FortiGate-VM from Fortinet's KVM image, WAN/LAN NICs on chosen bridges and VLANs, sized for the free evaluation license. deploy_cloud_vms: VMs from a cloud image (e.g. Ubuntu's) with cloud-init user, SSH key and a static IP or DHCP each, disk grown and started |
Tool names follow the Proxmox API: list_*, get_*, create_*, update_*/set_*, delete_*, plus actions such as start_vm, migrate_container or apply_sdn. Each area is one module in proxmox_mcp/tools/. Your MCP client shows every tool with its full input schema, or you can list them all locally:
uv run python -c "from proxmox_mcp.server import ALL_TOOLS; print('\n'.join(sorted(t.name for t in ALL_TOOLS)))"
| Task | Tools |
|---|---|
| Inventory | list_nodes, get_cluster_resources, list_vms, list_containers, list_storage |
| VM lifecycle | start_vm, shutdown_vm, stop_vm, reboot_vm, create_vm, clone_vm, migrate_vm |
| Disk images | download_url_to_storage with content=import, then create_vm with scsi0=local-lvm:0,import-from=local:import/<image>, or import_vm_disk |
| Snapshots | create_vm_snapshot, list_vm_snapshots, rollback_vm_snapshot, delete_vm_snapshot |
| Monitoring | get_node_status, get_vm_status, get_vm_rrddata, get_node_storage_status |
| Tasks | list_cluster_tasks, list_node_tasks, get_task_status, get_task_log |
| Guest agent | vm_agent_exec (returns a PID), then vm_agent_exec_status for the exit code and output |
| Cluster nodes | download_url_to_storage for a cloud image with content=import, then deploy_cloud_vms; hand the IPs to k3s-mcp-server's create_cluster |
You need Python 3.10+ with uv, or Docker, and Proxmox VE 6.0 or later.
1. Make an API token. In the Proxmox UI, go to Datacenter → Permissions → API Tokens → Add. For full access, uncheck Privilege Separation so the token inherits your user's permissions. Copy the secret; you won't see it again. The full token ID looks like root@pam!automation.
2. Run the server with one of these:
curl -LsSf https://astral.sh/uv/install.sh | sh # if you don't have uv
git clone https://github.com/ry-ops/proxmox-mcp-server && cd proxmox-mcp-server
./setup.sh # or: uv sync
export PROXMOX_HOST="192.168.1.100"
export PROXMOX_USER="root@pam"
export PROXMOX_TOKEN_NAME="automation"
export PROXMOX_TOKEN_VALUE="your-token-here"
./test-connection.sh # checks connection, auth and permissions
A .env file in the project directory is loaded automatically; see .env.example.
A multi-arch image is published to GitHub Container Registry on every push to main and for each release tag:
docker pull ghcr.io/ry-ops/proxmox-mcp-server:latest # or a version tag, e.g. :2.4.0
docker run -i --rm --env-file .env ghcr.io/ry-ops/proxmox-mcp-server:latest
MCP clients talk over stdio, so run the container interactively (-i). docker-compose.yaml does the same using your .env.
3. Connect your MCP client. For Claude Desktop, edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or %APPDATA%/Claude/claude_desktop_config.json on Windows:
{
"mcpServers": {
"proxmox": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/proxmox-mcp-server", "run", "proxmox-mcp-server"],
"env": {
"PROXMOX_HOST": "192.168.1.100",
"PROXMOX_USER": "root@pam",
"PROXMOX_TOKEN_NAME": "automation",
"PROXMOX_TOKEN_VALUE": "your-token-value-here"
}
}
}
}
Use the absolute path to your clone.
{
"mcpServers": {
"proxmox": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/proxmox-mcp-server", "run", "proxmox-mcp-server"],
"env": {
"PROXMOX_HOST": "192.168.1.100",
"PROXMOX_USER": "root@pam",
"PROXMOX_PASSWORD": "your-password-here"
}
}
}
}
{
"mcpServers": {
"proxmox": {
"command": "docker",
"args": ["run", "-i", "--rm",
"-e", "PROXMOX_HOST", "-e", "PROXMOX_USER", "-e", "PROXMOX_TOKEN_NAME", "-e", "PROXMOX_TOKEN_VALUE",
"ghcr.io/ry-ops/proxmox-mcp-server:latest"],
"env": {
"PROXMOX_HOST": "192.168.1.100",
"PROXMOX_USER": "root@pam",
"PROXMOX_TOKEN_NAME": "automation",
"PROXMOX_TOKEN_VALUE": "your-token-value-here"
}
}
}
}
4. Restart your client completely (quit it, don't just close the window), and ask it to list your VMs. More detail in QUICKSTART.md and SETUP.md.
| Variable | Required | Default | What it does |
|---|---|---|---|
PROXMOX_HOST | ✅ | Hostname or IP, without scheme or port (192.168.1.100, not https://192.168.1.100:8006) | |
PROXMOX_USER | ✅ | e.g. root@pam, admin@pve | |
PROXMOX_TOKEN_NAME + PROXMOX_TOKEN_VALUE | one of | API token auth (recommended) | |
PROXMOX_PASSWORD | one of | Password auth | |
PROXMOX_PORT | 8006 | API port | |
PROXMOX_VERIFY_SSL | false | Verify the server's TLS certificate | |
PROXMOX_READ_ONLY | false | Refuse every write; see below |
PROXMOX_READ_ONLY=true makes the server look-but-don't-touch. Only GET requests are sent, and every create, update, delete or action tool is refused inside the server before it reaches the network. 149 of the 340 tools are read-only and keep working. Three read-style tools send POST requests, so they're blocked too:
vm_agent_ping;get_vm_vnc_proxy and get_vm_spice_proxy, which create console access tickets.The rest of the security picture:
PROXMOX_READ_ONLY=true and a token with the PVEAuditor role. The flag stops the server sending writes; the role makes Proxmox refuse them anyway.PROXMOX_VERIFY_SSL=true in production with valid certificates.agent-card.json is this server's identity and capability manifest for other agents. It's generated from the tool registry, and lists all 340 tools in 14 skill categories, each with its name, description and inputs. It also covers authentication requirements and MCP protocol details.
| Category | Tools | Category | Tools |
|---|---|---|---|
node_management | 38 | disk_management | 17 |
virtual_machine_management | 46 | ceph_management | 33 |
container_management | 28 | certificate_management | 17 |
storage_management | 14 | sdn_management | 16 |
cluster_management | 37 | notification_management | 23 |
access_control | 33 | pool_management | 5 |
firewall_management | 31 | appliances | 2 |
import json
with open('agent-card.json') as f:
agent_card = json.load(f)
print(f"Agent: {agent_card['name']} Version: {agent_card['version']}")
for skill in agent_card['skills']:
print(f"\n{skill['category']}:")
for capability in skill['capabilities']:
print(f" - {capability['name']}: {capability['description']}")
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
server_params = StdioServerParameters(
command="uv",
args=["--directory", "/path/to/proxmox-mcp-server", "run", "proxmox-mcp-server"],
env={
"PROXMOX_HOST": "192.168.1.100",
"PROXMOX_USER": "root@pam",
"PROXMOX_TOKEN_NAME": "automation",
"PROXMOX_TOKEN_VALUE": "your-token-value",
},
)
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
result = await session.call_tool("list_vms", arguments={})
print(result.content)
# Snapshot every VM, then hand off to other agents
async def backup_workflow():
vms = await proxmox_agent.call_tool("list_vms", {})
for vm in vms['data']:
await proxmox_agent.call_tool("create_vm_snapshot", {
"node": vm['node'],
"vmid": vm['vmid'],
"snapname": f"backup-{datetime.now():%Y%m%d-%H%M%S}",
})
await storage_agent.call_tool("check_capacity", {})
await notification_agent.call_tool("send_alert", {"message": f"Backup completed: {len(vms['data'])} VMs"})
PROXMOX_HOST (no scheme, no port) and PROXMOX_PORT.curl -k https://YOUR_HOST:8006/api2/json/versionPROXMOX_VERIFY_SSL=true, the certificate must be valid for that host.The user or token needs privileges for each operation. Common ones: VM.Monitor, VM.Audit, Datastore.Audit, Sys.Audit, VM.PowerMgmt, VM.Snapshot.
./test-connection.sh
It checks the connection, the API, authentication, permission to list nodes, and access to cluster resources.
uv sync # dependencies, including dev tools
uv run proxmox-mcp-server # run the server directly
uv run pytest # tests
uv run ruff check . && uv run black .
proxmox_mcp/
├── server.py MCP server entrypoint and tool registry
├── client.py Proxmox API client: token/password auth, read-only guard
└── tools/ one module per API area:
nodes, qemu, lxc, storage, cluster, access, firewall,
disks, ceph, acme, sdn, notifications, pools, appliances
docs/ the animations on this page
agent-card.json A2A agent card
Dockerfile, docker-compose.yaml, setup.sh, test-connection.sh
QUICKSTART.md · SETUP.md · USAGE.md · CHANGELOG.md
Dependencies:
mcp (>=1.0.0, <2): 2.x changed the server API and isn't supported yet.httpx: the async HTTP client.python-dotenv: loads .env.mcp 2.xWhat has shipped is in CHANGELOG.md.
Issues and pull requests are welcome: new tools, better error handling, performance, docs, tests and bug fixes.
MIT. See LICENSE.