99 lines
2.7 KiB
JavaScript
99 lines
2.7 KiB
JavaScript
|
|
#!/usr/bin/env node
|
||
|
|
/**
|
||
|
|
* End-to-end smoke test for server/pb-mcp.mjs.
|
||
|
|
*
|
||
|
|
* Spawns the MCP server over stdio, sends an `initialize` + `tools/list`
|
||
|
|
* handshake, then calls `list_customers` to confirm the live PB connection
|
||
|
|
* is working. Prints whatever the server returns.
|
||
|
|
*
|
||
|
|
* node scripts/test-pb-mcp.mjs
|
||
|
|
*/
|
||
|
|
|
||
|
|
import { spawn } from "node:child_process";
|
||
|
|
import { fileURLToPath } from "node:url";
|
||
|
|
import path from "node:path";
|
||
|
|
|
||
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||
|
|
const ROOT = path.resolve(__dirname, "..");
|
||
|
|
|
||
|
|
const child = spawn("node", ["--import", "tsx/esm", "server/pb-mcp.mjs"], {
|
||
|
|
cwd: ROOT,
|
||
|
|
stdio: ["pipe", "pipe", "inherit"],
|
||
|
|
});
|
||
|
|
|
||
|
|
let buffer = "";
|
||
|
|
const pending = new Map();
|
||
|
|
let nextId = 1;
|
||
|
|
|
||
|
|
function send(method, params = {}) {
|
||
|
|
return new Promise((resolve, reject) => {
|
||
|
|
const id = nextId++;
|
||
|
|
pending.set(id, { resolve, reject });
|
||
|
|
const msg = JSON.stringify({ jsonrpc: "2.0", id, method, params });
|
||
|
|
child.stdin.write(msg + "\n");
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
child.stdout.on("data", (chunk) => {
|
||
|
|
buffer += chunk.toString("utf8");
|
||
|
|
let nl;
|
||
|
|
while ((nl = buffer.indexOf("\n")) !== -1) {
|
||
|
|
const line = buffer.slice(0, nl).trim();
|
||
|
|
buffer = buffer.slice(nl + 1);
|
||
|
|
if (!line) continue;
|
||
|
|
let parsed;
|
||
|
|
try {
|
||
|
|
parsed = JSON.parse(line);
|
||
|
|
} catch (err) {
|
||
|
|
console.error("[test] non-JSON line:", line);
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
if (parsed.id != null && pending.has(parsed.id)) {
|
||
|
|
const { resolve, reject } = pending.get(parsed.id);
|
||
|
|
pending.delete(parsed.id);
|
||
|
|
if (parsed.error) reject(new Error(JSON.stringify(parsed.error)));
|
||
|
|
else resolve(parsed.result);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
const shutdown = () => {
|
||
|
|
child.kill();
|
||
|
|
process.exit(0);
|
||
|
|
};
|
||
|
|
process.on("SIGINT", shutdown);
|
||
|
|
process.on("SIGTERM", shutdown);
|
||
|
|
|
||
|
|
try {
|
||
|
|
console.log("[test] initialize");
|
||
|
|
const init = await send("initialize", {
|
||
|
|
protocolVersion: "2024-11-05",
|
||
|
|
capabilities: {},
|
||
|
|
clientInfo: { name: "test-pb-mcp", version: "0.0.0" },
|
||
|
|
});
|
||
|
|
console.log("[test] server:", init.serverInfo);
|
||
|
|
|
||
|
|
const tools = await send("tools/list");
|
||
|
|
console.log(`[test] tools advertised: ${tools.tools.length}`);
|
||
|
|
for (const t of tools.tools) console.log(` - ${t.name}`);
|
||
|
|
|
||
|
|
console.log("\n[test] list_customers q=JER");
|
||
|
|
const customers = await send("tools/call", {
|
||
|
|
name: "list_customers",
|
||
|
|
arguments: { q: "JER" },
|
||
|
|
});
|
||
|
|
console.log(JSON.stringify(customers, null, 2));
|
||
|
|
|
||
|
|
console.log("\n[test] list_customer_pos perPage=3");
|
||
|
|
const cpos = await send("tools/call", {
|
||
|
|
name: "list_customer_pos",
|
||
|
|
arguments: { perPage: 3 },
|
||
|
|
});
|
||
|
|
console.log(JSON.stringify(cpos, null, 2));
|
||
|
|
} catch (err) {
|
||
|
|
console.error("[test] FAILED:", err?.message || err);
|
||
|
|
process.exitCode = 1;
|
||
|
|
} finally {
|
||
|
|
child.kill();
|
||
|
|
}
|