"""MCP smoke tests: the stdio transport from source, against a live Gitea.""" from __future__ import annotations from pathlib import Path from mcp import Client, StdioServerParameters from mcp.client.stdio import stdio_client from tests.integration.harness import GiteaInstance from tests.mcp.helpers import ( SOURCE_SERVE_ARGS, assert_jsonrpc_only, assert_no_secrets, exercise_server, server_env, ) def _stdio_params(gitea: GiteaInstance, data_dir: Path) -> StdioServerParameters: return StdioServerParameters( command=SOURCE_SERVE_ARGS[0], args=[*SOURCE_SERVE_ARGS[1:], "--transport", "stdio"], # The working directory is the empty temp dir so no ambient .env is read. env=server_env(gitea, gitea.base_url, data_dir), cwd=data_dir, ) async def test_stdio_lists_reads_and_writes(gitea: GiteaInstance, tmp_path: Path) -> None: """A real MCP client over stdio: initialize, list 538 tools, read, create and delete a repo.""" stderr_path = tmp_path / "server.stderr" with stderr_path.open("w", encoding="utf-8") as errlog: transport = stdio_client(_stdio_params(gitea, tmp_path), errlog=errlog) async with Client(transport, read_timeout_seconds=60.0) as client: assert client.server_info is not None assert client.server_info.name == "aegis-gitea-mcp" await exercise_server(client, gitea, [gitea.admin_token]) stderr = stderr_path.read_text(encoding="utf-8", errors="replace") assert_no_secrets(stderr, [gitea.admin_token], "the server stderr") async def test_stdio_stdout_is_json_rpc_only(gitea: GiteaInstance, tmp_path: Path) -> None: """Every stdout line of the stdio server is JSON-RPC; logs go to stderr without secrets.""" from tests.mcp.helpers import run_raw_stdio params = _stdio_params(gitea, tmp_path) session = await run_raw_stdio([params.command, *params.args], params.env or {}, tmp_path) assert_jsonrpc_only(session.stdout_lines) assert session.returncode == 0 assert_no_secrets("\n".join(session.stdout_lines), [gitea.admin_token], "the server stdout") assert_no_secrets(session.stderr, [gitea.admin_token], "the server stderr")