186 lines
4.5 KiB
JavaScript
186 lines
4.5 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Memvid MCP Search Helper
|
|
*
|
|
* Usage: node memvid-search.js <memory_file_path> <query> [top_k] [snippet_chars]
|
|
*
|
|
* This script calls the Memvid MCP server to perform semantic search.
|
|
*/
|
|
|
|
const { spawn } = require('child_process');
|
|
const path = require('path');
|
|
const fs = require('fs');
|
|
|
|
// Parse arguments
|
|
const args = process.argv.slice(2);
|
|
if (args.length < 2) {
|
|
console.error('Usage: node memvid-search.js <memory_file_path> <query> [top_k] [snippet_chars]');
|
|
process.exit(1);
|
|
}
|
|
|
|
const memoryFilePath = args[0];
|
|
const query = args[1];
|
|
const topK = parseInt(args[2]) || 3;
|
|
const snippetChars = parseInt(args[3]) || 500;
|
|
|
|
// Validate memory file exists
|
|
if (!fs.existsSync(memoryFilePath)) {
|
|
console.error(JSON.stringify({ error: `Memory file not found: ${memoryFilePath}` }));
|
|
process.exit(1);
|
|
}
|
|
|
|
// MCP configuration (from .claude/mcp.json)
|
|
const mcpCommand = 'uv';
|
|
const mcpArgs = [
|
|
'run',
|
|
'--directory',
|
|
'D:\\works\\projects-windows\\memvid-agent-mcp',
|
|
'memvid_mcp_server.py'
|
|
];
|
|
|
|
const mcpEnv = {
|
|
...process.env,
|
|
PYTHONUNBUFFERED: '1',
|
|
MEMVID_LOG_LEVEL: 'ERROR' // Reduce noise
|
|
};
|
|
|
|
// JSON-RPC communication
|
|
let messageId = 1;
|
|
|
|
function createRequest(method, params = {}) {
|
|
return {
|
|
jsonrpc: '2.0',
|
|
id: messageId++,
|
|
method,
|
|
params
|
|
};
|
|
}
|
|
|
|
function sendRequest(proc, request) {
|
|
const message = JSON.stringify(request) + '\n';
|
|
proc.stdin.write(message);
|
|
}
|
|
|
|
// Main execution
|
|
async function main() {
|
|
return new Promise((resolve, reject) => {
|
|
const proc = spawn(mcpCommand, mcpArgs, {
|
|
env: mcpEnv,
|
|
stdio: ['pipe', 'pipe', 'pipe']
|
|
});
|
|
|
|
let outputBuffer = '';
|
|
let errorBuffer = '';
|
|
let initialized = false;
|
|
let searchRequestSent = false;
|
|
let timeoutId = null;
|
|
|
|
function cleanup() {
|
|
if (timeoutId) clearTimeout(timeoutId);
|
|
proc.kill();
|
|
}
|
|
|
|
proc.stdout.on('data', (data) => {
|
|
outputBuffer += data.toString();
|
|
|
|
// Process complete JSON-RPC messages
|
|
const lines = outputBuffer.split('\n');
|
|
outputBuffer = lines.pop() || ''; // Keep incomplete line
|
|
|
|
for (const line of lines) {
|
|
if (!line.trim()) continue;
|
|
|
|
try {
|
|
const response = JSON.parse(line);
|
|
|
|
// Handle initialization
|
|
if (!initialized && response.id === 1) {
|
|
initialized = true;
|
|
|
|
// Send search request
|
|
const searchRequest = createRequest('tools/call', {
|
|
name: 'memvid_search',
|
|
arguments: {
|
|
file_path: memoryFilePath,
|
|
query: query,
|
|
top_k: topK,
|
|
snippet_chars: snippetChars
|
|
}
|
|
});
|
|
|
|
sendRequest(proc, searchRequest);
|
|
searchRequestSent = true;
|
|
}
|
|
// Handle search result
|
|
else if (searchRequestSent && response.result) {
|
|
console.log(JSON.stringify({
|
|
success: true,
|
|
result: response.result
|
|
}));
|
|
|
|
cleanup();
|
|
setTimeout(() => process.exit(0), 100);
|
|
resolve();
|
|
}
|
|
// Handle errors
|
|
else if (response.error) {
|
|
console.error(JSON.stringify({
|
|
error: response.error.message || 'MCP error'
|
|
}));
|
|
|
|
cleanup();
|
|
setTimeout(() => process.exit(1), 100);
|
|
reject(new Error(response.error.message));
|
|
}
|
|
} catch (e) {
|
|
// Ignore non-JSON lines (logs, etc.)
|
|
}
|
|
}
|
|
});
|
|
|
|
proc.stderr.on('data', (data) => {
|
|
errorBuffer += data.toString();
|
|
});
|
|
|
|
proc.on('error', (error) => {
|
|
console.error(JSON.stringify({ error: error.message }));
|
|
cleanup();
|
|
reject(error);
|
|
});
|
|
|
|
proc.on('exit', (code) => {
|
|
if (code !== 0 && code !== null) {
|
|
console.error(JSON.stringify({
|
|
error: `MCP server exited with code ${code}`,
|
|
stderr: errorBuffer
|
|
}));
|
|
reject(new Error(`Process exited with code ${code}`));
|
|
}
|
|
});
|
|
|
|
// Initialize MCP connection
|
|
const initRequest = createRequest('initialize', {
|
|
protocolVersion: '2024-11-05',
|
|
capabilities: {},
|
|
clientInfo: {
|
|
name: 'claudian-memvid-helper',
|
|
version: '1.0.0'
|
|
}
|
|
});
|
|
|
|
sendRequest(proc, initRequest);
|
|
|
|
// Timeout after 10 seconds
|
|
timeoutId = setTimeout(() => {
|
|
proc.kill();
|
|
console.error(JSON.stringify({ error: 'Search timeout' }));
|
|
reject(new Error('Timeout'));
|
|
}, 10000);
|
|
});
|
|
}
|
|
|
|
main().catch((error) => {
|
|
process.exit(1);
|
|
});
|