Copies source (no node_modules, dist, .tasks, .wiki, __pycache__) for: - projects-meta-mcp v2.25.0 (TypeScript/Node) - wiki-graph v0.3.1 (TypeScript/Node) - interns-mcp v0.3.3 (Python/FastMCP) .gitignore: exclude lib build artefacts (node_modules, dist, .venv, __pycache__, *.pyc) bootstrap.ps1: add MCP build step — npm install+build for TS servers, venv+pip for Python Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
83 lines
2.7 KiB
JavaScript
83 lines
2.7 KiB
JavaScript
// Smoke test: drive the built MCP server over stdio against a live .wiki corpus.
|
|
// Usage: node scripts/smoke.mjs <corpusDir> [from] [to] [hubNode]
|
|
import { spawn } from 'node:child_process';
|
|
import { dirname, join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const here = dirname(fileURLToPath(import.meta.url));
|
|
const serverPath = join(here, '..', 'dist', 'server.js');
|
|
|
|
const corpus = process.argv[2];
|
|
const from = process.argv[3] ?? 'alm-pamelas-pro-workout';
|
|
const to = process.argv[4] ?? 'euclidean-rhythms';
|
|
const hub = process.argv[5] ?? 'euclidean-rhythms';
|
|
if (!corpus) {
|
|
console.error('usage: node scripts/smoke.mjs <corpusDir> [from] [to] [hubNode]');
|
|
process.exit(2);
|
|
}
|
|
|
|
const child = spawn('node', [serverPath], { stdio: ['pipe', 'pipe', 'inherit'] });
|
|
let buf = '';
|
|
const pending = new Map();
|
|
child.stdout.on('data', (d) => {
|
|
buf += d.toString();
|
|
let nl;
|
|
while ((nl = buf.indexOf('\n')) >= 0) {
|
|
const line = buf.slice(0, nl).trim();
|
|
buf = buf.slice(nl + 1);
|
|
if (!line) continue;
|
|
const msg = JSON.parse(line);
|
|
if (msg.id && pending.has(msg.id)) {
|
|
pending.get(msg.id)(msg);
|
|
pending.delete(msg.id);
|
|
}
|
|
}
|
|
});
|
|
|
|
let nextId = 1;
|
|
function rpc(method, params) {
|
|
const id = nextId++;
|
|
return new Promise((resolve) => {
|
|
pending.set(id, resolve);
|
|
child.stdin.write(JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\n');
|
|
});
|
|
}
|
|
function notify(method, params) {
|
|
child.stdin.write(JSON.stringify({ jsonrpc: '2.0', method, params }) + '\n');
|
|
}
|
|
async function call(name, args) {
|
|
const t0 = performance.now();
|
|
const res = await rpc('tools/call', { name, arguments: { corpus, ...args } });
|
|
const ms = (performance.now() - t0).toFixed(1);
|
|
return { text: res.result.content.map((c) => c.text).join('\n'), ms };
|
|
}
|
|
|
|
const init = await rpc('initialize', {
|
|
protocolVersion: '2024-11-05',
|
|
capabilities: {},
|
|
clientInfo: { name: 'wg-smoke', version: '0' },
|
|
});
|
|
notify('notifications/initialized', {});
|
|
console.log(`server: ${init.result.serverInfo.name} ${init.result.serverInfo.version}`);
|
|
console.log(`corpus: ${corpus}\n`);
|
|
|
|
const cold = await call('stats', {});
|
|
console.log(`stats [cold ${cold.ms}ms] ${cold.text}`);
|
|
const warm = await call('stats', {});
|
|
console.log(`stats [warm ${warm.ms}ms] ${warm.text}`);
|
|
|
|
const p = await call('path', { from, to });
|
|
console.log(`path [${p.ms}ms] ${from} → ${to}\n ${p.text}`);
|
|
|
|
const n = await call('neighbors', { node: hub, depth: 1 });
|
|
console.log(`neighbrs[${n.ms}ms] ${n.text}`);
|
|
|
|
const b = await call('backlinks', { node: hub });
|
|
console.log(`backlnks[${b.ms}ms] ${b.text}`);
|
|
|
|
const o = await call('orphans', {});
|
|
console.log(`orphans [${o.ms}ms] ${o.text.split('\n')[0]} ...`);
|
|
|
|
child.stdin.end();
|
|
child.kill();
|