Skip to main content
Glama

Wikipedia MCP Server

test_server_tools.py22 kB
""" Comprehensive tests for Wikipedia MCP server tools. """ import asyncio import pytest import requests from unittest.mock import Mock, patch, MagicMock from wikipedia_mcp.server import create_server from wikipedia_mcp.wikipedia_client import WikipediaClient class TestWikipediaClient: """Test the WikipediaClient class.""" def setup_method(self): """Set up test fixtures.""" self.client = WikipediaClient() @patch("wikipedia_mcp.wikipedia_client.requests.get") def test_search_success(self, mock_get): """Test successful search operation.""" # Mock API response mock_response = Mock() mock_response.raise_for_status.return_value = None mock_response.json.return_value = { "query": { "search": [ { "title": "Python (programming language)", "snippet": "Python is a programming language", "pageid": 12345, "wordcount": 1000, "timestamp": "2023-01-01T00:00:00Z", } ] } } mock_get.return_value = mock_response # Test search results = self.client.search("Python", limit=1) # Assertions assert len(results) == 1 assert results[0]["title"] == "Python (programming language)" assert results[0]["snippet"] == "Python is a programming language" assert results[0]["pageid"] == 12345 mock_get.assert_called_once() @patch("wikipedia_mcp.wikipedia_client.requests.get") def test_search_failure(self, mock_get): """Test handling of search failures when exceptions occur.""" mock_get.side_effect = Exception("API error") results = self.client.search("Python") assert results == [] @patch("wikipedia_mcp.wikipedia_client.requests.get") def test_search_empty_query(self, mock_get): """Empty queries should not trigger HTTP calls.""" results = self.client.search("") assert results == [] mock_get.assert_not_called() results = self.client.search(" ") assert results == [] mock_get.assert_not_called() @patch("wikipedia_mcp.wikipedia_client.requests.get") def test_search_limit_validation(self, mock_get): """Ensure the limit is bounded within API constraints.""" mock_response = Mock() mock_response.raise_for_status.return_value = None mock_response.json.return_value = {"query": {"search": []}} mock_get.return_value = mock_response self.client.search("Python", limit=1000) _, kwargs = mock_get.call_args assert kwargs["params"]["srlimit"] == 500 @patch("wikipedia_mcp.wikipedia_client.requests.get") def test_search_api_error(self, mock_get): """Handle API error payloads gracefully.""" mock_response = Mock() mock_response.raise_for_status.return_value = None mock_response.json.return_value = {"error": {"code": "badquery", "info": "Invalid query"}} mock_get.return_value = mock_response results = self.client.search("Python") assert results == [] @patch("wikipedia_mcp.wikipedia_client.WikipediaClient._extract_sections") def test_get_article_success(self, mock_extract_sections): """Test successful article retrieval.""" # Mock Wikipedia page mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Python (programming language)" mock_page.pageid = 12345 mock_page.summary = "Python is a programming language" mock_page.text = "Full article text here" mock_page.fullurl = "https://en.wikipedia.org/wiki/Python_(programming_language)" mock_page.categories = {"Category:Programming languages": None} mock_page.links = {"Link1": None, "Link2": None} mock_page.sections = [] mock_extract_sections.return_value = [{"title": "History", "level": 0, "text": "History text", "sections": []}] with patch.object(self.client.wiki, "page", return_value=mock_page): article = self.client.get_article("Python (programming language)") assert article["exists"] is True assert article["title"] == "Python (programming language)" assert article["pageid"] == 12345 assert article["summary"] == "Python is a programming language" assert article["text"] == "Full article text here" assert len(article["categories"]) == 1 assert len(article["links"]) == 2 def test_get_article_not_found(self): """Test article retrieval for non-existent page.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): article = self.client.get_article("NonExistentPage") assert article["exists"] is False assert article["error"] == "Page does not exist" def test_get_summary_success(self): """Test successful summary retrieval.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.summary = "This is a test summary" with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.get_summary("Test Page") assert summary == "This is a test summary" def test_get_summary_not_found(self): """Test summary retrieval for non-existent page.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.get_summary("NonExistentPage") assert "No Wikipedia article found for 'NonExistentPage'" in summary @patch("wikipedia_mcp.wikipedia_client.WikipediaClient._extract_sections") def test_get_sections_success(self, mock_extract_sections): """Test successful sections retrieval.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.sections = [] mock_extract_sections.return_value = [ {"title": "History", "level": 0, "text": "History text", "sections": []}, {"title": "Features", "level": 0, "text": "Features text", "sections": []}, ] with patch.object(self.client.wiki, "page", return_value=mock_page): sections = self.client.get_sections("Test Page") assert len(sections) == 2 assert sections[0]["title"] == "History" assert sections[1]["title"] == "Features" def test_get_sections_not_found(self): """Test sections retrieval for non-existent page.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): sections = self.client.get_sections("NonExistentPage") assert sections == [] def test_get_links_success(self): """Test successful links retrieval.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.links = {"Link1": None, "Link2": None, "Link3": None} with patch.object(self.client.wiki, "page", return_value=mock_page): links = self.client.get_links("Test Page") assert len(links) == 3 assert "Link1" in links assert "Link2" in links assert "Link3" in links def test_get_links_not_found(self): """Test links retrieval for non-existent page.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): links = self.client.get_links("NonExistentPage") assert links == [] def test_get_related_topics_success(self): """Test successful related topics retrieval.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.links = {"Related Link 1": None, "Related Link 2": None} mock_page.categories = {"Category:Test Category": None} # Mock related page mock_related_page = Mock() mock_related_page.exists.return_value = True mock_related_page.summary = "Summary of related page" mock_related_page.fullurl = "https://en.wikipedia.org/wiki/Related_Link_1" with patch.object(self.client.wiki, "page") as mock_wiki_page: mock_wiki_page.side_effect = lambda title: ( mock_related_page if title in ["Related Link 1", "Related Link 2"] else mock_page ) related = self.client.get_related_topics("Test Page", limit=3) assert len(related) >= 1 assert any(topic["type"] == "link" for topic in related) def test_get_related_topics_not_found(self): """Test related topics retrieval for non-existent page.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): related = self.client.get_related_topics("NonExistentPage") assert related == [] def test_extract_sections(self): """Test section extraction helper method.""" # Mock section structure mock_subsection = Mock() mock_subsection.title = "Subsection" mock_subsection.text = "Subsection text" mock_subsection.sections = [] mock_section = Mock() mock_section.title = "Main Section" mock_section.text = "Main section text" mock_section.sections = [mock_subsection] sections = self.client._extract_sections([mock_section]) assert len(sections) == 1 assert sections[0]["title"] == "Main Section" assert sections[0]["level"] == 0 assert sections[0]["text"] == "Main section text" assert len(sections[0]["sections"]) == 1 assert sections[0]["sections"][0]["title"] == "Subsection" assert sections[0]["sections"][0]["level"] == 1 def test_summarize_for_query_success(self): """Test successful query-focused summary retrieval.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.text = ( "This is a long text about a specific keyword. " "We want to find this keyword and summarize around it." ) mock_page.summary = "This is a general summary." with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.summarize_for_query("Test Page", "keyword", max_length=50) assert "keyword" in summary assert len(summary) <= 50 + 3 # for "..." def test_summarize_for_query_not_found(self): """Test query-focused summary when query is not in text.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.text = "This is some other text." mock_page.summary = "A general summary content." with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.summarize_for_query("Test Page", "missing_keyword", max_length=30) assert "A general summary content."[:30] in summary # Should return start of summary def test_summarize_for_query_page_not_exists(self): """Test query-focused summary when page does not exist.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.summarize_for_query("NonExistent Page", "keyword") assert "No Wikipedia article found for 'NonExistent Page'" in summary def test_summarize_section_success(self): """Test successful section summary retrieval.""" mock_section_target = Mock() mock_section_target.title = "Target Section" mock_section_target.text = "This is the text of the target section. It is fairly long." mock_section_target.sections = [] mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.sections = [mock_section_target] with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.summarize_section("Test Page", "Target Section", max_length=20) assert summary == "This is the text of ..." assert len(summary) <= 20 + 3 def test_summarize_section_not_found(self): """Test section summary when section does not exist.""" mock_other_section = Mock() mock_other_section.title = "Other Section" mock_other_section.text = "Some text." mock_other_section.sections = [] mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.sections = [mock_other_section] with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.summarize_section("Test Page", "Missing Section") assert "Section 'Missing Section' not found or is empty" in summary def test_summarize_section_page_not_exists(self): """Test section summary when page does not exist.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): summary = self.client.summarize_section("NonExistent Page", "Any Section") assert "No Wikipedia article found for 'NonExistent Page'" in summary def test_extract_facts_success_from_summary(self): """Test successful fact extraction from page summary.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.summary = "Fact one. Fact two. Fact three. Fact four. Fact five. Fact six." mock_page.sections = [] with patch.object(self.client.wiki, "page", return_value=mock_page): facts = self.client.extract_facts("Test Page", count=3) assert len(facts) == 3 assert facts[0] == "Fact one." assert facts[1] == "Fact two." assert facts[2] == "Fact three." def test_extract_facts_success_from_section(self): """Test successful fact extraction from a specific section.""" mock_target_section = Mock() mock_target_section.title = "Key Info" mock_target_section.text = "Important fact A. Important fact B. Important fact C." mock_target_section.sections = [] mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.summary = "General summary." mock_page.sections = [mock_target_section] with patch.object(self.client.wiki, "page", return_value=mock_page): facts = self.client.extract_facts("Test Page", topic_within_article="Key Info", count=2) assert len(facts) == 2 assert facts[0] == "Important fact A." assert facts[1] == "Important fact B." def test_extract_facts_section_not_found_fallback_to_summary(self): """Test fact extraction falls back to summary if section not found.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Test Page" mock_page.summary = "Summary fact 1. Summary fact 2." mock_page.sections = [] # No sections defined with patch.object(self.client.wiki, "page", return_value=mock_page): facts = self.client.extract_facts("Test Page", topic_within_article="Missing Section", count=1) assert len(facts) == 1 assert facts[0] == "Summary fact 1." def test_extract_facts_page_not_exists(self): """Test fact extraction when page does not exist.""" mock_page = Mock() mock_page.exists.return_value = False with patch.object(self.client.wiki, "page", return_value=mock_page): facts = self.client.extract_facts("NonExistent Page") assert len(facts) == 1 assert "No Wikipedia article found for 'NonExistent Page'" in facts[0] def test_extract_facts_no_content(self): """Test fact extraction when there is no summary or section text.""" mock_page = Mock() mock_page.exists.return_value = True mock_page.title = "Empty Page" mock_page.summary = "" # Empty summary mock_page.sections = [] with patch.object(self.client.wiki, "page", return_value=mock_page): facts = self.client.extract_facts("Empty Page") assert len(facts) == 1 assert "No content found to extract facts from." in facts[0] class TestMCPServerTools: """Test the MCP server tools.""" def setup_method(self): """Set up test fixtures.""" self.server = create_server() @patch("wikipedia_mcp.server.WikipediaClient") def test_create_server_with_language(self, MockWikipediaClient): """Test that create_server initializes WikipediaClient with the specified language.""" create_server(language="ja") MockWikipediaClient.assert_called_once_with(language="ja", country=None, enable_cache=False, access_token=None) @patch("wikipedia_mcp.server.WikipediaClient") def test_create_server_default_language(self, MockWikipediaClient): """Test that create_server uses 'en' if no language is specified.""" create_server() MockWikipediaClient.assert_called_once_with(language="en", country=None, enable_cache=False, access_token=None) @patch("wikipedia_mcp.server.WikipediaClient") def test_create_server_with_cache_enabled(self, MockWikipediaClient): """Test that create_server initializes WikipediaClient with caching enabled.""" create_server(language="en", enable_cache=True) MockWikipediaClient.assert_called_once_with(language="en", country=None, enable_cache=True, access_token=None) @patch("wikipedia_mcp.server.WikipediaClient") def test_create_server_with_cache_disabled(self, MockWikipediaClient): """Test that create_server initializes WikipediaClient with caching disabled by default.""" create_server(language="en", enable_cache=False) MockWikipediaClient.assert_called_once_with(language="en", country=None, enable_cache=False, access_token=None) def test_search_wikipedia_tool(self): """Test search_wikipedia tool registration.""" # Test that server can be created without errors server = create_server() assert server is not None assert server.name == "Wikipedia" def test_get_article_tool(self): """Test get_article tool registration.""" server = create_server() assert server is not None assert server.name == "Wikipedia" def test_get_summary_tool(self): """Test get_summary tool registration.""" server = create_server() assert server is not None assert server.name == "Wikipedia" def test_get_sections_tool(self): """Test get_sections tool registration.""" server = create_server() assert server is not None assert server.name == "Wikipedia" def test_get_links_tool(self): """Test get_links tool registration.""" server = create_server() assert server is not None assert server.name == "Wikipedia" def test_get_related_topics_tool(self): """Test get_related_topics tool registration.""" server = create_server() assert server is not None assert server.name == "Wikipedia" def test_connectivity_tool(self): """Ensure the connectivity test tool is registered.""" server = create_server() assert server is not None async def gather_tools(): tools = await server.get_tools() return list(tools.keys()) tool_names = asyncio.run(gather_tools()) assert "test_wikipedia_connectivity" in tool_names class TestIntegration: """Integration tests for the complete system.""" def test_server_creation(self): """Test that server can be created without errors.""" server = create_server() assert server is not None assert server.name == "Wikipedia" def test_client_initialization(self): """Test that client can be initialized with different languages.""" client_en = WikipediaClient("en") assert client_en.original_language == "en" assert client_en.base_language == "en" assert client_en.language_variant is None client_es = WikipediaClient("es") assert client_es.original_language == "es" assert client_es.base_language == "es" assert client_es.language_variant is None @pytest.mark.integration def test_real_wikipedia_search(self): """Integration test with real Wikipedia API (marked as integration).""" client = WikipediaClient() results = client.search("Python programming", limit=1) # This test requires internet connection if results: # Only assert if we got results (network dependent) assert len(results) >= 1 assert "title" in results[0] assert "snippet" in results[0] @pytest.mark.integration def test_real_wikipedia_summary(self): """Integration test for real summary retrieval.""" client = WikipediaClient() summary = client.get_summary("Python (programming language)") # This test requires internet connection if "Error" not in summary and "No Wikipedia article found" not in summary: assert len(summary) > 0 assert isinstance(summary, str) if __name__ == "__main__": pytest.main([__file__, "-v"])

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/Rudra-ravi/wikipedia-mcp'

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