Skip to main content
Glama
test_integration.py7.74 kB
""" Integration tests for the MCP Tourism server. Tests server initialization, tool registration, and basic functionality. """ import pytest from unittest.mock import patch, MagicMock, AsyncMock from fastmcp import Client from mcp_tourism.server import mcp from mcp_tourism.api_client import KoreaTourismApiClient @pytest.fixture def mock_env_vars(monkeypatch): """Set up environment variables for testing.""" monkeypatch.setenv("KOREA_TOURISM_API_KEY", "test-api-key-12345") monkeypatch.setenv("MCP_TOURISM_DEFAULT_LANGUAGE", "en") monkeypatch.setenv("MCP_TOURISM_CACHE_TTL", "3600") monkeypatch.setenv("MCP_TOURISM_RATE_LIMIT_CALLS", "10") monkeypatch.setenv("MCP_TOURISM_RATE_LIMIT_PERIOD", "1") monkeypatch.setenv("MCP_TOURISM_CONCURRENCY_LIMIT", "5") @pytest.fixture def mock_api_client(): """Create a mock API client.""" mock_client = MagicMock(spec=KoreaTourismApiClient) mock_client._ensure_full_initialization = MagicMock() # Mock async methods mock_client.search_by_keyword = AsyncMock() mock_client.get_area_based_list = AsyncMock() mock_client.get_location_based_list = AsyncMock() mock_client.search_festival = AsyncMock() mock_client.search_stay = AsyncMock() mock_client.get_detail_common = AsyncMock() mock_client.get_detail_intro = AsyncMock() mock_client.get_detail_info = AsyncMock() mock_client.get_detail_images = AsyncMock() mock_client.get_area_code_list = AsyncMock() return mock_client @pytest.mark.asyncio async def test_server_initialization_and_tools_list(mock_env_vars): """ Test that the FastMCP server initializes correctly and all tools are registered. """ # Create a client connected to our server client = Client(mcp) async with client: # Test that we can list tools without errors tools = await client.list_tools() # Expected tool names expected_tools = { "search_tourism_by_keyword", "get_tourism_by_area", "find_nearby_attractions", "search_festivals_by_date", "find_accommodations", "get_detailed_information", "get_tourism_images", "get_area_codes", } # Get actual tool names actual_tools = {tool.name for tool in tools} # Assert all expected tools are present assert expected_tools == actual_tools, ( f"Expected tools: {expected_tools}, but got: {actual_tools}" ) # Verify each tool has proper metadata for tool in tools: assert tool.name in expected_tools assert tool.description is not None and len(tool.description) > 0 assert tool.inputSchema is not None @pytest.mark.asyncio @patch("mcp_tourism.server.get_api_client") async def test_search_tourism_tool_execution( mock_get_api_client, mock_api_client, mock_env_vars ): """ Test that we can actually call a tool through the MCP interface. """ # Setup mock API client mock_get_api_client.return_value = mock_api_client mock_api_client.search_by_keyword.return_value = { "total_count": 1, "items": [{"title": "Test Attraction", "content_id": "123"}], "page_no": 1, "num_of_rows": 1, } # Create a client connected to our server client = Client(mcp) async with client: # Call the search tool result = await client.call_tool( "search_tourism_by_keyword", {"keyword": "Seoul Tower"} ) # Verify we got a result assert len(result) > 0 # The result should be TextContent with JSON data (dict is auto-converted) assert result[0].type == "text" # Verify the mock was called correctly mock_api_client.search_by_keyword.assert_called_once_with( keyword="Seoul Tower", content_type_id=None, area_code=None, language=None, page=1, rows=20, ) @pytest.mark.asyncio @patch("mcp_tourism.server.get_api_client") async def test_tool_with_validation_error( mock_get_api_client, mock_api_client, mock_env_vars ): """ Test that validation errors are properly handled and returned through MCP. """ # Setup mock API client mock_get_api_client.return_value = mock_api_client # Create a client connected to our server client = Client(mcp) async with client: # Call the search tool with invalid content_type with pytest.raises(Exception) as exc_info: await client.call_tool( "search_tourism_by_keyword", {"keyword": "Seoul Tower", "content_type": "InvalidType"}, ) # The error should mention the invalid type assert "InvalidType" in str(exc_info.value) assert "Valid types are:" in str(exc_info.value) # The API client should not have been called mock_api_client.search_by_keyword.assert_not_called() @pytest.mark.asyncio async def test_server_tools_have_correct_parameters(mock_env_vars): """ Test that all tools have the correct parameter schemas. """ client = Client(mcp) async with client: tools = await client.list_tools() # Find the search_tourism_by_keyword tool search_tool = None for tool in tools: if tool.name == "search_tourism_by_keyword": search_tool = tool break assert search_tool is not None, "search_tourism_by_keyword tool not found" # Check that the tool has the expected parameters schema = search_tool.inputSchema assert "properties" in schema properties = schema["properties"] # Required parameter assert "keyword" in properties assert properties["keyword"]["type"] == "string" # Optional parameters optional_params = ["content_type", "area_code", "language", "page", "rows"] for param in optional_params: assert param in properties # Check that keyword is required assert "required" in schema assert "keyword" in schema["required"] @pytest.mark.asyncio @patch("mcp_tourism.server.get_api_client") async def test_multiple_tool_calls(mock_get_api_client, mock_api_client, mock_env_vars): """ Test that we can make multiple tool calls successfully. """ # Setup mock API client mock_get_api_client.return_value = mock_api_client # Setup different mock responses mock_api_client.search_by_keyword.return_value = {"total_count": 5, "items": []} mock_api_client.get_area_code_list.return_value = {"total_count": 3, "items": []} client = Client(mcp) async with client: # Make first tool call result1 = await client.call_tool( "search_tourism_by_keyword", {"keyword": "Busan"} ) # Make second tool call result2 = await client.call_tool("get_area_codes", {"parent_area_code": "1"}) # Both calls should succeed assert len(result1) > 0 assert len(result2) > 0 # Verify both mocks were called mock_api_client.search_by_keyword.assert_called_once() mock_api_client.get_area_code_list.assert_called_once() @pytest.mark.asyncio async def test_server_ping(mock_env_vars): """ Test that we can ping the server successfully. """ client = Client(mcp) async with client: # Ping server - should not raise an exception await client.ping() # Also test that we can list tools to ensure server is responsive tools = await client.list_tools() assert len(tools) > 0

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/harimkang/mcp-korea-tourism-api'

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