Skip to main content
Glama
base.py•4.34 kB
""" 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 from mcp.types import TextContent as Content from proxmoxer import ProxmoxAPI from ..formatting import ProxmoxTemplates class ProxmoxTool: """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. Args: proxmox_api: Initialized ProxmoxAPI instance """ self.proxmox = proxmox_api self.logger = logging.getLogger(f"proxmox-mcp.{self.__class__.__name__.lower()}") 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: 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 formatted according to resource type """ if resource_type == "nodes": formatted = ProxmoxTemplates.node_list(data) elif resource_type == "node_status": # For node_status, data should be a tuple of (node_name, status_dict) if isinstance(data, tuple) and len(data) == 2: formatted = ProxmoxTemplates.node_status(data[0], data[1]) else: formatted = ProxmoxTemplates.node_status("unknown", data) elif resource_type == "vms": formatted = ProxmoxTemplates.vm_list(data) elif resource_type == "storage": formatted = ProxmoxTemplates.storage_list(data) elif resource_type == "containers": formatted = ProxmoxTemplates.container_list(data) elif resource_type == "cluster": formatted = ProxmoxTemplates.cluster_status(data) else: # Fallback to JSON formatting for unknown types import json formatted = json.dumps(data, indent=2) return [Content(type="text", text=formatted)] def _handle_error(self, operation: str, error: Exception) -> None: """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 (e.g., "get node status") error: The exception that occurred during the operation Raises: 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}") if "not found" in error_msg.lower(): raise ValueError(f"Resource not found: {error_msg}") if "permission denied" in error_msg.lower(): raise ValueError(f"Permission denied: {error_msg}") if "invalid" in error_msg.lower(): raise ValueError(f"Invalid input: {error_msg}") raise RuntimeError(f"Failed to {operation}: {error_msg}")

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RekklesNA/ProxmoxMCP-Plus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server