Skip to main content
Glama
test_mcp_server.py14.3 kB
""" Comprehensive tests for MCP server tools and resources. Tests all MCP tools, resources, and essential edge cases. """ from unittest.mock import AsyncMock import pytest from mcp_mitm_mem0.mcp_server import ( add_memory, analyze_conversations, delete_memory, list_memories, search_memories, suggest_next_actions, ) class TestMCPTools: """Test MCP server tools functionality.""" @pytest.mark.asyncio async def test_search_memories_success( self, mock_mcp_dependencies, sample_memories ): """Test successful memory search.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories = AsyncMock(return_value=sample_memories[:2]) result = await search_memories("coding questions", "test-user", limit=2) assert len(result) == 2 assert result[0]["id"] == "mem1" mock_memory.search_memories.assert_called_once_with( query="coding questions", user_id="test-user", limit=2 ) @pytest.mark.asyncio async def test_search_memories_with_defaults(self, mock_mcp_dependencies): """Test search with default parameters.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories.return_value = [] result = await search_memories("test query", "user") assert result == [] mock_memory.search_memories.assert_called_once_with( query="test query", user_id="user", limit=10 ) @pytest.mark.asyncio async def test_list_memories_success(self, mock_mcp_dependencies, sample_memories): """Test successful memory listing.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.get_all_memories.return_value = sample_memories result = await list_memories("test-user") assert len(result) == 4 assert result[0]["id"] == "mem1" mock_memory.get_all_memories.assert_called_once_with(user_id="test-user") @pytest.mark.asyncio async def test_add_memory_success(self, mock_mcp_dependencies, sample_messages): """Test successful memory addition.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.add_memory.return_value = {"id": "new-mem-123"} result = await add_memory(sample_messages, "test-user") assert result["id"] == "new-mem-123" mock_memory.add_memory.assert_called_once_with( messages=sample_messages, user_id="test-user", metadata=None ) @pytest.mark.asyncio async def test_add_memory_with_metadata(self, mock_mcp_dependencies): """Test memory addition with metadata.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.add_memory.return_value = {"id": "meta-mem"} messages = [{"role": "user", "content": "Important message"}] metadata = {"priority": "high", "source": "manual"} result = await add_memory(messages, "test-user", metadata) assert result["id"] == "meta-mem" mock_memory.add_memory.assert_called_once_with( messages=messages, user_id="test-user", metadata=metadata ) @pytest.mark.asyncio async def test_delete_memory_success(self, mock_mcp_dependencies): """Test successful memory deletion.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.delete_memory.return_value = {"status": "deleted"} result = await delete_memory("mem-123") assert result["memory_id"] == "mem-123" assert result["status"] == "deleted" mock_memory.delete_memory.assert_called_once_with(memory_id="mem-123") @pytest.mark.asyncio async def test_analyze_conversations_success(self, mock_mcp_dependencies): """Test successful conversation analysis.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies analysis_result = { "status": "analyzed", "memory_count": 5, "insights": [ {"type": "focus_area", "description": "Primary focus on coding"}, {"type": "frequent_questions", "description": "Many questions asked"}, ], } mock_agent.analyze_recent_conversations.return_value = analysis_result result = await analyze_conversations("test-user", limit=20) assert result["status"] == "analyzed" assert result["memory_count"] == 5 assert len(result["insights"]) == 2 mock_agent.analyze_recent_conversations.assert_called_once_with( user_id="test-user", limit=20 ) @pytest.mark.asyncio async def test_suggest_next_actions_success(self, mock_mcp_dependencies): """Test successful next action suggestions.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies suggestions = [ "Consider creating a coding reference guide", "Set up a FAQ for common questions", ] mock_agent.suggest_next_steps.return_value = suggestions result = await suggest_next_actions("test-user") assert len(result) == 2 assert "coding reference" in result[0] assert "FAQ" in result[1] mock_agent.suggest_next_steps.assert_called_once_with(user_id="test-user") # Essential Edge Cases @pytest.mark.asyncio async def test_search_memories_empty_query(self, mock_mcp_dependencies): """Test search with empty query.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories.return_value = [] result = await search_memories("", "test-user") assert result == [] mock_memory.search_memories.assert_called_once_with( query="", user_id="test-user", limit=10 ) @pytest.mark.asyncio async def test_search_memories_unicode_query(self, mock_mcp_dependencies): """Test search with unicode characters.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories.return_value = [] unicode_query = "🤖 search with émoji and spëcial chars" result = await search_memories(unicode_query, "test-user") assert result == [] mock_memory.search_memories.assert_called_once_with( query=unicode_query, user_id="test-user", limit=10 ) @pytest.mark.asyncio async def test_add_memory_empty_messages(self, mock_mcp_dependencies): """Test adding memory with empty messages.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.add_memory.return_value = {"id": "empty-mem"} result = await add_memory([], "test-user") assert result["id"] == "empty-mem" mock_memory.add_memory.assert_called_once_with( messages=[], user_id="test-user", metadata=None ) @pytest.mark.asyncio async def test_add_memory_malformed_messages(self, mock_mcp_dependencies): """Test adding memory with malformed messages.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.add_memory.return_value = {"id": "malformed-mem"} malformed_messages = [ {"wrong_field": "value"}, # Missing role/content {"role": "user"}, # Missing content {"content": "text"}, # Missing role {}, # Empty dict ] result = await add_memory(malformed_messages, "test-user") assert result["id"] == "malformed-mem" @pytest.mark.asyncio async def test_delete_memory_empty_id(self, mock_mcp_dependencies): """Test delete with empty memory ID.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.delete_memory.return_value = {"status": "deleted"} result = await delete_memory("") assert result["memory_id"] == "" assert result["status"] == "deleted" @pytest.mark.asyncio async def test_list_memories_empty_user_id(self, mock_mcp_dependencies): """Test list memories with empty user ID.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.get_all_memories.return_value = [] result = await list_memories("") assert result == [] mock_memory.get_all_memories.assert_called_once_with(user_id="") @pytest.mark.asyncio async def test_analyze_conversations_zero_limit(self, mock_mcp_dependencies): """Test analysis with zero limit.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_agent.analyze_recent_conversations.return_value = { "status": "analyzed", "memory_count": 0, "insights": [], } result = await analyze_conversations("test-user", limit=0) assert result["memory_count"] == 0 mock_agent.analyze_recent_conversations.assert_called_once_with( user_id="test-user", limit=0 ) @pytest.mark.asyncio async def test_suggest_next_actions_empty_result(self, mock_mcp_dependencies): """Test suggestions when none available.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_agent.suggest_next_steps.return_value = [] result = await suggest_next_actions("test-user") assert result == [] # Error Handling Tests @pytest.mark.asyncio async def test_search_memories_api_failure(self, mock_mcp_dependencies): """Test search when memory service fails.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories.side_effect = Exception("API timeout") with pytest.raises(RuntimeError, match="Search failed: API timeout"): await search_memories("test query", "test-user") @pytest.mark.asyncio async def test_list_memories_api_failure(self, mock_mcp_dependencies): """Test list when memory service fails.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.get_all_memories.side_effect = Exception("Connection error") with pytest.raises(RuntimeError, match="List failed: Connection error"): await list_memories("test-user") @pytest.mark.asyncio async def test_add_memory_api_failure(self, mock_mcp_dependencies): """Test add memory when service fails.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.add_memory.side_effect = Exception("Rate limit exceeded") with pytest.raises(RuntimeError, match="Add failed: Rate limit exceeded"): await add_memory([{"role": "user", "content": "test"}], "test-user") @pytest.mark.asyncio async def test_delete_memory_api_failure(self, mock_mcp_dependencies): """Test delete when memory not found.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.delete_memory.side_effect = Exception("Memory not found") with pytest.raises(RuntimeError, match="Delete failed: Memory not found"): await delete_memory("nonexistent-id") @pytest.mark.asyncio async def test_analyze_conversations_api_failure(self, mock_mcp_dependencies): """Test analysis when reflection agent fails.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_agent.analyze_recent_conversations.side_effect = Exception( "Analysis service down" ) with pytest.raises( RuntimeError, match="Analysis failed: Analysis service down" ): await analyze_conversations("test-user") @pytest.mark.asyncio async def test_suggest_next_actions_api_failure(self, mock_mcp_dependencies): """Test suggestions when reflection agent fails.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_agent.suggest_next_steps.side_effect = Exception("Suggestion engine error") with pytest.raises( RuntimeError, match="Failed to generate suggestions: Suggestion engine error", ): await suggest_next_actions("test-user") # Default User ID Handling @pytest.mark.asyncio async def test_tools_use_none_for_default_user(self, mock_mcp_dependencies): """Test that tools pass None through for default user handling.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories.return_value = [] # MCP server passes None through, memory service handles default result = await search_memories("test query", None) assert result == [] mock_memory.search_memories.assert_called_once_with( query="test query", user_id=None, limit=10 ) @pytest.mark.asyncio async def test_message_order_preservation(self, mock_mcp_dependencies): """Test that message order is preserved.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.add_memory.return_value = {"id": "ordered-mem"} ordered_messages = [ {"role": "user", "content": "First message"}, {"role": "assistant", "content": "Second message"}, {"role": "user", "content": "Third message"}, ] await add_memory(ordered_messages, "test-user") # Verify exact message order was passed call_args = mock_memory.add_memory.call_args passed_messages = call_args[1]["messages"] assert passed_messages == ordered_messages @pytest.mark.asyncio async def test_unicode_user_ids(self, mock_mcp_dependencies): """Test handling of unicode user IDs.""" mock_memory, mock_agent, mock_settings = mock_mcp_dependencies mock_memory.search_memories.return_value = [] unicode_user_id = "用户_🤖_123" result = await search_memories("test", unicode_user_id) assert result == [] mock_memory.search_memories.assert_called_once_with( query="test", user_id=unicode_user_id, limit=10 )

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/terrymunro/mcp-mitm-mem0'

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