Bound shared MCP container lifecycle

This commit is contained in:
2026-07-24 13:03:09 -07:00
parent 8de9658b8c
commit 6177a995d5
17 changed files with 1351 additions and 117 deletions

View File

@@ -0,0 +1,53 @@
import { fileURLToPath } from "node:url";
const protocolVersion = "2024-11-05";
const expectedTools = ["fetch_url", "search_web"];
async function rpc(url, id, method, params = {}, timeoutMs = 5000) {
const response = await fetch(url, {
method: "POST",
headers: {
Accept: "application/json, text/event-stream",
"Content-Type": "application/json",
"MCP-Protocol-Version": protocolVersion
},
body: JSON.stringify({ jsonrpc: "2.0", id, method, params }),
signal: AbortSignal.timeout(timeoutMs)
});
const text = await response.text();
if (!response.ok) throw new Error(`${method} returned HTTP ${response.status}: ${text.slice(0, 300)}`);
let payload;
if (response.headers.get("content-type")?.includes("text/event-stream")) {
const data = text.split("\n").find(line => line.startsWith("data: "))?.slice(6);
if (!data) throw new Error(`${method} returned an empty event stream`);
payload = JSON.parse(data);
} else {
payload = JSON.parse(text);
}
if (payload.error) throw new Error(`${method} returned ${JSON.stringify(payload.error)}`);
return payload.result;
}
export async function probeMcp(url, { timeoutMs = 5000 } = {}) {
const initialized = await rpc(url, 1, "initialize", {
protocolVersion,
capabilities: {},
clientInfo: { name: "context-kit-health", version: "1" }
}, timeoutMs);
if (!initialized?.serverInfo?.name) throw new Error("initialize response omitted serverInfo");
const listed = await rpc(url, 2, "tools/list", {}, timeoutMs);
const names = new Set((listed?.tools || []).map(tool => tool.name));
for (const name of expectedTools) {
if (!names.has(name)) throw new Error(`tools/list omitted ${name}`);
}
return Array.from(names).sort();
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
const url = process.argv[2];
if (!url) throw new Error("usage: node mcp-probe.mjs <streamable-http-url>");
const tools = await probeMcp(url);
console.log(JSON.stringify({ tools }));
}