"""
Base Classes for MCP Resources
Provides abstract base classes and common patterns for implementing
MCP resources with consistent interfaces and logging.
"""
import logging
from abc import ABC, abstractmethod
from typing import Any, Dict, Optional
from fastmcp import FastMCP
from ..config.logging import get_logger
logger = get_logger(__name__)
class BaseResource(ABC):
"""
Abstract base class for all MCP resources.
Provides common functionality and enforces consistent interface
for resource registration and logging.
"""
def __init__(self, name: Optional[str] = None):
"""
Initialize the resource.
Args:
name: Optional resource name override
"""
self.name = name or self.__class__.__name__.lower().replace('resources', '')
self.logger = get_logger(f"resources.{self.name}")
@abstractmethod
def register_with_mcp(self, mcp: FastMCP) -> None:
"""
Register this resource's methods with the FastMCP instance.
Args:
mcp: The FastMCP instance to register with
"""
pass
def _log_resource_call(self, method_name: str, **kwargs) -> None:
"""
Log a resource method call with consistent formatting.
Args:
method_name: Name of the resource method being called
**kwargs: Arguments passed to the method
"""
# Filter out sensitive information if needed
safe_kwargs = {k: v for k, v in kwargs.items()
if not k.lower().startswith(('password', 'token', 'secret'))}
self.logger.info(f">>> 📄 Resource '{method_name}' called with: {safe_kwargs}")
def get_info(self) -> Dict[str, Any]:
"""
Get information about this resource.
Returns:
Dictionary containing resource metadata
"""
return {
"name": self.name,
"class": self.__class__.__name__,
"module": self.__class__.__module__
}
class StaticResource(BaseResource):
"""
Base class for resources that provide static data.
Useful for configuration values, version information, etc.
"""
def __init__(self, name: Optional[str] = None, data: Any = None):
super().__init__(name)
self.data = data
def get_data(self) -> Any:
"""Get the static data for this resource."""
return self.data
def set_data(self, data: Any) -> None:
"""Set the static data for this resource."""
self.data = data
class DynamicResource(BaseResource):
"""
Base class for resources that provide dynamically generated data.
Useful for system information, computed values, etc.
"""
def __init__(self, name: Optional[str] = None):
super().__init__(name)
@abstractmethod
def generate_data(self, **kwargs) -> Any:
"""
Generate dynamic data for this resource.
Args:
**kwargs: Parameters for data generation
Returns:
The generated data
"""
pass