Files
yvgude--lean-ctx/rust/tests/fixtures/mcp_stdio_addon.mjs
T
wehub-resource-sync 26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:35:30 +08:00

91 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env node
// MCP stdio fixture for the deeper-addon-integration E2E (#1102).
//
// A *real* MCP stdio server (newline-delimited JSON-RPC 2.0) whose tools return
// the output shapes the L1L4 pipeline consumes, so the gateway's production
// proxy → postprocess → adapters path is exercised end to end against a spawned
// child process (no protocol mocks). Tools:
// echo -> `echo:<text>` (drives L1/L2/L3 + secret redaction)
// pack_codebase -> repomix-shaped JSON {outputId, directoryStructure, …}
// query_graph -> code-graph JSON {edges:[{from,to,type}]}
// search_memories -> memory JSON {results:[{memory,id,score}]}
// compress_text -> `compressed:<text>` (drives the compression adapter)
// Only Node.js is required.
import { createInterface } from 'node:readline';
const rl = createInterface({ input: process.stdin });
const send = (msg) => process.stdout.write(JSON.stringify(msg) + '\n');
const textResult = (id, text) =>
send({ jsonrpc: '2.0', id, result: { content: [{ type: 'text', text }], isError: false } });
const TOOLS = [
{ name: 'echo', description: 'Echo back the provided text',
inputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] } },
{ name: 'pack_codebase', description: 'Pack a repository (repomix-shaped)',
inputSchema: { type: 'object', properties: { directory: { type: 'string' } } } },
{ name: 'query_graph', description: 'Return code-graph edges',
inputSchema: { type: 'object', properties: { q: { type: 'string' } } } },
{ name: 'search_memories', description: 'Search stored memories',
inputSchema: { type: 'object', properties: { query: { type: 'string' } } } },
{ name: 'compress_text', description: 'Compress text',
inputSchema: { type: 'object', properties: { text: { type: 'string' } }, required: ['text'] } },
];
function callTool(id, name, args) {
switch (name) {
case 'echo':
return textResult(id, 'echo:' + (args.text ?? ''));
case 'compress_text':
return textResult(id, 'compressed:' + (args.text ?? ''));
case 'pack_codebase':
return textResult(id, JSON.stringify({
outputId: 'rmx_e2e_001',
directoryStructure: 'src/\n auth.rs\n db.rs\n',
totalFiles: 2,
totalTokens: 4321,
}));
case 'query_graph':
return textResult(id, JSON.stringify({
edges: [
{ from: 'src/auth.rs', to: 'src/db.rs', type: 'calls' },
{ from: 'src/api.rs', to: 'src/auth.rs', type: 'imports' },
],
}));
case 'search_memories':
return textResult(id, JSON.stringify({
results: [
{ memory: 'the user prefers structured logging', id: 'mem-e2e-1', score: 0.88 },
],
}));
default:
return send({ jsonrpc: '2.0', id, error: { code: -32602, message: 'unknown tool: ' + name } });
}
}
rl.on('line', (line) => {
const trimmed = line.trim();
if (!trimmed) return;
let req;
try { req = JSON.parse(trimmed); } catch { return; }
const { id, method, params } = req;
if (method === 'initialize') {
send({ jsonrpc: '2.0', id, result: {
protocolVersion: (params && params.protocolVersion) || '2025-06-18',
capabilities: { tools: {} },
serverInfo: { name: 'mcp-stdio-addon', version: '0.1.0' },
} });
} else if (method === 'notifications/initialized') {
// no response
} else if (method === 'tools/list') {
send({ jsonrpc: '2.0', id, result: { tools: TOOLS } });
} else if (method === 'tools/call') {
callTool(id, params && params.name, (params && params.arguments) || {});
} else if (id !== undefined && id !== null) {
send({ jsonrpc: '2.0', id, error: { code: -32601, message: 'method not found: ' + method } });
}
});
rl.on('close', () => process.exit(0));