From d27767499aa5092813e2193ef550f138dd4d9488 Mon Sep 17 00:00:00 2001 From: canvrno Date: Tue, 18 Feb 2025 23:59:42 -0700 Subject: [PATCH] Readme, documentation --- README.md | 291 ++++++++++++++--------- src/proxmox_mcp/config/loader.py | 49 +++- src/proxmox_mcp/config/models.py | 72 +++++- src/proxmox_mcp/core/logging.py | 45 +++- src/proxmox_mcp/core/proxmox.py | 55 ++++- src/proxmox_mcp/server.py | 35 ++- src/proxmox_mcp/tools/base.py | 48 +++- src/proxmox_mcp/tools/cluster.py | 51 +++- src/proxmox_mcp/tools/console/manager.py | 69 +++++- src/proxmox_mcp/tools/node.py | 77 +++++- src/proxmox_mcp/tools/storage.py | 50 +++- src/proxmox_mcp/tools/vm.py | 76 +++++- 12 files changed, 741 insertions(+), 177 deletions(-) diff --git a/README.md b/README.md index 304bf30..135dd40 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,28 @@ -# Proxmox MCP Server +# 🚀 Proxmox MCP Server A Python-based Model Context Protocol (MCP) server for interacting with Proxmox hypervisors, providing a clean interface for managing nodes, VMs, and containers. -## Features +## 🏗️ Built With -- Built with the official MCP SDK -- Secure token-based authentication with Proxmox -- Tools for managing nodes, VMs, and containers -- VM console command execution -- Configurable logging system -- Type-safe implementation with Pydantic -- Full integration with Claude Desktop +- [Cline](https://github.com/cline/cline) - Autonomous coding agent - Go faster with Cline. +- [Proxmoxer](https://github.com/proxmoxer/proxmoxer) - Python wrapper for Proxmox API +- [MCP SDK](https://github.com/modelcontextprotocol/sdk) - Model Context Protocol SDK +- [Pydantic](https://docs.pydantic.dev/) - Data validation using Python type annotations -## Installation +## ✨ Features -1. Create a directory for your MCP servers (if you haven't already): +- 🛠️ Built with the official MCP SDK +- 🔒 Secure token-based authentication with Proxmox +- 🖥️ Tools for managing nodes and VMs +- 💻 VM console command execution +- 📝 Configurable logging system +- ✅ Type-safe implementation with Pydantic +- 🤖 Full integration with Claude Desktop +- 🎨 Rich output formatting with customizable themes + +## 📦 Installation + +1. Create a directory for your [Cline](https://github.com/cline/cline) MCP servers (if you haven't already): ```bash mkdir -p ~/Documents/Cline/MCP cd ~/Documents/Cline/MCP @@ -23,7 +31,7 @@ A Python-based Model Context Protocol (MCP) server for interacting with Proxmox 2. Clone and install the package: ```bash # Clone the repository - git clone https://github.com/yourusername/proxmox-mcp.git + git clone https://github.com/canvrno/ProxmoxMCP.git # Install in development mode with dependencies pip install -e "proxmox-mcp[dev]" @@ -31,7 +39,8 @@ A Python-based Model Context Protocol (MCP) server for interacting with Proxmox 3. Create and verify your configuration: ```bash - # Create config directory + # Create config directory in the project root + cd ProxmoxMCP mkdir proxmox-config cd proxmox-config ``` @@ -71,12 +80,14 @@ A Python-based Model Context Protocol (MCP) server for interacting with Proxmox - `get_nodes`: List all nodes in the cluster - `get_node_status`: Get detailed status of a node - `get_vms`: List all VMs - - `get_containers`: List all LXC containers - `get_storage`: List available storage - `get_cluster_status`: Get cluster status - `execute_vm_command`: Run commands in VM consoles -## Development Setup +Requirements: +- Python 3.9 or higher + +## 🛠️ Development Setup 1. Install UV: ```bash @@ -85,7 +96,7 @@ A Python-based Model Context Protocol (MCP) server for interacting with Proxmox 2. Clone the repository: ```bash - git clone https://github.com/yourusername/proxmox-mcp.git + git clone https://github.com/canvrno/ProxmoxMCP.git cd proxmox-mcp ``` @@ -108,7 +119,7 @@ A Python-based Model Context Protocol (MCP) server for interacting with Proxmox uv pip install -e . ``` -## Configuration +## ⚙️ Configuration ### Proxmox API Token Setup 1. Log into your Proxmox web interface @@ -168,7 +179,7 @@ LOG_FORMAT=%(asctime)s... # Default: standard format LOG_FILE=proxmox_mcp.log # Default: None (stdout) ``` -## Available Tools +## 🔧 Available Tools The server provides the following MCP tools for interacting with Proxmox: @@ -177,17 +188,32 @@ Lists all nodes in the Proxmox cluster. - Parameters: None - Example Response: - ```json - [ - { - "node": "pve1", - "status": "online" - }, - { - "node": "pve2", - "status": "online" - } - ] + ``` + 🖥️ Proxmox Nodes + + 🖥️ pve-compute-01 + • Status: ONLINE + • Uptime: ⏳ 156d 12h + • CPU Cores: 64 + • Memory: 186.5 GB / 512.0 GB (36.4%) + + 🖥️ pve-compute-02 + • Status: ONLINE + • Uptime: ⏳ 156d 11h + • CPU Cores: 64 + • Memory: 201.3 GB / 512.0 GB (39.3%) + + 🖥️ pve-storage-01 + • Status: ONLINE + • Uptime: ⏳ 156d 12h + • CPU Cores: 32 + • Memory: 89.2 GB / 256.0 GB (34.8%) + + 🖥️ pve-storage-02 + • Status: ONLINE + • Uptime: ⏳ 156d 12h + • CPU Cores: 32 + • Memory: 92.8 GB / 256.0 GB (36.2%) ``` ### get_node_status @@ -196,17 +222,15 @@ Get detailed status of a specific node. - Parameters: - `node` (string, required): Name of the node - Example Response: - ```json - { - "status": "running", - "uptime": 1234567, - "cpu": 0.12, - "memory": { - "total": 16777216, - "used": 8388608, - "free": 8388608 - } - } + ``` + 🖥️ Node: pve-compute-01 + • Status: ONLINE + • Uptime: ⏳ 156d 12h + • CPU Usage: 42.3% + • CPU Cores: 64 (AMD EPYC 7763) + • Memory: 186.5 GB / 512.0 GB (36.4%) + • Network: ⬆️ 12.8 GB/s ⬇️ 9.2 GB/s + • Temperature: 38°C ``` ### get_vms @@ -214,43 +238,56 @@ List all VMs across the cluster. - Parameters: None - Example Response: - ```json - [ - { - "vmid": "100", - "name": "web-server", - "status": "running", - "node": "pve1" - }, - { - "vmid": "101", - "name": "database", - "status": "stopped", - "node": "pve2" - } - ] ``` + 🗃️ Virtual Machines -### get_containers -List all LXC containers. + 🗃️ prod-db-master (ID: 100) + • Status: RUNNING + • Node: pve-compute-01 + • CPU Cores: 16 + • Memory: 92.3 GB / 128.0 GB (72.1%) -- Parameters: None -- Example Response: - ```json - [ - { - "vmid": "200", - "name": "docker-host", - "status": "running", - "node": "pve1" - }, - { - "vmid": "201", - "name": "nginx-proxy", - "status": "running", - "node": "pve1" - } - ] + 🗃️ prod-db-replica-01 (ID: 101) + • Status: RUNNING + • Node: pve-compute-02 + • CPU Cores: 16 + • Memory: 86.5 GB / 128.0 GB (67.6%) + + 🗃️ prod-web-01 (ID: 102) + • Status: RUNNING + • Node: pve-compute-01 + • CPU Cores: 8 + • Memory: 12.8 GB / 32.0 GB (40.0%) + + 🗃️ prod-web-02 (ID: 103) + • Status: RUNNING + • Node: pve-compute-02 + • CPU Cores: 8 + • Memory: 13.2 GB / 32.0 GB (41.3%) + + 🗃️ prod-cache-01 (ID: 104) + • Status: RUNNING + • Node: pve-compute-01 + • CPU Cores: 4 + • Memory: 24.6 GB / 64.0 GB (38.4%) + + 🗃️ prod-cache-02 (ID: 105) + • Status: RUNNING + • Node: pve-compute-02 + • CPU Cores: 4 + • Memory: 25.1 GB / 64.0 GB (39.2%) + + 🗃️ staging-env (ID: 106) + • Status: RUNNING + • Node: pve-compute-02 + • CPU Cores: 32 + • Memory: 48.2 GB / 128.0 GB (37.7%) + + 🗃️ dev-env (ID: 107) + • Status: STOPPED + • Node: pve-compute-01 + • CPU Cores: 16 + • Memory: 0.0 GB / 64.0 GB (0.0%) ``` ### get_storage @@ -258,17 +295,32 @@ List available storage. - Parameters: None - Example Response: - ```json - [ - { - "storage": "local", - "type": "dir" - }, - { - "storage": "ceph-pool", - "type": "rbd" - } - ] + ``` + 💾 Storage Pools + + 💾 ceph-prod + • Status: ONLINE + • Type: rbd + • Usage: 12.8 TB / 20.0 TB (64.0%) + • IOPS: ⬆️ 15.2k ⬇️ 12.8k + + 💾 ceph-backup + • Status: ONLINE + • Type: rbd + • Usage: 28.6 TB / 40.0 TB (71.5%) + • IOPS: ⬆️ 8.4k ⬇️ 6.2k + + 💾 nvme-cache + • Status: ONLINE + • Type: lvmthin + • Usage: 856.2 GB / 2.0 TB (42.8%) + • IOPS: ⬆️ 125.6k ⬇️ 98.4k + + 💾 local-zfs + • Status: ONLINE + • Type: zfspool + • Usage: 3.2 TB / 8.0 TB (40.0%) + • IOPS: ⬆️ 42.8k ⬇️ 35.6k ``` ### get_cluster_status @@ -276,13 +328,24 @@ Get overall cluster status. - Parameters: None - Example Response: - ```json - { - "quorate": true, - "nodes": 2, - "version": "7.4-15", - "cluster_name": "proxmox-cluster" - } + ``` + ⚙️ Proxmox Cluster + + • Name: enterprise-cloud + • Status: HEALTHY + • Quorum: OK + • Nodes: 4 ONLINE + • Version: 8.1.3 + • HA Status: ACTIVE + • Resources: + - Total CPU Cores: 192 + - Total Memory: 1536 GB + - Total Storage: 70 TB + • Workload: + - Running VMs: 7 + - Total VMs: 8 + - Average CPU Usage: 38.6% + - Average Memory Usage: 42.8% ``` ### execute_vm_command @@ -293,13 +356,26 @@ Execute a command in a VM's console using QEMU Guest Agent. - `vmid` (string, required): ID of the VM - `command` (string, required): Command to execute - Example Response: - ```json - { - "success": true, - "output": "command output here", - "error": "", - "exit_code": 0 - } + ``` + 🔧 Console Command Result + • Status: SUCCESS + • Command: systemctl status nginx + • Node: pve-compute-01 + • VM: prod-web-01 (ID: 102) + + Output: + ● nginx.service - A high performance web server and a reverse proxy server + Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled) + Active: active (running) since Tue 2025-02-18 15:23:45 UTC; 2 months 3 days ago + Docs: man:nginx(8) + Main PID: 1234 (nginx) + Tasks: 64 + Memory: 256.2M + CPU: 42.6h + CGroup: /system.slice/nginx.service + ├─1234 "nginx: master process /usr/sbin/nginx -g daemon on; master_pr..." + ├─1235 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" + └─1236 "nginx: worker process" "" "" "" "" "" "" "" "" "" "" "" "" "" ``` - Requirements: - VM must be running @@ -311,7 +387,7 @@ Execute a command in a VM's console using QEMU Guest Agent. - Returns error if command execution fails - Includes command output even if command returns non-zero exit code -## Running the Server +## 🚀 Running the Server ### Development Mode For testing and development, use the MCP development server: @@ -340,7 +416,7 @@ Run the server directly: python -m proxmox_mcp.server ``` -## Error Handling +## ⚠️ Error Handling The server implements comprehensive error handling: @@ -351,7 +427,7 @@ The server implements comprehensive error handling: All errors are properly logged and returned with descriptive messages. -## Logging +## 📝 Logging Logging can be configured through the config file or environment variables: @@ -366,22 +442,25 @@ Example log output: 2025-02-18 19:15:25,123 - proxmox-mcp - DEBUG - Tool called: get_nodes ``` -## Development +## 👨‍💻 Development - Run tests: `pytest` - Format code: `black .` - Type checking: `mypy .` - Lint: `ruff .` -## Project Structure +## 📁 Project Structure ``` proxmox-mcp/ ├── src/ │ └── proxmox_mcp/ │ ├── server.py # Main MCP server implementation +│ ├── config/ # Configuration handling +│ ├── core/ # Core functionality +│ ├── formatting/ # Output formatting and themes │ ├── tools/ # Tool implementations -│ │ └── vm_console.py # VM console operations +│ │ └── console/ # VM console operations │ └── utils/ # Utilities (auth, logging) ├── tests/ # Test suite ├── config/ @@ -392,6 +471,6 @@ proxmox-mcp/ └── LICENSE # MIT License ``` -## License +## 📄 License MIT License diff --git a/src/proxmox_mcp/config/loader.py b/src/proxmox_mcp/config/loader.py index fbdae83..98af6f6 100644 --- a/src/proxmox_mcp/config/loader.py +++ b/src/proxmox_mcp/config/loader.py @@ -1,5 +1,14 @@ """ Configuration loading utilities for the Proxmox MCP server. + +This module handles loading and validation of server configuration: +- JSON configuration file loading +- Environment variable handling +- Configuration validation using Pydantic models +- Error handling for invalid configurations + +The module ensures that all required configuration is present +and valid before the server starts operation. """ import json import os @@ -7,16 +16,48 @@ from typing import Optional from .models import Config def load_config(config_path: Optional[str] = None) -> Config: - """Load configuration from file. + """Load and validate configuration from JSON file. + Performs the following steps: + 1. Verifies config path is provided + 2. Loads JSON configuration file + 3. Validates required fields are present + 4. Converts to typed Config object using Pydantic + + Configuration must include: + - Proxmox connection settings (host, port, etc.) + - Authentication credentials (user, token) + - Logging configuration + Args: - config_path: Path to the configuration file + config_path: Path to the JSON configuration file + If not provided, raises ValueError Returns: - Config object containing the loaded configuration + Config object containing validated configuration: + { + "proxmox": { + "host": "proxmox-host", + "port": 8006, + ... + }, + "auth": { + "user": "username", + "token_name": "token-name", + ... + }, + "logging": { + "level": "INFO", + ... + } + } Raises: - ValueError: If config path is not provided or config is invalid + ValueError: If: + - Config path is not provided + - JSON is invalid + - Required fields are missing + - Field values are invalid """ if not config_path: raise ValueError("PROXMOX_MCP_CONFIG environment variable must be set") diff --git a/src/proxmox_mcp/config/models.py b/src/proxmox_mcp/config/models.py index 80028e5..2e8a3c7 100644 --- a/src/proxmox_mcp/config/models.py +++ b/src/proxmox_mcp/config/models.py @@ -1,34 +1,80 @@ """ Configuration models for the Proxmox MCP server. + +This module defines Pydantic models for configuration validation: +- Proxmox connection settings +- Authentication credentials +- Logging configuration +- Tool-specific parameter models + +The models provide: +- Type validation +- Default values +- Field descriptions +- Required vs optional field handling """ from typing import Optional, Annotated from pydantic import BaseModel, Field class NodeStatus(BaseModel): + """Model for node status query parameters. + + Validates and documents the required parameters for + querying a specific node's status in the cluster. + """ node: Annotated[str, Field(description="Name/ID of node to query (e.g. 'pve1', 'proxmox-node2')")] class VMCommand(BaseModel): + """Model for VM command execution parameters. + + Validates and documents the required parameters for + executing commands within a VM via QEMU guest agent. + """ node: Annotated[str, Field(description="Host node name (e.g. 'pve1', 'proxmox-node2')")] vmid: Annotated[str, Field(description="VM ID number (e.g. '100', '101')")] command: Annotated[str, Field(description="Shell command to run (e.g. 'uname -a', 'systemctl status nginx')")] class ProxmoxConfig(BaseModel): - host: str - port: int = 8006 - verify_ssl: bool = True - service: str = "PVE" + """Model for Proxmox connection configuration. + + Defines the required and optional parameters for + establishing a connection to the Proxmox API server. + Provides sensible defaults for optional parameters. + """ + host: str # Required: Proxmox host address + port: int = 8006 # Optional: API port (default: 8006) + verify_ssl: bool = True # Optional: SSL verification (default: True) + service: str = "PVE" # Optional: Service type (default: PVE) class AuthConfig(BaseModel): - user: str - token_name: str - token_value: str + """Model for Proxmox authentication configuration. + + Defines the required parameters for API authentication + using token-based authentication. All fields are required + to ensure secure API access. + """ + user: str # Required: Username (e.g., 'root@pam') + token_name: str # Required: API token name + token_value: str # Required: API token secret class LoggingConfig(BaseModel): - level: str = "INFO" - format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" - file: Optional[str] = None + """Model for logging configuration. + + Defines logging parameters with sensible defaults. + Supports both file and console logging with + customizable format and log levels. + """ + level: str = "INFO" # Optional: Log level (default: INFO) + format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s" # Optional: Log format + file: Optional[str] = None # Optional: Log file path (default: None for console logging) class Config(BaseModel): - proxmox: ProxmoxConfig - auth: AuthConfig - logging: LoggingConfig + """Root configuration model. + + Combines all configuration models into a single validated + configuration object. All sections are required to ensure + proper server operation. + """ + proxmox: ProxmoxConfig # Required: Proxmox connection settings + auth: AuthConfig # Required: Authentication credentials + logging: LoggingConfig # Required: Logging configuration diff --git a/src/proxmox_mcp/core/logging.py b/src/proxmox_mcp/core/logging.py index 708fb5f..a22e326 100644 --- a/src/proxmox_mcp/core/logging.py +++ b/src/proxmox_mcp/core/logging.py @@ -1,5 +1,18 @@ """ Logging configuration for the Proxmox MCP server. + +This module handles logging setup and configuration: +- File and console logging handlers +- Log level management +- Format customization +- Handler lifecycle management + +The logging system supports: +- Configurable log levels +- File-based logging with path resolution +- Console logging for errors +- Custom format strings +- Multiple handler management """ import logging import os @@ -7,13 +20,39 @@ from typing import Optional from ..config.models import LoggingConfig def setup_logging(config: LoggingConfig) -> logging.Logger: - """Configure logging based on settings. + """Configure and initialize logging system. + Sets up a comprehensive logging system with: + - File logging (if configured): + * Handles relative/absolute paths + * Uses configured log level + * Applies custom format + + - Console logging: + * Always enabled for errors + * Ensures critical issues are visible + + - Handler Management: + * Removes existing handlers + * Configures new handlers + * Sets up formatters + Args: - config: Logging configuration + config: Logging configuration containing: + - Log level (e.g., "INFO", "DEBUG") + - Format string + - Optional log file path Returns: - Configured logger instance + Configured logger instance for "proxmox-mcp" + with appropriate handlers and formatting + + Example config: + { + "level": "INFO", + "format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s", + "file": "/path/to/log/file.log" # Optional + } """ # Convert relative path to absolute log_file = config.file diff --git a/src/proxmox_mcp/core/proxmox.py b/src/proxmox_mcp/core/proxmox.py index 496ce20..2466de1 100644 --- a/src/proxmox_mcp/core/proxmox.py +++ b/src/proxmox_mcp/core/proxmox.py @@ -1,5 +1,15 @@ """ Proxmox API setup and management. + +This module handles the core Proxmox API integration, providing: +- Secure API connection setup and management +- Token-based authentication +- Connection testing and validation +- Error handling for API operations + +The ProxmoxManager class serves as the central point for all Proxmox API +interactions, ensuring consistent connection handling and authentication +across the MCP server. """ import logging from typing import Dict, Any @@ -7,7 +17,17 @@ from proxmoxer import ProxmoxAPI from ..config.models import ProxmoxConfig, AuthConfig class ProxmoxManager: - """Manager class for Proxmox API operations.""" + """Manager class for Proxmox API operations. + + This class handles: + - API connection initialization and management + - Configuration validation and merging + - Connection testing and health checks + - Token-based authentication setup + + The manager provides a single point of access to the Proxmox API, + ensuring proper initialization and error handling for all API operations. + """ def __init__(self, proxmox_config: ProxmoxConfig, auth_config: AuthConfig): """Initialize the Proxmox API manager. @@ -23,12 +43,19 @@ class ProxmoxManager: def _create_config(self, proxmox_config: ProxmoxConfig, auth_config: AuthConfig) -> Dict[str, Any]: """Create a configuration dictionary for ProxmoxAPI. + Merges connection and authentication configurations into a single + dictionary suitable for ProxmoxAPI initialization. Handles: + - Host and port configuration + - SSL verification settings + - Token-based authentication details + - Service type specification + Args: - proxmox_config: Proxmox connection configuration - auth_config: Authentication configuration + proxmox_config: Proxmox connection configuration (host, port, SSL settings) + auth_config: Authentication configuration (user, token details) Returns: - Dictionary containing merged configuration + Dictionary containing merged configuration ready for API initialization """ return { 'host': proxmox_config.host, @@ -43,11 +70,21 @@ class ProxmoxManager: def _setup_api(self) -> ProxmoxAPI: """Initialize and test Proxmox API connection. + Performs the following steps: + 1. Creates ProxmoxAPI instance with configured settings + 2. Tests connection by making a version check request + 3. Validates authentication and permissions + 4. Logs connection status and any issues + Returns: - Initialized ProxmoxAPI instance + Initialized and tested ProxmoxAPI instance Raises: - RuntimeError: If connection fails + RuntimeError: If connection fails due to: + - Invalid host/port + - Authentication failure + - Network connectivity issues + - SSL certificate validation errors """ try: self.logger.info(f"Connecting to Proxmox host: {self.config['host']}") @@ -64,8 +101,12 @@ class ProxmoxManager: def get_api(self) -> ProxmoxAPI: """Get the initialized Proxmox API instance. + + Provides access to the configured and tested ProxmoxAPI instance + for making API calls. The instance maintains connection state and + handles authentication automatically. Returns: - ProxmoxAPI instance + ProxmoxAPI instance ready for making API calls """ return self.api diff --git a/src/proxmox_mcp/server.py b/src/proxmox_mcp/server.py index 9b1e397..3a77324 100644 --- a/src/proxmox_mcp/server.py +++ b/src/proxmox_mcp/server.py @@ -1,5 +1,18 @@ """ Main server implementation for Proxmox MCP. + +This module implements the core MCP server for Proxmox integration, providing: +- Configuration loading and validation +- Logging setup +- Proxmox API connection management +- MCP tool registration and routing +- Signal handling for graceful shutdown + +The server exposes a set of tools for managing Proxmox resources including: +- Node management +- VM operations +- Storage management +- Cluster status monitoring """ import logging import os @@ -56,7 +69,17 @@ class ProxmoxMCPServer: self._setup_tools() def _setup_tools(self) -> None: - """Register MCP tools.""" + """Register MCP tools with the server. + + Initializes and registers all available tools with the MCP server: + - Node management tools (list nodes, get status) + - VM operation tools (list VMs, execute commands) + - Storage management tools (list storage) + - Cluster tools (get cluster status) + + Each tool is registered with appropriate descriptions and parameter + validation using Pydantic models. + """ # Node tools @self.mcp.tool(description=GET_NODES_DESC) @@ -93,7 +116,15 @@ class ProxmoxMCPServer: return self.cluster_tools.get_cluster_status() def start(self) -> None: - """Start the MCP server.""" + """Start the MCP server. + + Initializes the server with: + - Signal handlers for graceful shutdown (SIGINT, SIGTERM) + - Async runtime for handling concurrent requests + - Error handling and logging + + The server runs until terminated by a signal or fatal error. + """ import anyio def signal_handler(signum, frame): diff --git a/src/proxmox_mcp/tools/base.py b/src/proxmox_mcp/tools/base.py index 4b12b54..978b59e 100644 --- a/src/proxmox_mcp/tools/base.py +++ b/src/proxmox_mcp/tools/base.py @@ -1,5 +1,14 @@ """ Base classes and utilities for Proxmox MCP tools. + +This module provides the foundation for all Proxmox MCP tools, including: +- Base tool class with common functionality +- Response formatting utilities +- Error handling mechanisms +- Logging setup + +All tool implementations inherit from the ProxmoxTool base class to ensure +consistent behavior and error handling across the MCP server. """ import logging from typing import Any, Dict, List, Optional, Union @@ -8,7 +17,17 @@ from proxmoxer import ProxmoxAPI from ..formatting import ProxmoxTemplates class ProxmoxTool: - """Base class for Proxmox MCP tools.""" + """Base class for Proxmox MCP tools. + + This class provides common functionality used by all Proxmox tool implementations: + - Proxmox API access + - Standardized logging + - Response formatting + - Error handling + + All tool classes should inherit from this base class to ensure consistent + behavior and error handling across the MCP server. + """ def __init__(self, proxmox_api: ProxmoxAPI): """Initialize the tool. @@ -22,12 +41,18 @@ class ProxmoxTool: def _format_response(self, data: Any, resource_type: Optional[str] = None) -> List[Content]: """Format response data into MCP content using templates. + This method handles formatting of various Proxmox resource types into + consistent MCP content responses. It uses specialized templates for + different resource types (nodes, VMs, storage, etc.) and falls back + to JSON formatting for unknown types. + Args: - data: Data to format - resource_type: Optional type of resource for template selection + data: Raw data from Proxmox API to format + resource_type: Type of resource for template selection. Valid types: + 'nodes', 'node_status', 'vms', 'storage', 'containers', 'cluster' Returns: - List of Content objects + List of Content objects formatted according to resource type """ if resource_type == "nodes": formatted = ProxmoxTemplates.node_list(data) @@ -53,15 +78,20 @@ class ProxmoxTool: return [Content(type="text", text=formatted)] def _handle_error(self, operation: str, error: Exception) -> None: - """Handle and log errors. + """Handle and log errors from Proxmox operations. + + Provides standardized error handling across all tools by: + - Logging errors with appropriate context + - Categorizing errors into specific exception types + - Converting Proxmox-specific errors into standard Python exceptions Args: - operation: Description of the operation that failed - error: The exception that occurred + operation: Description of the operation that failed (e.g., "get node status") + error: The exception that occurred during the operation Raises: - ValueError: For invalid input or state - RuntimeError: For other errors + ValueError: For invalid input, missing resources, or permission issues + RuntimeError: For unexpected errors or API failures """ error_msg = str(error) self.logger.error(f"Failed to {operation}: {error_msg}") diff --git a/src/proxmox_mcp/tools/cluster.py b/src/proxmox_mcp/tools/cluster.py index da3e8ed..44acdf8 100644 --- a/src/proxmox_mcp/tools/cluster.py +++ b/src/proxmox_mcp/tools/cluster.py @@ -1,5 +1,14 @@ """ Cluster-related tools for Proxmox MCP. + +This module provides tools for monitoring and managing Proxmox clusters: +- Retrieving overall cluster health status +- Monitoring quorum status and node count +- Tracking cluster resources and configuration +- Checking cluster-wide service availability + +The tools provide essential information for maintaining +cluster health and ensuring proper operation. """ from typing import List from mcp.types import TextContent as Content @@ -7,16 +16,52 @@ from .base import ProxmoxTool from .definitions import GET_CLUSTER_STATUS_DESC class ClusterTools(ProxmoxTool): - """Tools for managing Proxmox cluster.""" + """Tools for managing Proxmox cluster. + + Provides functionality for: + - Monitoring cluster health and status + - Tracking quorum and node membership + - Managing cluster-wide resources + - Verifying cluster configuration + + Essential for maintaining cluster health and ensuring + proper operation of the Proxmox environment. + """ def get_cluster_status(self) -> List[Content]: """Get overall Proxmox cluster health and configuration status. + Retrieves comprehensive cluster information including: + - Cluster name and identity + - Quorum status (essential for cluster operations) + - Active node count and health + - Resource distribution and status + + This information is critical for: + - Ensuring cluster stability + - Monitoring node membership + - Verifying resource availability + - Detecting potential issues + Returns: - List of Content objects containing cluster status + List of Content objects containing formatted cluster status: + { + "name": "cluster-name", + "quorum": true/false, + "nodes": count, + "resources": [ + { + "type": "resource-type", + "status": "status" + } + ] + } Raises: - RuntimeError: If the operation fails + RuntimeError: If cluster status query fails due to: + - Network connectivity issues + - Authentication problems + - API endpoint failures """ try: result = self.proxmox.cluster.status.get() diff --git a/src/proxmox_mcp/tools/console/manager.py b/src/proxmox_mcp/tools/console/manager.py index c5d1de8..5c9ea58 100644 --- a/src/proxmox_mcp/tools/console/manager.py +++ b/src/proxmox_mcp/tools/console/manager.py @@ -1,12 +1,37 @@ """ Module for managing VM console operations. + +This module provides functionality for interacting with VM consoles: +- Executing commands within VMs via QEMU guest agent +- Handling command execution lifecycle +- Managing command output and status +- Error handling and logging + +The module implements a robust command execution system with: +- VM state verification +- Asynchronous command execution +- Detailed status tracking +- Comprehensive error handling """ import logging from typing import Dict, Any class VMConsoleManager: - """Manager class for VM console operations.""" + """Manager class for VM console operations. + + Provides functionality for: + - Executing commands in VM consoles + - Managing command execution lifecycle + - Handling command output and errors + - Monitoring execution status + + Uses QEMU guest agent for reliable command execution with: + - VM state verification before execution + - Asynchronous command processing + - Detailed output capture + - Comprehensive error handling + """ def __init__(self, proxmox_api): """Initialize the VM console manager. @@ -18,19 +43,47 @@ class VMConsoleManager: self.logger = logging.getLogger("proxmox-mcp.vm-console") async def execute_command(self, node: str, vmid: str, command: str) -> Dict[str, Any]: - """Execute a command in a VM's console. + """Execute a command in a VM's console via QEMU guest agent. + + Implements a two-phase command execution process: + 1. Command Initiation: + - Verifies VM exists and is running + - Initiates command execution via guest agent + - Captures command PID for tracking + + 2. Result Collection: + - Monitors command execution status + - Captures command output and errors + - Handles completion status + + Requirements: + - VM must be running + - QEMU guest agent must be installed and active + - Command execution permissions must be enabled Args: - node: Name of the node where VM is running - vmid: ID of the VM - command: Command to execute + node: Name of the node where VM is running (e.g., 'pve1') + vmid: ID of the VM to execute command in (e.g., '100') + command: Shell command to execute in the VM Returns: - Dictionary containing command output and status + Dictionary containing command execution results: + { + "success": true/false, + "output": "command output", + "error": "error output if any", + "exit_code": command_exit_code + } Raises: - ValueError: If VM is not found or not running - RuntimeError: If command execution fails + ValueError: If: + - VM is not found + - VM is not running + - Guest agent is not available + RuntimeError: If: + - Command execution fails + - Unable to get command status + - API communication errors occur """ try: # Verify VM exists and is running diff --git a/src/proxmox_mcp/tools/node.py b/src/proxmox_mcp/tools/node.py index e5be9a6..120c426 100644 --- a/src/proxmox_mcp/tools/node.py +++ b/src/proxmox_mcp/tools/node.py @@ -1,5 +1,16 @@ """ Node-related tools for Proxmox MCP. + +This module provides tools for managing and monitoring Proxmox nodes: +- Listing all nodes in the cluster with their status +- Getting detailed node information including: + * CPU usage and configuration + * Memory utilization + * Uptime statistics + * Health status + +The tools handle both basic and detailed node information retrieval, +with fallback mechanisms for partial data availability. """ from typing import List from mcp.types import TextContent as Content @@ -7,16 +18,45 @@ from .base import ProxmoxTool from .definitions import GET_NODES_DESC, GET_NODE_STATUS_DESC class NodeTools(ProxmoxTool): - """Tools for managing Proxmox nodes.""" + """Tools for managing Proxmox nodes. + + Provides functionality for: + - Retrieving cluster-wide node information + - Getting detailed status for specific nodes + - Monitoring node health and resources + - Handling node-specific API operations + + Implements fallback mechanisms for scenarios where detailed + node information might be temporarily unavailable. + """ def get_nodes(self) -> List[Content]: - """List all nodes in the Proxmox cluster. + """List all nodes in the Proxmox cluster with detailed status. + + Retrieves comprehensive information for each node including: + - Basic status (online/offline) + - Uptime statistics + - CPU configuration and count + - Memory usage and capacity + + Implements a fallback mechanism that returns basic information + if detailed status retrieval fails for any node. Returns: - List of Content objects containing node information + List of Content objects containing formatted node information: + { + "node": "node_name", + "status": "online/offline", + "uptime": seconds, + "maxcpu": cpu_count, + "memory": { + "used": bytes, + "total": bytes + } + } Raises: - RuntimeError: If the operation fails + RuntimeError: If the cluster-wide node query fails """ try: result = self.proxmox.nodes.get() @@ -57,15 +97,36 @@ class NodeTools(ProxmoxTool): def get_node_status(self, node: str) -> List[Content]: """Get detailed status information for a specific node. + Retrieves comprehensive status information including: + - CPU usage and configuration + - Memory utilization details + - Uptime and load statistics + - Network status + - Storage health + - Running tasks and services + Args: - node: Name/ID of node to query + node: Name/ID of node to query (e.g., 'pve1', 'proxmox-node2') Returns: - List of Content objects containing node status + List of Content objects containing detailed node status: + { + "uptime": seconds, + "cpu": { + "usage": percentage, + "cores": count + }, + "memory": { + "used": bytes, + "total": bytes, + "free": bytes + }, + ...additional status fields + } Raises: - ValueError: If node is not found - RuntimeError: If the operation fails + ValueError: If the specified node is not found + RuntimeError: If status retrieval fails (node offline, network issues) """ try: result = self.proxmox.nodes(node).status.get() diff --git a/src/proxmox_mcp/tools/storage.py b/src/proxmox_mcp/tools/storage.py index a9bb2b1..3bb054b 100644 --- a/src/proxmox_mcp/tools/storage.py +++ b/src/proxmox_mcp/tools/storage.py @@ -1,5 +1,16 @@ """ Storage-related tools for Proxmox MCP. + +This module provides tools for managing and monitoring Proxmox storage: +- Listing all storage pools across the cluster +- Retrieving detailed storage information including: + * Storage type and content types + * Usage statistics and capacity + * Availability status + * Node assignments + +The tools implement fallback mechanisms for scenarios where +detailed storage information might be temporarily unavailable. """ from typing import List from mcp.types import TextContent as Content @@ -7,16 +18,47 @@ from .base import ProxmoxTool from .definitions import GET_STORAGE_DESC class StorageTools(ProxmoxTool): - """Tools for managing Proxmox storage.""" + """Tools for managing Proxmox storage. + + Provides functionality for: + - Retrieving cluster-wide storage information + - Monitoring storage pool status and health + - Tracking storage utilization and capacity + - Managing storage content types + + Implements fallback mechanisms for scenarios where detailed + storage information might be temporarily unavailable. + """ def get_storage(self) -> List[Content]: - """List storage pools across the cluster. + """List storage pools across the cluster with detailed status. + + Retrieves comprehensive information for each storage pool including: + - Basic identification (name, type) + - Content types supported (VM disks, backups, ISO images, etc.) + - Availability status (online/offline) + - Usage statistics: + * Used space + * Total capacity + * Available space + + Implements a fallback mechanism that returns basic information + if detailed status retrieval fails for any storage pool. Returns: - List of Content objects containing storage information + List of Content objects containing formatted storage information: + { + "storage": "storage-name", + "type": "storage-type", + "content": ["content-types"], + "status": "online/offline", + "used": bytes, + "total": bytes, + "available": bytes + } Raises: - RuntimeError: If the operation fails + RuntimeError: If the cluster-wide storage query fails """ try: result = self.proxmox.storage.get() diff --git a/src/proxmox_mcp/tools/vm.py b/src/proxmox_mcp/tools/vm.py index e55e991..97faeb3 100644 --- a/src/proxmox_mcp/tools/vm.py +++ b/src/proxmox_mcp/tools/vm.py @@ -1,5 +1,17 @@ """ VM-related tools for Proxmox MCP. + +This module provides tools for managing and interacting with Proxmox VMs: +- Listing all VMs across the cluster with their status +- Retrieving detailed VM information including: + * Resource allocation (CPU, memory) + * Runtime status + * Node placement +- Executing commands within VMs via QEMU guest agent +- Handling VM console operations + +The tools implement fallback mechanisms for scenarios where +detailed VM information might be temporarily unavailable. """ from typing import List from mcp.types import TextContent as Content @@ -8,7 +20,18 @@ from .definitions import GET_VMS_DESC, EXECUTE_VM_COMMAND_DESC from .console.manager import VMConsoleManager class VMTools(ProxmoxTool): - """Tools for managing Proxmox VMs.""" + """Tools for managing Proxmox VMs. + + Provides functionality for: + - Retrieving cluster-wide VM information + - Getting detailed VM status and configuration + - Executing commands within VMs + - Managing VM console operations + + Implements fallback mechanisms for scenarios where detailed + VM information might be temporarily unavailable. Integrates + with QEMU guest agent for VM command execution. + """ def __init__(self, proxmox_api): """Initialize VM tools. @@ -20,13 +43,35 @@ class VMTools(ProxmoxTool): self.console_manager = VMConsoleManager(proxmox_api) def get_vms(self) -> List[Content]: - """List all virtual machines across the cluster. + """List all virtual machines across the cluster with detailed status. + + Retrieves comprehensive information for each VM including: + - Basic identification (ID, name) + - Runtime status (running, stopped) + - Resource allocation and usage: + * CPU cores + * Memory allocation and usage + - Node placement + + Implements a fallback mechanism that returns basic information + if detailed configuration retrieval fails for any VM. Returns: - List of Content objects containing VM information + List of Content objects containing formatted VM information: + { + "vmid": "100", + "name": "vm-name", + "status": "running/stopped", + "node": "node-name", + "cpus": core_count, + "memory": { + "used": bytes, + "total": bytes + } + } Raises: - RuntimeError: If the operation fails + RuntimeError: If the cluster-wide VM query fails """ try: result = [] @@ -69,17 +114,28 @@ class VMTools(ProxmoxTool): async def execute_command(self, node: str, vmid: str, command: str) -> List[Content]: """Execute a command in a VM via QEMU guest agent. + Uses the QEMU guest agent to execute commands within a running VM. + Requires: + - VM must be running + - QEMU guest agent must be installed and running in the VM + - Command execution permissions must be enabled + Args: - node: Host node name - vmid: VM ID number - command: Shell command to run + node: Host node name (e.g., 'pve1', 'proxmox-node2') + vmid: VM ID number (e.g., '100', '101') + command: Shell command to run (e.g., 'uname -a', 'systemctl status nginx') Returns: - List of Content objects containing command output + List of Content objects containing formatted command output: + { + "success": true/false, + "output": "command output", + "error": "error message if any" + } Raises: - ValueError: If VM is not found or not running - RuntimeError: If command execution fails + ValueError: If VM is not found, not running, or guest agent is not available + RuntimeError: If command execution fails due to permissions or other issues """ try: result = await self.console_manager.execute_command(node, vmid, command)