Spaces:
Running
Running
| from fastmcp.exceptions import ToolError | |
| from fastmcp.tools.base import Tool | |
| from typing import Any, Callable, Dict, Optional, TYPE_CHECKING | |
| from fastmcp.utilities.logging import get_logger | |
| if TYPE_CHECKING: | |
| from fastmcp.server import Context | |
| logger = get_logger(__name__) | |
| class ToolManager: | |
| """Manages FastMCP tools.""" | |
| def __init__(self, warn_on_duplicate_tools: bool = True): | |
| self._tools: Dict[str, Tool] = {} | |
| self.warn_on_duplicate_tools = warn_on_duplicate_tools | |
| def get_tool(self, name: str) -> Optional[Tool]: | |
| """Get tool by name.""" | |
| return self._tools.get(name) | |
| def list_tools(self) -> list[Tool]: | |
| """List all registered tools.""" | |
| return list(self._tools.values()) | |
| def add_tool( | |
| self, | |
| fn: Callable, | |
| name: Optional[str] = None, | |
| description: Optional[str] = None, | |
| ) -> Tool: | |
| """Add a tool to the server.""" | |
| tool = Tool.from_function(fn, name=name, description=description) | |
| existing = self._tools.get(tool.name) | |
| if existing: | |
| if self.warn_on_duplicate_tools: | |
| logger.warning(f"Tool already exists: {tool.name}") | |
| return existing | |
| self._tools[tool.name] = tool | |
| return tool | |
| async def call_tool( | |
| self, name: str, arguments: dict, context: Optional["Context"] = None | |
| ) -> Any: | |
| """Call a tool by name with arguments.""" | |
| tool = self.get_tool(name) | |
| if not tool: | |
| raise ToolError(f"Unknown tool: {name}") | |
| return await tool.run(arguments, context=context) | |