feat: Add multi-cluster support with JSON config
All checks were successful
Build and Push Proxmox MCP Docker Image / build (push) Successful in 8s

This commit is contained in:
Ben
2025-12-15 01:37:31 +00:00
parent 2bb507cdac
commit 4b576d40ad
8 changed files with 317 additions and 229 deletions

View File

@@ -1,6 +1,6 @@
# Implementation Details
Technical documentation for the Proxmox MCP Server implementation.
Technical documentation for the Proxmox MCP Server.
## Architecture
@@ -8,93 +8,79 @@ Technical documentation for the Proxmox MCP Server implementation.
┌─────────────────────────────────────────────────────────┐
│ MCP Client (Gemini CLI) │
└─────────────────────────┬───────────────────────────────┘
│ SSE (Server-Sent Events)
┌─────────────────────────────────────────────────────────┐
│ Reverse Proxy (Traefik) │
│ proxmox-mcp.ext.ben.io:443 │
└─────────────────────────┬───────────────────────────────┘
│ HTTP
│ SSE
┌─────────────────────────────────────────────────────────┐
│ Docker Container (proxmox-mcp) │
│ ┌───────────────────────────────────────────────────┐ │
│ │ FastMCP + uvicorn (:8000) │ │
│ │ ┌─────────────────────────────────────────────┐ │ │
│ │ │ TransportSecuritySettings │ │ │
│ │ │ (DNS rebinding protection) │ │ │
│ │ └─────────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ proxmoxer │ │
│ │ (Proxmox API client) │ │
└───────────────────────┬───────────────────────────┘
└──────────────────────────┼──────────────────────────────┘
│ HTTPS
┌─────────────────────────────────────────────────────────┐
Proxmox VE API
pve.local.ben.io:8006 │
└─────────────────────────────────────────────────────────┘
│ │ ClusterManager │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ prod │ │ homelab │ │ ... │ │
│ │ └────────┘ └────────┘ └────┬────┘ │ │
└─────────┼────────────┼────────────┼──────────────┘ │
└────────────┼────────────┼────────────┼──────────────────┘
│ │ │
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Proxmox │ │ Proxmox │ │ Proxmox │
│ Cluster 1│ │ Cluster 2│ │ Cluster N│
└──────────┘ └──────────┘ └──────────┘
```
## Components
### Transport Layer
- **Protocol:** SSE (Server-Sent Events) over HTTP
- **Framework:** `mcp.server.fastmcp.FastMCP`
- **Server:** `uvicorn` (ASGI)
- **Binding:** `0.0.0.0:8000`
### ClusterManager
- Loads cluster configs from `clusters.json`
- Maintains `ProxmoxAPI` connections for each cluster
- Handles cluster selection logic (default if single cluster)
### Security
- **DNS Rebinding Protection:** `TransportSecuritySettings` validates Host headers
- **Allowed Hosts:** Configurable via `MCP_ALLOWED_HOSTS` environment variable
- **SSL:** Configurable verification for self-signed certificates
### Transport Security
- `TransportSecuritySettings` validates Host headers
- Configurable via `MCP_ALLOWED_HOSTS`
### Proxmox Integration
- **Client:** `proxmoxer.ProxmoxAPI`
- **Authentication:** API Token (recommended) or Username/Password
- **Token Format:** User (`user@realm`) + Token Name (not full ID) + Token Secret
### Tool Strategy
## The Hybrid Tool Strategy
**Layer 1: Curated Tools**
- `list_clusters()` - Discovery
- `list_nodes(cluster)` - Node status
- `get_cluster_resources(cluster)` - Resource summary
Instead of wrapping every Proxmox API endpoint (hundreds exist), we expose two layers:
**Layer 2: Raw Access**
- `proxmox_api_call(cluster, path, method, data)` - Any API endpoint
### Layer 1: Curated Tools
High-frequency operations with simplified interfaces:
- `list_nodes()` - Cluster node status
- `get_cluster_resources()` - All VMs, LXCs, and storage
## Configuration Format
### Layer 2: Raw API Access
- `proxmox_api_call(path, method, data)` - Direct access to any Proxmox API endpoint
- **Benefit:** Zero maintenance. New Proxmox features work immediately without code changes.
## Build & CI/CD
- **Build Tool:** `uv` (fast Python package manager)
- **Container:** Multi-stage Docker build
- **Registry:** Gitea Container Registry
- **CI/CD:** Gitea Actions (build & push on commit to main/master)
- **Orchestration:** Portainer (Docker Compose stack)
## Key Implementation Notes
```json
{
"clusters": {
"<name>": {
"url": "host:port",
"user": "user@realm",
"token_id": "token_name",
"token_secret": "secret",
"verify_ssl": false
}
}
}
```
### Token Authentication
The `proxmoxer` library constructs auth headers as:
The `proxmoxer` library uses:
```
Authorization: PVEAPIToken={user}!{token_name}={token_value}
Authorization: PVEAPIToken={user}!{token_id}={token_secret}
```
Therefore:
- `PROXMOX_USER` = Full user (`proxmox-mcp@pam`)
- `PROXMOX_TOKEN_ID` = Token name only (`token`)
- `PROXMOX_PASSWORD` = Token secret value
So for token `mcp@pam!mytoken`:
- `user` = `mcp@pam`
- `token_id` = `mytoken`
### Host Header Validation
The MCP SDK enforces strict Host header validation. For reverse proxy access:
```python
transport_security = TransportSecuritySettings(
enable_dns_rebinding_protection=True,
allowed_hosts=["proxmox-mcp.ext.ben.io", "localhost:*"],
)
```
## Build & Deploy
- **Build:** `uv` + multi-stage Docker
- **Registry:** Gitea Container Registry
- **CI/CD:** Gitea Actions
- **Deploy:** Docker Compose / Portainer