Skip to main content
Glama
armanzeroeight

Octopus Deploy MCP Server

test_mcp_server_integration.py9.73 kB
"""High-level integration tests for the complete MCP server functionality.""" import pytest import json from unittest.mock import Mock, patch from src.octopus_deploy_mcp.server import OctopusDeployServer class TestMCPServerIntegration: """Test complete MCP server integration scenarios.""" def test_server_tool_registration_complete(self, octopus_server): """Test that all expected tools are registered with the MCP server.""" # Setup all tools octopus_server.tools.setup_tools() # Get registered tool names registered_tools = [tool.name for tool in octopus_server.mcp._tools] # Verify all expected tools are registered expected_tools = [ 'get_project_details', 'get_latest_release', 'create_release', 'deploy_release', 'check_deployment_status' ] for expected_tool in expected_tools: assert expected_tool in registered_tools, f"Tool '{expected_tool}' should be registered" assert len(registered_tools) == len(expected_tools), "All tools should be registered" def test_complete_deployment_workflow(self, octopus_server, mock_httpx_client): """Test a complete deployment workflow from project details to deployment status.""" # Sample data space_data = {"Id": "Spaces-1", "Name": "Default"} project_data = {"Id": "Projects-1", "Name": "MyApp"} release_data = {"Id": "Releases-1", "Version": "1.0.0", "ProjectId": "Projects-1"} environment_data = {"Id": "Environments-1", "Name": "Production"} deployment_data = { "Id": "Deployments-1", "ReleaseId": "Releases-1", "EnvironmentId": "Environments-1", "TaskId": "ServerTasks-1", "State": "Success" } task_data = {"State": "Success", "IsCompleted": True} # Mock all API responses for the workflow mock_get_response = Mock() mock_get_response.status_code = 200 mock_get_response.json.side_effect = [ # get_project_details calls [space_data], # spaces/all [project_data], # projects/all {"Items": []}, # releases (no active environments) # get_latest_release calls [space_data], # spaces/all [project_data], # projects/all {"Items": [release_data]}, # releases # deploy_release calls [space_data], # spaces/all [project_data], # projects/all {"Items": [release_data]}, # releases [environment_data], # environments/all # check_deployment_status calls [space_data], # spaces/all [project_data], # projects/all {"Items": [release_data]}, # releases [environment_data], # environments/all {"Items": [deployment_data]}, # deployments task_data, # task details ] mock_post_response = Mock() mock_post_response.status_code = 201 mock_post_response.json.return_value = deployment_data mock_httpx_client.return_value.__enter__.return_value.get.return_value = mock_get_response mock_httpx_client.return_value.__enter__.return_value.post.return_value = mock_post_response # Setup all tools octopus_server.tools.setup_tools() # Get tool functions tools = {tool.name: tool.func for tool in octopus_server.mcp._tools} # Step 1: Get project details project_result = tools['get_project_details']("MyApp", "Default") project_data_result = json.loads(project_result) assert project_data_result["success"] is True assert project_data_result["project"]["name"] == "MyApp" # Step 2: Get latest release release_result = tools['get_latest_release']("MyApp", "Default") release_data_result = json.loads(release_result) assert release_data_result["success"] is True assert release_data_result["latest_release"]["version"] == "1.0.0" # Step 3: Deploy release deploy_result = tools['deploy_release']("MyApp", "Production", "1.0.0", "Default") deploy_data_result = json.loads(deploy_result) assert deploy_data_result["success"] is True assert "initiated successfully" in deploy_data_result["message"] # Step 4: Check deployment status status_result = tools['check_deployment_status']("MyApp", "1.0.0", "Production", "Default") status_data_result = json.loads(status_result) assert status_data_result["success"] is True assert len(status_data_result["deployment_statuses"]) == 1 assert status_data_result["deployment_statuses"][0]["deployment_status"]["state"] == "Success" def test_error_propagation_across_tools(self, octopus_server, mock_httpx_client): """Test that errors are properly propagated across different tools.""" # Mock authentication failure mock_response = Mock() mock_response.status_code = 401 mock_response.text = "Unauthorized" mock_httpx_client.return_value.__enter__.return_value.get.return_value = mock_response # Setup all tools octopus_server.tools.setup_tools() # Get tool functions tools = {tool.name: tool.func for tool in octopus_server.mcp._tools} # Test each tool handles authentication failure for tool_name, tool_func in tools.items(): if tool_name == 'get_project_details': result = tool_func("TestProject", "Default") elif tool_name == 'get_latest_release': result = tool_func("TestProject", "Default") elif tool_name == 'create_release': result = tool_func("TestProject", "1.0.0", "Default", "Default") elif tool_name == 'deploy_release': result = tool_func("TestProject", "Production", "1.0.0", "Default") elif tool_name == 'check_deployment_status': result = tool_func("TestProject", "1.0.0", "Production", "Default") result_data = json.loads(result) assert "error" in result_data, f"Tool {tool_name} should handle authentication error" assert "Authentication failed" in result_data["error"], f"Tool {tool_name} should show auth error" def test_cross_space_operations(self, octopus_server, mock_httpx_client): """Test operations across different Octopus Deploy spaces.""" # Sample data for different spaces spaces = [ {"Id": "Spaces-1", "Name": "Development"}, {"Id": "Spaces-2", "Name": "Production"} ] dev_project = {"Id": "Projects-1", "Name": "MyApp"} prod_project = {"Id": "Projects-2", "Name": "MyApp"} # Mock API responses mock_response = Mock() mock_response.status_code = 200 mock_response.json.side_effect = [ spaces, # spaces/all (Development) [dev_project], # Development projects {"Items": []}, # Development releases spaces, # spaces/all (Production) [prod_project], # Production projects {"Items": []}, # Production releases ] mock_httpx_client.return_value.__enter__.return_value.get.return_value = mock_response # Setup all tools octopus_server.tools.setup_tools() # Get tool function tools = {tool.name: tool.func for tool in octopus_server.mcp._tools} # Test project details in Development space dev_result = tools['get_project_details']("MyApp", "Development") dev_data = json.loads(dev_result) assert dev_data["success"] is True assert dev_data["space"]["name"] == "Development" # Test project details in Production space prod_result = tools['get_project_details']("MyApp", "Production") prod_data = json.loads(prod_result) assert prod_data["success"] is True assert prod_data["space"]["name"] == "Production" def test_server_handles_network_failures(self, octopus_server, mock_httpx_client): """Test server behavior when network requests fail.""" # Mock network failure mock_httpx_client.return_value.__enter__.return_value.get.side_effect = Exception("Connection timeout") # Setup all tools octopus_server.tools.setup_tools() # Get tool function tools = {tool.name: tool.func for tool in octopus_server.mcp._tools} # Test that network failures are handled gracefully result = tools['get_project_details']("TestProject", "Default") result_data = json.loads(result) assert "error" in result_data assert "Unexpected error" in result_data["error"] or "Failed to connect" in result_data["error"] @patch('src.octopus_deploy_mcp.server.OctopusDeployServer.run') def test_server_startup_and_shutdown(self, mock_run, octopus_server): """Test server startup and shutdown process.""" # Test that server can be started octopus_server.run("stdio") mock_run.assert_called_once_with(transport="stdio") # Verify tools are set up before running assert octopus_server.tools is not None assert len(octopus_server.mcp._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/armanzeroeight/octopus-deploy-mcp-server'

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