Skip to main content
Glama
base.py7.04 kB
""" Base Handler for MCP Operations This module provides the base functionality that all domain-specific handlers inherit from, ensuring consistent behavior and error handling. """ from abc import ABC, abstractmethod from typing import Any import structlog from ceph_mcp.api.base import CephAPIError, CephAuthenticationError from ceph_mcp.api.client import CephClient from ceph_mcp.models.base import MCPResponse class BaseHandler(ABC): """ Base class for all MCP request handlers. This class provides common functionality like logging, error handling, and response formatting that all handlers need. """ def __init__(self, domain: str): """ Initialize the base handler. Args: domain: The domain this handler is responsible for (health, hosts, etc.) """ self.domain = domain self.logger = structlog.get_logger(f"{__name__}.{domain}") async def get_global_client(self) -> CephClient: """Get the global authenticated Ceph client.""" # Import here to avoid circular imports from ceph_mcp.server import get_global_client return await get_global_client() @abstractmethod async def _handle_operation( self, operation: str, params: dict[str, Any] ) -> MCPResponse: """ Handle the specific operation for this domain. This method must be implemented by each domain-specific handler. Args: operation: The operation to perform params: Operation parameters Returns: MCPResponse with the operation result """ async def handle_request( self, operation: str, params: dict[str, Any] ) -> MCPResponse: """ Main entry point for handling MCP requests. This method provides consistent error handling and logging for all operations. Args: operation: The specific operation to perform params: Parameters for the operation Returns: MCPResponse with the operation result """ self.logger.info( "Processing MCP request", domain=self.domain, operation=operation, params=params, ) try: # Call the specific handler method response = await self._handle_operation(operation, params) self.logger.info( "MCP request completed successfully", domain=self.domain, operation=operation, success=response.success, ) return response except CephAuthenticationError as e: self.logger.error( "Authentication error during MCP request", domain=self.domain, operation=operation, error=str(e), ) return MCPResponse.error_response( message=f"Authentication failed: {str(e)}", error_code="AUTHENTICATION_ERROR", ) except CephAPIError as e: self.logger.error( "Ceph API error during MCP request", domain=self.domain, operation=operation, error=str(e), status_code=getattr(e, "status_code", None), ) return MCPResponse.error_response( message=f"Ceph API error: {str(e)}", error_code="CEPH_API_ERROR" ) except ValueError as e: self.logger.error( "Validation error during MCP request", domain=self.domain, operation=operation, error=str(e), ) return MCPResponse.error_response( message=f"Invalid parameters: {str(e)}", error_code="VALIDATION_ERROR" ) except Exception as e: # pylint: disable=broad-exception-caught self.logger.error( "Unexpected error during MCP request", domain=self.domain, operation=operation, error=str(e), exc_info=True, ) return MCPResponse.error_response( message=f"An unexpected error occurred: {str(e)}", error_code="INTERNAL_ERROR", ) def validate_required_params( self, params: dict[str, Any], required_keys: list ) -> None: """ Validate that required parameters are present. Args: params: Parameters to validate required_keys: List of required parameter names Raises: ValueError: If any required parameter is missing """ if len(required_keys) == 0: return missing_keys = [ key for key in required_keys if key not in params or params[key] is None ] if missing_keys: raise ValueError(f"Missing required parameters: {', '.join(missing_keys)}") def validate_param_type( self, params: dict[str, Any], key: str, expected_type: type ) -> None: """ Validate that a parameter has the expected type. Args: params: Parameters to validate key: Parameter key to check expected_type: Expected type for the parameter Raises: ValueError: If parameter type doesn't match """ if key in params and not isinstance(params[key], expected_type): raise ValueError( f"Parameter '{key}' must be of type {expected_type.__name__}" ) def get_optional_param( self, params: dict[str, Any], key: str, default: Any = None ) -> Any: """ Get an optional parameter with a default value. Args: params: Parameters dictionary key: Parameter key default: Default value if key is not present Returns: Parameter value or default """ return params.get(key, default) def create_success_response( self, data: Any, message: str, **kwargs: dict[str, Any] ) -> MCPResponse: """ Create a standardized success response. Args: data: Response data message: Success message **kwargs: Additional response fields Returns: MCPResponse for success """ return MCPResponse.success_response(data=data, message=message, **kwargs) def create_error_response( self, message: str, error_code: str, **kwargs: dict[str, Any] ) -> MCPResponse: """ Create a standardized error response. Args: message: Error message error_code: Error code **kwargs: Additional response fields Returns: MCPResponse for error """ return MCPResponse.error_response( message=message, error_code=error_code, **kwargs )

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/rajmohanram/ceph-mcp-server'

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