import { afterAll, beforeAll, test } from "bun:test"; import assert from "node:assert/strict"; import { mkdtempSync, rmSync } from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; import { createSqliteDb, openDatabase } from "../../src/runtime/bun/sqlite"; import { runMcpStdio } from "../../src/runtime/bun/mcp-stdio"; import { serve } from "../../src/runtime/bun/server"; import { provisionWith } from "../contract/harness"; const directory = mkdtempSync(join(tmpdir(), "titen-mcp-stdio-")); const cli = join(import.meta.dir, "../../src/runtime/bun/cli.ts"); let running: Awaited>; let key: string; beforeAll(async () => { const dbPath = join(directory, "titen.db"); running = await serve({ dbPath, port: 0, hostname: "127.0.0.1", quiet: true }); const database = openDatabase(dbPath); key = (await provisionWith(createSqliteDb(database), { scopes: ["*"] })).key; database.close(); }); afterAll(async () => { await running.stop(); rmSync(directory, { recursive: true, force: true }); }); const initialize = { jsonrpc: "2.0", id: 1, method: "initialize", params: { protocolVersion: "2025-06-18", capabilities: {}, clientInfo: { name: "stdio-test", version: "1" } }, }; const initialized = { jsonrpc: "2.0", method: "notifications/initialized" }; const tools = { jsonrpc: "2.0", id: 2, method: "tools/list" }; async function http(message: unknown): Promise { const response = await fetch(`${running.url}/mcp`, { method: "POST", headers: { accept: "application/json, text/event-stream", authorization: `Bearer ${key}`, "content-type": "application/json", }, body: JSON.stringify(message), }); return response.text(); } test("the installed CLI bridges requests, drops notification replies, and exits on EOF", async () => { const process = Bun.spawn(["bun", cli, "mcp"], { env: { ...globalThis.process.env, TITEN_MCP_URL: `${running.url}/mcp`, TITEN_API_KEY: key }, stdin: "pipe", stdout: "pipe", stderr: "pipe", }); process.stdin.write(`${JSON.stringify(initialize)}\n${JSON.stringify(initialized)}\n${JSON.stringify(tools)}`); process.stdin.end(); const [exitCode, stdout, stderr] = await Promise.all([ Promise.race([process.exited, Bun.sleep(1_000).then(() => -1)]), new Response(process.stdout).text(), new Response(process.stderr).text(), ]); assert.equal(exitCode, 0, stderr); assert.equal(stderr, ""); assert.deepEqual(stdout.trim().split("\n"), [await http(initialize), await http(tools)]); assert.doesNotMatch(`${stdout}${stderr}`, new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))); }); test("parse and network failures are sanitized without ending the bridge", async () => { async function* input() { yield new TextEncoder().encode([ JSON.stringify({ jsonrpc: "2.0", id: 7, method: "ping" }), JSON.stringify(initialized), "{", JSON.stringify({ jsonrpc: "2.0", id: 8, method: "tools/list" }), ].join("\n")); } const output: string[] = []; const logged: string[] = []; const secret = "never-print-this-key"; const realError = console.error; console.error = (line: string) => void logged.push(line); try { await runMcpStdio({ endpoint: "http://127.0.0.1:9/mcp", apiKey: secret, input: input(), write: (line) => output.push(line), }); } finally { console.error = realError; } assert.deepEqual(output.map((line) => JSON.parse(line)), [ { jsonrpc: "2.0", id: 7, error: { code: -32000, message: "Titen MCP request failed." } }, { jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error." } }, { jsonrpc: "2.0", id: 8, error: { code: -32000, message: "Titen MCP request failed." } }, ]); // -32000 says only that something failed. A revoked key and a dead port were // the same sentence until the reason went somewhere readable. Three lines for // two replies: the notification fails too, and used to vanish entirely. assert.equal(logged.length, 3, logged.join("\n")); for (const line of logged) assert.match(line, /^titen: http:\/\/127\.0\.0\.1:9\/mcp failed: ./); assert.doesNotMatch(`${output.join("")}${logged.join("")}`, new RegExp(secret)); }); test("the API key reaches only the authorization header and is redacted upstream", async () => { async function* input() { yield new TextEncoder().encode(JSON.stringify({ jsonrpc: "2.0", id: 9, method: "ping" })); } const output: string[] = []; const secret = "header-only-key"; await runMcpStdio({ endpoint: "https://titen.example/mcp", apiKey: secret, input: input(), fetcher: async (_input, init) => { assert.equal(new Headers(init?.headers).get("authorization"), `Bearer ${secret}`); return new Response(JSON.stringify({ jsonrpc: "2.0", id: 9, result: { echo: secret } })); }, write: (line) => output.push(line), }); assert.deepEqual(JSON.parse(output[0]!), { jsonrpc: "2.0", id: 9, result: { echo: "[redacted]" }, }); assert.doesNotMatch(output.join(""), new RegExp(secret)); }); async function bridge(lines: unknown[], fetcher?: (input: string | URL, init?: RequestInit) => Promise) { async function* input() { yield new TextEncoder().encode(lines.map((line) => JSON.stringify(line)).join("\n")); } const output: string[] = []; await runMcpStdio({ endpoint: `${running.url}/mcp`, apiKey: key, input: input(), fetcher, write: (line) => output.push(line) }); return output; } test("a batch on stdin gets the same one-line array that POST /mcp returns", async () => { const ping = { jsonrpc: "2.0", id: 1, method: "ping" }; const batch = [ping, initialized, tools]; const direct = JSON.parse(await http(batch)); const output = await bridge([batch]); assert.equal(output.length, 1); const bridged = JSON.parse(output[0]!); assert.ok(Array.isArray(bridged)); assert.deepEqual(bridged.map((reply: { id: unknown }) => reply.id), [1, 2]); assert.deepEqual(bridged, direct); }); test("a notification-only batch writes nothing", async () => { assert.deepEqual(await bridge([[initialized, { jsonrpc: "2.0", method: "notifications/cancelled", params: {} }]]), []); }); test("an initialize inside a batch sets the protocol header for later requests", async () => { const versions: Array = []; const output = await bridge([[initialize, { jsonrpc: "2.0", id: 3, method: "ping" }], tools], async (input, init) => { versions.push(new Headers(init?.headers).get("mcp-protocol-version")); return fetch(input, init); }); assert.equal(output.length, 2); assert.deepEqual(versions, [null, "2025-06-18"]); }); test("a failed batch writes one error per request id", async () => { async function* input() { yield new TextEncoder().encode(JSON.stringify([ { jsonrpc: "2.0", id: 4, method: "ping" }, initialized, { jsonrpc: "2.0", id: "five", method: "tools/list" }, ])); } const output: string[] = []; const realError = console.error; console.error = () => {}; try { await runMcpStdio({ endpoint: "http://127.0.0.1:9/mcp", apiKey: "batch-key", input: input(), write: (line) => output.push(line) }); } finally { console.error = realError; } assert.deepEqual(output.map((line) => JSON.parse(line)), [ { jsonrpc: "2.0", id: 4, error: { code: -32000, message: "Titen MCP request failed." } }, { jsonrpc: "2.0", id: "five", error: { code: -32000, message: "Titen MCP request failed." } }, ]); }); test("unsafe endpoints fail before fetch", async () => { async function* empty() {} for (const endpoint of [ "file:///tmp/mcp", "http://user:pass@localhost/mcp", "http://localhost/mcp?token=secret", "http://localhost/mcp#secret", "http://localhost/not-mcp", ]) { let fetched = false; await assert.rejects(runMcpStdio({ endpoint, apiKey: "safe-key", input: empty(), fetcher: async () => { fetched = true; return new Response(); }, }), /credential-free HTTP \/mcp endpoint/); assert.equal(fetched, false); } });