Files
proxmox-mcp-custom/IMPLEMENTATION.md
Ben 1c02d5cf6d
All checks were successful
Build and Push Proxmox MCP Docker Image / build (push) Successful in 8s
Initial commit: Custom Proxmox MCP with SSE wrapper
2025-12-14 20:39:56 +00:00

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

  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 (user@pam!token_id) or Username/Password.
    • 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).

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.

Challenges & Workarounds

  • Host Header Validation: The mcp SDK enforces strict Host header checks by default. We are currently configuring FastMCP settings to allow external access (e.g., proxmox-mcp.ext.ben.io).
  • 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 by correctly configuring mcp.settings.allowed_hosts or middleware.
  2. Deploy the final image to Portainer.
  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.