sverklo 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.
Files changed (117) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -0
  3. package/dist/bin/sverklo.d.ts +2 -0
  4. package/dist/bin/sverklo.js +41 -0
  5. package/dist/bin/sverklo.js.map +1 -0
  6. package/dist/src/index.d.ts +3 -0
  7. package/dist/src/index.js +3 -0
  8. package/dist/src/index.js.map +1 -0
  9. package/dist/src/indexer/describer.d.ts +2 -0
  10. package/dist/src/indexer/describer.js +112 -0
  11. package/dist/src/indexer/describer.js.map +1 -0
  12. package/dist/src/indexer/embedder.d.ts +4 -0
  13. package/dist/src/indexer/embedder.js +249 -0
  14. package/dist/src/indexer/embedder.js.map +1 -0
  15. package/dist/src/indexer/file-discovery.d.ts +9 -0
  16. package/dist/src/indexer/file-discovery.js +52 -0
  17. package/dist/src/indexer/file-discovery.js.map +1 -0
  18. package/dist/src/indexer/graph-builder.d.ts +5 -0
  19. package/dist/src/indexer/graph-builder.js +77 -0
  20. package/dist/src/indexer/graph-builder.js.map +1 -0
  21. package/dist/src/indexer/indexer.d.ts +26 -0
  22. package/dist/src/indexer/indexer.js +180 -0
  23. package/dist/src/indexer/indexer.js.map +1 -0
  24. package/dist/src/indexer/parser.d.ts +2 -0
  25. package/dist/src/indexer/parser.js +467 -0
  26. package/dist/src/indexer/parser.js.map +1 -0
  27. package/dist/src/indexer/setup.d.ts +1 -0
  28. package/dist/src/indexer/setup.js +38 -0
  29. package/dist/src/indexer/setup.js.map +1 -0
  30. package/dist/src/indexer/watcher.d.ts +2 -0
  31. package/dist/src/indexer/watcher.js +51 -0
  32. package/dist/src/indexer/watcher.js.map +1 -0
  33. package/dist/src/memory/git-state.d.ts +4 -0
  34. package/dist/src/memory/git-state.js +12 -0
  35. package/dist/src/memory/git-state.js.map +1 -0
  36. package/dist/src/memory/staleness.d.ts +4 -0
  37. package/dist/src/memory/staleness.js +19 -0
  38. package/dist/src/memory/staleness.js.map +1 -0
  39. package/dist/src/search/hybrid-search.d.ts +13 -0
  40. package/dist/src/search/hybrid-search.js +97 -0
  41. package/dist/src/search/hybrid-search.js.map +1 -0
  42. package/dist/src/search/pagerank.d.ts +4 -0
  43. package/dist/src/search/pagerank.js +64 -0
  44. package/dist/src/search/pagerank.js.map +1 -0
  45. package/dist/src/search/token-budget.d.ts +10 -0
  46. package/dist/src/search/token-budget.js +67 -0
  47. package/dist/src/search/token-budget.js.map +1 -0
  48. package/dist/src/server/mcp-server.d.ts +1 -0
  49. package/dist/src/server/mcp-server.js +120 -0
  50. package/dist/src/server/mcp-server.js.map +1 -0
  51. package/dist/src/server/tools/dependencies.d.ts +29 -0
  52. package/dist/src/server/tools/dependencies.js +118 -0
  53. package/dist/src/server/tools/dependencies.js.map +1 -0
  54. package/dist/src/server/tools/find-references.d.ts +20 -0
  55. package/dist/src/server/tools/find-references.js +80 -0
  56. package/dist/src/server/tools/find-references.js.map +1 -0
  57. package/dist/src/server/tools/forget.d.ts +16 -0
  58. package/dist/src/server/tools/forget.js +24 -0
  59. package/dist/src/server/tools/forget.js.map +1 -0
  60. package/dist/src/server/tools/index-status.d.ts +10 -0
  61. package/dist/src/server/tools/index-status.js +21 -0
  62. package/dist/src/server/tools/index-status.js.map +1 -0
  63. package/dist/src/server/tools/lookup.d.ts +25 -0
  64. package/dist/src/server/tools/lookup.js +54 -0
  65. package/dist/src/server/tools/lookup.js.map +1 -0
  66. package/dist/src/server/tools/memories.d.ts +24 -0
  67. package/dist/src/server/tools/memories.js +61 -0
  68. package/dist/src/server/tools/memories.js.map +1 -0
  69. package/dist/src/server/tools/overview.d.ts +19 -0
  70. package/dist/src/server/tools/overview.js +32 -0
  71. package/dist/src/server/tools/overview.js.map +1 -0
  72. package/dist/src/server/tools/recall.d.ts +29 -0
  73. package/dist/src/server/tools/recall.js +113 -0
  74. package/dist/src/server/tools/recall.js.map +1 -0
  75. package/dist/src/server/tools/remember.d.ts +39 -0
  76. package/dist/src/server/tools/remember.js +56 -0
  77. package/dist/src/server/tools/remember.js.map +1 -0
  78. package/dist/src/server/tools/search.d.ts +33 -0
  79. package/dist/src/server/tools/search.js +43 -0
  80. package/dist/src/server/tools/search.js.map +1 -0
  81. package/dist/src/storage/chunk-store.d.ts +25 -0
  82. package/dist/src/storage/chunk-store.js +74 -0
  83. package/dist/src/storage/chunk-store.js.map +1 -0
  84. package/dist/src/storage/database.d.ts +2 -0
  85. package/dist/src/storage/database.js +140 -0
  86. package/dist/src/storage/database.js.map +1 -0
  87. package/dist/src/storage/embedding-store.d.ts +14 -0
  88. package/dist/src/storage/embedding-store.js +42 -0
  89. package/dist/src/storage/embedding-store.js.map +1 -0
  90. package/dist/src/storage/file-store.d.ts +19 -0
  91. package/dist/src/storage/file-store.js +44 -0
  92. package/dist/src/storage/file-store.js.map +1 -0
  93. package/dist/src/storage/graph-store.d.ts +16 -0
  94. package/dist/src/storage/graph-store.js +37 -0
  95. package/dist/src/storage/graph-store.js.map +1 -0
  96. package/dist/src/storage/memory-embedding-store.d.ts +13 -0
  97. package/dist/src/storage/memory-embedding-store.js +38 -0
  98. package/dist/src/storage/memory-embedding-store.js.map +1 -0
  99. package/dist/src/storage/memory-store.d.ts +29 -0
  100. package/dist/src/storage/memory-store.js +86 -0
  101. package/dist/src/storage/memory-store.js.map +1 -0
  102. package/dist/src/types/index.d.ts +87 -0
  103. package/dist/src/types/index.js +21 -0
  104. package/dist/src/types/index.js.map +1 -0
  105. package/dist/src/utils/config.d.ts +2 -0
  106. package/dist/src/utils/config.js +18 -0
  107. package/dist/src/utils/config.js.map +1 -0
  108. package/dist/src/utils/ignore.d.ts +2 -0
  109. package/dist/src/utils/ignore.js +72 -0
  110. package/dist/src/utils/ignore.js.map +1 -0
  111. package/dist/src/utils/logger.d.ts +2 -0
  112. package/dist/src/utils/logger.js +16 -0
  113. package/dist/src/utils/logger.js.map +1 -0
  114. package/dist/src/utils/tokens.d.ts +2 -0
  115. package/dist/src/utils/tokens.js +12 -0
  116. package/dist/src/utils/tokens.js.map +1 -0
  117. package/package.json +59 -0
