#!/usr/bin/env python """Verify the ck3 MCP server end-to-end over real stdio JSON-RPC. DONE = the server starts, completes the MCP handshake, advertises the three tools, and returns sensible results for wiki_search and wiki_get_page. Exits non-zero on any failure. Uses the same interface Claude Code will use, so this confirms the server works without needing a session reload. """ from __future__ import annotations import sys import anyio from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client def _text(result: object) -> str: """Flatten a CallToolResult into a searchable string.""" parts: list[str] = [] structured = getattr(result, "structuredContent", None) if structured is not None: parts.append(str(structured)) for block in getattr(result, "content", []) or []: if hasattr(block, "text"): parts.append(block.text) return " ".join(parts) async def run() -> int: params = StdioServerParameters(command=sys.executable, args=["-m", "wikikb.server"]) ok = True async with stdio_client(params) as (read, write), ClientSession(read, write) as session: await session.initialize() tools = {t.name for t in (await session.list_tools()).tools} want = {"wiki_search", "wiki_get_page", "wiki_list_pages"} t_ok = want <= tools ok &= t_ok print(f"[{'PASS' if t_ok else 'FAIL'}] tools/list -> {sorted(tools)}") search_text = _text(await session.call_tool("wiki_search", {"query": "domain limit rank"})) s_ok = ( any(k in search_text for k in ("Titles", "Attributes")) and "domain" in search_text.lower() ) ok &= s_ok print(f"[{'PASS' if s_ok else 'FAIL'}] wiki_search -> {search_text[:80]!r}...") page_text = _text(await session.call_tool("wiki_get_page", {"title": "Traits"})) g_ok = "Genius" in page_text and "Herculean" in page_text ok &= g_ok print( f"[{'PASS' if g_ok else 'FAIL'}] wiki_get_page('Traits') has Genius+Herculean -> {g_ok}" ) list_text = _text(await session.call_tool("wiki_list_pages", {"prefix": "Tr"})) l_ok = "Traits" in list_text ok &= l_ok print(f"[{'PASS' if l_ok else 'FAIL'}] wiki_list_pages('Tr') includes Traits -> {l_ok}") print(f"\nMCP VERIFICATION: {'PASS' if ok else 'FAIL'}") return 0 if ok else 1 if __name__ == "__main__": sys.exit(anyio.run(run))