purecontext-mcp 1.1.7 → 1.2.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 (182) hide show
  1. package/AGENT_INSTRUCTIONS.md +393 -0
  2. package/AGENT_INSTRUCTIONS_SHORT.md +53 -0
  3. package/AST-SEARCH.md +274 -0
  4. package/CHANGELOG.md +62 -0
  5. package/CODE-INTELLIGENCE.md +369 -0
  6. package/HEALTH-DASHBOARDS.md +241 -0
  7. package/README.md +7 -0
  8. package/REFACTORING-SAFELY.md +279 -0
  9. package/UNDERSTANDING-RELATIONSHIPS.md +240 -0
  10. package/USER-GUIDE.md +14 -0
  11. package/VISUALIZING-CODE.md +199 -0
  12. package/WORKFLOW-TECH-DEBT.md +286 -0
  13. package/dist/core/db/dep-store.d.ts +75 -0
  14. package/dist/core/db/dep-store.d.ts.map +1 -1
  15. package/dist/core/db/dep-store.js +277 -0
  16. package/dist/core/db/dep-store.js.map +1 -1
  17. package/dist/core/db/schema.d.ts.map +1 -1
  18. package/dist/core/db/schema.js +12 -0
  19. package/dist/core/db/schema.js.map +1 -1
  20. package/dist/core/index-manager.js +1 -1
  21. package/dist/core/index-manager.js.map +1 -1
  22. package/dist/core/token-tracker.d.ts +0 -9
  23. package/dist/core/token-tracker.d.ts.map +1 -1
  24. package/dist/core/token-tracker.js +0 -21
  25. package/dist/core/token-tracker.js.map +1 -1
  26. package/dist/core/types.d.ts +5 -0
  27. package/dist/core/types.d.ts.map +1 -1
  28. package/dist/graph/diagram-renderer.d.ts +83 -0
  29. package/dist/graph/diagram-renderer.d.ts.map +1 -0
  30. package/dist/graph/diagram-renderer.js +294 -0
  31. package/dist/graph/diagram-renderer.js.map +1 -0
  32. package/dist/graph/graph-traversal.d.ts +92 -0
  33. package/dist/graph/graph-traversal.d.ts.map +1 -1
  34. package/dist/graph/graph-traversal.js +440 -2
  35. package/dist/graph/graph-traversal.js.map +1 -1
  36. package/dist/server/http-server.d.ts.map +1 -1
  37. package/dist/server/http-server.js +30 -1
  38. package/dist/server/http-server.js.map +1 -1
  39. package/dist/server/mcp-server.d.ts.map +1 -1
  40. package/dist/server/mcp-server.js +145 -0
  41. package/dist/server/mcp-server.js.map +1 -1
  42. package/dist/server/tools/_meta.d.ts +0 -2
  43. package/dist/server/tools/_meta.d.ts.map +1 -1
  44. package/dist/server/tools/_meta.js +1 -4
  45. package/dist/server/tools/_meta.js.map +1 -1
  46. package/dist/server/tools/check-delete-safe.d.ts +50 -0
  47. package/dist/server/tools/check-delete-safe.d.ts.map +1 -0
  48. package/dist/server/tools/check-delete-safe.js +308 -0
  49. package/dist/server/tools/check-delete-safe.js.map +1 -0
  50. package/dist/server/tools/check-move-safe.d.ts +44 -0
  51. package/dist/server/tools/check-move-safe.d.ts.map +1 -0
  52. package/dist/server/tools/check-move-safe.js +266 -0
  53. package/dist/server/tools/check-move-safe.js.map +1 -0
  54. package/dist/server/tools/check-rename-safe.d.ts +48 -0
  55. package/dist/server/tools/check-rename-safe.d.ts.map +1 -0
  56. package/dist/server/tools/check-rename-safe.js +218 -0
  57. package/dist/server/tools/check-rename-safe.js.map +1 -0
  58. package/dist/server/tools/diff-health-radar.d.ts +44 -0
  59. package/dist/server/tools/diff-health-radar.d.ts.map +1 -0
  60. package/dist/server/tools/diff-health-radar.js +192 -0
  61. package/dist/server/tools/diff-health-radar.js.map +1 -0
  62. package/dist/server/tools/find-cycles.d.ts +31 -0
  63. package/dist/server/tools/find-cycles.d.ts.map +1 -0
  64. package/dist/server/tools/find-cycles.js +85 -0
  65. package/dist/server/tools/find-cycles.js.map +1 -0
  66. package/dist/server/tools/find-implementations.d.ts +47 -0
  67. package/dist/server/tools/find-implementations.d.ts.map +1 -0
  68. package/dist/server/tools/find-implementations.js +167 -0
  69. package/dist/server/tools/find-implementations.js.map +1 -0
  70. package/dist/server/tools/find-untested-symbols.d.ts +52 -0
  71. package/dist/server/tools/find-untested-symbols.d.ts.map +1 -0
  72. package/dist/server/tools/find-untested-symbols.js +308 -0
  73. package/dist/server/tools/find-untested-symbols.js.map +1 -0
  74. package/dist/server/tools/get-architecture-snapshot.d.ts +43 -0
  75. package/dist/server/tools/get-architecture-snapshot.d.ts.map +1 -0
  76. package/dist/server/tools/get-architecture-snapshot.js +292 -0
  77. package/dist/server/tools/get-architecture-snapshot.js.map +1 -0
  78. package/dist/server/tools/get-call-hierarchy.d.ts +43 -0
  79. package/dist/server/tools/get-call-hierarchy.d.ts.map +1 -0
  80. package/dist/server/tools/get-call-hierarchy.js +119 -0
  81. package/dist/server/tools/get-call-hierarchy.js.map +1 -0
  82. package/dist/server/tools/get-class-hierarchy.d.ts +36 -0
  83. package/dist/server/tools/get-class-hierarchy.d.ts.map +1 -0
  84. package/dist/server/tools/get-class-hierarchy.js +125 -0
  85. package/dist/server/tools/get-class-hierarchy.js.map +1 -0
  86. package/dist/server/tools/get-complexity-hotspots.d.ts +50 -0
  87. package/dist/server/tools/get-complexity-hotspots.d.ts.map +1 -0
  88. package/dist/server/tools/get-complexity-hotspots.js +282 -0
  89. package/dist/server/tools/get-complexity-hotspots.js.map +1 -0
  90. package/dist/server/tools/get-coupling-map.d.ts +39 -0
  91. package/dist/server/tools/get-coupling-map.d.ts.map +1 -0
  92. package/dist/server/tools/get-coupling-map.js +107 -0
  93. package/dist/server/tools/get-coupling-map.js.map +1 -0
  94. package/dist/server/tools/get-debt-report.d.ts +44 -0
  95. package/dist/server/tools/get-debt-report.d.ts.map +1 -0
  96. package/dist/server/tools/get-debt-report.js +606 -0
  97. package/dist/server/tools/get-debt-report.js.map +1 -0
  98. package/dist/server/tools/get-entry-points.d.ts +79 -0
  99. package/dist/server/tools/get-entry-points.d.ts.map +1 -0
  100. package/dist/server/tools/get-entry-points.js +362 -0
  101. package/dist/server/tools/get-entry-points.js.map +1 -0
  102. package/dist/server/tools/get-public-api.d.ts +53 -0
  103. package/dist/server/tools/get-public-api.d.ts.map +1 -0
  104. package/dist/server/tools/get-public-api.js +218 -0
  105. package/dist/server/tools/get-public-api.js.map +1 -0
  106. package/dist/server/tools/get-savings-stats.d.ts.map +1 -1
  107. package/dist/server/tools/get-savings-stats.js +1 -3
  108. package/dist/server/tools/get-savings-stats.js.map +1 -1
  109. package/dist/server/tools/get-test-coverage-map.d.ts +66 -0
  110. package/dist/server/tools/get-test-coverage-map.d.ts.map +1 -0
  111. package/dist/server/tools/get-test-coverage-map.js +588 -0
  112. package/dist/server/tools/get-test-coverage-map.js.map +1 -0
  113. package/dist/server/tools/get-todos.d.ts +51 -0
  114. package/dist/server/tools/get-todos.d.ts.map +1 -0
  115. package/dist/server/tools/get-todos.js +180 -0
  116. package/dist/server/tools/get-todos.js.map +1 -0
  117. package/dist/server/tools/get-type-graph.d.ts +73 -0
  118. package/dist/server/tools/get-type-graph.d.ts.map +1 -0
  119. package/dist/server/tools/get-type-graph.js +437 -0
  120. package/dist/server/tools/get-type-graph.js.map +1 -0
  121. package/dist/server/tools/health-radar.d.ts +50 -0
  122. package/dist/server/tools/health-radar.d.ts.map +1 -0
  123. package/dist/server/tools/health-radar.js +426 -0
  124. package/dist/server/tools/health-radar.js.map +1 -0
  125. package/dist/server/tools/plan-refactoring.d.ts +74 -0
  126. package/dist/server/tools/plan-refactoring.d.ts.map +1 -0
  127. package/dist/server/tools/plan-refactoring.js +644 -0
  128. package/dist/server/tools/plan-refactoring.js.map +1 -0
  129. package/dist/server/tools/render-call-graph.d.ts +40 -0
  130. package/dist/server/tools/render-call-graph.d.ts.map +1 -0
  131. package/dist/server/tools/render-call-graph.js +215 -0
  132. package/dist/server/tools/render-call-graph.js.map +1 -0
  133. package/dist/server/tools/render-class-hierarchy.d.ts +42 -0
  134. package/dist/server/tools/render-class-hierarchy.d.ts.map +1 -0
  135. package/dist/server/tools/render-class-hierarchy.js +265 -0
  136. package/dist/server/tools/render-class-hierarchy.js.map +1 -0
  137. package/dist/server/tools/render-dep-matrix.d.ts +38 -0
  138. package/dist/server/tools/render-dep-matrix.d.ts.map +1 -0
  139. package/dist/server/tools/render-dep-matrix.js +186 -0
  140. package/dist/server/tools/render-dep-matrix.js.map +1 -0
  141. package/dist/server/tools/render-diagram.d.ts +47 -0
  142. package/dist/server/tools/render-diagram.d.ts.map +1 -0
  143. package/dist/server/tools/render-diagram.js +266 -0
  144. package/dist/server/tools/render-diagram.js.map +1 -0
  145. package/dist/server/tools/render-import-graph.d.ts +41 -0
  146. package/dist/server/tools/render-import-graph.d.ts.map +1 -0
  147. package/dist/server/tools/render-import-graph.js +158 -0
  148. package/dist/server/tools/render-import-graph.js.map +1 -0
  149. package/dist/server/tools/search-ast.d.ts +55 -0
  150. package/dist/server/tools/search-ast.d.ts.map +1 -0
  151. package/dist/server/tools/search-ast.js +279 -0
  152. package/dist/server/tools/search-ast.js.map +1 -0
  153. package/dist/server/tools/search-by-complexity.d.ts +92 -0
  154. package/dist/server/tools/search-by-complexity.d.ts.map +1 -0
  155. package/dist/server/tools/search-by-complexity.js +268 -0
  156. package/dist/server/tools/search-by-complexity.js.map +1 -0
  157. package/dist/server/tools/search-by-decorator.d.ts +48 -0
  158. package/dist/server/tools/search-by-decorator.d.ts.map +1 -0
  159. package/dist/server/tools/search-by-decorator.js +518 -0
  160. package/dist/server/tools/search-by-decorator.js.map +1 -0
  161. package/dist/server/tools/search-by-signature.d.ts +56 -0
  162. package/dist/server/tools/search-by-signature.d.ts.map +1 -0
  163. package/dist/server/tools/search-by-signature.js +200 -0
  164. package/dist/server/tools/search-by-signature.js.map +1 -0
  165. package/dist/ui/assets/BlastRadius-QdgESOL8.js +1 -0
  166. package/dist/ui/assets/{DependencyGraph-CDtBHM0U.js → DependencyGraph-BSMhzwWV.js} +6 -6
  167. package/dist/ui/assets/{NotFound-Cdt6X8pl.js → NotFound-CipFP_s1.js} +1 -1
  168. package/dist/ui/assets/RepoDetail-Dfp5z5Kq.js +1 -0
  169. package/dist/ui/assets/{RepoList-B9LaZvob.js → RepoList-BKtST3hB.js} +1 -1
  170. package/dist/ui/assets/{Search-CLqv2KGV.js → Search-DzhGDViy.js} +1 -1
  171. package/dist/ui/assets/{SymbolView-BlbDR1DU.js → SymbolView-ryVEwAHG.js} +1 -1
  172. package/dist/ui/assets/{index-DADf5y_L.css → index-Ny8gn9F0.css} +1 -1
  173. package/dist/ui/assets/{index-i3Q1XbEh.js → index-nX2chMqi.js} +6 -6
  174. package/dist/ui/assets/{useSearch-mbMk6-M1.js → useSearch-BnBCRKui.js} +1 -1
  175. package/dist/ui/index.html +2 -2
  176. package/dist/version.d.ts +1 -1
  177. package/dist/version.js +1 -1
  178. package/docs/dev/jcodemunch-gap-analysis.md +198 -0
  179. package/package.json +9 -1
  180. package/user-manual.md +2466 -0
  181. package/dist/ui/assets/BlastRadius-BDZWhEk-.js +0 -1
  182. package/dist/ui/assets/RepoDetail-M6WaYbZ3.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-architecture-snapshot.d.ts","sourceRoot":"","sources":["../../../src/server/tools/get-architecture-snapshot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAMxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,eAAO,MAAM,IAAI,8BAA8B,CAAC;AAEhD,eAAO,MAAM,WAAW,QAOqB,CAAC;AAE9C,eAAO,MAAM,WAAW;;;;;;;;;;;CAiBvB,CAAC;AAsJF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,QAAQ,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,cAAc,CAAC,CAwM1B"}
