Skip to main content
Glama

IaC Memory MCP Server

by AgentWong
test_integration.py19 kB
import logging import sys import pytest import pytest_asyncio from mcp import ClientSession from mcp.client.stdio import stdio_client from .test_utils.mcp_utils import create_server_params # Configure test logging logging.basicConfig( level=logging.DEBUG, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler(sys.stderr)], force=True, # Override any existing configuration ) # Get test logger logger = logging.getLogger("iac_memory.tests") @pytest_asyncio.fixture(scope="function") async def test_db_path(tmp_path): """Create a test database path for MCP server. With MCP_TEST_MODE=1, the server will automatically: 1. Reset the database state before each test 2. Initialize the schema with required tables 3. Apply proper pragmas and settings This fixture only provides the database path, as direct database access is not needed for integration testing. """ db_path = tmp_path / "test.db" yield str(db_path) @pytest_asyncio.fixture(scope="function") async def mcp_session(test_db_path): """Fixture that provides an MCP session with a clean test database.""" logger.info("Creating MCP test session") server_params = create_server_params( operation_name="test", env={ "PYTHONUNBUFFERED": "1", "MCP_DEBUG": "1", "MCP_TEST_MODE": "1", "MCP_DATABASE_PATH": test_db_path, "PYTHONPATH": "src", # Ensure server can find our package }, ) try: async with stdio_client(server_params) as streams: read_stream, write_stream = streams async with ClientSession(read_stream, write_stream) as session: logger.info("Initializing MCP session") await session.initialize() logger.info("MCP session initialized successfully") yield session except RuntimeError as e: if "Attempted to exit cancel scope in a different task than it was entered in" not in str(e): raise @pytest.mark.asyncio async def test_terraform_tools(mcp_session): """Test Terraform-specific tool operations. This test verifies all Terraform-related tools: 1. Provider management (add, update, info, list) 2. Resource management (add, update, info, list) """ logger.info("Starting Terraform tools test") try: # Add test provider logger.info("Adding test provider...") result = await mcp_session.call_tool( "add_terraform_provider", { "name": "test_provider", "version": "1.0.0", "source_url": "http://example.com/source", "doc_url": "http://example.com/docs" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Provider added successfully") # Update provider version logger.info("Updating provider version...") result = await mcp_session.call_tool( "update_provider_version", { "provider_name": "test_provider", "new_version": "2.0.0", "new_source_url": "http://example.com/source/v2", "new_doc_url": "http://example.com/docs/v2" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Provider version updated successfully") # Add test resource logger.info("Adding test resource...") result = await mcp_session.call_tool( "add_terraform_resource", { "provider": "test_provider", "name": "test_resource", "resource_type": "test_type", "schema": "{}", "version": "1.0.0", "doc_url": "http://example.com/resource" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Resource added successfully") # Update resource schema logger.info("Updating resource schema...") result = await mcp_session.call_tool( "update_resource_schema", { "resource_id": "test_resource", "new_schema": '{"updated": true}', "new_version": "2.0.0", "new_doc_url": "http://example.com/resource/v2" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Resource schema updated successfully") logger.info("All Terraform tool tests completed successfully") except Exception as e: logger.error(f"Test failed: {str(e)}", exc_info=True) raise @pytest.mark.asyncio async def test_server_lifecycle(mcp_session): """Test MCP server lifecycle and tool operations. This test verifies: 1. Basic server connectivity (ping) 2. Tool operations (adding and querying resources) 3. Core MCP capabilities (tools, resources, prompts) The test uses proper MCP tools rather than direct database access, making it a true integration test of the server's external interface. """ logger.info("Starting server lifecycle test") try: # Basic ping test logger.info("Testing ping...") await mcp_session.send_ping() logger.info("Ping successful") # Add test provider using MCP tool logger.info("Adding test provider...") result = await mcp_session.call_tool( "add_terraform_provider", { "name": "test_provider", "version": "1.0.0", "doc_url": "http://example.com", "source_url": "http://example.com/source" } ) logger.info("Provider added successfully") # Add test resource using MCP tool logger.info("Adding test resource...") result = await mcp_session.call_tool( "add_terraform_resource", { "provider": "test_provider", "name": "test_resource", "resource_type": "test_type", "version": "1.0.0", "doc_url": "http://example.com", "schema": "{}" } ) logger.info("Resource added successfully") # Verify provider info logger.info("Verifying provider info...") provider_info = await mcp_session.call_tool( "get_terraform_provider_info", {"provider_name": "test_provider"} ) assert hasattr(provider_info, "content"), "Result should have content attribute" assert isinstance(provider_info.content, list), "Content should be a list" assert len(provider_info.content) == 1, "Should have one info message" assert "test_provider" in provider_info.content[0].text, "Provider not found" logger.info("Provider verification successful") # Verify provider resources logger.info("Verifying provider resources...") provider_resources = await mcp_session.call_tool( "list_provider_resources", {"provider_name": "test_provider"} ) assert hasattr(provider_resources, "content"), "Result should have content attribute" assert isinstance(provider_resources.content, list), "Content should be a list" assert len(provider_resources.content) == 1, "Should have one resource message" assert "test_resource" in provider_resources.content[0].text, "Resource not found" logger.info("Resource verification successful") # Test standard MCP server capabilities logger.info("Testing server capabilities...") # Tool listing tools = await mcp_session.list_tools() assert hasattr(tools, "tools"), "Response should have tools attribute" assert isinstance(tools.tools, list), "Tools should be a list" assert len(tools.tools) > 0, "Expected tool list to not be empty" # Log each available tool logger.info("Available tools:") for tool in tools.tools: logger.info(f" - {tool.name}") logger.info(f"Tool listing successful - found {len(tools.tools)} tools") # Resource listing resources = await mcp_session.list_resources() assert hasattr(resources, "resources"), "Response should have resources attribute" assert isinstance(resources.resources, list), "Resources should be a list" assert len(resources.resources) > 0, "Expected resource list to not be empty" logger.info(f"Resource listing successful - found {len(resources.resources)} resources") # Prompt listing prompts = await mcp_session.list_prompts() assert hasattr(prompts, "prompts"), "Response should have prompts attribute" assert isinstance(prompts.prompts, list), "Prompts should be a list" logger.info(f"Prompt listing successful - found {len(prompts.prompts)} prompts") logger.info("All server lifecycle tests completed successfully") except TimeoutError as e: logger.error(f"Operation timed out: {str(e)}", exc_info=True) raise except Exception as e: logger.error(f"Test failed: {str(e)}", exc_info=True) raise @pytest.mark.asyncio async def test_ansible_tools(mcp_session): """Test Ansible-specific tool operations. This test verifies all Ansible-related tools: 1. Collection management (add, info, list, version history) 2. Module management (add, info, list, compatibility) """ logger.info("Starting Ansible tools test") try: # Add test collection logger.info("Adding test collection...") result = await mcp_session.call_tool( "add_ansible_collection", { "name": "test_collection", "version": "1.0.0", "source_url": "http://example.com/source", "doc_url": "http://example.com/docs" } ) logger.info("Collection added successfully") # Add test module logger.info("Adding test module...") result = await mcp_session.call_tool( "add_ansible_module", { "collection": "test_collection", "name": "test_module", "module_type": "cloud", "schema": "{}", "version": "1.0.0", "doc_url": "http://example.com/module" } ) logger.info("Module added successfully") # Test get_ansible_collection_info logger.info("Testing collection info retrieval...") collection_info = await mcp_session.call_tool( "get_ansible_collection_info", {"collection_name": "test_collection"} ) assert hasattr(collection_info, "content"), "Result should have content attribute" assert "test_collection" in collection_info.content[0].text, "Collection not found" logger.info("Collection info retrieval successful") # Test list_ansible_collections logger.info("Testing collection listing...") collections = await mcp_session.call_tool( "list_ansible_collections", {"filter_criteria": {"name_pattern": "test_collection"}} ) assert hasattr(collections, "content"), "Result should have content attribute" assert "test_collection" in collections.content[0].text, "Collection not found in list" logger.info("Collection listing successful") # Test get_collection_version_history logger.info("Testing version history retrieval...") version_history = await mcp_session.call_tool( "get_collection_version_history", {"collection_name": "test_collection"} ) assert hasattr(version_history, "content"), "Result should have content attribute" assert "1.0.0" in version_history.content[0].text, "Version history not found" logger.info("Version history retrieval successful") # Test get_ansible_module_info logger.info("Testing module info retrieval...") module_info = await mcp_session.call_tool( "get_ansible_module_info", { "collection_name": "test_collection", "module_name": "test_module" } ) assert hasattr(module_info, "content"), "Result should have content attribute" assert "test_module" in module_info.content[0].text, "Module not found" logger.info("Module info retrieval successful") # Test list_collection_modules logger.info("Testing module listing...") modules = await mcp_session.call_tool( "list_collection_modules", {"collection_name": "test_collection"} ) assert hasattr(modules, "content"), "Result should have content attribute" assert "test_module" in modules.content[0].text, "Module not found in list" logger.info("Module listing successful") # Test get_module_version_compatibility logger.info("Testing module compatibility check...") compatibility = await mcp_session.call_tool( "get_module_version_compatibility", { "collection_name": "test_collection", "module_name": "test_module", "version": "1.0.0" } ) assert hasattr(compatibility, "content"), "Result should have content attribute" assert "Compatible" in compatibility.content[0].text, "Compatibility check failed" logger.info("Module compatibility check successful") logger.info("All Ansible tool tests completed successfully") except Exception as e: logger.error(f"Test failed: {str(e)}", exc_info=True) raise @pytest.mark.asyncio async def test_ansible_update_tools(mcp_session): """Test Ansible update tool operations. This test verifies all Ansible version update tools: 1. Collection version updates 2. Module version updates """ logger.info("Starting Ansible update tools test") try: # Add test collection logger.info("Adding test collection...") result = await mcp_session.call_tool( "add_ansible_collection", { "name": "test_collection", "version": "1.0.0", "source_url": "http://example.com/source", "doc_url": "http://example.com/docs" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Collection added successfully") # Update collection version logger.info("Updating collection version...") result = await mcp_session.call_tool( "update_collection_version", { "collection_id": "test_collection", "new_version": "2.0.0", "new_source_url": "http://example.com/source/v2", "new_doc_url": "http://example.com/docs/v2" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Collection version updated successfully") # Add test module logger.info("Adding test module...") result = await mcp_session.call_tool( "add_ansible_module", { "collection": "test_collection", "name": "test_module", "module_type": "cloud", "schema": "{}", "version": "1.0.0", "doc_url": "http://example.com/module" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Module added successfully") # Update module version logger.info("Updating module version...") result = await mcp_session.call_tool( "update_module_version", { "module_id": "test_module", "new_schema": '{"updated": true}', "new_version": "2.0.0", "new_doc_url": "http://example.com/module/v2" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Module version updated successfully") logger.info("All Ansible update tool tests completed successfully") except Exception as e: logger.error(f"Test failed: {str(e)}", exc_info=True) raise @pytest.mark.asyncio async def test_entity_tools(mcp_session): """Test Entity-specific tool operations. This test verifies all Entity-related tools: 1. Entity creation 2. Entity updates 3. Entity deletion 4. Relationship viewing """ logger.info("Starting Entity tools test") try: # Create test entity logger.info("Creating test entity...") result = await mcp_session.call_tool( "create_entity", { "name": "test_entity", "type": "test_type", "attributes": { "key": "value" } } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Entity created successfully") # Update test entity logger.info("Updating test entity...") result = await mcp_session.call_tool( "update_entity", { "entity_id": "test_entity", "attributes": { "key": "new_value" } } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Entity updated successfully") # View relationships logger.info("Viewing entity relationships...") result = await mcp_session.call_tool( "view_relationships", { "entity_id": "test_entity" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Relationship viewing successful") # Delete test entity logger.info("Deleting test entity...") result = await mcp_session.call_tool( "delete_entity", { "entity_id": "test_entity" } ) assert hasattr(result, "content"), "Result should have content attribute" logger.info("Entity deleted successfully") logger.info("All Entity tool tests completed successfully") except Exception as e: logger.error(f"Test failed: {str(e)}", exc_info=True) raise

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/AgentWong/iac-memory-mcp-server-project'

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