3.9 KiB
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
-
Transport:
- Protocol: Server-Sent Events (SSE) over HTTP.
- Framework:
mcp(official Python SDK) usingFastMCP. - Server:
uvicorn(ASGI server). - Host Binding:
0.0.0.0:8000(exposed for Docker).
-
Proxmox Integration:
- Client Library:
proxmoxer(Python wrapper for Proxmox API). - Authentication: API Token (
user@pam!token_id) or Username/Password. - SSL: Configurable verification (default
falsefor homelabs).
- Client Library:
-
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).
- Container: Docker (multi-stage build with
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 byproxmoxer.- 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.
- Example:
Current Implementation Details
server.py
- Uses
mcp.server.fastmcp.FastMCPto define the server and tools. - Connects to Proxmox using
proxmoxer.ProxmoxAPI. - Exposes
mcp.sse_apptouvicornfor execution.
Challenges & Workarounds
- Host Header Validation: The
mcpSDK enforces strict Host header checks by default. We are currently configuringFastMCPsettings to allow external access (e.g.,proxmox-mcp.ext.ben.io). - Dependency Management: We use
uvfor fast, reliable builds in Docker. - API Client:
proxmoxerrequiresrequests(added topyproject.toml).
Next Steps
- Resolve the
Invalid Host headererror by correctly configuringmcp.settings.allowed_hostsor middleware. - Deploy the final image to Portainer.
- 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
uvicornExecution: I cannot directly run the Python server locally to quickly test changes. - Remote Docker Environment: Each code change requires:
- Committing and pushing to Gitea.
- Waiting for Gitea Actions to build and push the Docker image.
- Redeploying the Docker stack on the Portainer host.
- 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-mcpandproxmox-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.