Initial commit: Custom Proxmox MCP with SSE wrapper
All checks were successful
Build and Push Proxmox MCP Docker Image / build (push) Successful in 7s

This commit is contained in:
Ben
2025-12-14 18:07:57 +00:00
commit 9c7e2d41dc
11 changed files with 478 additions and 0 deletions

83
IMPLEMENTATION.md Normal file
View File

@@ -0,0 +1,83 @@
# Custom Proxmox MCP Server Implementation
## Architecture Overview
This project implements a **Model Context Protocol (MCP)** server for Proxmox VE using a "Hybrid" design pattern. It combines specific, high-value tools with raw API access to ensure both usability and comprehensive coverage.
### Core Components
1. **Transport:**
* **Protocol:** Server-Sent Events (SSE) over HTTP.
* **Framework:** `mcp` (official Python SDK) using `FastMCP`.
* **Server:** `uvicorn` (ASGI server).
* **Host Binding:** `0.0.0.0:8000` (exposed for Docker).
2. **Proxmox Integration:**
* **Client Library:** `proxmoxer` (Python wrapper for Proxmox API).
* **Authentication:** API Token or Username/Password.
* **User:** Must be full `user@realm` (e.g., `proxmox-mcp@pam`).
* **Token ID:** Just the token name (e.g., `token`), NOT the full ID.
* **SSL:** Configurable verification (default `false` for homelabs).
3. **Deployment:**
* **Container:** Docker (multi-stage build with `uv`).
* **Registry:** Gitea Container Registry (`gitea.ext.ben.io`).
* **Orchestration:** Portainer (Docker Compose stack).
* **CI/CD:** Gitea Actions (build & push on commit).
## Current Status (Dec 14, 2025)
* **Infrastructure:** Gitea build pipeline and Docker registry are fully operational.
* **Server:** `proxmox-mcp-custom` container is running and accessible via Gemini CLI.
* **Connectivity:** Direct `curl` tests confirmed Proxmox API connectivity and credential validity.
* **Resolved Issues:**
***Host Header:** Added `TransportSecuritySettings` with `MCP_ALLOWED_HOSTS` env var to allow reverse proxy access.
***Token Auth:** Fixed user string format (was incorrectly `user@token_id`, now just `user`).
***Local Testing:** Added `docker-compose.dev.yml`, `Makefile`, and `.env` support for local development.
## The Hybrid Tool Strategy
Instead of wrapping every Proxmox API endpoint (of which there are hundreds), we expose two layers of tools:
### Layer 1: Curated Tools (High Frequency)
These tools simplify common tasks for the LLM.
* `list_nodes()`: Returns cluster node status.
* `get_cluster_resources()`: Returns all VMs, LXCs, and storage.
### Layer 2: Raw Access (The "Escape Hatch")
* `proxmox_api_call(path, method, data)`: A generic tool that allows the LLM to construct *any* API call supported by `proxmoxer`.
* Example: `path="nodes/pve1/qemu/100/status/start", method="POST"`
* **Benefit:** Zero maintenance. If Proxmox adds a feature, the LLM can use it immediately without code changes.
## Current Implementation Details
### `server.py`
* Uses `mcp.server.fastmcp.FastMCP` to define the server and tools.
* Connects to Proxmox using `proxmoxer.ProxmoxAPI`.
* Exposes `mcp.sse_app` to `uvicorn` for execution.
* Configures `TransportSecuritySettings` for DNS rebinding protection with allowed hosts.
### Challenges & Workarounds
* **Host Header Validation:** Resolved by configuring `TransportSecuritySettings` with `MCP_ALLOWED_HOSTS`.
* **Dependency Management:** We use `uv` for fast, reliable builds in Docker.
* **API Client:** `proxmoxer` requires `requests` (added to `pyproject.toml`).
## Next Steps
1.~~Resolve the `Invalid Host header` error~~ - Fixed with `TransportSecuritySettings`.
2. Update Portainer stack with corrected `PROXMOX_TOKEN_ID` (just token name, not full ID).
3. Connect Gemini CLI via `https://proxmox-mcp.ext.ben.io/sse`.
## Local Testing Challenges
A significant challenge in this development environment is the **lack of direct local testing capabilities**. Due to the nature of operating within a sandboxed agent and the separation between the development VM (where this agent runs) and the target Docker/Portainer host, the standard iterative development loop (code -> test -> debug) is heavily impacted:
* **No Direct `uvicorn` Execution:** I cannot directly run the Python server locally to quickly test changes.
* **Remote Docker Environment:** Each code change requires:
1. Committing and pushing to Gitea.
2. Waiting for Gitea Actions to build and push the Docker image.
3. Redeploying the Docker stack on the Portainer host.
4. Analyzing remote container logs for feedback.
* **Limited Debugging:** The inability to attach a debugger or inspect live execution locally forces a heavy reliance on log analysis.
* **Slow Feedback Loop:** This multi-step remote process introduces significant delays, prolonging the time it takes to identify and fix issues (as evidenced by the numerous iterations for `portainer-mcp` and `proxmox-mcp-custom`).
This necessitates careful reasoning, documentation review, and a systematic approach to debugging, often leading to more turns than would be typical in a local development setup.