47d0d2accd
Document MIT dev-tool setup for Cursor code intelligence and add an offline probe for CLI, Cursor MCP config, and Memind index readiness. Co-authored-by: Cursor <cursoragent@cursor.com>
121 lines
4.3 KiB
JavaScript
121 lines
4.3 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Local codebase-memory-mcp smoke (dev machine only).
|
|
*
|
|
* Verifies the global CLI is installed and, when MEMIND_CBM_REQUIRE_INDEX=1
|
|
* (default), that this repository is indexed.
|
|
*/
|
|
import { spawnSync } from 'node:child_process';
|
|
import { existsSync, readFileSync } from 'node:fs';
|
|
import { homedir } from 'node:os';
|
|
import { basename, resolve } from 'node:path';
|
|
|
|
const repoRoot = resolve(process.cwd());
|
|
const requireIndex = process.env.MEMIND_CBM_REQUIRE_INDEX !== '0';
|
|
const cliName = process.env.MEMIND_CBM_CLI ?? 'codebase-memory-mcp';
|
|
|
|
function runCli(tool, args = {}) {
|
|
const payload = JSON.stringify(args);
|
|
const result = spawnSync(cliName, ['cli', '--json', tool, payload], {
|
|
encoding: 'utf8',
|
|
maxBuffer: 16 * 1024 * 1024,
|
|
});
|
|
const stdout = (result.stdout ?? '').trim();
|
|
const stderr = (result.stderr ?? '').trim();
|
|
if (result.error) {
|
|
return { ok: false, error: result.error.message, stdout, stderr };
|
|
}
|
|
if (result.status !== 0) {
|
|
return {
|
|
ok: false,
|
|
error: stderr.split('\n').pop() || `exit ${result.status}`,
|
|
stdout,
|
|
stderr,
|
|
};
|
|
}
|
|
try {
|
|
const parsed = JSON.parse(stdout);
|
|
const structured = parsed.structuredContent ?? parsed;
|
|
if (structured?.error || parsed.isError) {
|
|
return { ok: false, error: structured.error ?? parsed.isError, data: structured, stdout, stderr };
|
|
}
|
|
return { ok: true, data: structured, stdout, stderr };
|
|
} catch {
|
|
return { ok: false, error: 'invalid JSON from cli', stdout, stderr };
|
|
}
|
|
}
|
|
|
|
const versionResult = spawnSync(cliName, ['--version'], { encoding: 'utf8' });
|
|
const version = (versionResult.stdout ?? versionResult.stderr ?? '').trim();
|
|
if (versionResult.status !== 0 || !version) {
|
|
console.error('CODEBASE_MEMORY_MCP_FAIL: CLI not found');
|
|
console.error(' install: npm install -g codebase-memory-mcp && codebase-memory-mcp install -y');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log('CODEBASE_MEMORY_MCP_PROBE:');
|
|
console.log(` version=${version}`);
|
|
console.log(` repo=${repoRoot}`);
|
|
|
|
const cursorMcpPath = resolve(homedir(), '.cursor/mcp.json');
|
|
if (existsSync(cursorMcpPath)) {
|
|
try {
|
|
const cursorConfig = JSON.parse(readFileSync(cursorMcpPath, 'utf8'));
|
|
const servers = cursorConfig.mcpServers ?? cursorConfig;
|
|
const configured = Boolean(servers?.['codebase-memory-mcp']);
|
|
console.log(` cursor_mcp_configured=${configured}`);
|
|
if (!configured) {
|
|
console.warn('CODEBASE_MEMORY_MCP_WARN: ~/.cursor/mcp.json missing codebase-memory-mcp (run: codebase-memory-mcp install -y)');
|
|
}
|
|
} catch {
|
|
console.warn('CODEBASE_MEMORY_MCP_WARN: could not parse ~/.cursor/mcp.json');
|
|
}
|
|
} else {
|
|
console.warn('CODEBASE_MEMORY_MCP_WARN: ~/.cursor/mcp.json not found');
|
|
}
|
|
|
|
const projects = runCli('list_projects', {});
|
|
if (!projects.ok) {
|
|
console.error(`CODEBASE_MEMORY_MCP_FAIL: list_projects — ${projects.error}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const projectNames = (projects.data.projects ?? []).map((p) => p.name ?? p.project ?? p);
|
|
console.log(` indexed_projects=${projectNames.length}`);
|
|
|
|
const repoName = basename(repoRoot);
|
|
const matched = projectNames.find((name) => {
|
|
const normalized = String(name).toLowerCase();
|
|
return normalized === repoName.toLowerCase() || normalized.includes('memind');
|
|
});
|
|
|
|
if (!matched) {
|
|
const hint = 'codebase-memory-mcp cli --progress index_repository \'{"repo_path":"' + repoRoot + '"}\'';
|
|
if (requireIndex) {
|
|
console.error('CODEBASE_MEMORY_MCP_FAIL: Memind not indexed yet');
|
|
console.error(` run: ${hint}`);
|
|
console.error(' or in Cursor after restart: "Index this project"');
|
|
process.exit(1);
|
|
}
|
|
console.warn('CODEBASE_MEMORY_MCP_WARN: Memind not indexed (MEMIND_CBM_REQUIRE_INDEX=0)');
|
|
console.log('CODEBASE_MEMORY_MCP_CLI_OK');
|
|
process.exit(0);
|
|
}
|
|
|
|
const status = runCli('index_status', { project: matched });
|
|
if (!status.ok) {
|
|
console.error(`CODEBASE_MEMORY_MCP_FAIL: index_status — ${status.error}`);
|
|
process.exit(1);
|
|
}
|
|
|
|
const summary = {
|
|
project: status.data.project ?? matched,
|
|
status: status.data.status ?? null,
|
|
nodes: status.data.nodes ?? null,
|
|
edges: status.data.edges ?? null,
|
|
parse_partial_count: status.data.parse_partial?.count ?? status.data.parse_partial?.files?.length ?? 0,
|
|
};
|
|
console.log(` project=${summary.project}`);
|
|
console.log(` index=${JSON.stringify(summary)}`);
|
|
console.log('CODEBASE_MEMORY_MCP_OK');
|