Skip to main content
Glama

AWS Model Context Protocol Server

by alexei-led
test_server.py9.44 kB
"""Tests for the FastMCP server implementation.""" from unittest.mock import ANY, AsyncMock, patch import pytest from aws_mcp_server.cli_executor import CommandExecutionError, CommandValidationError from aws_mcp_server.server import aws_cli_help, aws_cli_pipeline, mcp, run_startup_checks def test_run_startup_checks(): """Test the run_startup_checks function.""" # Create a complete mock for asyncio.run to avoid the coroutine warning # We'll mock both the check_aws_cli_installed and asyncio.run # This way we don't rely on any actual coroutine behavior in testing # Test when AWS CLI is installed with patch("aws_mcp_server.server.check_aws_cli_installed") as mock_check: # Don't use the actual coroutine mock_check.return_value = None # Not used when mocking asyncio.run with patch("aws_mcp_server.server.asyncio.run", return_value=True): with patch("sys.exit") as mock_exit: run_startup_checks() mock_exit.assert_not_called() # Test when AWS CLI is not installed with patch("aws_mcp_server.server.check_aws_cli_installed") as mock_check: # Don't use the actual coroutine mock_check.return_value = None # Not used when mocking asyncio.run with patch("aws_mcp_server.server.asyncio.run", return_value=False): with patch("sys.exit") as mock_exit: run_startup_checks() mock_exit.assert_called_once_with(1) @pytest.mark.asyncio @pytest.mark.parametrize( "service,command,expected_result", [ ("s3", None, {"help_text": "Test help text"}), ("s3", "ls", {"help_text": "Test help text"}), ("ec2", "describe-instances", {"help_text": "Test help text"}), ], ) async def test_aws_cli_help(service, command, expected_result): """Test the aws_cli_help tool with various inputs.""" # Mock the get_command_help function instead of execute_aws_command with patch("aws_mcp_server.server.get_command_help", new_callable=AsyncMock) as mock_get_help: mock_get_help.return_value = expected_result # Call the tool with specified service and command result = await aws_cli_help(service=service, command=command) # Verify the result assert result == expected_result # Verify the correct arguments were passed to the mocked function mock_get_help.assert_called_with(service, command) @pytest.mark.asyncio async def test_aws_cli_help_with_context(): """Test the aws_cli_help tool with context.""" mock_ctx = AsyncMock() with patch("aws_mcp_server.server.get_command_help", new_callable=AsyncMock) as mock_get_help: mock_get_help.return_value = {"help_text": "Test help text"} result = await aws_cli_help(service="s3", command="ls", ctx=mock_ctx) assert result == {"help_text": "Test help text"} mock_ctx.info.assert_called_once() assert "Fetching help for AWS s3 ls" in mock_ctx.info.call_args[0][0] @pytest.mark.asyncio async def test_aws_cli_help_exception_handling(): """Test exception handling in aws_cli_help.""" with patch("aws_mcp_server.server.get_command_help", side_effect=Exception("Test exception")): result = await aws_cli_help(service="s3") assert "help_text" in result assert "Error retrieving help" in result["help_text"] assert "Test exception" in result["help_text"] @pytest.mark.asyncio @pytest.mark.parametrize( "command,timeout,expected_result", [ # Basic success case ("aws s3 ls", None, {"status": "success", "output": "Test output"}), # Success with custom timeout ("aws s3 ls", 60, {"status": "success", "output": "Test output"}), # Complex command success ("aws ec2 describe-instances --filters Name=instance-state-name,Values=running", None, {"status": "success", "output": "Running instances"}), ], ) async def test_aws_cli_pipeline_success(command, timeout, expected_result): """Test the aws_cli_pipeline tool with successful execution.""" # Need to patch check_aws_cli_installed to avoid the coroutine warning with patch("aws_mcp_server.server.check_aws_cli_installed", return_value=None): # Mock the execute_aws_command function with patch("aws_mcp_server.server.execute_aws_command", new_callable=AsyncMock) as mock_execute: mock_execute.return_value = expected_result # Call the aws_cli_pipeline function result = await aws_cli_pipeline(command=command, timeout=timeout) # Verify the result assert result["status"] == expected_result["status"] assert result["output"] == expected_result["output"] # Verify the correct arguments were passed to the mocked function mock_execute.assert_called_with(command, timeout if timeout else ANY) @pytest.mark.asyncio async def test_aws_cli_pipeline_with_context(): """Test the aws_cli_pipeline tool with context.""" mock_ctx = AsyncMock() # Need to patch check_aws_cli_installed to avoid the coroutine warning with patch("aws_mcp_server.server.check_aws_cli_installed", return_value=None): # Test successful command with context with patch("aws_mcp_server.server.execute_aws_command", new_callable=AsyncMock) as mock_execute: mock_execute.return_value = {"status": "success", "output": "Test output"} result = await aws_cli_pipeline(command="aws s3 ls", ctx=mock_ctx) assert result["status"] == "success" assert result["output"] == "Test output" # Verify context was used correctly assert mock_ctx.info.call_count == 2 assert "Executing AWS CLI command" in mock_ctx.info.call_args_list[0][0][0] assert "Command executed successfully" in mock_ctx.info.call_args_list[1][0][0] # Test failed command with context mock_ctx.reset_mock() with patch("aws_mcp_server.server.execute_aws_command", new_callable=AsyncMock) as mock_execute: mock_execute.return_value = {"status": "error", "output": "Error output"} result = await aws_cli_pipeline(command="aws s3 ls", ctx=mock_ctx) assert result["status"] == "error" assert result["output"] == "Error output" # Verify context was used correctly assert mock_ctx.info.call_count == 1 assert mock_ctx.warning.call_count == 1 assert "Command failed" in mock_ctx.warning.call_args[0][0] @pytest.mark.asyncio async def test_aws_cli_pipeline_with_context_and_timeout(): """Test the aws_cli_pipeline tool with context and timeout.""" mock_ctx = AsyncMock() # Need to patch check_aws_cli_installed to avoid the coroutine warning with patch("aws_mcp_server.server.check_aws_cli_installed", return_value=None): with patch("aws_mcp_server.server.execute_aws_command", new_callable=AsyncMock) as mock_execute: mock_execute.return_value = {"status": "success", "output": "Test output"} await aws_cli_pipeline(command="aws s3 ls", timeout=60, ctx=mock_ctx) # Verify timeout was mentioned in the context message message = mock_ctx.info.call_args_list[0][0][0] assert "with timeout: 60s" in message @pytest.mark.asyncio @pytest.mark.parametrize( "command,exception,expected_error_type,expected_message", [ # Validation error ("not aws", CommandValidationError("Invalid command"), "Command validation error", "Invalid command"), # Execution error ("aws s3 ls", CommandExecutionError("Execution failed"), "Command execution error", "Execution failed"), # Timeout error ("aws ec2 describe-instances", CommandExecutionError("Command timed out"), "Command execution error", "Command timed out"), # Generic/unexpected error ("aws dynamodb scan", Exception("Unexpected error"), "Unexpected error", "Unexpected error"), ], ) async def test_aws_cli_pipeline_errors(command, exception, expected_error_type, expected_message): """Test the aws_cli_pipeline tool with various error scenarios.""" # Need to patch check_aws_cli_installed to avoid the coroutine warning with patch("aws_mcp_server.server.check_aws_cli_installed", return_value=None): # Mock the execute_aws_command function to raise the specified exception with patch("aws_mcp_server.server.execute_aws_command", side_effect=exception) as mock_execute: # Call the tool result = await aws_cli_pipeline(command=command) # Verify error status and message assert result["status"] == "error" assert expected_error_type in result["output"] assert expected_message in result["output"] # Verify the command was called correctly mock_execute.assert_called_with(command, ANY) @pytest.mark.asyncio async def test_mcp_server_initialization(): """Test that the MCP server initializes correctly.""" # Verify server was created with correct name assert mcp.name == "AWS MCP Server" # Verify tools are registered by calling them # This ensures the tools exist without depending on FastMCP's internal structure assert callable(aws_cli_help) assert callable(aws_cli_pipeline)

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/alexei-led/aws-mcp-server'

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