Initial commit: Custom Proxmox MCP with SSE wrapper
All checks were successful
Build and Push Proxmox MCP Docker Image / build (push) Successful in 7s
All checks were successful
Build and Push Proxmox MCP Docker Image / build (push) Successful in 7s
This commit is contained in:
83
IMPLEMENTATION.md
Normal file
83
IMPLEMENTATION.md
Normal 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.
|
||||
|
||||
Reference in New Issue
Block a user