| 93 | |
| 94 | |
| 95 | async def _exercise_app(mcp_port: int) -> None: |
| 96 | app_module = _load_app_module(mcp_port) |
| 97 | app = app_module.app |
| 98 | expected_server_url = f"http://{HOST}:{mcp_port}/mcp" |
| 99 | |
| 100 | async with app.router.lifespan_context(app): |
| 101 | transport = httpx.ASGITransport(app=app) |
| 102 | async with httpx.AsyncClient(transport=transport, base_url="http://test") as client: |
| 103 | health_response = await client.get("/health") |
| 104 | health_response.raise_for_status() |
| 105 | health = health_response.json() |
| 106 | _require( |
| 107 | any(expected_server_url in name for name in health["connected_servers"]), |
| 108 | f"Expected connected MCP server in health response: {health}", |
| 109 | ) |
| 110 | _require( |
| 111 | health["failed_servers"] == [], |
| 112 | f"Expected no failed MCP servers in health response: {health}", |
| 113 | ) |
| 114 | |
| 115 | tools_response = await client.get("/tools") |
| 116 | tools_response.raise_for_status() |
| 117 | tools = tools_response.json()["tools"] |
| 118 | _require({"add", "echo"} <= set(tools), f"Expected add and echo tools: {tools}") |
| 119 | |
| 120 | add_response = await client.post("/add", json={"a": 2, "b": 3}) |
| 121 | add_response.raise_for_status() |
| 122 | add_result = add_response.json()["result"] |
| 123 | texts = [ |
| 124 | item.get("text") |
| 125 | for item in add_result.get("content", []) |
| 126 | if item.get("type") == "text" |
| 127 | ] |
| 128 | _require("5" in texts, f"Expected add tool result to include 5: {add_result}") |
| 129 | |
| 130 | |
| 131 | async def main() -> None: |