"""
Base Classes for MCP Tools
Provides abstract base classes and common patterns for implementing
MCP tools 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 BaseTool(ABC):
"""
Abstract base class for all MCP tools.
Provides common functionality and enforces consistent interface
for tool registration and logging.
"""
def __init__(self, name: Optional[str] = None):
"""
Initialize the tool.
Args:
name: Optional tool name override
"""
self.name = name or self.__class__.__name__.lower().replace('tools', '')
self.logger = get_logger(f"tools.{self.name}")
@abstractmethod
def register_with_mcp(self, mcp: FastMCP) -> None:
"""
Register this tool's methods with the FastMCP instance.
Args:
mcp: The FastMCP instance to register with
"""
pass
def _log_tool_call(self, method_name: str, **kwargs) -> None:
"""
Log a tool method call with consistent formatting.
Args:
method_name: Name of the tool 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">>> 🛠️ Tool '{method_name}' called with: {safe_kwargs}")
def get_info(self) -> Dict[str, Any]:
"""
Get information about this tool.
Returns:
Dictionary containing tool metadata
"""
return {
"name": self.name,
"class": self.__class__.__name__,
"module": self.__class__.__module__
}
class ToolGroup(BaseTool):
"""
Base class for tools that group multiple related functions.
Useful for organizing related functionality like arithmetic operations,
file operations, etc.
"""
def __init__(self, name: Optional[str] = None):
super().__init__(name)
self.tools = {}
def add_tool_method(self, method_name: str, method_func, description: str = ""):
"""
Add a method to this tool group.
Args:
method_name: Name of the method
method_func: The actual method function
description: Description of what the method does
"""
self.tools[method_name] = {
"function": method_func,
"description": description
}
self.logger.debug(f"Added tool method '{method_name}' to group '{self.name}'")
def get_tool_methods(self) -> Dict[str, Any]:
"""Get all tool methods in this group."""
return self.tools