Skip to main content
Glama
test_stdio_logging.py4.18 kB
""" Integration test for stdio mode logging behavior. Verifies that when running in stdio mode, the server produces NO log output on stdout or stderr that could interfere with the MCP JSON-RPC protocol. """ import asyncio import json import os import subprocess import sys import pytest @pytest.mark.integration def test_stdio_mode_no_log_output(): """ Verify that stdio mode produces no non-JSON-RPC output. In stdio mode, the MCP protocol uses stdin/stdout for JSON-RPC communication. Any non-JSON-RPC output corrupts the protocol. Simple test strategy: 1. Start server in stdio mode 2. Let it run for a moment 3. Check that stderr is completely empty 4. Check that any stdout lines are valid JSON-RPC """ # Start server as subprocess in stdio mode env = os.environ.copy() env["MCP_TRANSPORT"] = "stdio" process = subprocess.Popen( [sys.executable, "-m", "mcp_outline"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, text=True, ) try: # Give server time to start up # Any startup logs would appear during this time asyncio.run(asyncio.sleep(2)) # Check if still running if process.poll() is not None: stdout, stderr = process.communicate() pytest.fail( f"Server exited unexpectedly " f"(exit code {process.returncode})\n" f"stderr: {stderr}\nstdout: {stdout}" ) finally: # Capture output if process.poll() is None: process.terminate() try: stdout, stderr = process.communicate(timeout=5) except subprocess.TimeoutExpired: process.kill() stdout, stderr = process.communicate() else: stdout, stderr = process.communicate() # CHECK 1: stderr must be completely empty (no logs allowed) assert not stderr.strip(), ( f"stderr should be empty in stdio mode but got:\n{stderr}" ) # CHECK 2: any stdout output must be valid JSON-RPC for line in stdout.strip().split("\n"): if not line.strip(): continue # Try to parse as JSON try: msg = json.loads(line) # Must be a dict with jsonrpc field (or error/result) if isinstance(msg, dict): assert "jsonrpc" in msg or "result" in msg or "error" in msg, ( f"stdout line is not JSON-RPC: {line}" ) except json.JSONDecodeError: # Any non-JSON output is a log message - fail the test pytest.fail( f"Found non-JSON output in stdout " f"(likely a log message):\n{line}\n" f"Full stdout:\n{stdout}" ) @pytest.mark.integration def test_sse_mode_allows_log_output(): """ Verify that non-stdio modes (SSE) DO produce log output. This is the inverse test - ensuring that logging works properly in SSE/HTTP modes where logs are helpful for debugging. """ # Start server in SSE mode env = os.environ.copy() env["MCP_TRANSPORT"] = "sse" process = subprocess.Popen( [sys.executable, "-m", "mcp_outline"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, text=True, ) try: # Give server time to start and log # Increased to 4 seconds to allow for slower startup on some systems asyncio.run(asyncio.sleep(4)) finally: process.terminate() try: stdout, stderr = process.communicate(timeout=5) except subprocess.TimeoutExpired: process.kill() stdout, stderr = process.communicate() # In SSE mode, we SHOULD see startup logs combined_output = stdout + stderr assert "Starting MCP Outline server" in combined_output, ( "SSE mode should produce startup logs" ) assert "sse" in combined_output.lower(), ( "SSE mode should mention transport mode in logs" )

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/Vortiago/mcp-outline'

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