#!/usr/bin/env python3 """ e2e-mcp-stdio-test.py End-to-end test for MCP Gitea stdio transport. 1. Spawn stdio bridge via bun 2. Call initialize 3. Call tools/list 4. Call tools/call gitea_get_issue for issue #110 5. Validate response 6. Compare with REST API fallback """ import subprocess import json import sys import time STDIO_CMD = ["bun", "scripts/mcp-gitea-stdio.cjs"] GITEA_API = "https://git.softuniq.eu/api/v1/repos/UniqueSoft/APAW" USER, PASS = "NW", "eshkink0t" def main(): print("="*60) print("E2E MCP Stdio Test") print("="*60) proc = subprocess.Popen( STDIO_CMD, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, cwd="/home/swp/Projects/APAW", ) def send(msg): line = json.dumps(msg) + "\n" proc.stdin.write(line) proc.stdin.flush() print(f"→ {line.strip()}") def recv(): line = proc.stdout.readline() print(f"← {line.strip()}") return json.loads(line) # 1. Initialize print("\n[1] Initialize...") send({ "jsonrpc": "2.0", "method": "initialize", "params": { "protocolVersion": "2024-05-08", "capabilities": {}, "clientInfo": {"name": "e2e-test-client", "version": "1.0.0"} }, "id": 1 }) resp = recv() assert resp["result"]["serverInfo"]["name"] == "forgejo-mcp", "Unexpected server name" print("✅ Initialize OK") # 2. tools/list print("\n[2] List tools...") send({"jsonrpc": "2.0", "method": "tools/list", "params": {}, "id": 2}) resp = recv() tools = resp.get("result", {}).get("tools", []) assert len(tools) > 50, f"Expected >50 tools, got {len(tools)}" print(f"✅ Tools listed: {len(tools)}") # 3. tools/call get_issue print("\n[3] Call get_issue #110...") send({ "jsonrpc": "2.0", "method": "tools/call", "params": { "name": "get_issue", "arguments": { "owner": "UniqueSoft", "repo": "APAW", "index": 110 } }, "id": 3 }) resp = recv() print(f"DEBUG: Response received: {resp}") result_content = resp["result"]["content"] print(f"DEBUG: Result content: {result_content}") result_text = result_content[0]["text"] print(f"DEBUG: Result text: {result_text}") issue_data = json.loads(result_text) assert issue_data["number"] == 110, f"Expected issue 110, got {issue_data.get('number')}" print(f"✅ Issue fetched: #{issue_data['number']} - {issue_data.get('title', 'N/A')}") # 4. Verify checkpoint exists in issue body print("\n[4] Verify checkpoint in issue body...") assert "## GNS Checkpoint" in (issue_data.get("body") or ""), "Checkpoint not found in issue body" print("✅ Checkpoint found") # 5. Compare with REST API for consistency print("\n[5] REST API consistency check...") import urllib.request import base64 creds = base64.b64encode(f"{USER}:{PASS}".encode()).decode() req = urllib.request.Request( f"{GITEA_API}/issues/110", headers={"Accept": "application/json", "Authorization": f"Basic {creds}"} ) with urllib.request.urlopen(req) as r: rest_issue = json.loads(r.read()) assert rest_issue["number"] == issue_data["number"], "MCP and REST issue numbers differ" assert rest_issue["title"] == issue_data["title"], "MCP and REST issue titles differ" print("✅ REST API consistent") # 6. Close gracefully print("\n[6] Terminate stdio bridge...") proc.stdin.close() proc.wait(timeout=5) print("✅ Stdio bridge closed") print("\n" + "="*60) print("✅ ALL E2E MCP STDIO TESTS PASSED") print("="*60) return 0 if __name__ == "__main__": try: sys.exit(main()) except Exception as e: print(f"\n❌ FAILED: {e}") import traceback traceback.print_exc() sys.exit(1)