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":"find-cycles.js","sourceRoot":"","sources":["../../../src/server/tools/find-cycles.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,CAAC,MAAM,IAAI,GAAG,aAAa,CAAC;AAElC,MAAM,CAAC,MAAM,WAAW,GACtB,8EAA8E;IAC9E,+EAA+E;IAC/E,4EAA4E;IAC5E,4EAA4E;IAC5E,gFAAgF,CAAC;AAEnF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2CAA2C,CAAC;IACxE,QAAQ,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CACP,kEAAkE;QAClE,kEAAkE,CACnE;IACH,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,GAAG,CAAC;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,kDAAkD,CAAC;IAC/D,SAAS,EAAE,CAAC;SACT,MAAM,EAAE;SACR,GAAG,EAAE;SACL,GAAG,CAAC,CAAC,CAAC;SACN,GAAG,CAAC,EAAE,CAAC;SACP,QAAQ,EAAE;SACV,QAAQ,CACP,8CAA8C;QAC9C,sEAAsE,CACvE;CACJ,CAAC;AAkBF,iFAAiF;AAEjF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAK7B;IACC,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACtB,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,GAAG,EAAE,EAAE,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC;IAEjE,MAAM,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IAEhC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;4BACnB,KAAK,EAAE,SAAS,MAAM,sCAAsC;yBAC7D,CAAC;qBACH;iBACF;gBACD,OAAO,EAAE,IAAI;aACd,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,EAAE,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QAE5E,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnD,MAAM,MAAM,GAAqB;YAC/B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;YAClD,KAAK,EAAE,SAAS,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;SAChD,CAAC;QAEF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;SACnE,CAAC;IACJ,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * find-implementations.ts
3
+ *
4
+ * MCP tool: find_implementations
5
+ *
6
+ * Find all concrete implementations of a TypeScript interface or abstract class,
7
+ * and all method overrides for a given base method.
8
+ *
9
+ * Detection strategy (two-pass):
10
+ * 1. Name-based: search class symbols whose signature contains
11
+ * `implements InterfaceName` or `extends ClassName` via LIKE on symbols.signature.
12
+ * 2. Import-based: any file that imports the interface's file is also scanned
13
+ * for classes that match, catching cases where the name-based pass missed due
14
+ * to signature truncation.
15
+ *
16
+ * `implementedMethods` / `missingMethods` are computed by comparing the method
17
+ * symbols stored under the interface name against those stored under the
18
+ * implementing class name.
19
+ */
20
+ import { z } from 'zod';
21
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
22
+ export declare const name = "find_implementations";
23
+ export declare const description: string;
24
+ export declare const inputSchema: {
25
+ repoId: z.ZodString;
26
+ symbolId: z.ZodString;
27
+ includeAbstract: z.ZodOptional<z.ZodBoolean>;
28
+ limit: z.ZodOptional<z.ZodNumber>;
29
+ };
30
+ export interface ImplementationRecord {
31
+ symbolId: string;
32
+ name: string;
33
+ kind: string;
34
+ filePath: string;
35
+ startLine: number;
36
+ signature: string;
37
+ summary: string;
38
+ implementedMethods: string[];
39
+ missingMethods: string[];
40
+ }
41
+ export declare function handler(args: {
42
+ repoId: string;
43
+ symbolId: string;
44
+ includeAbstract?: boolean;
45
+ limit?: number;
46
+ }): Promise<CallToolResult>;
47
+ //# sourceMappingURL=find-implementations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-implementations.d.ts","sourceRoot":"","sources":["../../../src/server/tools/find-implementations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,eAAO,MAAM,IAAI,yBAAyB,CAAC;AAE3C,eAAO,MAAM,WAAW,QAI6D,CAAC;AAEtF,eAAO,MAAM,WAAW;;;;;CAmBvB,CAAC;AAIF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAyBD,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgI1B"}
@@ -0,0 +1,167 @@
1
+ /**
2
+ * find-implementations.ts
3
+ *
4
+ * MCP tool: find_implementations
5
+ *
6
+ * Find all concrete implementations of a TypeScript interface or abstract class,
7
+ * and all method overrides for a given base method.
8
+ *
9
+ * Detection strategy (two-pass):
10
+ * 1. Name-based: search class symbols whose signature contains
11
+ * `implements InterfaceName` or `extends ClassName` via LIKE on symbols.signature.
12
+ * 2. Import-based: any file that imports the interface's file is also scanned
13
+ * for classes that match, catching cases where the name-based pass missed due
14
+ * to signature truncation.
15
+ *
16
+ * `implementedMethods` / `missingMethods` are computed by comparing the method
17
+ * symbols stored under the interface name against those stored under the
18
+ * implementing class name.
19
+ */
20
+ import { z } from 'zod';
21
+ import { openDatabase, getRepo } from '../../core/db/schema.js';
22
+ import { getSymbolById } from '../../core/db/symbol-store.js';
23
+ import { findClassImplementations, getMethodNamesForSymbol, extractInterfaceMethodNames, } from '../../core/db/dep-store.js';
24
+ import { buildMeta } from './_meta.js';
25
+ import { getFileContent } from '../../core/db/file-store.js';
26
+ export const name = 'find_implementations';
27
+ export const description = 'Find all concrete implementations of a TypeScript interface or abstract class, ' +
28
+ 'and all method overrides for a given base method. ' +
29
+ 'Returns implementing classes with their implemented and missing methods. ' +
30
+ 'Use search_symbols to find the symbolId for an interface or abstract class first.';
31
+ export const inputSchema = {
32
+ repoId: z.string().describe('Repo ID from index_folder or resolve_repo'),
33
+ symbolId: z
34
+ .string()
35
+ .describe('Symbol ID of the interface or abstract class to search for'),
36
+ includeAbstract: z
37
+ .boolean()
38
+ .optional()
39
+ .describe('Include abstract subclasses in results (default false). ' +
40
+ 'When true, abstract classes that extend the target are included alongside concrete implementations.'),
41
+ limit: z
42
+ .number()
43
+ .int()
44
+ .min(1)
45
+ .max(200)
46
+ .optional()
47
+ .describe('Maximum number of implementations to return (default 50)'),
48
+ };
49
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
50
+ /** Compute 1-based line number from a byte/char offset within file content. */
51
+ function byteToLine(content, offset) {
52
+ const slice = content.slice(0, Math.min(offset, content.length));
53
+ let line = 1;
54
+ for (let i = 0; i < slice.length; i++) {
55
+ if (slice[i] === 0x0a)
56
+ line++;
57
+ }
58
+ return line;
59
+ }
60
+ // ─── Handler ──────────────────────────────────────────────────────────────────
61
+ export async function handler(args) {
62
+ const t0 = Date.now();
63
+ const { repoId, symbolId, includeAbstract = false, limit = 50 } = args;
64
+ const db = openDatabase(repoId);
65
+ try {
66
+ const repo = getRepo(db, repoId);
67
+ if (!repo) {
68
+ return {
69
+ content: [
70
+ {
71
+ type: 'text',
72
+ text: JSON.stringify({
73
+ error: `Repo "${repoId}" not found. Run index_folder first.`,
74
+ }),
75
+ },
76
+ ],
77
+ isError: true,
78
+ };
79
+ }
80
+ // Look up the target interface / abstract class
81
+ const target = getSymbolById(db, repoId, symbolId);
82
+ if (!target) {
83
+ return {
84
+ content: [
85
+ {
86
+ type: 'text',
87
+ text: JSON.stringify({
88
+ error: `Symbol "${symbolId}" not found in repo "${repoId}".`,
89
+ }),
90
+ },
91
+ ],
92
+ isError: true,
93
+ };
94
+ }
95
+ if (target.kind !== 'interface' && target.kind !== 'class') {
96
+ return {
97
+ content: [
98
+ {
99
+ type: 'text',
100
+ text: JSON.stringify({
101
+ error: `Symbol "${target.name}" has kind "${target.kind}". ` +
102
+ 'find_implementations only works with interface or class symbols.',
103
+ }),
104
+ },
105
+ ],
106
+ isError: true,
107
+ };
108
+ }
109
+ // Get interface/abstract-class method names.
110
+ // Interface methods are NOT indexed as separate symbols by the TypeScript handler,
111
+ // so we extract them from the raw file content using the target's byte range.
112
+ // For abstract classes, the indexed method symbols are used as fallback.
113
+ let interfaceMethods;
114
+ const targetFileContent = getFileContent(db, repoId, target.filePath);
115
+ if (targetFileContent) {
116
+ interfaceMethods = extractInterfaceMethodNames(targetFileContent, target.startByte, target.endByte);
117
+ }
118
+ else {
119
+ // Fallback to indexed method symbols (works for abstract classes)
120
+ interfaceMethods = getMethodNamesForSymbol(db, repoId, target.name, target.filePath);
121
+ }
122
+ // Find all classes/interfaces that implement or extend this target
123
+ const implementors = findClassImplementations(db, repoId, target.name, target.filePath, includeAbstract, limit);
124
+ // Build ImplementationRecord for each implementor
125
+ const implementations = [];
126
+ for (const impl of implementors) {
127
+ // Get the implementing class's method stems
128
+ const classMethods = getMethodNamesForSymbol(db, repoId, impl.name, impl.filePath);
129
+ const classMethodSet = new Set(classMethods);
130
+ const implementedMethods = interfaceMethods.filter((m) => classMethodSet.has(m));
131
+ const missingMethods = interfaceMethods.filter((m) => !classMethodSet.has(m));
132
+ // Compute startLine from file content
133
+ let startLine = 1;
134
+ const fileContent = getFileContent(db, repoId, impl.filePath);
135
+ if (fileContent) {
136
+ startLine = byteToLine(fileContent, impl.startByte);
137
+ }
138
+ implementations.push({
139
+ symbolId: impl.id,
140
+ name: impl.name,
141
+ kind: impl.kind,
142
+ filePath: impl.filePath,
143
+ startLine,
144
+ signature: impl.signature,
145
+ summary: impl.summary,
146
+ implementedMethods,
147
+ missingMethods,
148
+ });
149
+ }
150
+ const responseText = JSON.stringify(implementations);
151
+ const output = {
152
+ interfaceName: target.name,
153
+ interfaceFilePath: target.filePath,
154
+ implementations,
155
+ totalFound: implementations.length,
156
+ _tokenEstimate: Math.ceil(responseText.length / 4),
157
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
158
+ };
159
+ return {
160
+ content: [{ type: 'text', text: JSON.stringify(output, null, 2) }],
161
+ };
162
+ }
163
+ finally {
164
+ db.close();
165
+ }
166
+ }
167
+ //# sourceMappingURL=find-implementations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-implementations.js","sourceRoot":"","sources":["../../../src/server/tools/find-implementations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * find-untested-symbols.ts
3
+ *
4
+ * MCP tool: find_untested_symbols
5
+ *
6
+ * Identifies exported symbols (functions, methods, classes, etc.) in the
7
+ * codebase that do not appear to have any test coverage — i.e. whose names
8
+ * are not referenced in any test file.
9
+ *
10
+ * Detection strategy (static heuristic):
11
+ * 1. Identify test files by path convention:
12
+ * - Path segment is "test", "tests", "spec", "specs", or "__tests__"
13
+ * - Filename ends with .test.*, .spec.*, _test.*, or _spec.*
14
+ * 2. Extract all identifiers referenced in those test files.
15
+ * 3. Any non-test symbol whose name does NOT appear in the test identifier
16
+ * set is considered "untested".
17
+ *
18
+ * Limitations:
19
+ * - Name-based matching only; dynamic dispatch, aliases, and indirect calls
20
+ * can produce false negatives (symbol appears tested when it is not) or
21
+ * false positives (common names like `get` match unrelated things).
22
+ * - Does not read coverage reports; for accurate coverage, pipe in a
23
+ * coverage JSON file via get_test_coverage_map instead.
24
+ *
25
+ * Priority rating (per untested symbol):
26
+ * high — cyclomatic_complexity >= 5 OR line_count >= 20
27
+ * medium — cyclomatic_complexity >= 2 OR line_count >= 8
28
+ * low — all other symbols
29
+ */
30
+ import { z } from 'zod';
31
+ import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
32
+ export declare const name = "find_untested_symbols";
33
+ export declare const description: string;
34
+ export declare const inputSchema: {
35
+ repoId: z.ZodString;
36
+ scope: z.ZodOptional<z.ZodString>;
37
+ kinds: z.ZodOptional<z.ZodArray<z.ZodString>>;
38
+ filePath: z.ZodOptional<z.ZodString>;
39
+ minLineCount: z.ZodOptional<z.ZodNumber>;
40
+ includeTestRefs: z.ZodOptional<z.ZodBoolean>;
41
+ limit: z.ZodOptional<z.ZodNumber>;
42
+ };
43
+ export declare function handler(args: {
44
+ repoId: string;
45
+ scope?: string;
46
+ kinds?: string[];
47
+ filePath?: string;
48
+ minLineCount?: number;
49
+ includeTestRefs?: boolean;
50
+ limit?: number;
51
+ }): Promise<CallToolResult>;
52
+ //# sourceMappingURL=find-untested-symbols.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-untested-symbols.d.ts","sourceRoot":"","sources":["../../../src/server/tools/find-untested-symbols.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAGzE,eAAO,MAAM,IAAI,0BAA0B,CAAC;AAE5C,eAAO,MAAM,WAAW,QAYyD,CAAC;AAQlF,eAAO,MAAM,WAAW;;;;;;;;CAsCvB,CAAC;AA4FF,wBAAsB,OAAO,CAAC,IAAI,EAAE;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,cAAc,CAAC,CAoN1B"}
@@ -0,0 +1,308 @@
1
+ /**
2
+ * find-untested-symbols.ts
3
+ *
4
+ * MCP tool: find_untested_symbols
5
+ *
6
+ * Identifies exported symbols (functions, methods, classes, etc.) in the
7
+ * codebase that do not appear to have any test coverage — i.e. whose names
8
+ * are not referenced in any test file.
9
+ *
10
+ * Detection strategy (static heuristic):
11
+ * 1. Identify test files by path convention:
12
+ * - Path segment is "test", "tests", "spec", "specs", or "__tests__"
13
+ * - Filename ends with .test.*, .spec.*, _test.*, or _spec.*
14
+ * 2. Extract all identifiers referenced in those test files.
15
+ * 3. Any non-test symbol whose name does NOT appear in the test identifier
16
+ * set is considered "untested".
17
+ *
18
+ * Limitations:
19
+ * - Name-based matching only; dynamic dispatch, aliases, and indirect calls
20
+ * can produce false negatives (symbol appears tested when it is not) or
21
+ * false positives (common names like `get` match unrelated things).
22
+ * - Does not read coverage reports; for accurate coverage, pipe in a
23
+ * coverage JSON file via get_test_coverage_map instead.
24
+ *
25
+ * Priority rating (per untested symbol):
26
+ * high — cyclomatic_complexity >= 5 OR line_count >= 20
27
+ * medium — cyclomatic_complexity >= 2 OR line_count >= 8
28
+ * low — all other symbols
29
+ */
30
+ import { z } from 'zod';
31
+ import { openDatabase, getRepo } from '../../core/db/schema.js';
32
+ import { buildMeta } from './_meta.js';
33
+ export const name = 'find_untested_symbols';
34
+ export const description = 'Identify symbols (functions, methods, classes) that do not appear to have ' +
35
+ 'test coverage by scanning test files for references to each symbol name. ' +
36
+ 'Returns a prioritised list of untested symbols ranked by cyclomatic ' +
37
+ 'complexity so you can focus testing effort where it matters most.' +
38
+ '\n\nDetection strategy: static heuristic — symbol name must appear as an ' +
39
+ 'identifier in at least one test file (path-based detection). ' +
40
+ 'This is not a coverage-report parser; use get_test_coverage_map for ' +
41
+ 'line-level accuracy.' +
42
+ '\n\nDiffers from related tools:' +
43
+ '\n find_dead_code — exports with no importers (unused API)' +
44
+ '\n get_test_coverage_map — line-level coverage from a coverage JSON report' +
45
+ '\n get_complexity_hotspots — complexity ranking without test-coverage filter';
46
+ // ─── Default testable kinds ────────────────────────────────────────────────────
47
+ const DEFAULT_KINDS = ['function', 'method', 'class', 'interface', 'middleware', 'route'];
48
+ // ─── Input schema ──────────────────────────────────────────────────────────────
49
+ export const inputSchema = {
50
+ repoId: z.string().describe('Repository ID returned by index_folder or list_repos'),
51
+ scope: z
52
+ .string()
53
+ .optional()
54
+ .describe('Restrict analysis to a directory prefix (e.g. "src/services/"). ' +
55
+ 'Omit to analyse the whole repo.'),
56
+ kinds: z
57
+ .array(z.string())
58
+ .optional()
59
+ .describe(`Symbol kinds to include (default: ${DEFAULT_KINDS.join(', ')}). ` +
60
+ 'Narrow to e.g. ["function","method"] to focus on callable units.'),
61
+ filePath: z
62
+ .string()
63
+ .optional()
64
+ .describe('Restrict to a specific source file path (relative to repo root).'),
65
+ minLineCount: z
66
+ .number().int().min(1)
67
+ .optional()
68
+ .describe('Minimum symbol line count to include (default 3). ' +
69
+ 'Filters out trivial one-liners that are not worth testing individually.'),
70
+ includeTestRefs: z
71
+ .boolean()
72
+ .optional()
73
+ .describe('When true, include the list of test files that reference each ' +
74
+ 'symbol (the "testRefs" field). Increases response size. Default false.'),
75
+ limit: z
76
+ .number().int().min(1).max(500)
77
+ .optional()
78
+ .describe('Maximum number of untested symbols to return (default 50).'),
79
+ };
80
+ // ─── Helpers ───────────────────────────────────────────────────────────────────
81
+ /**
82
+ * Returns true when a file path looks like a test file by convention.
83
+ */
84
+ function isTestFile(filePath) {
85
+ // Normalise separators
86
+ const norm = filePath.replace(/\\/g, '/');
87
+ // Path-segment match: /test/, /tests/, /spec/, /specs/, /__tests__/
88
+ if (/(?:^|\/)(?:tests?|specs?|__tests__)\//.test(norm))
89
+ return true;
90
+ // Filename suffix: .test.ts, .spec.ts, .test.js, _test.go, etc.
91
+ if (/[._](?:test|spec)\.[a-z]+$/.test(norm))
92
+ return true;
93
+ // Filename prefix: test_foo.py, spec_foo.rb
94
+ const filename = norm.split('/').pop() ?? '';
95
+ if (/^(?:test|spec)_/.test(filename))
96
+ return true;
97
+ return false;
98
+ }
99
+ /**
100
+ * Extract all identifier tokens from source text.
101
+ * Returns a Set for O(1) membership checks.
102
+ */
103
+ function extractIdentifiers(text) {
104
+ const ids = new Set();
105
+ for (const m of text.matchAll(/\b([A-Za-z_$][A-Za-z0-9_$]*)\b/g)) {
106
+ ids.add(m[1]);
107
+ }
108
+ return ids;
109
+ }
110
+ /**
111
+ * Assign a priority to an untested symbol based on its complexity and size.
112
+ */
113
+ function computePriority(cc, lineCount) {
114
+ if (cc >= 5 || lineCount >= 20)
115
+ return 'high';
116
+ if (cc >= 2 || lineCount >= 8)
117
+ return 'medium';
118
+ return 'low';
119
+ }
120
+ /**
121
+ * Compute the 1-based line number for a given byte offset in a buffer.
122
+ */
123
+ function lineOf(buf, startByte) {
124
+ const slice = buf.slice(0, Math.min(startByte, buf.length));
125
+ let line = 1;
126
+ for (let i = 0; i < slice.length; i++) {
127
+ if (slice[i] === 0x0a)
128
+ line++;
129
+ }
130
+ return line;
131
+ }
132
+ // ─── Handler ───────────────────────────────────────────────────────────────────
133
+ export async function handler(args) {
134
+ const t0 = Date.now();
135
+ const { repoId, minLineCount = 3, includeTestRefs = false, limit = 50, } = args;
136
+ const kinds = (args.kinds && args.kinds.length > 0)
137
+ ? args.kinds
138
+ : DEFAULT_KINDS;
139
+ const db = openDatabase(repoId);
140
+ try {
141
+ // ── Validate repo ─────────────────────────────────────────────────────────
142
+ const repo = getRepo(db, repoId);
143
+ if (!repo) {
144
+ return {
145
+ content: [{
146
+ type: 'text',
147
+ text: JSON.stringify({ error: `Repo "${repoId}" not found. Run index_folder first.` }),
148
+ }],
149
+ isError: true,
150
+ };
151
+ }
152
+ // ── Load all indexed files (with content) ─────────────────────────────────
153
+ const allFiles = db
154
+ .prepare('SELECT path, raw_content FROM files WHERE repo_id = ?')
155
+ .all(repoId);
156
+ // ── Partition files: test vs source ───────────────────────────────────────
157
+ const testFiles = [];
158
+ for (const f of allFiles) {
159
+ if (isTestFile(f.path))
160
+ testFiles.push(f);
161
+ }
162
+ // ── Build identifier sets per test file ───────────────────────────────────
163
+ // identifiersByTestFile[i] = Set of identifiers in testFiles[i]
164
+ const identifiersByTestFile = [];
165
+ // Global union for fast "is this symbol name referenced at all?" check
166
+ const allTestIdentifiers = new Set();
167
+ for (const tf of testFiles) {
168
+ if (!tf.raw_content)
169
+ continue;
170
+ const text = tf.raw_content.toString('utf8');
171
+ const ids = extractIdentifiers(text);
172
+ identifiersByTestFile.push({ path: tf.path, ids });
173
+ for (const id of ids)
174
+ allTestIdentifiers.add(id);
175
+ }
176
+ // ── Load candidate symbols ────────────────────────────────────────────────
177
+ const kindPlaceholders = kinds.map(() => '?').join(', ');
178
+ const conditions = [
179
+ 'repo_id = ?',
180
+ `kind IN (${kindPlaceholders})`,
181
+ 'COALESCE(line_count, 1) >= ?',
182
+ ];
183
+ const params = [repoId, ...kinds, minLineCount];
184
+ if (args.scope) {
185
+ const prefix = args.scope.endsWith('/') ? args.scope : `${args.scope}/`;
186
+ conditions.push('(file_path = ? OR file_path LIKE ?)');
187
+ params.push(args.scope, `${prefix}%`);
188
+ }
189
+ if (args.filePath) {
190
+ conditions.push('file_path = ?');
191
+ params.push(args.filePath);
192
+ }
193
+ const sql = `
194
+ SELECT id, name, kind, file_path, start_byte, signature, summary,
195
+ COALESCE(line_count, 1) AS line_count,
196
+ COALESCE(cyclomatic_complexity, 1) AS cyclomatic_complexity
197
+ FROM symbols
198
+ WHERE ${conditions.join(' AND ')}
199
+ AND file_path NOT IN (SELECT path FROM files WHERE repo_id = ? AND path IN (
200
+ ${allFiles.filter(f => isTestFile(f.path)).map(() => '?').join(',') || 'SELECT NULL'}
201
+ ))
202
+ ORDER BY cyclomatic_complexity DESC, line_count DESC
203
+ `;
204
+ // Avoid building a huge IN clause for test-file exclusion — instead
205
+ // filter in JS after the query (simpler and still fast for typical repos).
206
+ const sqlSimple = `
207
+ SELECT id, name, kind, file_path, start_byte, signature, summary,
208
+ COALESCE(line_count, 1) AS line_count,
209
+ COALESCE(cyclomatic_complexity, 1) AS cyclomatic_complexity
210
+ FROM symbols
211
+ WHERE ${conditions.join(' AND ')}
212
+ ORDER BY cyclomatic_complexity DESC, line_count DESC
213
+ `;
214
+ void sql; // suppress unused-variable warning for the filtered version above
215
+ const allSymbols = db
216
+ .prepare(sqlSimple)
217
+ .all(params);
218
+ // Exclude symbols that live in test files
219
+ const testFilePaths = new Set(testFiles.map((f) => f.path));
220
+ const sourceSymbols = allSymbols.filter((s) => !testFilePaths.has(s.file_path));
221
+ // ── Classify each symbol ──────────────────────────────────────────────────
222
+ const untestedSymbols = [];
223
+ let testedCount = 0;
224
+ // Cache file buffers for line computation
225
+ const fileBufferCache = new Map();
226
+ const getFileBuffer = (filePath) => {
227
+ if (fileBufferCache.has(filePath))
228
+ return fileBufferCache.get(filePath) ?? null;
229
+ const row = db
230
+ .prepare('SELECT raw_content FROM files WHERE repo_id = ? AND path = ?')
231
+ .get(repoId, filePath);
232
+ const buf = row?.raw_content ?? null;
233
+ if (buf)
234
+ fileBufferCache.set(filePath, buf);
235
+ return buf;
236
+ };
237
+ for (const sym of sourceSymbols) {
238
+ const isTested = allTestIdentifiers.has(sym.name);
239
+ if (isTested) {
240
+ testedCount++;
241
+ continue;
242
+ }
243
+ // Build start line
244
+ const buf = getFileBuffer(sym.file_path);
245
+ const startLine = buf ? lineOf(buf, sym.start_byte) : 1;
246
+ const cc = sym.cyclomatic_complexity ?? 1;
247
+ const lc = sym.line_count ?? 1;
248
+ const entry = {
249
+ symbolId: sym.id,
250
+ name: sym.name,
251
+ kind: sym.kind,
252
+ filePath: sym.file_path,
253
+ startLine,
254
+ signature: sym.signature,
255
+ summary: sym.summary,
256
+ lineCount: lc,
257
+ cyclomaticComplexity: cc,
258
+ priority: computePriority(cc, lc),
259
+ };
260
+ if (includeTestRefs) {
261
+ // For untested symbols, testRefs is empty (none reference it)
262
+ entry.testRefs = [];
263
+ }
264
+ untestedSymbols.push(entry);
265
+ }
266
+ const truncated = untestedSymbols.length > limit;
267
+ const visibleUntested = untestedSymbols.slice(0, limit);
268
+ // ── Summary ───────────────────────────────────────────────────────────────
269
+ const totalSymbols = sourceSymbols.length;
270
+ const untestedCount = untestedSymbols.length;
271
+ const testCoverageRate = totalSymbols > 0
272
+ ? Math.round(((testedCount) / totalSymbols) * 1000) / 1000
273
+ : 1;
274
+ const highCount = untestedSymbols.filter((s) => s.priority === 'high').length;
275
+ const mediumCount = untestedSymbols.filter((s) => s.priority === 'medium').length;
276
+ const lowCount = untestedSymbols.filter((s) => s.priority === 'low').length;
277
+ // ── Token estimate ─────────────────────────────────────────────────────────
278
+ const tokenEstimate = Math.ceil(visibleUntested.reduce((sum, s) => sum + s.signature.length + s.summary.length + s.filePath.length + 80, 0) / 4);
279
+ return {
280
+ content: [{
281
+ type: 'text',
282
+ text: JSON.stringify({
283
+ repoId,
284
+ totalSymbols,
285
+ testedCount,
286
+ untestedCount,
287
+ testCoverageRate,
288
+ testFilesScanned: testFiles.length,
289
+ truncated,
290
+ untestedSymbols: visibleUntested,
291
+ summary: {
292
+ highPriority: highCount,
293
+ mediumPriority: mediumCount,
294
+ lowPriority: lowCount,
295
+ kindsAnalyzed: kinds,
296
+ minLineCount,
297
+ },
298
+ _tokenEstimate: tokenEstimate,
299
+ _meta: buildMeta({ timingMs: Date.now() - t0 }),
300
+ }, null, 2),
301
+ }],
302
+ };
303
+ }
304
+ finally {
305
+ db.close();
306
+ }
307
+ }
308
+ //# sourceMappingURL=find-untested-symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-untested-symbols.js","sourceRoot":"","sources":["../../../src/server/tools/find-untested-symbols.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
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 type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
22
+ export declare const name = "get_architecture_snapshot";
23
+ export declare const description: string;
24
+ export declare const inputSchema: {
25
+ repoId: z.ZodString;
26
+ action: z.ZodEnum<{
27
+ delete: "delete";
28
+ create: "create";
29
+ diff: "diff";
30
+ list: "list";
31
+ }>;
32
+ snapshotId: z.ZodOptional<z.ZodString>;
33
+ compareId: z.ZodOptional<z.ZodString>;
34
+ label: z.ZodOptional<z.ZodString>;
35
+ };
36
+ export declare function handler(args: {
37
+ repoId: string;
38
+ action: 'create' | 'list' | 'diff' | 'delete';
39
+ snapshotId?: string;
40
+ compareId?: string;
41
+ label?: string;
42
+ }): Promise<CallToolResult>;
43
+ //# sourceMappingURL=get-architecture-snapshot.d.ts.map