@@ -0,0 +1,292 @@
1
+ /**
2
+ * get-architecture-snapshot.ts
3
+ *
4
+ * MCP tool: get_architecture_snapshot
5
+ *
6
+ * Freeze the current architecture state (dep graph topology + quality metrics)
7
+ * into a named snapshot, and diff two snapshots to show what changed structurally
8
+ * between commits or dates.
9
+ *
10
+ * Actions:
11
+ * 'create' — compute current metrics, store as a snapshot row
12
+ * 'list' — return all snapshots for the repo, newest first
13
+ * 'diff' — compare two snapshot records and return deltas
14
+ * 'delete' — remove a snapshot by ID
15
+ *
16
+ * Storage: `snapshots` table in SQLite — stores aggregated metrics as a JSON
17
+ * blob plus the file list (for filesAdded/filesRemoved diffing).
18
+ * No full graph copies are stored.
19
+ */
20
+ import { z } from 'zod';
21
+ import { randomBytes } from 'crypto';
22
+ import { openDatabase, getRepo } from '../../core/db/schema.js';
23
+ import { getCouplingMap } from '../../core/db/dep-store.js';
24
+ import { findImportCycles } from '../../graph/graph-traversal.js';
25
+ import { buildMeta } from './_meta.js';
26
+ export const name = 'get_architecture_snapshot';
27
+ export const description = 'Freeze the current architecture state into a named snapshot, then diff two snapshots ' +
28
+ 'to measure structural change over time. ' +
29
+ 'action "create": compute fileCount, symbolCount, edgeCount, cycleCount, avgCoupling, ' +
30
+ 'avgComplexity and store them with an optional label. ' +
31
+ 'action "list": return all snapshots for the repo, newest first. ' +
32
+ 'action "diff": compare two snapshots and return deltas (cycleCountDelta < 0 means fewer cycles — good). ' +
33
+ 'action "delete": remove a snapshot by ID.';
34
+ export const inputSchema = {
35
+ repoId: z.string().describe('Repo ID from index_folder or resolve_repo'),
36
+ action: z
37
+ .enum(['create', 'list', 'diff', 'delete'])
38
+ .describe('"create" | "list" | "diff" | "delete"'),
39
+ snapshotId: z
40
+ .string()
41
+ .optional()
42
+ .describe('Snapshot ID — required for diff (snapshotId = base) and delete'),
43
+ compareId: z
44
+ .string()
45
+ .optional()
46
+ .describe('The second snapshot ID to compare against — required for diff'),
47
+ label: z
48
+ .string()
49
+ .optional()
50
+ .describe('Human-readable label for the snapshot (e.g. "before-auth-refactor")'),
51
+ };
52
+ function ensureSnapshotsTable(db) {
53
+ db.exec(`
54
+ CREATE TABLE IF NOT EXISTS snapshots (
55
+ snapshot_id TEXT NOT NULL,
56
+ repo_id TEXT NOT NULL,
57
+ label TEXT NOT NULL DEFAULT '',
58
+ created_at INTEGER NOT NULL,
59
+ metrics TEXT NOT NULL,
60
+ PRIMARY KEY (snapshot_id, repo_id),
61
+ FOREIGN KEY (repo_id) REFERENCES repos(id) ON DELETE CASCADE
62
+ )
63
+ `);
64
+ try {
65
+ db.exec('CREATE INDEX IF NOT EXISTS idx_snapshots_repo ON snapshots(repo_id, created_at)');
66
+ }
67
+ catch {
68
+ // already exists
69
+ }
70
+ }
71
+ function rowToRecord(row) {
72
+ const m = JSON.parse(row.metrics);
73
+ return {
74
+ snapshotId: row.snapshot_id,
75
+ label: row.label,
76
+ createdAt: new Date(row.created_at).toISOString(),
77
+ fileCount: m.fileCount,
78
+ symbolCount: m.symbolCount,
79
+ edgeCount: m.edgeCount,
80
+ cycleCount: m.cycleCount,
81
+ avgCoupling: m.avgCoupling,
82
+ avgComplexity: m.avgComplexity,
83
+ };
84
+ }
85
+ // ─── Metrics computation ──────────────────────────────────────────────────────
86
+ function computeMetrics(db, repoId) {
87
+ // File count
88
+ const fileRow = db
89
+ .prepare('SELECT COUNT(*) AS n FROM files WHERE repo_id = ?')
90
+ .get(repoId);
91
+ const fileCount = fileRow?.n ?? 0;
92
+ // Symbol count
93
+ const symRow = db
94
+ .prepare('SELECT COUNT(*) AS n FROM symbols WHERE repo_id = ?')
95
+ .get(repoId);
96
+ const symbolCount = symRow?.n ?? 0;
97
+ // Edge count
98
+ const edgeRow = db
99
+ .prepare('SELECT COUNT(*) AS n FROM dep_edges WHERE repo_id = ?')
100
+ .get(repoId);
101
+ const edgeCount = edgeRow?.n ?? 0;
102
+ // File paths list
103
+ const filePaths = db
104
+ .prepare('SELECT path FROM files WHERE repo_id = ? ORDER BY path')
105
+ .all(repoId)
106
+ .map((r) => r.path);
107
+ // Cycle count — use DFS-based findImportCycles, cap at 500
108
+ const cyclesResult = findImportCycles(repoId, db, undefined, 500);
109
+ const cycleCount = cyclesResult.cycles.length;
110
+ // Average coupling (efferent + afferent per file / 2 averaged across files)
111
+ const couplingRows = getCouplingMap(db, repoId);
112
+ let avgCoupling = 0;
113
+ if (couplingRows.length > 0) {
114
+ const totalCoupling = couplingRows.reduce((sum, r) => sum + r.efferentCoupling + r.afferentCoupling, 0);
115
+ avgCoupling = Math.round((totalCoupling / couplingRows.length) * 100) / 100;
116
+ }
117
+ // Average cyclomatic complexity from indexed symbols (skip NULLs)
118
+ const complexityRow = db
119
+ .prepare('SELECT AVG(cyclomatic_complexity) AS avg FROM symbols WHERE repo_id = ? AND cyclomatic_complexity IS NOT NULL')
120
+ .get(repoId);
121
+ const avgComplexity = complexityRow?.avg != null
122
+ ? Math.round(complexityRow.avg * 100) / 100
123
+ : 0;
124
+ return { fileCount, symbolCount, edgeCount, cycleCount, avgCoupling, avgComplexity, files: filePaths };
125
+ }
126
+ // ─── Handler ──────────────────────────────────────────────────────────────────
127
+ export async function handler(args) {
128
+ const t0 = Date.now();
129
+ const { repoId, action, snapshotId, compareId, label = '' } = args;
130
+ const db = openDatabase(repoId);
131
+ try {
132
+ const repo = getRepo(db, repoId);
133
+ if (!repo) {
134
+ return {
135
+ content: [
136
+ {
137
+ type: 'text',
138
+ text: JSON.stringify({ error: `Repo "${repoId}" not found. Run index_folder first.` }),
139
+ },
140
+ ],
141
+ isError: true,
142
+ };
143
+ }
144
+ // Ensure the snapshots table exists (safe with IF NOT EXISTS)
145
+ ensureSnapshotsTable(db);
146
+ if (action === 'create') {
147
+ const metrics = computeMetrics(db, repoId);
148
+ const snapId = randomBytes(6).toString('hex'); // 12-char hex
149
+ const now = Date.now();
150
+ db.prepare(`
151
+ INSERT INTO snapshots (snapshot_id, repo_id, label, created_at, metrics)
152
+ VALUES (?, ?, ?, ?, ?)
153
+ `).run(snapId, repoId, label, now, JSON.stringify(metrics));
154
+ const record = {
155
+ snapshotId: snapId,
156
+ label,
157
+ createdAt: new Date(now).toISOString(),
158
+ fileCount: metrics.fileCount,
159
+ symbolCount: metrics.symbolCount,
160
+ edgeCount: metrics.edgeCount,
161
+ cycleCount: metrics.cycleCount,
162
+ avgCoupling: metrics.avgCoupling,
163
+ avgComplexity: metrics.avgComplexity,
164
+ };
165
+ const output = {
166
+ action: 'create',
167
+ snapshot: record,
168
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
169
+ };
170
+ return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
171
+ }
172
+ if (action === 'list') {
173
+ const rows = db
174
+ .prepare('SELECT * FROM snapshots WHERE repo_id = ? ORDER BY created_at DESC')
175
+ .all(repoId);
176
+ const output = {
177
+ action: 'list',
178
+ snapshots: rows.map(rowToRecord),
179
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
180
+ };
181
+ return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
182
+ }
183
+ if (action === 'diff') {
184
+ if (!snapshotId || !compareId) {
185
+ return {
186
+ content: [
187
+ {
188
+ type: 'text',
189
+ text: JSON.stringify({
190
+ error: 'action "diff" requires both snapshotId (base) and compareId (compare).',
191
+ }),
192
+ },
193
+ ],
194
+ isError: true,
195
+ };
196
+ }
197
+ const baseRow = db
198
+ .prepare('SELECT * FROM snapshots WHERE snapshot_id = ? AND repo_id = ?')
199
+ .get(snapshotId, repoId);
200
+ const compareRow = db
201
+ .prepare('SELECT * FROM snapshots WHERE snapshot_id = ? AND repo_id = ?')
202
+ .get(compareId, repoId);
203
+ if (!baseRow) {
204
+ return {
205
+ content: [
206
+ {
207
+ type: 'text',
208
+ text: JSON.stringify({ error: `Snapshot "${snapshotId}" not found.` }),
209
+ },
210
+ ],
211
+ isError: true,
212
+ };
213
+ }
214
+ if (!compareRow) {
215
+ return {
216
+ content: [
217
+ {
218
+ type: 'text',
219
+ text: JSON.stringify({ error: `Snapshot "${compareId}" not found.` }),
220
+ },
221
+ ],
222
+ isError: true,
223
+ };
224
+ }
225
+ const baseMetrics = JSON.parse(baseRow.metrics);
226
+ const compareMetrics = JSON.parse(compareRow.metrics);
227
+ const baseFiles = new Set(baseMetrics.files);
228
+ const compareFiles = new Set(compareMetrics.files);
229
+ const filesAdded = compareMetrics.files.filter((f) => !baseFiles.has(f));
230
+ const filesRemoved = baseMetrics.files.filter((f) => !compareFiles.has(f));
231
+ const diff = {
232
+ filesAdded,
233
+ filesRemoved,
234
+ symbolsAdded: Math.max(0, compareMetrics.symbolCount - baseMetrics.symbolCount),
235
+ symbolsRemoved: Math.max(0, baseMetrics.symbolCount - compareMetrics.symbolCount),
236
+ edgesAdded: Math.max(0, compareMetrics.edgeCount - baseMetrics.edgeCount),
237
+ edgesRemoved: Math.max(0, baseMetrics.edgeCount - compareMetrics.edgeCount),
238
+ cycleCountDelta: compareMetrics.cycleCount - baseMetrics.cycleCount,
239
+ avgCouplingDelta: Math.round((compareMetrics.avgCoupling - baseMetrics.avgCoupling) * 100) / 100,
240
+ avgComplexityDelta: Math.round((compareMetrics.avgComplexity - baseMetrics.avgComplexity) * 100) / 100,
241
+ };
242
+ const output = {
243
+ action: 'diff',
244
+ snapshot: rowToRecord(baseRow),
245
+ diff,
246
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
247
+ };
248
+ return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
249
+ }
250
+ if (action === 'delete') {
251
+ if (!snapshotId) {
252
+ return {
253
+ content: [
254
+ {
255
+ type: 'text',
256
+ text: JSON.stringify({ error: 'action "delete" requires snapshotId.' }),
257
+ },
258
+ ],
259
+ isError: true,
260
+ };
261
+ }
262
+ const result = db
263
+ .prepare('DELETE FROM snapshots WHERE snapshot_id = ? AND repo_id = ?')
264
+ .run(snapshotId, repoId);
265
+ if (result.changes === 0) {
266
+ return {
267
+ content: [
268
+ {
269
+ type: 'text',
270
+ text: JSON.stringify({ error: `Snapshot "${snapshotId}" not found.` }),
271
+ },
272
+ ],
273
+ isError: true,
274
+ };
275
+ }
276
+ const output = {
277
+ action: 'delete',
278
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
279
+ };
280
+ return { content: [{ type: 'text', text: JSON.stringify(output, null, 2) }] };
281
+ }
282
+ // Should never reach here (Zod enum validation prevents it)
283
+ return {
284
+ content: [{ type: 'text', text: JSON.stringify({ error: `Unknown action: ${action}` }) }],
285
+ isError: true,
286
+ };
287
+ }
288
+ finally {
289
+ db.close();
290
+ }
291
+ }
292
+ //# sourceMappingURL=get-architecture-snapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-architecture-snapshot.js","sourceRoot":"","sources":["../../../src/server/tools/get-architecture-snapshot.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * get-call-hierarchy.ts
3
+ *
4
+ * MCP tool: get_call_hierarchy
5
+ *
6
+ * Return the callers and callees of a function, N levels deep, as a tree
7
+ * structure. Unlike get_blast_radius (file-level, reverse-only) and
8
+ * find_references (flat call sites), this tool returns a hierarchical view
9
+ * of the call stack suitable for understanding execution flow.
10
+ *
11
+ * Direction options:
12
+ * - 'callees' — what does this function call? (forward walk)
13
+ * - 'callers' — what calls this function? (reverse walk)
14
+ * - 'both' — bidirectional tree: callers above root, callees below
15
+ *
16
+ * Cycle detection: recursive calls are included as leaf nodes with
17
+ * `cyclic: true` to prevent infinite expansion.
18
+ */
19
+ import { z } from 'zod';
20
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
21
+ export declare const name = "get_call_hierarchy";
22
+ export declare const description: string;
23
+ export declare const inputSchema: {
24
+ repoId: z.ZodString;
25
+ symbolId: z.ZodString;
26
+ direction: z.ZodEnum<{
27
+ both: "both";
28
+ callers: "callers";
29
+ callees: "callees";
30
+ }>;
31
+ maxDepth: z.ZodOptional<z.ZodNumber>;
32
+ maxNodes: z.ZodOptional<z.ZodNumber>;
33
+ maxTokens: z.ZodOptional<z.ZodNumber>;
34
+ };
35
+ export declare function handler(args: {
36
+ repoId: string;
37
+ symbolId: string;
38
+ direction: 'callers' | 'callees' | 'both';
39
+ maxDepth?: number;
40
+ maxNodes?: number;
41
+ maxTokens?: number;
42
+ }): Promise<CallToolResult>;
43
+ //# sourceMappingURL=get-call-hierarchy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-call-hierarchy.d.ts","sourceRoot":"","sources":["../../../src/server/tools/get-call-hierarchy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,eAAO,MAAM,IAAI,uBAAuB,CAAC;AAEzC,eAAO,MAAM,WAAW,QAK2C,CAAC;AAEpE,eAAO,MAAM,WAAW;;;;;;;;;;;CAuCvB,CAAC;AA2BF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,cAAc,CAAC,CAoE1B"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * get-call-hierarchy.ts
3
+ *
4
+ * MCP tool: get_call_hierarchy
5
+ *
6
+ * Return the callers and callees of a function, N levels deep, as a tree
7
+ * structure. Unlike get_blast_radius (file-level, reverse-only) and
8
+ * find_references (flat call sites), this tool returns a hierarchical view
9
+ * of the call stack suitable for understanding execution flow.
10
+ *
11
+ * Direction options:
12
+ * - 'callees' — what does this function call? (forward walk)
13
+ * - 'callers' — what calls this function? (reverse walk)
14
+ * - 'both' — bidirectional tree: callers above root, callees below
15
+ *
16
+ * Cycle detection: recursive calls are included as leaf nodes with
17
+ * `cyclic: true` to prevent infinite expansion.
18
+ */
19
+ import { z } from 'zod';
20
+ import { openDatabase, getRepo } from '../../core/db/schema.js';
21
+ import { buildCallHierarchy } from '../../graph/graph-traversal.js';
22
+ import { buildMeta } from './_meta.js';
23
+ export const name = 'get_call_hierarchy';
24
+ export const description = 'Return the callers and callees of a function, N levels deep, as a tree ' +
25
+ 'structure. Use direction="callees" to see what a function calls, ' +
26
+ '"callers" to see what calls it, or "both" for a bidirectional view. ' +
27
+ 'Recursive functions are detected and marked with cyclic=true. ' +
28
+ 'Use search_symbols to find the symbolId for the function first.';
29
+ export const inputSchema = {
30
+ repoId: z.string().describe('Repo ID from index_folder or resolve_repo'),
31
+ symbolId: z
32
+ .string()
33
+ .describe('Symbol ID of the function or method to build the hierarchy for'),
34
+ direction: z
35
+ .enum(['callers', 'callees', 'both'])
36
+ .describe('"callees" — what this function calls; ' +
37
+ '"callers" — what calls this function; ' +
38
+ '"both" — bidirectional (callers and callees combined at each level)'),
39
+ maxDepth: z
40
+ .number()
41
+ .int()
42
+ .min(1)
43
+ .max(6)
44
+ .optional()
45
+ .describe('Maximum tree depth (default 3, max 6)'),
46
+ maxNodes: z
47
+ .number()
48
+ .int()
49
+ .min(1)
50
+ .max(500)
51
+ .optional()
52
+ .describe('Stop expanding the tree once total nodes reach this count (default 50). ' +
53
+ 'When hit, truncated=true is set in the response.'),
54
+ maxTokens: z
55
+ .number()
56
+ .int()
57
+ .min(100)
58
+ .optional()
59
+ .describe('Soft cap on response size in tokens. ' +
60
+ 'When the estimated token count exceeds this value, the tree is returned as-is ' +
61
+ 'with truncated=true.'),
62
+ };
63
+ // ─── Handler ──────────────────────────────────────────────────────────────────
64
+ export async function handler(args) {
65
+ const t0 = Date.now();
66
+ const { repoId, symbolId, direction, maxDepth = 3, maxNodes = 50, maxTokens, } = args;
67
+ const db = openDatabase(repoId);
68
+ try {
69
+ const repo = getRepo(db, repoId);
70
+ if (!repo) {
71
+ return {
72
+ content: [
73
+ {
74
+ type: 'text',
75
+ text: JSON.stringify({
76
+ error: `Repo "${repoId}" not found. Run index_folder first.`,
77
+ }),
78
+ },
79
+ ],
80
+ isError: true,
81
+ };
82
+ }
83
+ const result = buildCallHierarchy(symbolId, repoId, db, direction, maxDepth, maxNodes);
84
+ if (!result) {
85
+ return {
86
+ content: [
87
+ {
88
+ type: 'text',
89
+ text: JSON.stringify({
90
+ error: `Symbol "${symbolId}" not found in repo "${repoId}".`,
91
+ }),
92
+ },
93
+ ],
94
+ isError: true,
95
+ };
96
+ }
97
+ const responseText = JSON.stringify(result.root);
98
+ const tokenEstimate = Math.ceil(responseText.length / 4);
99
+ let truncated = result.truncated;
100
+ if (maxTokens !== undefined && tokenEstimate > maxTokens) {
101
+ truncated = true;
102
+ }
103
+ const output = {
104
+ root: result.root,
105
+ direction: result.direction,
106
+ totalNodes: result.totalNodes,
107
+ truncated,
108
+ _tokenEstimate: tokenEstimate,
109
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
110
+ };
111
+ return {
112
+ content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
113
+ };
114
+ }
115
+ finally {
116
+ db.close();
117
+ }
118
+ }
119
+ //# sourceMappingURL=get-call-hierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-call-hierarchy.js","sourceRoot":"","sources":["../../../src/server/tools/get-call-hierarchy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * get-class-hierarchy.ts
3
+ *
4
+ * MCP tool: get_class_hierarchy
5
+ *
6
+ * Return the full inheritance chain for a class or interface — ancestors
7
+ * (extends chain upward) and/or descendants (all subclasses downward).
8
+ *
9
+ * Detection strategy: signature-based LIKE queries on `symbols.signature`
10
+ * with word-boundary regex post-filtering. External base classes (e.g.
11
+ * `extends Error`) that are not indexed appear as leaf nodes with
12
+ * `symbolId: null`.
13
+ */
14
+ import { z } from 'zod';
15
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
16
+ export declare const name = "get_class_hierarchy";
17
+ export declare const description: string;
18
+ export declare const inputSchema: {
19
+ repoId: z.ZodString;
20
+ symbolId: z.ZodString;
21
+ direction: z.ZodOptional<z.ZodEnum<{
22
+ both: "both";
23
+ ancestors: "ancestors";
24
+ descendants: "descendants";
25
+ }>>;
26
+ maxDepth: z.ZodOptional<z.ZodNumber>;
27
+ includeInterfaces: z.ZodOptional<z.ZodBoolean>;
28
+ };
29
+ export declare function handler(args: {
30
+ repoId: string;
31
+ symbolId: string;
32
+ direction?: 'ancestors' | 'descendants' | 'both';
33
+ maxDepth?: number;
34
+ includeInterfaces?: boolean;
35
+ }): Promise<CallToolResult>;
36
+ //# sourceMappingURL=get-class-hierarchy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-class-hierarchy.d.ts","sourceRoot":"","sources":["../../../src/server/tools/get-class-hierarchy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,eAAO,MAAM,IAAI,wBAAwB,CAAC;AAE1C,eAAO,MAAM,WAAW,QAKJ,CAAC;AAErB,eAAO,MAAM,WAAW;;;;;;;;;;CA0BvB,CAAC;AAIF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,WAAW,GAAG,aAAa,GAAG,MAAM,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B,GAAG,OAAO,CAAC,cAAc,CAAC,CAgG1B"}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * get-class-hierarchy.ts
3
+ *
4
+ * MCP tool: get_class_hierarchy
5
+ *
6
+ * Return the full inheritance chain for a class or interface — ancestors
7
+ * (extends chain upward) and/or descendants (all subclasses downward).
8
+ *
9
+ * Detection strategy: signature-based LIKE queries on `symbols.signature`
10
+ * with word-boundary regex post-filtering. External base classes (e.g.
11
+ * `extends Error`) that are not indexed appear as leaf nodes with
12
+ * `symbolId: null`.
13
+ */
14
+ import { z } from 'zod';
15
+ import { openDatabase, getRepo } from '../../core/db/schema.js';
16
+ import { getSymbolById } from '../../core/db/symbol-store.js';
17
+ import { buildClassHierarchy } from '../../graph/graph-traversal.js';
18
+ import { buildMeta } from './_meta.js';
19
+ export const name = 'get_class_hierarchy';
20
+ export const description = 'Return the full inheritance chain for a class or interface — ancestors ' +
21
+ '(extends chain upward) and/or descendants (all subclasses/implementations ' +
22
+ 'downward). External base classes not in the repo appear as leaf nodes with ' +
23
+ 'symbolId: null. Use search_symbols to find the symbolId for a class or ' +
24
+ 'interface first.';
25
+ export const inputSchema = {
26
+ repoId: z.string().describe('Repo ID from index_folder or resolve_repo'),
27
+ symbolId: z
28
+ .string()
29
+ .describe('Symbol ID of the class or interface to root the hierarchy at'),
30
+ direction: z
31
+ .enum(['ancestors', 'descendants', 'both'])
32
+ .optional()
33
+ .describe('Which direction to traverse: "ancestors" (extends chain upward), ' +
34
+ '"descendants" (all subclasses downward), or "both" (default: "both")'),
35
+ maxDepth: z
36
+ .number()
37
+ .int()
38
+ .min(1)
39
+ .max(10)
40
+ .optional()
41
+ .describe('Maximum traversal depth in each direction (default 5)'),
42
+ includeInterfaces: z
43
+ .boolean()
44
+ .optional()
45
+ .describe('Include implemented interfaces in the ancestor chain and interface ' +
46
+ 'subclasses in descendants (default true)'),
47
+ };
48
+ // ─── Handler ──────────────────────────────────────────────────────────────────
49
+ export async function handler(args) {
50
+ const t0 = Date.now();
51
+ const { repoId, symbolId, direction = 'both', maxDepth = 5, includeInterfaces = true, } = args;
52
+ const db = openDatabase(repoId);
53
+ try {
54
+ const repo = getRepo(db, repoId);
55
+ if (!repo) {
56
+ return {
57
+ content: [
58
+ {
59
+ type: 'text',
60
+ text: JSON.stringify({
61
+ error: `Repo "${repoId}" not found. Run index_folder first.`,
62
+ }),
63
+ },
64
+ ],
65
+ isError: true,
66
+ };
67
+ }
68
+ const target = getSymbolById(db, repoId, symbolId);
69
+ if (!target) {
70
+ return {
71
+ content: [
72
+ {
73
+ type: 'text',
74
+ text: JSON.stringify({
75
+ error: `Symbol "${symbolId}" not found in repo "${repoId}".`,
76
+ }),
77
+ },
78
+ ],
79
+ isError: true,
80
+ };
81
+ }
82
+ if (target.kind !== 'class' && target.kind !== 'interface') {
83
+ return {
84
+ content: [
85
+ {
86
+ type: 'text',
87
+ text: JSON.stringify({
88
+ error: `Symbol "${target.name}" has kind "${target.kind}". ` +
89
+ 'get_class_hierarchy only works with class or interface symbols.',
90
+ }),
91
+ },
92
+ ],
93
+ isError: true,
94
+ };
95
+ }
96
+ const result = buildClassHierarchy(symbolId, repoId, db, direction, maxDepth, includeInterfaces);
97
+ if (!result) {
98
+ return {
99
+ content: [
100
+ {
101
+ type: 'text',
102
+ text: JSON.stringify({
103
+ error: `Symbol "${symbolId}" not found during hierarchy traversal.`,
104
+ }),
105
+ },
106
+ ],
107
+ isError: true,
108
+ };
109
+ }
110
+ const responseText = JSON.stringify(result.root);
111
+ const output = {
112
+ root: result.root,
113
+ totalNodes: result.totalNodes,
114
+ _tokenEstimate: Math.ceil(responseText.length / 4),
115
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
116
+ };
117
+ return {
118
+ content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
119
+ };
120
+ }
121
+ finally {
122
+ db.close();
123
+ }
124
+ }
125
+ //# sourceMappingURL=get-class-hierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-class-hierarchy.js","sourceRoot":"","sources":["../../../src/server/tools/get-class-hierarchy.ts"],"names":[],"mappings":"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"}