@@ -0,0 +1,19 @@
1
+ export function checkStaleness(memory, fileStore, memoryStore) {
2
+ if (!memory.related_files)
3
+ return false;
4
+ let files;
5
+ try {
6
+ files = JSON.parse(memory.related_files);
7
+ }
8
+ catch {
9
+ return false;
10
+ }
11
+ if (!Array.isArray(files) || files.length === 0)
12
+ return false;
13
+ const anyMissing = files.some((path) => !fileStore.getByPath(path));
14
+ if (anyMissing !== Boolean(memory.is_stale)) {
15
+ memoryStore.markStale(memory.id, anyMissing);
16
+ }
17
+ return anyMissing;
18
+ }
19
+ //# sourceMappingURL=staleness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"staleness.js","sourceRoot":"","sources":["../../../src/memory/staleness.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,cAAc,CAC5B,MAAc,EACd,SAAoB,EACpB,WAAwB;IAExB,IAAI,CAAC,MAAM,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IAExC,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAE9D,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAEpE,IAAI,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Indexer } from "../indexer/indexer.js";
2
+ import type { SearchResult, ChunkType } from "../types/index.js";
3
+ interface SearchOptions {
4
+ query: string;
5
+ tokenBudget: number;
6
+ scope?: string;
7
+ language?: string;
8
+ type?: ChunkType | "any";
9
+ }
10
+ export declare function hybridSearch(indexer: Indexer, options: SearchOptions): Promise<SearchResult[]>;
11
+ export declare function packResults(candidates: SearchResult[], tokenBudget: number): SearchResult[];
12
+ export declare function formatResults(results: SearchResult[]): string;
13
+ export {};
@@ -0,0 +1,97 @@
1
+ import { embed, cosineSimilarity } from "../indexer/embedder.js";
2
+ // Reciprocal Rank Fusion constant
3
+ const RRF_K = 60;
4
+ export async function hybridSearch(indexer, options) {
5
+ const { query, tokenBudget, scope, language, type } = options;
6
+ // Signal A: BM25 text search
7
+ const ftsResults = indexer.chunkStore.searchFts(query, 50);
8
+ // Signal B: Vector similarity search
9
+ const [queryVector] = await embed([query]);
10
+ const allEmbeddings = indexer.embeddingStore.getAll();
11
+ const vectorScores = [];
12
+ for (const [chunkId, vec] of allEmbeddings) {
13
+ const score = cosineSimilarity(queryVector, vec);
14
+ vectorScores.push({ chunkId, score });
15
+ }
16
+ vectorScores.sort((a, b) => b.score - a.score);
17
+ const topVector = vectorScores.slice(0, 50);
18
+ // Build file cache for PageRank lookup
19
+ const fileCache = new Map();
20
+ for (const f of indexer.fileStore.getAll()) {
21
+ fileCache.set(f.id, f);
22
+ }
23
+ // Reciprocal Rank Fusion
24
+ const rrfScores = new Map();
25
+ // Add FTS scores
26
+ for (let rank = 0; rank < ftsResults.length; rank++) {
27
+ const chunkId = ftsResults[rank].id;
28
+ const score = 1 / (RRF_K + rank + 1);
29
+ rrfScores.set(chunkId, (rrfScores.get(chunkId) || 0) + score);
30
+ }
31
+ // Add vector scores
32
+ for (let rank = 0; rank < topVector.length; rank++) {
33
+ const chunkId = topVector[rank].chunkId;
34
+ const score = 1 / (RRF_K + rank + 1);
35
+ rrfScores.set(chunkId, (rrfScores.get(chunkId) || 0) + score);
36
+ }
37
+ // Collect candidates with full data
38
+ const candidates = [];
39
+ for (const [chunkId, rrfScore] of rrfScores) {
40
+ const chunk = indexer.chunkStore.getById(chunkId);
41
+ if (!chunk)
42
+ continue;
43
+ const file = fileCache.get(chunk.file_id);
44
+ if (!file)
45
+ continue;
46
+ // Apply filters
47
+ if (scope && !file.path.startsWith(scope))
48
+ continue;
49
+ if (language && file.language !== language)
50
+ continue;
51
+ if (type && type !== "any" && chunk.type !== type)
52
+ continue;
53
+ // Boost by PageRank
54
+ const pagerankBoost = 1 + 0.3 * file.pagerank;
55
+ const finalScore = rrfScore * pagerankBoost;
56
+ candidates.push({ chunk, file, score: finalScore });
57
+ }
58
+ // Sort by score
59
+ candidates.sort((a, b) => b.score - a.score);
60
+ // Pack into token budget
61
+ return packResults(candidates, tokenBudget);
62
+ }
63
+ export function packResults(candidates, tokenBudget) {
64
+ const results = [];
65
+ let remaining = tokenBudget;
66
+ for (const candidate of candidates) {
67
+ // Estimate overhead per result (file path, line numbers, formatting)
68
+ const overhead = 30;
69
+ const cost = candidate.chunk.token_count + overhead;
70
+ if (cost <= remaining) {
71
+ results.push(candidate);
72
+ remaining -= cost;
73
+ }
74
+ else if (remaining < 100) {
75
+ break;
76
+ }
77
+ }
78
+ return results;
79
+ }
80
+ export function formatResults(results) {
81
+ if (results.length === 0) {
82
+ return "No results found.";
83
+ }
84
+ const parts = [];
85
+ for (const { chunk, file, score } of results) {
86
+ const header = chunk.name
87
+ ? `## ${file.path}:${chunk.start_line}-${chunk.end_line} (${chunk.type}: ${chunk.name})`
88
+ : `## ${file.path}:${chunk.start_line}-${chunk.end_line} (${chunk.type})`;
89
+ parts.push(header);
90
+ parts.push(`\`\`\`${file.language || ""}`);
91
+ parts.push(chunk.content);
92
+ parts.push("```");
93
+ parts.push("");
94
+ }
95
+ return parts.join("\n");
96
+ }
97
+ //# sourceMappingURL=hybrid-search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hybrid-search.js","sourceRoot":"","sources":["../../../src/search/hybrid-search.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare function computePageRank(fileIds: number[], edges: {
2
+ source: number;
3
+ target: number;
4
+ }[]): Map<number, number>;
@@ -0,0 +1,64 @@
1
+ // PageRank implementation for file importance ranking.
2
+ // Aider's key innovation: apply PageRank to the dependency graph
3
+ // so that structurally important files (many importers) rank higher.
4
+ const DAMPING = 0.85;
5
+ const ITERATIONS = 20;
6
+ const CONVERGENCE_THRESHOLD = 0.0001;
7
+ export function computePageRank(fileIds, edges) {
8
+ const n = fileIds.length;
9
+ if (n === 0)
10
+ return new Map();
11
+ // Build adjacency lists
12
+ const outLinks = new Map();
13
+ const inLinks = new Map();
14
+ for (const id of fileIds) {
15
+ outLinks.set(id, new Set());
16
+ inLinks.set(id, new Set());
17
+ }
18
+ for (const { source, target } of edges) {
19
+ outLinks.get(source)?.add(target);
20
+ inLinks.get(target)?.add(source);
21
+ }
22
+ // Initialize ranks equally
23
+ let ranks = new Map();
24
+ const initialRank = 1 / n;
25
+ for (const id of fileIds) {
26
+ ranks.set(id, initialRank);
27
+ }
28
+ // Iterate
29
+ for (let iter = 0; iter < ITERATIONS; iter++) {
30
+ const newRanks = new Map();
31
+ let maxDelta = 0;
32
+ for (const id of fileIds) {
33
+ let incomingRank = 0;
34
+ const incomers = inLinks.get(id);
35
+ if (incomers) {
36
+ for (const srcId of incomers) {
37
+ const srcOutDegree = outLinks.get(srcId)?.size || 1;
38
+ incomingRank += (ranks.get(srcId) || 0) / srcOutDegree;
39
+ }
40
+ }
41
+ const newRank = (1 - DAMPING) / n + DAMPING * incomingRank;
42
+ newRanks.set(id, newRank);
43
+ const delta = Math.abs(newRank - (ranks.get(id) || 0));
44
+ if (delta > maxDelta)
45
+ maxDelta = delta;
46
+ }
47
+ ranks = newRanks;
48
+ if (maxDelta < CONVERGENCE_THRESHOLD)
49
+ break;
50
+ }
51
+ // Normalize to 0-1 range
52
+ let maxRank = 0;
53
+ for (const r of ranks.values()) {
54
+ if (r > maxRank)
55
+ maxRank = r;
56
+ }
57
+ if (maxRank > 0) {
58
+ for (const [id, r] of ranks) {
59
+ ranks.set(id, r / maxRank);
60
+ }
61
+ }
62
+ return ranks;
63
+ }
64
+ //# sourceMappingURL=pagerank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pagerank.js","sourceRoot":"","sources":["../../../src/search/pagerank.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { FileRecord, CodeChunk } from "../types/index.js";
2
+ export interface OverviewEntry {
3
+ file: FileRecord;
4
+ chunks: CodeChunk[];
5
+ }
6
+ export declare function formatOverview(entries: OverviewEntry[], tokenBudget: number, basePath?: string): string;
7
+ export declare function formatLookup(chunks: (CodeChunk & {
8
+ filePath?: string;
9
+ pagerank?: number;
10
+ })[], files: Map<number, FileRecord>, tokenBudget: number): string;
@@ -0,0 +1,67 @@
1
+ export function formatOverview(entries, tokenBudget, basePath) {
2
+ const parts = [];
3
+ let remaining = tokenBudget;
4
+ // Group by directory
5
+ const dirs = new Map();
6
+ for (const entry of entries) {
7
+ const dir = entry.file.path.split("/").slice(0, -1).join("/") || ".";
8
+ if (!basePath || dir.startsWith(basePath)) {
9
+ const existing = dirs.get(dir) || [];
10
+ existing.push(entry);
11
+ dirs.set(dir, existing);
12
+ }
13
+ }
14
+ // Sort directories, most important files first within each
15
+ const sortedDirs = [...dirs.entries()].sort((a, b) => {
16
+ const maxA = Math.max(...a[1].map((e) => e.file.pagerank));
17
+ const maxB = Math.max(...b[1].map((e) => e.file.pagerank));
18
+ return maxB - maxA;
19
+ });
20
+ for (const [dir, dirEntries] of sortedDirs) {
21
+ const dirLine = `${dir}/`;
22
+ const dirCost = 5; // tokens for dir header
23
+ if (remaining < dirCost + 20)
24
+ break;
25
+ parts.push(dirLine);
26
+ remaining -= dirCost;
27
+ // Sort files by PageRank within directory
28
+ dirEntries.sort((a, b) => b.file.pagerank - a.file.pagerank);
29
+ for (const entry of dirEntries) {
30
+ const fileName = entry.file.path.split("/").pop() || entry.file.path;
31
+ const symbols = entry.chunks
32
+ .filter((c) => c.name)
33
+ .map((c) => `${c.name}()`)
34
+ .slice(0, 8)
35
+ .join(", ");
36
+ const line = ` ${fileName} [${entry.file.pagerank.toFixed(2)}] — ${symbols || "(no named exports)"}`;
37
+ const lineCost = Math.ceil(line.length / 3.5);
38
+ if (remaining < lineCost)
39
+ break;
40
+ parts.push(line);
41
+ remaining -= lineCost;
42
+ }
43
+ }
44
+ return parts.join("\n");
45
+ }
46
+ export function formatLookup(chunks, files, tokenBudget) {
47
+ const parts = [];
48
+ let remaining = tokenBudget;
49
+ for (const chunk of chunks) {
50
+ const file = files.get(chunk.file_id);
51
+ const filePath = chunk.filePath || file?.path || "unknown";
52
+ const lang = file?.language || "";
53
+ const header = `## ${filePath}:${chunk.start_line}-${chunk.end_line} (${chunk.type}: ${chunk.name})`;
54
+ const headerCost = Math.ceil(header.length / 3.5);
55
+ const contentCost = chunk.token_count;
56
+ const totalCost = headerCost + contentCost + 10;
57
+ if (remaining < totalCost)
58
+ break;
59
+ parts.push(header);
60
+ parts.push(`\`\`\`${lang}`);
61
+ parts.push(chunk.content);
62
+ parts.push("```\n");
63
+ remaining -= totalCost;
64
+ }
65
+ return parts.length > 0 ? parts.join("\n") : "No results found.";
66
+ }
67
+ //# sourceMappingURL=token-budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-budget.js","sourceRoot":"","sources":["../../../src/search/token-budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function startMcpServer(rootPath: string): Promise<void>;
@@ -0,0 +1,120 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
+ import { Indexer } from "../indexer/indexer.js";
5
+ import { startWatcher } from "../indexer/watcher.js";
6
+ import { getProjectConfig } from "../utils/config.js";
7
+ import { log, logError } from "../utils/logger.js";
8
+ import { searchTool, handleSearch } from "./tools/search.js";
9
+ import { overviewTool, handleOverview } from "./tools/overview.js";
10
+ import { lookupTool, handleLookup } from "./tools/lookup.js";
11
+ import { findReferencesTool, handleFindReferences, } from "./tools/find-references.js";
12
+ import { dependenciesTool, handleDependencies, } from "./tools/dependencies.js";
13
+ import { indexStatusTool, handleIndexStatus, } from "./tools/index-status.js";
14
+ import { rememberTool, handleRemember } from "./tools/remember.js";
15
+ import { recallTool, handleRecall } from "./tools/recall.js";
16
+ import { forgetTool, handleForget } from "./tools/forget.js";
17
+ import { memoriesTool, handleMemories } from "./tools/memories.js";
18
+ export async function startMcpServer(rootPath) {
19
+ const config = getProjectConfig(rootPath);
20
+ const indexer = new Indexer(config);
21
+ // Start indexing in background
22
+ const indexPromise = indexer.index().catch((err) => {
23
+ logError("Initial indexing failed", err);
24
+ });
25
+ // Start file watcher
26
+ startWatcher(indexer, rootPath);
27
+ const server = new Server({
28
+ name: "sverklo",
29
+ version: "0.1.0",
30
+ }, {
31
+ capabilities: {
32
+ tools: {},
33
+ },
34
+ });
35
+ // List tools
36
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
37
+ tools: [
38
+ searchTool,
39
+ overviewTool,
40
+ lookupTool,
41
+ findReferencesTool,
42
+ dependenciesTool,
43
+ indexStatusTool,
44
+ rememberTool,
45
+ recallTool,
46
+ forgetTool,
47
+ memoriesTool,
48
+ ],
49
+ }));
50
+ // Handle tool calls
51
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
52
+ const { name, arguments: args } = request.params;
53
+ // Ensure index is ready for search operations
54
+ if (name !== "index_status") {
55
+ await indexPromise;
56
+ }
57
+ try {
58
+ let result;
59
+ switch (name) {
60
+ case "search":
61
+ result = await handleSearch(indexer, args || {});
62
+ break;
63
+ case "overview":
64
+ result = handleOverview(indexer, args || {});
65
+ break;
66
+ case "lookup":
67
+ result = handleLookup(indexer, args || {});
68
+ break;
69
+ case "find_references":
70
+ result = handleFindReferences(indexer, args || {});
71
+ break;
72
+ case "dependencies":
73
+ result = handleDependencies(indexer, args || {});
74
+ break;
75
+ case "index_status":
76
+ result = handleIndexStatus(indexer);
77
+ break;
78
+ case "remember":
79
+ result = await handleRemember(indexer, args || {});
80
+ break;
81
+ case "recall":
82
+ result = await handleRecall(indexer, args || {});
83
+ break;
84
+ case "forget":
85
+ result = handleForget(indexer, args || {});
86
+ break;
87
+ case "memories":
88
+ result = handleMemories(indexer, args || {});
89
+ break;
90
+ default:
91
+ result = `Unknown tool: ${name}`;
92
+ }
93
+ return {
94
+ content: [{ type: "text", text: result }],
95
+ };
96
+ }
97
+ catch (err) {
98
+ const message = err instanceof Error ? err.message : "Unknown error";
99
+ logError(`Tool ${name} failed`, err);
100
+ return {
101
+ content: [{ type: "text", text: `Error: ${message}` }],
102
+ isError: true,
103
+ };
104
+ }
105
+ });
106
+ // Connect via stdio
107
+ const transport = new StdioServerTransport();
108
+ await server.connect(transport);
109
+ log(`MCP server started for ${rootPath}`);
110
+ // Handle shutdown
111
+ process.on("SIGINT", () => {
112
+ indexer.close();
113
+ process.exit(0);
114
+ });
115
+ process.on("SIGTERM", () => {
116
+ indexer.close();
117
+ process.exit(0);
118
+ });
119
+ }
120
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../../src/server/mcp-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { Indexer } from "../../indexer/indexer.js";
2
+ export declare const dependenciesTool: {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: "object";
7
+ properties: {
8
+ path: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ direction: {
13
+ type: string;
14
+ enum: string[];
15
+ description: string;
16
+ };
17
+ depth: {
18
+ type: string;
19
+ description: string;
20
+ };
21
+ token_budget: {
22
+ type: string;
23
+ description: string;
24
+ };
25
+ };
26
+ required: string[];
27
+ };
28
+ };
29
+ export declare function handleDependencies(indexer: Indexer, args: Record<string, unknown>): string;
@@ -0,0 +1,118 @@
1
+ export const dependenciesTool = {
2
+ name: "dependencies",
3
+ description: "Show what a file imports/depends on and what depends on it. Helps understand the impact of changing a file.",
4
+ inputSchema: {
5
+ type: "object",
6
+ properties: {
7
+ path: {
8
+ type: "string",
9
+ description: "File path to analyze",
10
+ },
11
+ direction: {
12
+ type: "string",
13
+ enum: ["imports", "importers", "both"],
14
+ description: "Direction of dependencies (default: both)",
15
+ },
16
+ depth: {
17
+ type: "number",
18
+ description: "How many levels deep to traverse (default: 1)",
19
+ },
20
+ token_budget: {
21
+ type: "number",
22
+ description: "Max tokens to return (default: 2000)",
23
+ },
24
+ },
25
+ required: ["path"],
26
+ },
27
+ };
28
+ export function handleDependencies(indexer, args) {
29
+ const path = args.path;
30
+ const direction = args.direction || "both";
31
+ const depth = args.depth || 1;
32
+ const tokenBudget = args.token_budget || 2000;
33
+ const file = indexer.fileStore.getByPath(path);
34
+ if (!file) {
35
+ return `File not found in index: ${path}`;
36
+ }
37
+ const fileCache = new Map();
38
+ for (const f of indexer.fileStore.getAll()) {
39
+ fileCache.set(f.id, f);
40
+ }
41
+ const parts = [];
42
+ let remaining = tokenBudget;
43
+ parts.push(`## Dependencies for ${path}\n`);
44
+ remaining -= 20;
45
+ if (direction === "imports" || direction === "both") {
46
+ parts.push("### This file imports:");
47
+ remaining -= 10;
48
+ const visited = new Set();
49
+ const queue = [
50
+ { fileId: file.id, depth: 0 },
51
+ ];
52
+ while (queue.length > 0) {
53
+ const { fileId, depth: d } = queue.shift();
54
+ if (d >= depth)
55
+ continue;
56
+ if (visited.has(fileId))
57
+ continue;
58
+ visited.add(fileId);
59
+ const deps = indexer.graphStore.getImports(fileId);
60
+ for (const dep of deps) {
61
+ const targetFile = fileCache.get(dep.target_file_id);
62
+ if (!targetFile)
63
+ continue;
64
+ const indent = " ".repeat(d + 1);
65
+ const line = `${indent}→ ${targetFile.path} (${dep.reference_count} refs)`;
66
+ const cost = Math.ceil(line.length / 3.5);
67
+ if (remaining < cost)
68
+ break;
69
+ parts.push(line);
70
+ remaining -= cost;
71
+ if (d + 1 < depth) {
72
+ queue.push({ fileId: dep.target_file_id, depth: d + 1 });
73
+ }
74
+ }
75
+ }
76
+ if (parts[parts.length - 1] === "### This file imports:") {
77
+ parts.push(" (none)");
78
+ }
79
+ parts.push("");
80
+ }
81
+ if (direction === "importers" || direction === "both") {
82
+ parts.push("### Files that import this:");
83
+ remaining -= 10;
84
+ const visited = new Set();
85
+ const queue = [
86
+ { fileId: file.id, depth: 0 },
87
+ ];
88
+ while (queue.length > 0) {
89
+ const { fileId, depth: d } = queue.shift();
90
+ if (d >= depth)
91
+ continue;
92
+ if (visited.has(fileId))
93
+ continue;
94
+ visited.add(fileId);
95
+ const importers = indexer.graphStore.getImporters(fileId);
96
+ for (const imp of importers) {
97
+ const sourceFile = fileCache.get(imp.source_file_id);
98
+ if (!sourceFile)
99
+ continue;
100
+ const indent = " ".repeat(d + 1);
101
+ const line = `${indent}← ${sourceFile.path} (${imp.reference_count} refs)`;
102
+ const cost = Math.ceil(line.length / 3.5);
103
+ if (remaining < cost)
104
+ break;
105
+ parts.push(line);
106
+ remaining -= cost;
107
+ if (d + 1 < depth) {
108
+ queue.push({ fileId: imp.source_file_id, depth: d + 1 });
109
+ }
110
+ }
111
+ }
112
+ if (parts[parts.length - 1] === "### Files that import this:") {
113
+ parts.push(" (none)");
114
+ }
115
+ }
116
+ return parts.join("\n");
117
+ }
118
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../../src/server/tools/dependencies.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,6GAA6G;IAC/G,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sBAAsB;aACpC;YACD,SAAS,EAAE;gBACT,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC;gBACtC,WAAW,EAAE,2CAA2C;aACzD;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,+CAA+C;aAC7D;YACD,YAAY,EAAE;gBACZ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,sCAAsC;aACpD;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;KACnB;CACF,CAAC;AAEF,MAAM,UAAU,kBAAkB,CAChC,OAAgB,EAChB,IAA6B;IAE7B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAc,CAAC;IACjC,MAAM,SAAS,GAAI,IAAI,CAAC,SAAoB,IAAI,MAAM,CAAC;IACvD,MAAM,KAAK,GAAI,IAAI,CAAC,KAAgB,IAAI,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAI,IAAI,CAAC,YAAuB,IAAI,IAAI,CAAC;IAE1D,MAAM,IAAI,GAAG,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,4BAA4B,IAAI,EAAE,CAAC;IAC5C,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3C,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,SAAS,GAAG,WAAW,CAAC;IAE5B,KAAK,CAAC,IAAI,CAAC,uBAAuB,IAAI,IAAI,CAAC,CAAC;IAC5C,SAAS,IAAI,EAAE,CAAC;IAEhB,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,SAAS,IAAI,EAAE,CAAC;QAEhB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,KAAK,GAAwC;YACjD,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;SAC9B,CAAC;QAEF,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YAC5C,IAAI,CAAC,IAAI,KAAK;gBAAE,SAAS;YACzB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAEpB,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YACnD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACrD,IAAI,CAAC,UAAU;oBAAE,SAAS;gBAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,MAAM,IAAI,GAAG,GAAG,MAAM,KAAK,UAAU,CAAC,IAAI,KAAK,GAAG,CAAC,eAAe,QAAQ,CAAC;gBAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;gBAC1C,IAAI,SAAS,GAAG,IAAI;oBAAE,MAAM;gBAE5B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,SAAS,IAAI,IAAI,CAAC;gBAElB,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC;oBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC3D,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,wBAAwB,EAAE,CAAC;YACzD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC1C,SAAS,IAAI,EAAE,CAAC;QAEhB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAClC,MAAM,KAAK,GAAwC;YACjD,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE;SAC9B,CAAC;QAEF,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YAC5C,IAAI,CAAC,IAAI,KAAK;gBAAE,SAAS;YACzB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,SAAS;YAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAEpB,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC1D,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;gBAC5B,MAAM,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACrD,IAAI,CAAC,UAAU;oBAAE,SAAS;gBAE1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAClC,MAAM,IAAI,GAAG,GAAG,MAAM,KAAK,UAAU,CAAC,IAAI,KAAK,GAAG,CAAC,eAAe,QAAQ,CAAC;gBAC3E,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;gBAC1C,IAAI,SAAS,GAAG,IAAI;oBAAE,MAAM;gBAE5B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjB,SAAS,IAAI,IAAI,CAAC;gBAElB,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,EAAE,CAAC;oBAClB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC3D,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,6BAA6B,EAAE,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Indexer } from "../../indexer/indexer.js";
2
+ export declare const findReferencesTool: {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ type: "object";
7
+ properties: {
8
+ symbol: {
9
+ type: string;
10
+ description: string;
11
+ };
12
+ token_budget: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ };
17
+ required: string[];
18
+ };
19
+ };
20
+ export declare function handleFindReferences(indexer: Indexer, args: Record<string, unknown>): string;