{
  "markdown": "# cursor-proxmox-mcp\n\n[![CI](https://github.com/hackmods/cursor-proxmox-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/hackmods/cursor-proxmox-mcp/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![PyPI](https://img.shields.io/pypi/v/cursor-proxmox-mcp)](https://pypi.org/project/cursor-proxmox-mcp/)\n[![GHCR](https://img.shields.io/badge/GHCR-cursor--proxmox--mcp-blue)](https://github.com/hackmods/cursor-proxmox-mcp/pkgs/container/cursor-proxmox-mcp)\n\n**Formal Cursor ↔ [Proxmox VE](https://www.proxmox.com/) MCP integration** — 212 tools covering QEMU VMs (incl. guest-agent network/file/guest-info/fsfreeze + `bootstrap_cloudinit_vm` / `provision_vm` + `qm_set_vm`), LXC (incl. `provision_lxc`, `bootstrap_docker_lxc`, crun Path B, DNS/SSH helpers, `deploy_node_app`), unified guest power, storage admin (incl. PBS plugin + status), cluster/tasks (incl. join), snapshots, backups, migration, HA, firewall, access control, replication, SDN write + apply, ACME order/renew, Ceph status/pools + gated OSD create/destroy, node network CRUD, console tickets/`get_console_connection`, and host reboot/shutdown. **v1.9.0** adds optional dual-credential elevated mode (`auth_write`, D31) + `provision_vm` + Cursor day-2 auto-approve docs.\n\n**Repo:** [hackmods/cursor-proxmox-mcp](https://github.com/hackmods/cursor-proxmox-mcp)\n\nDocs: [**Setup guide**](SETUP.md) · [Wiki](https://github.com/hackmods/cursor-proxmox-mcp/wiki) ([`docs/wiki/`](docs/wiki/)) · [Publishing](PUBLISHING.md) · [Security](SECURITY.md) · [Contributing](CONTRIBUTING.md) · [API coverage](docs/api-coverage.md) · [Changelog](CHANGELOG.md)\n\n<!-- mcp-name: io.github.hackmods/cursor-proxmox-mcp -->\n\n## MCP tools\n\nRegistered via `tools/register.py` (called from `ProxmoxMCPServer._setup_tools()`) — inventory locked by `tools/inventory.py` / `tests/expected_tools.py` (CI fails on drift).\n\n| Domain | Tools |\n|--------|--------|\n| **Nodes** | `get_nodes`, `get_node_status`, `list_node_networks` + create/update/delete + `reload_node_network`, `get_node_subscription`, `list_node_certificates`, `get_node_report`, `list_node_services`, `get_node_time`, `wake_node`, `reboot_node` / `shutdown_node` (`confirm=<node>`) |\n| **Cluster / tasks** | `get_cluster_status`, `get_next_vmid`, `get_task_status`, `list_tasks`, `wait_for_task`, `get_version`, `get_mcp_capabilities`, `get_cluster_resources`, `get_cluster_log`, `get_cluster_options`, `get_cluster_join_info`, `join_cluster` (`confirm=JOIN`) |\n| **QEMU** | lifecycle + config (ISO/cloud-init/net/onboot/tags/description; optional `wait=true`) + `get_vm_network` / `get_vm_guest_info` / `fsfreeze_vm` / `fsthaw_vm` / `push_to_vm` / `pull_from_vm` (guest agent) + `bootstrap_cloudinit_vm` / `provision_vm` (one-shot create or clone→CI→IP) + `qm_set_vm` + `get_vm_status`, `get_vm_rrd_data`, console tickets |\n| **LXC** | lifecycle + config + suspend/resume (CRIU warn) + `get_lxc_status` / `get_lxc_network` / `get_lxc_rrd_data` + VNC/SPICE/termproxy; `ssh_public_keys` / `docker_ready` / `nameserver` / `wait` / `onboot` / `description` / `tags` on create; `provision_lxc` (one-shot create→start→IP→SSH) / `bootstrap_docker_lxc` / `prepare_lxc_for_docker` (`docker_mode=auto|keyctl|crun`) / `configure_lxc_dns` / `configure_lxc_ssh` / `get_docker_lxc_status` / `pct_set_lxc` / `push_to_lxc` / `pull_from_lxc` / `deploy_static_nginx` / `deploy_node_app` via opt-in **host** SSH + `pct` ([setup](SETUP.md#ssh-for-lxc-exec-opt-in)); optional `get_containers(probes=true)` |\n| **Guest (unified)** | `start/stop/shutdown/reboot/delete_guest`, `get_guest_status`, `get_guest_pending`, `move_guest_disk`, `get_console_connection` (`guest_type`) |\n| **Snapshots / Backups** | snapshot CRUD/rollback; one-shot backup CRUD; scheduled `list/create/delete_backup_job` |\n| **Storage** | list, content, `list_os_templates`, `list_isos`, download-url, definition CRUD; PBS via `create_storage(type=pbs)` + `get_pbs_storage_status` |\n| **Migrate / HA** | `migrate_guest`; HA groups + resources CRUD |\n| **Firewall** | cluster + guest rules/options; aliases; IP sets + CIDR members; macros |\n| **Access** | users, groups, roles, ACL, tokens, `get_permissions`, `get_token_permissions` |\n| **Replication** | list/status/run/create/update/delete jobs |\n| **SDN** | zones/vnets/subnets CRUD + list controllers/ipams/dns + `apply_sdn` |\n| **ACME** | list + create account/plugin, delete plugin, `order_acme_certificate` / `renew_acme_certificate` |\n| **Ceph** | status, list pools/OSDs/MONs/MGRs, pool CRUD; gated OSD: `list_node_disks` → `propose_ceph_osd` → `create_ceph_osd`/`destroy_ceph_osd` (typed confirm; create defaults `dry_run=true`) |\n| **Pools** | list/get/create/update/delete |\n\n### Suggested agent flow\n\n1. `get_next_vmid` → `list_os_templates` / `list_isos` → `list_node_networks`\n2. `provision_lxc` / `provision_vm` (preferred one-shot) or `create_lxc` / `create_vm` → `wait_for_task` → start\n3. `create_snapshot` before risky changes → `update_*_config` → `get_guest_pending` → reboot if needed\n4. `migrate_guest` / HA / firewall / access / replication as needed\n\n**Guest type unknown?** Prefer unified tools (`start_guest`, `stop_guest`, `shutdown_guest`, `reboot_guest`, `delete_guest`, `get_guest_status`) with `guest_type=qemu|lxc`. Parallel `*_vm` / `*_lxc` names stay for existing prompts.\n\n## Installation\n\n### Prerequisites\n\n- [uv](https://github.com/astral-sh/uv) (recommended) **or** Python 3.10+\n- Proxmox API token\n\n### Path 1 — uvx (recommended)\n\nPyPI package name is **`cursor-proxmox-mcp`** (console scripts: `cursor-proxmox-mcp`, plus aliases `proxmox-mcp-server` / `proxmox-mcp`).\n\n> **Note:** The unrelated PyPI project `proxmox-mcp-server` is a different codebase. Always install **`cursor-proxmox-mcp`**.\n\n```bash\n# Install uv if needed:  pip install uv   OR   winget install astral-sh.uv\n\n# After PyPI publish (GitHub Release → publish.yml):\nuvx cursor-proxmox-mcp\n\n# From a local checkout (dev / before first publish):\nuvx --from . cursor-proxmox-mcp\n```\n\nCursor MCP (published package — no checkout):\n\n```json\n{\n  \"mcpServers\": {\n    \"proxmox\": {\n      \"command\": \"uvx\",\n      \"args\": [\"cursor-proxmox-mcp\"],\n      \"env\": {\n        \"PROXMOX_MCP_CONFIG\": \"C:/Users/YOU/proxmox-config/config.json\"\n      }\n    }\n  }\n}\n```\n\nFrom a local checkout, use `\"args\": [\"--from\", \"C:/Users/YOU/Projects/cursor-proxmox-mcp\", \"cursor-proxmox-mcp\"]` instead.\n\nWhy uvx: it resolves dependencies into an isolated ephemeral env so Cursor does not depend on a hand-managed venv/`PYTHONPATH`.\n\n### Path 2 — uv from source\n\n```bash\ngit clone https://github.com/hackmods/cursor-proxmox-mcp.git\ncd cursor-proxmox-mcp\nuv venv\n# Windows: .\\.venv\\Scripts\\Activate.ps1\n# Linux/macOS: source .venv/bin/activate\nuv pip install -e \".[dev]\"\ncp proxmox-config/config.example.json proxmox-config/config.json\n# Edit host + token, then:\nuv run cursor-proxmox-mcp\n```\n\n### Path 3 — pip fallback\n\n```bash\npython -m venv .venv\n# activate venv\npip install -e \".[dev]\"\n# optional OpenAPI bridge: pip install -e \".[openapi]\"\n$env:PROXMOX_MCP_CONFIG=\"proxmox-config\\config.json\"   # PowerShell\npython -m proxmox_mcp.server\n```\n\nCursor MCP (direct Python — use absolute paths):\n\n```json\n{\n  \"mcpServers\": {\n    \"proxmox\": {\n      \"command\": \"python\",\n      \"args\": [\"-m\", \"proxmox_mcp.server\"],\n      \"cwd\": \"C:/Users/YOU/Projects/cursor-proxmox-mcp\",\n      \"env\": {\n        \"PROXMOX_MCP_CONFIG\": \"C:/Users/YOU/Projects/cursor-proxmox-mcp/proxmox-config/config.json\",\n        \"PYTHONPATH\": \"C:/Users/YOU/Projects/cursor-proxmox-mcp/src\"\n      }\n    }\n  }\n}\n```\n\nRestart the **proxmox** MCP server in Cursor after pulling new tools. Manual launchers: `start.bat` (Windows) / `start.sh` (Unix) — prefer `uvx cursor-proxmox-mcp` in `mcp.json`.\n\n### Verify / local CI\n\n```powershell\n.\\scripts\\ci-local.ps1\n```\n\n```bash\n./scripts/ci-local.sh\n```\n\nRuns: editable install → entrypoint smoke → ruff → pytest → inventory floor (≥100 tools).\n\n### Troubleshooting\n\n| Symptom | Fix |\n|---------|-----|\n| `spawn uvx ENOENT` | Install uv (`pip install uv` or `winget install astral-sh.uv`), then restart Cursor |\n| `ModuleNotFoundError: proxmox_mcp` | Use uvx/`uv run`, or set `PYTHONPATH=.../src` for plain python |\n| `ModuleNotFoundError: mcp.server.fastmcp` | MCP SDK v2 dropped FastMCP — this server pins `mcp<2`. Reinstall from this checkout (`pip install -e \".[dev]\"` / `uvx --from .`) so the cap applies |\n| `PROXMOX_MCP_CONFIG ... must be set` | Point env at `proxmox-config/config.json` (absolute path) |\n| Auth OK but empty data / odd 403 | Privilege Separation **Yes** without token ACL — see [SETUP.md](SETUP.md#privilege-separation-the-gotcha) |\n| 403 on HA / firewall / `keyctl` | Token needs elevated role; prefer scoped `mcp@pve` over `root@pam` when possible |\n| Tools missing in Cursor | Restart MCP server after git pull |\n\nFirst-time cluster wiring (token, privsep, Cursor JSON, example prompts): **[SETUP.md](SETUP.md)**. LXC shell / runtime IP needs opt-in host SSH (`authorized_keys`, optional `host_overrides`, reload MCP): **[SETUP.md — SSH for LXC exec](SETUP.md#ssh-for-lxc-exec-opt-in)**.\n\n## Configuration\n\nExample `proxmox-config/config.json`:\n\n```json\n{\n  \"proxmox\": {\n    \"host\": \"PROXMOX_HOST\",\n    \"port\": 8006,\n    \"verify_ssl\": false,\n    \"service\": \"PVE\"\n  },\n  \"auth\": {\n    \"user\": \"USER@pve\",\n    \"token_name\": \"TOKEN_NAME\",\n    \"token_value\": \"TOKEN_VALUE\"\n  },\n  \"logging\": {\n    \"level\": \"INFO\",\n    \"format\": \"%(asctime)s - %(name)s - %(levelname)s - %(message)s\",\n    \"file\": \"proxmox_mcp.log\",\n    \"verbose\": false,\n    \"tool_calls\": true\n  }\n}\n```\n\nTool invocations are audited to the log file as `tool_call name=… ok=… duration_ms=…` (secrets redacted). Set `verbose: true` or env `PROXMOX_MCP_VERBOSE=1` for richer diagnostics without urllib3 spam. Details: [`proxmox-config/README.md` — Logging](proxmox-config/README.md#logging).\n\nCreate the token in Proxmox UI: Datacenter → Permissions → API Tokens. See **[SETUP.md — API token & Privilege Separation](SETUP.md#1-create-a-proxmox-api-token)** for the full walkthrough.\n\n**Privilege Separation:** leave **Yes** (default) and grant ACLs to the **token** (`user@realm!tokenid`). Setting it to **No** makes the token inherit the user’s full permissions (common lab shortcut; larger blast radius if leaked). Grant roles matching the tools you use (`PVEAuditor`, `PVEVMAdmin`, `Datastore.*`, `Sys.Audit`/`Sys.Modify` for HA/firewall/access).\n\nPrefer `\"token_value\": \"${PROXMOX_TOKEN_VALUE}\"` in config and set the env var in Cursor MCP config so secrets stay out of the JSON file.\n\n## Security\n\nThis server can create/delete guests, change firewall/ACL, and run guest commands. Treat the API token like production infra credentials. Full policy: **[SECURITY.md](SECURITY.md)**.\n\n## Features\n\n- Token auth via proxmoxer (JSON config + optional `${ENV}` secret interpolation)\n- Structured `tool_call` audit logging (redacted) + `verbose` / env log overrides\n- Full guest lifecycle, snapshots, vzdump backups\n- Storage content + definition CRUD + URL download\n- Cluster HA, firewall (rules/aliases/ipsets), access/ACL/tokens\n- Replication jobs, SDN write + apply, ACME order/renew, Ceph status/pools, pools\n- Console **ticket mint** + `get_console_connection` (VNC/SPICE/termproxy) — no websocket proxy (D6)\n- PBS as PVE storage plugin (not full PBS product admin); node network CRUD + reload\n- uvx / uv / pip / Docker (GHCR) install paths; optional `.[openapi]` for mcpo\n- Local + GitHub CI (`ruff` + `pytest` + coverage + inventory + design invariants)\n\n### Closed non-goals (not missing — D30)\n\nDo not treat these as planned gaps: long-lived VNC/SPICE **websocket proxy** (tickets only — D6), **full PBS product admin**, or **ungated** Ceph OSD/MON/MGR create/destroy. Gated OSD tools are shipped; MON/MGR lifecycle stays on Ceph/PVE tooling.\n\n## Development\n\n```powershell\n.\\scripts\\ci-local.ps1\n```\n\nAfter adding a tool: update `definitions.py`, README table, `.cursor/research/proxmox-api-coverage.md`, `.cursor/research/next-expansion.md` (if closing a planned row), and `tests/expected_tools.py`.\n\n## Status\n\n- [x] Formal multi-domain Proxmox API coverage (212 tools)\n- [x] Phase B + Phase D agent QOL tools\n- [x] Phase F LXC day-2 + Phase F.1 VM network/push + create wait opt-in\n- [x] Phase C light: node reboot/shutdown + cluster join (typed confirm)\n- [x] Phase C remainder: SDN write / ACME / Ceph pools / console helper / PBS storage / node net CRUD\n- [x] Gated Ceph OSD create/destroy (confirm + dry-run default)\n- [x] v1.0 security hardening, code-design audit, full test suite\n- [x] uvx `cursor-proxmox-mcp` + PyPI/GHCR release workflow\n- [x] Local + GitHub CI with coverage + design invariants\n\n## License\n\nMIT\n\n## Acknowledgments\n\nBased on [ProxmoxMCP](https://github.com/RekklesNA/ProxmoxMCP-Plus) / [canvrno/ProxmoxMCP](https://github.com/canvrno/ProxmoxMCP). Extended for Cursor IDE as a formal Proxmox VE integration.\n",
  "bytes": 12989,
  "sha": "f75a9fbabea6e58260918bf565076864e6c7c760907a6fe52cc1d589a6a0b31d",
  "repo_slug": "hackmods/cursor-proxmox-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_hackmods_cursor_proxmox_mcp_6d2bc6be/readme"
}