// `archilyzer mcp` starts the real MCP server, and stdout stays JSON-RPC. // // Run with: // pnpm --filter yt-dlp-transcript-common test // // Spawns the CLI the way `claude mcp add … -- ` would, sends the 2025 // initialize request, and reads the answer. The arguments after `mcp` reach the // server untouched (the `--local` dir comes back in its stderr banner), and the // FIRST line on stdout is the server's JSON-RPC answer: anything the CLI printed // before it would break every MCP client. import { test, after } from "node:test"; import assert from "node:assert/strict"; import { spawn } from "node:child_process"; import { mkdtempSync, rmSync } from "node:fs"; import os from "node:os"; import path from "node:path"; import { fileURLToPath } from "node:url"; const HERE = path.dirname(fileURLToPath(import.meta.url)); const TSX = path.join(HERE, "..", "node_modules", ".bin", "tsx"); const DIR = mkdtempSync(path.join(os.tmpdir(), "archilyzer-mcp-")); after(() => rmSync(DIR, { recursive: true, force: true })); test("archilyzer mcp answers initialize on stdout, with its argv passed through", { timeout: 60_000 }, async () => { const child = spawn(TSX, [path.join(HERE, "archilyzer.ts"), "mcp", "--local", DIR], { stdio: ["pipe", "pipe", "pipe"], }); // Listened for from the start: a CLI that refuses at once exits before any // later listener could see it. const exited = new Promise((r) => child.on("exit", (c) => r(c))); let stdout = ""; let stderr = ""; child.stdout.on("data", (b) => (stdout += b)); child.stderr.on("data", (b) => (stderr += b)); child.stdin.write( `${JSON.stringify({ jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "test", version: "0" } }, })}\n`, ); const deadline = Date.now() + 30_000; let ended = false; void exited.then(() => (ended = true)); while (!stdout.includes("\n") && !ended && Date.now() < deadline) { await new Promise((r) => setTimeout(r, 50)); } child.stdin.end(); const code = await exited; const first = stdout.split("\n")[0]; const msg = JSON.parse(first) as { id: number; result?: { serverInfo?: { name?: string } } }; assert.equal(msg.id, 1); assert.equal(msg.result?.serverInfo?.name, "yt-dlp-transcript-mcp"); assert.match(stderr, new RegExp(`default corpus: local:${DIR.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`)); // stdin closed: the server ends, and the CLI ends with it. assert.equal(code, 0); });