Skip to main content
Glama
wehnsdaefflae

Interactive Automation MCP Server

test_execute_command.py11.4 kB
#!/usr/bin/env python3 """ Functional tests for command execution workflows Tests the core command execution functionality including: - Basic command execution and output capture - Interactive command workflows with input/output - Session lifecycle management - Python REPL and other interactive programs """ import asyncio from typing import Any import pytest from src.terminal_control_mcp.main import ( exit_terminal, get_screen_content, list_terminal_sessions, open_terminal, send_input, ) from src.terminal_control_mcp.models import ( DestroySessionRequest, GetScreenContentRequest, OpenTerminalRequest, SendInputRequest, ) class TestBasicCommands: """Test basic non-interactive command execution""" @pytest.mark.asyncio async def test_echo_command(self, mock_context: Any) -> None: """Test simple echo command""" request = OpenTerminalRequest( shell="bash", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success assert result.session_id # Send echo command to the shell if result.success and result.session_id: input_request = SendInputRequest( session_id=result.session_id, input_text="echo 'Hello World'\n" ) await send_input(input_request, mock_context) # Get output using screen content await asyncio.sleep(0.5) # Give time for command to execute screen_request = GetScreenContentRequest( session_id=result.session_id, content_mode="screen", line_count=None ) screen_result = await get_screen_content(screen_request, mock_context) if screen_result.success and screen_result.screen_content: assert "Hello World" in screen_result.screen_content # Cleanup destroy_request = DestroySessionRequest(session_id=result.session_id) await exit_terminal(destroy_request, mock_context) @pytest.mark.asyncio async def test_python_version(self, mock_context: Any) -> None: """Test Python version command""" request = OpenTerminalRequest( shell="bash", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success assert result.session_id # Send python version command to the shell if result.success and result.session_id: input_request = SendInputRequest( session_id=result.session_id, input_text="python3 --version\n" ) await send_input(input_request, mock_context) # Get output using screen content await asyncio.sleep(0.5) # Give time for command to execute screen_request = GetScreenContentRequest( session_id=result.session_id, content_mode="screen", line_count=None ) screen_result = await get_screen_content(screen_request, mock_context) if screen_result.success and screen_result.screen_content: assert "Python" in screen_result.screen_content # Cleanup destroy_request = DestroySessionRequest(session_id=result.session_id) await exit_terminal(destroy_request, mock_context) @pytest.mark.asyncio async def test_whoami_command(self, mock_context: Any) -> None: """Test whoami command""" request = OpenTerminalRequest( shell="bash", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success # Send whoami command to the shell if result.success and result.session_id: input_request = SendInputRequest( session_id=result.session_id, input_text="whoami\n" ) await send_input(input_request, mock_context) # Don't check content since it varies by system # Cleanup destroy_request = DestroySessionRequest(session_id=result.session_id) await exit_terminal(destroy_request, mock_context) class TestSessionManagement: """Test session lifecycle management""" @pytest.mark.asyncio async def test_list_sessions_initially_empty(self, mock_context: Any) -> None: """Test that session list is initially empty""" sessions = await list_terminal_sessions(mock_context) assert sessions.success # Note: other tests might have sessions running, so we just check it works assert isinstance(sessions.sessions, list) @pytest.mark.asyncio async def test_create_and_destroy_session(self, mock_context: Any) -> None: """Test creating and destroying a session""" # Create session request = OpenTerminalRequest( shell="python3", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success session_id = result.session_id # Send Python command to the shell if result.success and result.session_id: input_request = SendInputRequest( session_id=result.session_id, input_text="input('Press enter: '); print('done')\n", ) await send_input(input_request, mock_context) # Check session exists sessions = await list_terminal_sessions(mock_context) assert sessions.success session_ids = [s.session_id for s in sessions.sessions] assert session_id in session_ids # Destroy session destroy_request = DestroySessionRequest(session_id=session_id) destroy_result = await exit_terminal(destroy_request, mock_context) assert destroy_result.success class TestInteractiveWorkflows: """Test interactive command workflows""" @pytest.mark.asyncio async def test_python_input_workflow(self, mock_context: Any) -> None: """Test Python interactive input workflow""" # Start interactive command request = OpenTerminalRequest( shell="python3", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success session_id = result.session_id # Send Python command if result.success and result.session_id: input_request = SendInputRequest( session_id=result.session_id, input_text="name=input('Enter name: '); print(f'Hello {name}!')\n", ) await send_input(input_request, mock_context) try: # Give time for output to appear await asyncio.sleep(0.5) # Get screen content screen_request = GetScreenContentRequest( session_id=session_id, content_mode="screen", line_count=None ) screen_result = await get_screen_content(screen_request, mock_context) assert screen_result.success if screen_result.process_running: # Send input input_request = SendInputRequest( session_id=session_id, input_text="Alice\n" ) input_result = await send_input(input_request, mock_context) assert input_result.success # Give time for processing await asyncio.sleep(0.5) # Get final output final_screen = await get_screen_content(screen_request, mock_context) assert final_screen.success finally: # Cleanup destroy_request = DestroySessionRequest(session_id=session_id) await exit_terminal(destroy_request, mock_context) @pytest.mark.asyncio async def test_python_choice_workflow(self, mock_context: Any) -> None: """Test Python choice workflow""" # Start interactive command request = OpenTerminalRequest( shell="python3", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success session_id = result.session_id # Send Python command if result.success and result.session_id: input_request = SendInputRequest( session_id=result.session_id, input_text="choice=input('Continue? (y/n): '); print('Yes!' if choice=='y' else 'No!')\n", ) await send_input(input_request, mock_context) try: # Give time for output to appear await asyncio.sleep(0.5) # Get screen content screen_request = GetScreenContentRequest( session_id=session_id, content_mode="screen", line_count=None ) screen_result = await get_screen_content(screen_request, mock_context) assert screen_result.success if screen_result.process_running: # Send input input_request = SendInputRequest( session_id=session_id, input_text="y\n" ) input_result = await send_input(input_request, mock_context) assert input_result.success # Give time for processing await asyncio.sleep(0.5) finally: # Cleanup destroy_request = DestroySessionRequest(session_id=session_id) await exit_terminal(destroy_request, mock_context) class TestPythonREPL: """Test Python REPL workflows""" @pytest.mark.asyncio async def test_python_repl_workflow(self, mock_context: Any) -> None: """Test Python REPL as a complex interactive workflow""" # Start Python REPL request = OpenTerminalRequest( shell="python3", working_directory=None, environment=None ) result = await open_terminal(request, mock_context) assert result.success session_id = result.session_id try: interactions = [ "import math", "print(math.pi)", "result = 2 + 3", "print(f'Result: {result}')", "exit()", ] for input_text in interactions: # Give time for prompt to appear await asyncio.sleep(0.5) # Get screen content screen_request = GetScreenContentRequest( session_id=session_id, content_mode="screen", line_count=None ) screen_result = await get_screen_content(screen_request, mock_context) assert screen_result.success # Check if process is still running if not screen_result.process_running: break # Send input input_request = SendInputRequest( session_id=session_id, input_text=input_text + "\n" ) input_result = await send_input(input_request, mock_context) assert input_result.success finally: # Cleanup (process might have already exited) destroy_request = DestroySessionRequest(session_id=session_id) await exit_terminal(destroy_request, mock_context)

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/wehnsdaefflae/MCPAutomationServer'

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