rho-graph 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +277 -0
- package/bin/rho-graph.js +2 -0
- package/dist/cli/commands/index-cmd.d.ts +2 -0
- package/dist/cli/commands/index-cmd.js +45 -0
- package/dist/cli/commands/index-cmd.js.map +1 -0
- package/dist/cli/commands/init.d.ts +3 -0
- package/dist/cli/commands/init.js +55 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install-hook.d.ts +3 -0
- package/dist/cli/commands/install-hook.js +37 -0
- package/dist/cli/commands/install-hook.js.map +1 -0
- package/dist/cli/commands/install-mcp.d.ts +3 -0
- package/dist/cli/commands/install-mcp.js +32 -0
- package/dist/cli/commands/install-mcp.js.map +1 -0
- package/dist/cli/commands/query.d.ts +2 -0
- package/dist/cli/commands/query.js +92 -0
- package/dist/cli/commands/query.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +2 -0
- package/dist/cli/commands/setup.js +15 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.js +40 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/visualize.d.ts +2 -0
- package/dist/cli/commands/visualize.js +45 -0
- package/dist/cli/commands/visualize.js.map +1 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +32 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +95 -0
- package/dist/config.js.map +1 -0
- package/dist/db/connection.d.ts +13 -0
- package/dist/db/connection.js +25 -0
- package/dist/db/connection.js.map +1 -0
- package/dist/db/queries.d.ts +106 -0
- package/dist/db/queries.js +247 -0
- package/dist/db/queries.js.map +1 -0
- package/dist/db/schema.d.ts +2 -0
- package/dist/db/schema.js +22 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/docker/neo4j.d.ts +5 -0
- package/dist/docker/neo4j.js +85 -0
- package/dist/docker/neo4j.js.map +1 -0
- package/dist/indexer/batch-writer.d.ts +35 -0
- package/dist/indexer/batch-writer.js +202 -0
- package/dist/indexer/batch-writer.js.map +1 -0
- package/dist/indexer/extractor.d.ts +35 -0
- package/dist/indexer/extractor.js +141 -0
- package/dist/indexer/extractor.js.map +1 -0
- package/dist/indexer/graph-writer.d.ts +12 -0
- package/dist/indexer/graph-writer.js +75 -0
- package/dist/indexer/graph-writer.js.map +1 -0
- package/dist/indexer/import-resolver.d.ts +8 -0
- package/dist/indexer/import-resolver.js +80 -0
- package/dist/indexer/import-resolver.js.map +1 -0
- package/dist/indexer/index.d.ts +21 -0
- package/dist/indexer/index.js +262 -0
- package/dist/indexer/index.js.map +1 -0
- package/dist/indexer/language-map.json +101 -0
- package/dist/indexer/parallel-pipeline.d.ts +41 -0
- package/dist/indexer/parallel-pipeline.js +82 -0
- package/dist/indexer/parallel-pipeline.js.map +1 -0
- package/dist/indexer/parser.d.ts +9 -0
- package/dist/indexer/parser.js +85 -0
- package/dist/indexer/parser.js.map +1 -0
- package/dist/indexer/staleness.d.ts +12 -0
- package/dist/indexer/staleness.js +60 -0
- package/dist/indexer/staleness.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +38 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/staleness-check.d.ts +7 -0
- package/dist/mcp/staleness-check.js +31 -0
- package/dist/mcp/staleness-check.js.map +1 -0
- package/dist/mcp/tools/get-callees.d.ts +3 -0
- package/dist/mcp/tools/get-callees.js +34 -0
- package/dist/mcp/tools/get-callees.js.map +1 -0
- package/dist/mcp/tools/get-callers.d.ts +3 -0
- package/dist/mcp/tools/get-callers.js +34 -0
- package/dist/mcp/tools/get-callers.js.map +1 -0
- package/dist/mcp/tools/get-class.d.ts +3 -0
- package/dist/mcp/tools/get-class.js +42 -0
- package/dist/mcp/tools/get-class.js.map +1 -0
- package/dist/mcp/tools/get-dependencies.d.ts +3 -0
- package/dist/mcp/tools/get-dependencies.js +26 -0
- package/dist/mcp/tools/get-dependencies.js.map +1 -0
- package/dist/mcp/tools/get-dependents.d.ts +3 -0
- package/dist/mcp/tools/get-dependents.js +26 -0
- package/dist/mcp/tools/get-dependents.js.map +1 -0
- package/dist/mcp/tools/get-file-structure.d.ts +3 -0
- package/dist/mcp/tools/get-file-structure.js +33 -0
- package/dist/mcp/tools/get-file-structure.js.map +1 -0
- package/dist/mcp/tools/get-function.d.ts +3 -0
- package/dist/mcp/tools/get-function.js +34 -0
- package/dist/mcp/tools/get-function.js.map +1 -0
- package/dist/mcp/tools/get-repo-structure.d.ts +3 -0
- package/dist/mcp/tools/get-repo-structure.js +39 -0
- package/dist/mcp/tools/get-repo-structure.js.map +1 -0
- package/dist/mcp/tools/reindex.d.ts +4 -0
- package/dist/mcp/tools/reindex.js +27 -0
- package/dist/mcp/tools/reindex.js.map +1 -0
- package/dist/mcp/tools/search-code.d.ts +3 -0
- package/dist/mcp/tools/search-code.js +43 -0
- package/dist/mcp/tools/search-code.js.map +1 -0
- package/dist/visualize/public/graph.js +445 -0
- package/dist/visualize/public/index.html +88 -0
- package/dist/visualize/queries.d.ts +14 -0
- package/dist/visualize/queries.js +84 -0
- package/dist/visualize/queries.js.map +1 -0
- package/dist/visualize/server.d.ts +19 -0
- package/dist/visualize/server.js +293 -0
- package/dist/visualize/server.js.map +1 -0
- package/docker-compose.yml +16 -0
- package/package.json +69 -0
- package/src/indexer/language-map.json +128 -0
- package/src/visualize/public/graph.js +445 -0
- package/src/visualize/public/index.html +88 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// src/indexer/parser.ts
|
|
2
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
3
|
+
import { extname, resolve, join, dirname } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import Parser from "web-tree-sitter";
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
let parser = null;
|
|
8
|
+
const languageCache = new Map();
|
|
9
|
+
const EXTENSION_MAP = {
|
|
10
|
+
".ts": "typescript",
|
|
11
|
+
".tsx": "tsx",
|
|
12
|
+
".js": "javascript",
|
|
13
|
+
".jsx": "javascript",
|
|
14
|
+
".py": "python",
|
|
15
|
+
".go": "go",
|
|
16
|
+
".java": "java",
|
|
17
|
+
".rs": "rust",
|
|
18
|
+
".c": "c",
|
|
19
|
+
".h": "c",
|
|
20
|
+
".cpp": "cpp",
|
|
21
|
+
".hpp": "cpp",
|
|
22
|
+
".cc": "cpp",
|
|
23
|
+
".cs": "c_sharp",
|
|
24
|
+
".rb": "ruby",
|
|
25
|
+
".php": "php",
|
|
26
|
+
".swift": "swift",
|
|
27
|
+
".kt": "kotlin",
|
|
28
|
+
".scala": "scala",
|
|
29
|
+
".graphql": "graphql",
|
|
30
|
+
".gql": "graphql",
|
|
31
|
+
".html": "html",
|
|
32
|
+
".css": "css",
|
|
33
|
+
".yaml": "yaml",
|
|
34
|
+
".yml": "yaml",
|
|
35
|
+
".json": "json",
|
|
36
|
+
".sql": "sql",
|
|
37
|
+
".sh": "bash",
|
|
38
|
+
".bash": "bash",
|
|
39
|
+
".lua": "lua",
|
|
40
|
+
".zig": "zig",
|
|
41
|
+
".ex": "elixir",
|
|
42
|
+
".exs": "elixir",
|
|
43
|
+
".dart": "dart",
|
|
44
|
+
};
|
|
45
|
+
export function detectLanguage(filePath) {
|
|
46
|
+
const ext = extname(filePath).toLowerCase();
|
|
47
|
+
return EXTENSION_MAP[ext] ?? null;
|
|
48
|
+
}
|
|
49
|
+
export async function initParser() {
|
|
50
|
+
if (parser)
|
|
51
|
+
return;
|
|
52
|
+
await Parser.init();
|
|
53
|
+
parser = new Parser();
|
|
54
|
+
}
|
|
55
|
+
async function loadLanguage(languageName) {
|
|
56
|
+
if (languageCache.has(languageName)) {
|
|
57
|
+
return languageCache.get(languageName);
|
|
58
|
+
}
|
|
59
|
+
const wasmPath = join(__dirname, "../../node_modules/tree-sitter-wasms/out", `tree-sitter-${languageName}.wasm`);
|
|
60
|
+
if (!existsSync(wasmPath)) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const language = await Parser.Language.load(wasmPath);
|
|
64
|
+
languageCache.set(languageName, language);
|
|
65
|
+
return language;
|
|
66
|
+
}
|
|
67
|
+
export async function parseFile(filePath) {
|
|
68
|
+
if (!parser) {
|
|
69
|
+
await initParser();
|
|
70
|
+
}
|
|
71
|
+
const language = detectLanguage(filePath);
|
|
72
|
+
if (!language)
|
|
73
|
+
return null;
|
|
74
|
+
const absPath = resolve(filePath);
|
|
75
|
+
if (!existsSync(absPath))
|
|
76
|
+
return null;
|
|
77
|
+
const lang = await loadLanguage(language);
|
|
78
|
+
if (!lang)
|
|
79
|
+
return null;
|
|
80
|
+
parser.setLanguage(lang);
|
|
81
|
+
const source = readFileSync(absPath, "utf-8");
|
|
82
|
+
const tree = parser.parse(source);
|
|
83
|
+
return { tree, language, source };
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../../src/indexer/parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare function computeFileHash(filePath: string, content?: string | Buffer): string;
|
|
2
|
+
export declare function getFileMtime(filePath: string): number;
|
|
3
|
+
export declare function isFileStale(filePath: string, storedHash: string, storedMtime: number): boolean;
|
|
4
|
+
export interface GitDiffResult {
|
|
5
|
+
changed: string[];
|
|
6
|
+
deleted: string[];
|
|
7
|
+
error?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function getChangedFilesSinceCommit(repoPath: string, baseSha?: string, options?: {
|
|
10
|
+
includeDeleted?: boolean;
|
|
11
|
+
}): GitDiffResult;
|
|
12
|
+
export declare function getCurrentCommitSha(repoPath: string): string | null;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// src/indexer/staleness.ts
|
|
2
|
+
import { readFileSync, statSync, existsSync } from "node:fs";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { execFileSync } from "node:child_process";
|
|
5
|
+
export function computeFileHash(filePath, content) {
|
|
6
|
+
const data = content ?? readFileSync(filePath);
|
|
7
|
+
return createHash("sha256").update(data).digest("hex");
|
|
8
|
+
}
|
|
9
|
+
export function getFileMtime(filePath) {
|
|
10
|
+
const stat = statSync(filePath);
|
|
11
|
+
return stat.mtimeMs;
|
|
12
|
+
}
|
|
13
|
+
export function isFileStale(filePath, storedHash, storedMtime) {
|
|
14
|
+
if (!existsSync(filePath)) {
|
|
15
|
+
return true; // File was deleted
|
|
16
|
+
}
|
|
17
|
+
const currentMtime = getFileMtime(filePath);
|
|
18
|
+
if (currentMtime <= storedMtime) {
|
|
19
|
+
return false; // mtime hasn't changed, skip expensive hash
|
|
20
|
+
}
|
|
21
|
+
const currentHash = computeFileHash(filePath);
|
|
22
|
+
return currentHash !== storedHash;
|
|
23
|
+
}
|
|
24
|
+
export function getChangedFilesSinceCommit(repoPath, baseSha, options) {
|
|
25
|
+
const base = baseSha ?? "HEAD~1";
|
|
26
|
+
try {
|
|
27
|
+
if (options?.includeDeleted) {
|
|
28
|
+
const output = execFileSync("git", ["diff", "--name-status", `${base}..HEAD`], { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
29
|
+
const changed = [];
|
|
30
|
+
const deleted = [];
|
|
31
|
+
for (const line of output.trim().split("\n").filter((l) => l.length > 0)) {
|
|
32
|
+
const [status, ...rest] = line.split("\t");
|
|
33
|
+
const filePath = rest.join("\t"); // handles paths with tabs (rare)
|
|
34
|
+
if (status === "D") {
|
|
35
|
+
deleted.push(filePath);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
changed.push(filePath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { changed, deleted };
|
|
42
|
+
}
|
|
43
|
+
const result = execFileSync("git", ["diff", "--name-only", `${base}..HEAD`], { cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n").filter((f) => f.length > 0);
|
|
44
|
+
return { changed: result, deleted: [] };
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return { changed: [], deleted: [], error: true };
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export function getCurrentCommitSha(repoPath) {
|
|
51
|
+
try {
|
|
52
|
+
return execFileSync("git", ["rev-parse", "HEAD"], {
|
|
53
|
+
cwd: repoPath, encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"],
|
|
54
|
+
}).trim();
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=staleness.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness.js","sourceRoot":"","sources":["../../src/indexer/staleness.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function startMcpServer(): Promise<void>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// src/mcp/index.ts
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { resolve } from "node:path";
|
|
5
|
+
import { loadConfig } from "../config.js";
|
|
6
|
+
import { createConnection } from "../db/connection.js";
|
|
7
|
+
import { registerSearchCode } from "./tools/search-code.js";
|
|
8
|
+
import { registerGetFunction } from "./tools/get-function.js";
|
|
9
|
+
import { registerGetClass } from "./tools/get-class.js";
|
|
10
|
+
import { registerGetFileStructure } from "./tools/get-file-structure.js";
|
|
11
|
+
import { registerGetCallers } from "./tools/get-callers.js";
|
|
12
|
+
import { registerGetCallees } from "./tools/get-callees.js";
|
|
13
|
+
import { registerGetDependencies } from "./tools/get-dependencies.js";
|
|
14
|
+
import { registerGetDependents } from "./tools/get-dependents.js";
|
|
15
|
+
import { registerGetRepoStructure } from "./tools/get-repo-structure.js";
|
|
16
|
+
import { registerReindex } from "./tools/reindex.js";
|
|
17
|
+
export async function startMcpServer() {
|
|
18
|
+
const repoPath = resolve(".");
|
|
19
|
+
const config = loadConfig(repoPath);
|
|
20
|
+
const db = createConnection(config.neo4j);
|
|
21
|
+
const server = new McpServer({
|
|
22
|
+
name: "code-graph-rag",
|
|
23
|
+
version: "0.1.0",
|
|
24
|
+
});
|
|
25
|
+
registerSearchCode(server, db);
|
|
26
|
+
registerGetFunction(server, db);
|
|
27
|
+
registerGetClass(server, db);
|
|
28
|
+
registerGetFileStructure(server, db);
|
|
29
|
+
registerGetCallers(server, db);
|
|
30
|
+
registerGetCallees(server, db);
|
|
31
|
+
registerGetDependencies(server, db);
|
|
32
|
+
registerGetDependents(server, db);
|
|
33
|
+
registerGetRepoStructure(server, db);
|
|
34
|
+
registerReindex(server, db, config, repoPath);
|
|
35
|
+
const transport = new StdioServerTransport();
|
|
36
|
+
await server.connect(transport);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":"AAAA,mBAAmB;AACnB,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,MAAM,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,EAAE,GAAG,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,gBAAgB;QACtB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;IAEH,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/B,mBAAmB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAChC,gBAAgB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC7B,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/B,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC/B,uBAAuB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpC,qBAAqB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAClC,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACrC,eAAe,CAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IAE9C,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DbConnection } from "../db/connection.js";
|
|
2
|
+
export interface StalenessResult {
|
|
3
|
+
staleFiles: string[];
|
|
4
|
+
needsWarning: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function checkStaleness(db: DbConnection, filePaths: string[], isStaleCheck?: (filePath: string, storedHash: string, storedMtime: number) => boolean): Promise<StalenessResult>;
|
|
7
|
+
export declare function formatStalenessWarning(staleCount: number): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { isFileStale as defaultIsFileStale } from "../indexer/staleness.js";
|
|
2
|
+
const STALE_THRESHOLD = 20;
|
|
3
|
+
export async function checkStaleness(db, filePaths, isStaleCheck = defaultIsFileStale) {
|
|
4
|
+
if (filePaths.length === 0) {
|
|
5
|
+
return { staleFiles: [], needsWarning: false };
|
|
6
|
+
}
|
|
7
|
+
const session = db.session();
|
|
8
|
+
try {
|
|
9
|
+
const result = await session.run("MATCH (f:File) WHERE f.path IN $paths RETURN f.path AS path, f.hash AS hash, f.lastModified AS lastModified", { paths: filePaths });
|
|
10
|
+
const staleFiles = [];
|
|
11
|
+
for (const record of result.records) {
|
|
12
|
+
const path = record.get("path");
|
|
13
|
+
const hash = record.get("hash");
|
|
14
|
+
const lastModified = record.get("lastModified");
|
|
15
|
+
if (isStaleCheck(path, hash, lastModified)) {
|
|
16
|
+
staleFiles.push(path);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
staleFiles,
|
|
21
|
+
needsWarning: staleFiles.length > STALE_THRESHOLD,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await session.close();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export function formatStalenessWarning(staleCount) {
|
|
29
|
+
return `Warning: Index is stale for ${staleCount} files. Run \`code-graph-rag index --changed\` for full refresh.`;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=staleness-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staleness-check.js","sourceRoot":"","sources":["../../src/mcp/staleness-check.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,IAAI,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE5E,MAAM,eAAe,GAAG,EAAE,CAAC;AAO3B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,EAAgB,EAChB,SAAmB,EACnB,eAIe,kBAAkB;IAEjC,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC;IACjD,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,6GAA6G,EAC7G,EAAE,KAAK,EAAE,SAAS,EAAE,CACrB,CAAC;QAEF,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAW,CAAC;YAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,MAAM,CAAW,CAAC;YAC1C,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAW,CAAC;YAE1D,IAAI,YAAY,CAAC,IAAI,EAAE,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC;gBAC3C,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QAED,OAAO;YACL,UAAU;YACV,YAAY,EAAE,UAAU,CAAC,MAAM,GAAG,eAAe;SAClD,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,UAAkB;IACvD,OAAO,+BAA+B,UAAU,kEAAkE,CAAC;AACrH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetCallees(server, db) {
|
|
3
|
+
server.tool("get_callees", "Find all functions that a specific function calls. Use this to understand what a function depends on.", {
|
|
4
|
+
functionName: z.string().describe("Name of the function to find callees of"),
|
|
5
|
+
filePath: z.string().optional().describe("Disambiguate by file path"),
|
|
6
|
+
}, async ({ functionName, filePath }) => {
|
|
7
|
+
const session = db.session();
|
|
8
|
+
try {
|
|
9
|
+
let cypher = `
|
|
10
|
+
MATCH (caller:Function {name: $functionName})
|
|
11
|
+
`;
|
|
12
|
+
const params = { functionName };
|
|
13
|
+
if (filePath) {
|
|
14
|
+
cypher += ` WHERE caller.filePath = $filePath`;
|
|
15
|
+
params.filePath = filePath;
|
|
16
|
+
}
|
|
17
|
+
cypher += `
|
|
18
|
+
MATCH (caller)-[:CALLS]->(callee:Function)
|
|
19
|
+
RETURN callee.name AS calleeName, callee.filePath AS calleeFilePath,
|
|
20
|
+
callee.signature AS signature, callee.startLine AS startLine
|
|
21
|
+
ORDER BY calleeFilePath, calleeName
|
|
22
|
+
`;
|
|
23
|
+
const result = await session.run(cypher, params);
|
|
24
|
+
const records = result.records.map((r) => r.toObject());
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await session.close();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=get-callees.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-callees.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-callees.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,EAAgB;IACpE,MAAM,CAAC,IAAI,CACT,aAAa,EACb,uGAAuG,EACvG;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QAC5E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACtE,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,EAAE;QACnC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,MAAM,GAAG;;SAEZ,CAAC;YACF,MAAM,MAAM,GAA4B,EAAE,YAAY,EAAE,CAAC;YACzD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,oCAAoC,CAAC;gBAC/C,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC7B,CAAC;YACD,MAAM,IAAI;;;;;SAKT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetCallers(server, db) {
|
|
3
|
+
server.tool("get_callers", "Find all functions that call a specific function. Use this to understand who depends on a function.", {
|
|
4
|
+
functionName: z.string().describe("Name of the function to find callers of"),
|
|
5
|
+
filePath: z.string().optional().describe("Disambiguate by file path"),
|
|
6
|
+
}, async ({ functionName, filePath }) => {
|
|
7
|
+
const session = db.session();
|
|
8
|
+
try {
|
|
9
|
+
let cypher = `
|
|
10
|
+
MATCH (callee:Function {name: $functionName})
|
|
11
|
+
`;
|
|
12
|
+
const params = { functionName };
|
|
13
|
+
if (filePath) {
|
|
14
|
+
cypher += ` WHERE callee.filePath = $filePath`;
|
|
15
|
+
params.filePath = filePath;
|
|
16
|
+
}
|
|
17
|
+
cypher += `
|
|
18
|
+
MATCH (caller:Function)-[:CALLS]->(callee)
|
|
19
|
+
RETURN caller.name AS callerName, caller.filePath AS callerFilePath,
|
|
20
|
+
caller.signature AS signature, caller.startLine AS startLine
|
|
21
|
+
ORDER BY callerFilePath, callerName
|
|
22
|
+
`;
|
|
23
|
+
const result = await session.run(cypher, params);
|
|
24
|
+
const records = result.records.map((r) => r.toObject());
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await session.close();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=get-callers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-callers.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-callers.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,kBAAkB,CAAC,MAAiB,EAAE,EAAgB;IACpE,MAAM,CAAC,IAAI,CACT,aAAa,EACb,qGAAqG,EACrG;QACE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC;QAC5E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;KACtE,EACD,KAAK,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,EAAE,EAAE;QACnC,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,MAAM,GAAG;;SAEZ,CAAC;YACF,MAAM,MAAM,GAA4B,EAAE,YAAY,EAAE,CAAC;YACzD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,oCAAoC,CAAC;gBAC/C,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC7B,CAAC;YACD,MAAM,IAAI;;;;;SAKT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetClass(server, db) {
|
|
3
|
+
server.tool("get_class", "Get a class definition with all its methods. Use this INSTEAD OF reading the file.", {
|
|
4
|
+
name: z.string().describe("Class name"),
|
|
5
|
+
filePath: z.string().optional().describe("File path for disambiguation"),
|
|
6
|
+
}, async ({ name, filePath }) => {
|
|
7
|
+
const session = db.session();
|
|
8
|
+
try {
|
|
9
|
+
let cypher = `
|
|
10
|
+
MATCH (c:Class {name: $name})
|
|
11
|
+
`;
|
|
12
|
+
const params = { name };
|
|
13
|
+
if (filePath) {
|
|
14
|
+
cypher += ` WHERE c.filePath = $filePath`;
|
|
15
|
+
params.filePath = filePath;
|
|
16
|
+
}
|
|
17
|
+
cypher += `
|
|
18
|
+
OPTIONAL MATCH (c)-[:HAS_METHOD]->(m:Function)
|
|
19
|
+
RETURN c.name AS className, c.filePath AS filePath,
|
|
20
|
+
c.startLine AS startLine, c.endLine AS endLine,
|
|
21
|
+
c.docstring AS docstring,
|
|
22
|
+
collect({
|
|
23
|
+
name: m.name,
|
|
24
|
+
signature: m.signature,
|
|
25
|
+
snippet: m.snippet,
|
|
26
|
+
startLine: m.startLine,
|
|
27
|
+
endLine: m.endLine,
|
|
28
|
+
docstring: m.docstring
|
|
29
|
+
}) AS methods
|
|
30
|
+
`;
|
|
31
|
+
const result = await session.run(cypher, params);
|
|
32
|
+
const records = result.records.map((r) => r.toObject());
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
await session.close();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=get-class.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-class.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-class.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,gBAAgB,CAAC,MAAiB,EAAE,EAAgB;IAClE,MAAM,CAAC,IAAI,CACT,WAAW,EACX,oFAAoF,EACpF;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC;QACvC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;KACzE,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,MAAM,GAAG;;SAEZ,CAAC;YACF,MAAM,MAAM,GAA4B,EAAE,IAAI,EAAE,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,+BAA+B,CAAC;gBAC1C,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC7B,CAAC;YACD,MAAM,IAAI;;;;;;;;;;;;;SAaT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetDependencies(server, db) {
|
|
3
|
+
server.tool("get_dependencies", "Get all files that a specific file imports. Use this to understand a file's dependencies.", {
|
|
4
|
+
filePath: z.string().describe("Absolute or relative path of the file"),
|
|
5
|
+
}, async ({ filePath }) => {
|
|
6
|
+
const session = db.session();
|
|
7
|
+
try {
|
|
8
|
+
const result = await session.run(`
|
|
9
|
+
MATCH (f:File)
|
|
10
|
+
WHERE f.path = $filePath OR f.relativePath = $filePath
|
|
11
|
+
MATCH (f)-[:IMPORTS]->(dep:File)
|
|
12
|
+
RETURN dep.path AS dependencyPath, dep.relativePath AS relativePath,
|
|
13
|
+
dep.language AS language
|
|
14
|
+
ORDER BY relativePath
|
|
15
|
+
`, { filePath });
|
|
16
|
+
const records = result.records.map((r) => r.toObject());
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
await session.close();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=get-dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-dependencies.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-dependencies.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,uBAAuB,CAAC,MAAiB,EAAE,EAAgB;IACzE,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,2FAA2F,EAC3F;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;KACvE,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;WAOC,EACD,EAAE,QAAQ,EAAE,CACb,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetDependents(server, db) {
|
|
3
|
+
server.tool("get_dependents", "Get all files that import a specific file. Use this to understand what depends on a file before making changes.", {
|
|
4
|
+
filePath: z.string().describe("Absolute or relative path of the file"),
|
|
5
|
+
}, async ({ filePath }) => {
|
|
6
|
+
const session = db.session();
|
|
7
|
+
try {
|
|
8
|
+
const result = await session.run(`
|
|
9
|
+
MATCH (f:File)
|
|
10
|
+
WHERE f.path = $filePath OR f.relativePath = $filePath
|
|
11
|
+
MATCH (dependent:File)-[:IMPORTS]->(f)
|
|
12
|
+
RETURN dependent.path AS dependentPath, dependent.relativePath AS relativePath,
|
|
13
|
+
dependent.language AS language
|
|
14
|
+
ORDER BY relativePath
|
|
15
|
+
`, { filePath });
|
|
16
|
+
const records = result.records.map((r) => r.toObject());
|
|
17
|
+
return {
|
|
18
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
await session.close();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=get-dependents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-dependents.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-dependents.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,qBAAqB,CAAC,MAAiB,EAAE,EAAgB;IACvE,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,iHAAiH,EACjH;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uCAAuC,CAAC;KACvE,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;WAOC,EACD,EAAE,QAAQ,EAAE,CACb,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetFileStructure(server, db) {
|
|
3
|
+
server.tool("get_file_structure", "Get the structure of a file — classes and functions with their signatures but without code bodies. Much more efficient than reading the whole file.", {
|
|
4
|
+
filePath: z.string().describe("Absolute or relative file path"),
|
|
5
|
+
}, async ({ filePath }) => {
|
|
6
|
+
const session = db.session();
|
|
7
|
+
try {
|
|
8
|
+
const result = await session.run(`
|
|
9
|
+
MATCH (f:File)
|
|
10
|
+
WHERE f.path = $filePath OR f.relativePath = $filePath
|
|
11
|
+
OPTIONAL MATCH (f)-[:CONTAINS]->(symbol)
|
|
12
|
+
WHERE symbol:Function OR symbol:Class
|
|
13
|
+
RETURN f.path AS filePath, f.language AS language,
|
|
14
|
+
collect({
|
|
15
|
+
type: labels(symbol)[0],
|
|
16
|
+
name: symbol.name,
|
|
17
|
+
signature: symbol.signature,
|
|
18
|
+
startLine: symbol.startLine,
|
|
19
|
+
endLine: symbol.endLine,
|
|
20
|
+
docstring: symbol.docstring
|
|
21
|
+
}) AS symbols
|
|
22
|
+
`, { filePath });
|
|
23
|
+
const records = result.records.map((r) => r.toObject());
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await session.close();
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=get-file-structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-file-structure.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-file-structure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,EAAgB;IAC1E,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,qJAAqJ,EACrJ;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;KAChE,EACD,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;QACrB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B;;;;;;;;;;;;;;WAcC,EACD,EAAE,QAAQ,EAAE,CACb,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetFunction(server, db) {
|
|
3
|
+
server.tool("get_function", "Get the full source code of a specific function by name. Use this INSTEAD OF reading the file to find a function.", {
|
|
4
|
+
name: z.string().describe("Function name"),
|
|
5
|
+
filePath: z.string().optional().describe("File path for disambiguation when multiple functions share a name"),
|
|
6
|
+
}, async ({ name, filePath }) => {
|
|
7
|
+
const session = db.session();
|
|
8
|
+
try {
|
|
9
|
+
let cypher = `
|
|
10
|
+
MATCH (fn:Function {name: $name})
|
|
11
|
+
`;
|
|
12
|
+
const params = { name };
|
|
13
|
+
if (filePath) {
|
|
14
|
+
cypher += ` WHERE fn.filePath = $filePath`;
|
|
15
|
+
params.filePath = filePath;
|
|
16
|
+
}
|
|
17
|
+
cypher += `
|
|
18
|
+
RETURN fn.name AS name, fn.filePath AS filePath,
|
|
19
|
+
fn.signature AS signature, fn.snippet AS snippet,
|
|
20
|
+
fn.startLine AS startLine, fn.endLine AS endLine,
|
|
21
|
+
fn.docstring AS docstring, fn.className AS className
|
|
22
|
+
`;
|
|
23
|
+
const result = await session.run(cypher, params);
|
|
24
|
+
const records = result.records.map((r) => r.toObject());
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
finally {
|
|
30
|
+
await session.close();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=get-function.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-function.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-function.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,mBAAmB,CAAC,MAAiB,EAAE,EAAgB;IACrE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,mHAAmH,EACnH;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC1C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;KAC9G,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,MAAM,GAAG;;SAEZ,CAAC;YACF,MAAM,MAAM,GAA4B,EAAE,IAAI,EAAE,CAAC;YACjD,IAAI,QAAQ,EAAE,CAAC;gBACb,MAAM,IAAI,gCAAgC,CAAC;gBAC3C,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAC7B,CAAC;YACD,MAAM,IAAI;;;;;SAKT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerGetRepoStructure(server, db) {
|
|
3
|
+
server.tool("get_repo_structure", "Get a bird's-eye view of a repository — file counts by directory and top-level symbols. Use this to orient yourself in a new codebase.", {
|
|
4
|
+
repo: z.string().optional().describe("Repository path to query (defaults to all repos)"),
|
|
5
|
+
depth: z.number().optional().default(3).describe("Directory depth to show"),
|
|
6
|
+
}, async ({ repo, depth }) => {
|
|
7
|
+
const session = db.session();
|
|
8
|
+
try {
|
|
9
|
+
let cypher = `
|
|
10
|
+
MATCH (r:Repository)
|
|
11
|
+
`;
|
|
12
|
+
const params = { depth: depth ?? 3 };
|
|
13
|
+
if (repo) {
|
|
14
|
+
cypher += ` WHERE r.path = $repo OR r.name = $repo`;
|
|
15
|
+
params.repo = repo;
|
|
16
|
+
}
|
|
17
|
+
cypher += `
|
|
18
|
+
MATCH (r)-[:CONTAINS_FILE]->(f:File)
|
|
19
|
+
WITH r, f
|
|
20
|
+
OPTIONAL MATCH (f)-[:CONTAINS]->(fn:Function)
|
|
21
|
+
OPTIONAL MATCH (f)-[:CONTAINS]->(c:Class)
|
|
22
|
+
RETURN r.name AS repo, r.path AS repoPath,
|
|
23
|
+
f.relativePath AS filePath, f.language AS language,
|
|
24
|
+
count(DISTINCT fn) AS functionCount,
|
|
25
|
+
count(DISTINCT c) AS classCount
|
|
26
|
+
ORDER BY filePath
|
|
27
|
+
`;
|
|
28
|
+
const result = await session.run(cypher, params);
|
|
29
|
+
const records = result.records.map((r) => r.toObject());
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: "text", text: JSON.stringify(records, null, 2) }],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
await session.close();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=get-repo-structure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-repo-structure.js","sourceRoot":"","sources":["../../../src/mcp/tools/get-repo-structure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,wBAAwB,CAAC,MAAiB,EAAE,EAAgB;IAC1E,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,wIAAwI,EACxI;QACE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;QACxF,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KAC5E,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,IAAI,MAAM,GAAG;;SAEZ,CAAC;YACF,MAAM,MAAM,GAA4B,EAAE,KAAK,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;YAC9D,IAAI,IAAI,EAAE,CAAC;gBACT,MAAM,IAAI,yCAAyC,CAAC;gBACpD,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;YACrB,CAAC;YACD,MAAM,IAAI;;;;;;;;;;SAUT,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YACxD,OAAO;gBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;aACpE,CAAC;QACJ,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QACxB,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { DbConnection } from "../../db/connection.js";
|
|
3
|
+
import type { Config } from "../../config.js";
|
|
4
|
+
export declare function registerReindex(server: McpServer, db: DbConnection, config: Config, repoPath: string): void;
|