@lzehrung/codegraph 2.1.0 → 2.1.1

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 (426) hide show
  1. package/README.md +27 -29
  2. package/codegraph-skill/codegraph/SKILL.md +23 -21
  3. package/dist/agent/candidateTests.d.ts +12 -0
  4. package/dist/agent/candidateTests.d.ts.map +1 -0
  5. package/dist/agent/candidateTests.js +17 -0
  6. package/dist/agent/candidateTests.js.map +1 -0
  7. package/dist/agent/explore.d.ts.map +1 -1
  8. package/dist/agent/explore.js +9 -6
  9. package/dist/agent/explore.js.map +1 -1
  10. package/dist/agent/fileView.d.ts.map +1 -1
  11. package/dist/agent/fileView.js +113 -120
  12. package/dist/agent/fileView.js.map +1 -1
  13. package/dist/agent/orient.d.ts.map +1 -1
  14. package/dist/agent/orient.js +5 -4
  15. package/dist/agent/orient.js.map +1 -1
  16. package/dist/agent/query-index/candidates.d.ts +13 -2
  17. package/dist/agent/query-index/candidates.d.ts.map +1 -1
  18. package/dist/agent/query-index/candidates.js +28 -39
  19. package/dist/agent/query-index/candidates.js.map +1 -1
  20. package/dist/agent/query-index/schema.d.ts.map +1 -1
  21. package/dist/agent/query-index/schema.js.map +1 -1
  22. package/dist/agent/query-index/sessionStore.d.ts.map +1 -1
  23. package/dist/agent/query-index/sessionStore.js +42 -26
  24. package/dist/agent/query-index/sessionStore.js.map +1 -1
  25. package/dist/agent/query-index/store.d.ts +7 -0
  26. package/dist/agent/query-index/store.d.ts.map +1 -1
  27. package/dist/agent/query-index/store.js +71 -0
  28. package/dist/agent/query-index/store.js.map +1 -1
  29. package/dist/agent/refactorPlan.d.ts.map +1 -1
  30. package/dist/agent/refactorPlan.js +6 -14
  31. package/dist/agent/refactorPlan.js.map +1 -1
  32. package/dist/agent/renamePreview.d.ts +2 -5
  33. package/dist/agent/renamePreview.d.ts.map +1 -1
  34. package/dist/agent/renamePreview.js +82 -78
  35. package/dist/agent/renamePreview.js.map +1 -1
  36. package/dist/agent/search.d.ts.map +1 -1
  37. package/dist/agent/search.js +39 -17
  38. package/dist/agent/search.js.map +1 -1
  39. package/dist/agent/semanticSymbols.d.ts.map +1 -1
  40. package/dist/agent/semanticSymbols.js +2 -1
  41. package/dist/agent/semanticSymbols.js.map +1 -1
  42. package/dist/agent/session.d.ts +4 -0
  43. package/dist/agent/session.d.ts.map +1 -1
  44. package/dist/agent/session.js +19 -6
  45. package/dist/agent/session.js.map +1 -1
  46. package/dist/agent-tools.d.ts +1 -1
  47. package/dist/agent-tools.d.ts.map +1 -1
  48. package/dist/agent-tools.js +6 -15
  49. package/dist/agent-tools.js.map +1 -1
  50. package/dist/bin/cli.js +27556 -24941
  51. package/dist/bin/queryIndexWorker.js +47 -6
  52. package/dist/bin/rawQueryWorker.js +246 -0
  53. package/dist/chunking/chunkFile.d.ts +5 -0
  54. package/dist/chunking/chunkFile.d.ts.map +1 -1
  55. package/dist/chunking/chunkFile.js +14 -15
  56. package/dist/chunking/chunkFile.js.map +1 -1
  57. package/dist/cli/affected.d.ts.map +1 -1
  58. package/dist/cli/affected.js +17 -10
  59. package/dist/cli/affected.js.map +1 -1
  60. package/dist/cli/commandTable.d.ts.map +1 -1
  61. package/dist/cli/commandTable.js +15 -3
  62. package/dist/cli/commandTable.js.map +1 -1
  63. package/dist/cli/doctor.d.ts +7 -0
  64. package/dist/cli/doctor.d.ts.map +1 -1
  65. package/dist/cli/doctor.js +166 -0
  66. package/dist/cli/doctor.js.map +1 -1
  67. package/dist/cli/graph.d.ts +2 -1
  68. package/dist/cli/graph.d.ts.map +1 -1
  69. package/dist/cli/graph.js +8 -0
  70. package/dist/cli/graph.js.map +1 -1
  71. package/dist/cli/graphDelta.d.ts +2 -1
  72. package/dist/cli/graphDelta.d.ts.map +1 -1
  73. package/dist/cli/graphDelta.js +5 -0
  74. package/dist/cli/graphDelta.js.map +1 -1
  75. package/dist/cli/help.d.ts +34 -34
  76. package/dist/cli/help.d.ts.map +1 -1
  77. package/dist/cli/help.js +17 -8
  78. package/dist/cli/help.js.map +1 -1
  79. package/dist/cli/impact.d.ts +2 -1
  80. package/dist/cli/impact.d.ts.map +1 -1
  81. package/dist/cli/impact.js +5 -0
  82. package/dist/cli/impact.js.map +1 -1
  83. package/dist/cli/index.d.ts +2 -1
  84. package/dist/cli/index.d.ts.map +1 -1
  85. package/dist/cli/index.js +3 -0
  86. package/dist/cli/index.js.map +1 -1
  87. package/dist/cli/indexPolicy.d.ts.map +1 -1
  88. package/dist/cli/indexPolicy.js.map +1 -1
  89. package/dist/cli/inspect.d.ts +2 -1
  90. package/dist/cli/inspect.d.ts.map +1 -1
  91. package/dist/cli/inspect.js +25 -13
  92. package/dist/cli/inspect.js.map +1 -1
  93. package/dist/cli/invocationContext.d.ts.map +1 -1
  94. package/dist/cli/invocationContext.js +3 -0
  95. package/dist/cli/invocationContext.js.map +1 -1
  96. package/dist/cli/links.d.ts +2 -0
  97. package/dist/cli/links.d.ts.map +1 -1
  98. package/dist/cli/links.js +1 -1
  99. package/dist/cli/links.js.map +1 -1
  100. package/dist/cli/navigation.d.ts +41 -1
  101. package/dist/cli/navigation.d.ts.map +1 -1
  102. package/dist/cli/navigation.js +4 -1
  103. package/dist/cli/navigation.js.map +1 -1
  104. package/dist/cli/options.d.ts.map +1 -1
  105. package/dist/cli/options.js +9 -7
  106. package/dist/cli/options.js.map +1 -1
  107. package/dist/cli/review.d.ts +2 -1
  108. package/dist/cli/review.d.ts.map +1 -1
  109. package/dist/cli/review.js +5 -0
  110. package/dist/cli/review.js.map +1 -1
  111. package/dist/cli/skill.js +1 -1
  112. package/dist/cli/skill.js.map +1 -1
  113. package/dist/cli/viewer.d.ts.map +1 -1
  114. package/dist/cli/viewer.js +46 -34
  115. package/dist/cli/viewer.js.map +1 -1
  116. package/dist/config.d.ts +3 -0
  117. package/dist/config.d.ts.map +1 -1
  118. package/dist/config.js +35 -3
  119. package/dist/config.js.map +1 -1
  120. package/dist/documentLinks/check.d.ts +2 -1
  121. package/dist/documentLinks/check.d.ts.map +1 -1
  122. package/dist/documentLinks/check.js +2 -2
  123. package/dist/documentLinks/check.js.map +1 -1
  124. package/dist/duplicate-token-normalization.d.ts.map +1 -1
  125. package/dist/duplicate-token-normalization.js +10 -2
  126. package/dist/duplicate-token-normalization.js.map +1 -1
  127. package/dist/duplicates/scoring.d.ts +0 -10
  128. package/dist/duplicates/scoring.d.ts.map +1 -1
  129. package/dist/duplicates/scoring.js +9 -9
  130. package/dist/duplicates/scoring.js.map +1 -1
  131. package/dist/duplicates/unitCache.d.ts +15 -9
  132. package/dist/duplicates/unitCache.d.ts.map +1 -1
  133. package/dist/duplicates/unitCache.js +184 -33
  134. package/dist/duplicates/unitCache.js.map +1 -1
  135. package/dist/duplicates/units.d.ts +6 -15
  136. package/dist/duplicates/units.d.ts.map +1 -1
  137. package/dist/duplicates/units.js +36 -18
  138. package/dist/duplicates/units.js.map +1 -1
  139. package/dist/frameworks/angularjs.d.ts.map +1 -1
  140. package/dist/frameworks/angularjs.js +18 -12
  141. package/dist/frameworks/angularjs.js.map +1 -1
  142. package/dist/graph-builder.d.ts.map +1 -1
  143. package/dist/graph-builder.js +12 -9
  144. package/dist/graph-builder.js.map +1 -1
  145. package/dist/graph-edge-collector.d.ts +1 -0
  146. package/dist/graph-edge-collector.d.ts.map +1 -1
  147. package/dist/graph-edge-collector.js +1 -1
  148. package/dist/graph-edge-collector.js.map +1 -1
  149. package/dist/graphs/grep.d.ts.map +1 -1
  150. package/dist/graphs/grep.js +7 -2
  151. package/dist/graphs/grep.js.map +1 -1
  152. package/dist/graphs/specifiers.d.ts.map +1 -1
  153. package/dist/graphs/specifiers.js +8 -2
  154. package/dist/graphs/specifiers.js.map +1 -1
  155. package/dist/graphs/symbol-graph-detailed.d.ts.map +1 -1
  156. package/dist/graphs/symbol-graph-detailed.js +3 -1
  157. package/dist/graphs/symbol-graph-detailed.js.map +1 -1
  158. package/dist/impact/analyzer.d.ts.map +1 -1
  159. package/dist/impact/analyzer.js +15 -1
  160. package/dist/impact/analyzer.js.map +1 -1
  161. package/dist/impact/call-compatibility/textScanner.d.ts +23 -0
  162. package/dist/impact/call-compatibility/textScanner.d.ts.map +1 -0
  163. package/dist/impact/call-compatibility/textScanner.js +615 -0
  164. package/dist/impact/call-compatibility/textScanner.js.map +1 -0
  165. package/dist/impact/callCompatibility.d.ts.map +1 -1
  166. package/dist/impact/callCompatibility.js +9 -570
  167. package/dist/impact/callCompatibility.js.map +1 -1
  168. package/dist/impact/direct.js +7 -6
  169. package/dist/impact/direct.js.map +1 -1
  170. package/dist/impact/index.d.ts +6 -0
  171. package/dist/impact/index.d.ts.map +1 -1
  172. package/dist/impact/index.js +0 -8
  173. package/dist/impact/index.js.map +1 -1
  174. package/dist/impact/map.js +2 -2
  175. package/dist/impact/map.js.map +1 -1
  176. package/dist/impact/memberResolutionCoverage.d.ts.map +1 -1
  177. package/dist/impact/memberResolutionCoverage.js +5 -1
  178. package/dist/impact/memberResolutionCoverage.js.map +1 -1
  179. package/dist/impact/parse.d.ts.map +1 -1
  180. package/dist/impact/parse.js +98 -36
  181. package/dist/impact/parse.js.map +1 -1
  182. package/dist/impact/referenceCache.js +1 -1
  183. package/dist/impact/referenceCache.js.map +1 -1
  184. package/dist/impact/report-suggestions.d.ts.map +1 -1
  185. package/dist/impact/report-suggestions.js +330 -61
  186. package/dist/impact/report-suggestions.js.map +1 -1
  187. package/dist/impact/reportCompact.js +7 -0
  188. package/dist/impact/reportCompact.js.map +1 -1
  189. package/dist/impact/streaming.d.ts +32 -2
  190. package/dist/impact/streaming.d.ts.map +1 -1
  191. package/dist/impact/streaming.js +61 -2
  192. package/dist/impact/streaming.js.map +1 -1
  193. package/dist/impact/suggestions.d.ts.map +1 -1
  194. package/dist/impact/suggestions.js +1 -1
  195. package/dist/impact/suggestions.js.map +1 -1
  196. package/dist/impact/types.d.ts +7 -20
  197. package/dist/impact/types.d.ts.map +1 -1
  198. package/dist/impact/types.js.map +1 -1
  199. package/dist/index.d.ts +2 -2
  200. package/dist/index.d.ts.map +1 -1
  201. package/dist/index.js +1 -1
  202. package/dist/index.js.map +1 -1
  203. package/dist/indexer/build-cache/location.d.ts +19 -0
  204. package/dist/indexer/build-cache/location.d.ts.map +1 -0
  205. package/dist/indexer/build-cache/location.js +132 -0
  206. package/dist/indexer/build-cache/location.js.map +1 -0
  207. package/dist/indexer/build-cache/manifest.d.ts +9 -3
  208. package/dist/indexer/build-cache/manifest.d.ts.map +1 -1
  209. package/dist/indexer/build-cache/manifest.js +77 -20
  210. package/dist/indexer/build-cache/manifest.js.map +1 -1
  211. package/dist/indexer/build-cache/module-cache.d.ts +23 -2
  212. package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
  213. package/dist/indexer/build-cache/module-cache.js +92 -32
  214. package/dist/indexer/build-cache/module-cache.js.map +1 -1
  215. package/dist/indexer/build-cache/options.d.ts +3 -1
  216. package/dist/indexer/build-cache/options.d.ts.map +1 -1
  217. package/dist/indexer/build-cache/options.js +10 -2
  218. package/dist/indexer/build-cache/options.js.map +1 -1
  219. package/dist/indexer/build-cache/project-snapshot.d.ts +32 -8
  220. package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
  221. package/dist/indexer/build-cache/project-snapshot.js +333 -44
  222. package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
  223. package/dist/indexer/build-cache/reports.d.ts.map +1 -1
  224. package/dist/indexer/build-cache/reports.js +10 -1
  225. package/dist/indexer/build-cache/reports.js.map +1 -1
  226. package/dist/indexer/build-cache/resolver-environment.d.ts +9 -0
  227. package/dist/indexer/build-cache/resolver-environment.d.ts.map +1 -0
  228. package/dist/indexer/build-cache/resolver-environment.js +133 -0
  229. package/dist/indexer/build-cache/resolver-environment.js.map +1 -0
  230. package/dist/indexer/build-cache.d.ts +4 -3
  231. package/dist/indexer/build-cache.d.ts.map +1 -1
  232. package/dist/indexer/build-cache.js +4 -3
  233. package/dist/indexer/build-cache.js.map +1 -1
  234. package/dist/indexer/build-index.d.ts.map +1 -1
  235. package/dist/indexer/build-index.js +154 -47
  236. package/dist/indexer/build-index.js.map +1 -1
  237. package/dist/indexer/build-manifest.d.ts +1 -0
  238. package/dist/indexer/build-manifest.d.ts.map +1 -1
  239. package/dist/indexer/build-manifest.js +12 -5
  240. package/dist/indexer/build-manifest.js.map +1 -1
  241. package/dist/indexer/call-hierarchy.d.ts.map +1 -1
  242. package/dist/indexer/call-hierarchy.js.map +1 -1
  243. package/dist/indexer/finalize.d.ts.map +1 -1
  244. package/dist/indexer/finalize.js +7 -4
  245. package/dist/indexer/finalize.js.map +1 -1
  246. package/dist/indexer/imports/jsTextImports.d.ts.map +1 -1
  247. package/dist/indexer/imports/jsTextImports.js +14 -6
  248. package/dist/indexer/imports/jsTextImports.js.map +1 -1
  249. package/dist/indexer/imports/languageSpecific.d.ts.map +1 -1
  250. package/dist/indexer/imports/languageSpecific.js +10 -5
  251. package/dist/indexer/imports/languageSpecific.js.map +1 -1
  252. package/dist/indexer/imports/nativeCaptures.d.ts.map +1 -1
  253. package/dist/indexer/imports/nativeCaptures.js +4 -1
  254. package/dist/indexer/imports/nativeCaptures.js.map +1 -1
  255. package/dist/indexer/imports/python.d.ts.map +1 -1
  256. package/dist/indexer/imports/python.js +7 -2
  257. package/dist/indexer/imports/python.js.map +1 -1
  258. package/dist/indexer/load-current-index.d.ts.map +1 -1
  259. package/dist/indexer/load-current-index.js.map +1 -1
  260. package/dist/indexer/locals-and-exports.d.ts.map +1 -1
  261. package/dist/indexer/locals-and-exports.js +52 -22
  262. package/dist/indexer/locals-and-exports.js.map +1 -1
  263. package/dist/indexer/navigation-goto.d.ts.map +1 -1
  264. package/dist/indexer/navigation-goto.js +26 -16
  265. package/dist/indexer/navigation-goto.js.map +1 -1
  266. package/dist/indexer/navigation-local.d.ts.map +1 -1
  267. package/dist/indexer/navigation-local.js +7 -4
  268. package/dist/indexer/navigation-local.js.map +1 -1
  269. package/dist/indexer/navigation-references.d.ts +1 -1
  270. package/dist/indexer/navigation-references.d.ts.map +1 -1
  271. package/dist/indexer/navigation-references.js +27 -16
  272. package/dist/indexer/navigation-references.js.map +1 -1
  273. package/dist/indexer/navigation-resolve.d.ts.map +1 -1
  274. package/dist/indexer/navigation-resolve.js +116 -53
  275. package/dist/indexer/navigation-resolve.js.map +1 -1
  276. package/dist/indexer/navigation.d.ts +2 -1
  277. package/dist/indexer/navigation.d.ts.map +1 -1
  278. package/dist/indexer/navigation.js +24 -20
  279. package/dist/indexer/navigation.js.map +1 -1
  280. package/dist/indexer/parse-context.d.ts +1 -1
  281. package/dist/indexer/parse-context.d.ts.map +1 -1
  282. package/dist/indexer/parse-context.js +2 -2
  283. package/dist/indexer/parse-context.js.map +1 -1
  284. package/dist/indexer/reference-context.d.ts +2 -2
  285. package/dist/indexer/reference-context.d.ts.map +1 -1
  286. package/dist/indexer/reference-context.js +4 -2
  287. package/dist/indexer/reference-context.js.map +1 -1
  288. package/dist/indexer/scope-types.d.ts +3 -0
  289. package/dist/indexer/scope-types.d.ts.map +1 -1
  290. package/dist/indexer/scope.js +37 -38
  291. package/dist/indexer/scope.js.map +1 -1
  292. package/dist/indexer/shared.d.ts.map +1 -1
  293. package/dist/indexer/shared.js +3 -1
  294. package/dist/indexer/shared.js.map +1 -1
  295. package/dist/indexer/type-hierarchy.d.ts.map +1 -1
  296. package/dist/indexer/type-hierarchy.js +12 -8
  297. package/dist/indexer/type-hierarchy.js.map +1 -1
  298. package/dist/indexer/types.d.ts +22 -0
  299. package/dist/indexer/types.d.ts.map +1 -1
  300. package/dist/indexer/workspace-symbols.d.ts.map +1 -1
  301. package/dist/indexer/workspace-symbols.js +5 -3
  302. package/dist/indexer/workspace-symbols.js.map +1 -1
  303. package/dist/installer/locks.d.ts +10 -0
  304. package/dist/installer/locks.d.ts.map +1 -0
  305. package/dist/installer/locks.js +234 -0
  306. package/dist/installer/locks.js.map +1 -0
  307. package/dist/installer/registry.d.ts.map +1 -1
  308. package/dist/installer/registry.js +13 -230
  309. package/dist/installer/registry.js.map +1 -1
  310. package/dist/languages/definitions/csharp.d.ts.map +1 -1
  311. package/dist/languages/definitions/csharp.js +8 -0
  312. package/dist/languages/definitions/csharp.js.map +1 -1
  313. package/dist/languages/definitions/java.d.ts.map +1 -1
  314. package/dist/languages/definitions/java.js +3 -0
  315. package/dist/languages/definitions/java.js.map +1 -1
  316. package/dist/languages/definitions/python.d.ts.map +1 -1
  317. package/dist/languages/definitions/python.js +2 -0
  318. package/dist/languages/definitions/python.js.map +1 -1
  319. package/dist/languages/definitions/rust.d.ts.map +1 -1
  320. package/dist/languages/definitions/rust.js +2 -0
  321. package/dist/languages/definitions/rust.js.map +1 -1
  322. package/dist/languages/importStatementParsers.d.ts +2 -0
  323. package/dist/languages/importStatementParsers.d.ts.map +1 -1
  324. package/dist/languages/importStatementParsers.js +24 -10
  325. package/dist/languages/importStatementParsers.js.map +1 -1
  326. package/dist/mcp/http.d.ts +3 -1
  327. package/dist/mcp/http.d.ts.map +1 -1
  328. package/dist/mcp/http.js +69 -20
  329. package/dist/mcp/http.js.map +1 -1
  330. package/dist/mcp/server.d.ts +43 -16
  331. package/dist/mcp/server.d.ts.map +1 -1
  332. package/dist/mcp/server.js +342 -127
  333. package/dist/mcp/server.js.map +1 -1
  334. package/dist/mcp/tools.d.ts +51 -1
  335. package/dist/mcp/tools.d.ts.map +1 -1
  336. package/dist/mcp/tools.js +121 -2
  337. package/dist/mcp/tools.js.map +1 -1
  338. package/dist/native/byteIndex.d.ts +26 -0
  339. package/dist/native/byteIndex.d.ts.map +1 -0
  340. package/dist/native/byteIndex.js +70 -0
  341. package/dist/native/byteIndex.js.map +1 -0
  342. package/dist/native/projectedTree.d.ts +3 -2
  343. package/dist/native/projectedTree.d.ts.map +1 -1
  344. package/dist/native/projectedTree.js +6 -50
  345. package/dist/native/projectedTree.js.map +1 -1
  346. package/dist/native/queryResults.d.ts +7 -1
  347. package/dist/native/queryResults.d.ts.map +1 -1
  348. package/dist/native/queryResults.js +13 -5
  349. package/dist/native/queryResults.js.map +1 -1
  350. package/dist/review/changes.d.ts +2 -0
  351. package/dist/review/changes.d.ts.map +1 -1
  352. package/dist/review/changes.js +10 -0
  353. package/dist/review/changes.js.map +1 -1
  354. package/dist/review/deleted.d.ts.map +1 -1
  355. package/dist/review/deleted.js +20 -2
  356. package/dist/review/deleted.js.map +1 -1
  357. package/dist/review/summaries.d.ts.map +1 -1
  358. package/dist/review/summaries.js +13 -10
  359. package/dist/review/summaries.js.map +1 -1
  360. package/dist/review.d.ts.map +1 -1
  361. package/dist/review.js +7 -2
  362. package/dist/review.js.map +1 -1
  363. package/dist/session.d.ts +20 -4
  364. package/dist/session.d.ts.map +1 -1
  365. package/dist/session.js +76 -16
  366. package/dist/session.js.map +1 -1
  367. package/dist/sql/types.d.ts.map +1 -1
  368. package/dist/sqlite/query.d.ts +29 -0
  369. package/dist/sqlite/query.d.ts.map +1 -1
  370. package/dist/sqlite/query.js +98 -11
  371. package/dist/sqlite/query.js.map +1 -1
  372. package/dist/sqlite/rawQueryWorker.d.ts +22 -0
  373. package/dist/sqlite/rawQueryWorker.d.ts.map +1 -0
  374. package/dist/sqlite/rawQueryWorker.js +31 -0
  375. package/dist/sqlite/rawQueryWorker.js.map +1 -0
  376. package/dist/sqlite/rawQueryWorkerPool.d.ts +66 -0
  377. package/dist/sqlite/rawQueryWorkerPool.d.ts.map +1 -0
  378. package/dist/sqlite/rawQueryWorkerPool.js +142 -0
  379. package/dist/sqlite/rawQueryWorkerPool.js.map +1 -0
  380. package/dist/sqlite/schema.d.ts.map +1 -1
  381. package/dist/sqlite/schema.js.map +1 -1
  382. package/dist/sqlite-driver.d.ts.map +1 -1
  383. package/dist/sqlite-driver.js +2 -1
  384. package/dist/sqlite-driver.js.map +1 -1
  385. package/dist/sqlite.d.ts +1 -1
  386. package/dist/sqlite.d.ts.map +1 -1
  387. package/dist/sqlite.js +1 -1
  388. package/dist/sqlite.js.map +1 -1
  389. package/dist/util/bloomFilter.d.ts +3 -2
  390. package/dist/util/bloomFilter.d.ts.map +1 -1
  391. package/dist/util/bloomFilter.js +8 -8
  392. package/dist/util/bloomFilter.js.map +1 -1
  393. package/dist/util/confinedFile.d.ts +41 -2
  394. package/dist/util/confinedFile.d.ts.map +1 -1
  395. package/dist/util/confinedFile.js +101 -2
  396. package/dist/util/confinedFile.js.map +1 -1
  397. package/dist/util/git.d.ts +2 -0
  398. package/dist/util/git.d.ts.map +1 -1
  399. package/dist/util/git.js +109 -26
  400. package/dist/util/git.js.map +1 -1
  401. package/dist/util/identifiers.d.ts +75 -0
  402. package/dist/util/identifiers.d.ts.map +1 -0
  403. package/dist/util/identifiers.js +82 -0
  404. package/dist/util/identifiers.js.map +1 -0
  405. package/dist/util/paths.d.ts.map +1 -1
  406. package/dist/util/paths.js.map +1 -1
  407. package/dist/util/projectFiles.d.ts.map +1 -1
  408. package/dist/util/projectFiles.js +43 -14
  409. package/dist/util/projectFiles.js.map +1 -1
  410. package/dist/util/resolution/jvm.d.ts.map +1 -1
  411. package/dist/util/resolution/jvm.js +9 -4
  412. package/dist/util/resolution/jvm.js.map +1 -1
  413. package/dist/util/resolution/php.d.ts.map +1 -1
  414. package/dist/util/resolution/php.js +6 -5
  415. package/dist/util/resolution/php.js.map +1 -1
  416. package/dist/util/rustTestModules.d.ts.map +1 -1
  417. package/dist/util/rustTestModules.js +4 -2
  418. package/dist/util/rustTestModules.js.map +1 -1
  419. package/dist/util/specifiers.d.ts.map +1 -1
  420. package/dist/util/specifiers.js +10 -3
  421. package/dist/util/specifiers.js.map +1 -1
  422. package/dist/util/sqliteSchema.d.ts.map +1 -1
  423. package/dist/util/sqliteSchema.js +10 -1
  424. package/dist/util/sqliteSchema.js.map +1 -1
  425. package/docs/mcp.md +32 -13
  426. package/package.json +3 -3
@@ -1,4 +1,5 @@
1
1
  import { randomUUID } from "node:crypto";
2
+ import { AsyncLocalStorage } from "node:async_hooks";
2
3
  import fs from "node:fs/promises";
3
4
  import { createServer } from "node:http";
4
5
  import path from "node:path";
@@ -28,16 +29,17 @@ import { DEFAULT_BOUNDED_IMPACT_BUDGETS } from "../impact/budgets.js";
28
29
  import { buildReviewReport } from "../review.js";
29
30
  import { boundReviewReportForTransport } from "../review/types.js";
30
31
  import { SQLITE_ARTIFACT_FILE_SIGNATURES_METADATA_KEY, queryGraphSqliteRaw } from "../sqlite.js";
32
+ import { boundList, countOmitted } from "../presentation/bounds.js";
31
33
  import { isPlainRecord } from "../util/guards.js";
32
34
  import { toProjectDisplayPath } from "../util/paths.js";
33
35
  import { errorMessage } from "../util/errors.js";
34
- import { createAgentSession, listAgentSessionFiles } from "../agent/session.js";
36
+ import { assertNoPrebuiltSessionWithBuildOptions, createAgentSession, listAgentSessionFiles, } from "../agent/session.js";
35
37
  import { mapLimit } from "../util/concurrency.js";
36
38
  import { assertRealPathCandidateWithinRoot, resolveProjectFile } from "../util/confinedFile.js";
37
39
  import { SymbolKind } from "../indexer/types.js";
38
40
  import { DEFAULT_WORKSPACE_SYMBOL_LIMIT, MAX_WORKSPACE_SYMBOL_LIMIT } from "../indexer/workspace-symbols.js";
39
- import { assertMcpSqliteQueryResourceBounded, boundRawSqlResult, DEFAULT_SQLITE_BYTE_LIMIT, normalizeSqliteRowLimit, } from "./sqliteGuard.js";
40
- import { DEFAULT_CALL_HIERARCHY_LIMIT, MAX_CALL_HIERARCHY_LIMIT, DEFAULT_MCP_COLLECTION_LIMIT, DEFAULT_TYPE_HIERARCHY_LIMIT, listCodegraphMcpTools, MAX_TYPE_HIERARCHY_LIMIT, MAX_MCP_COLLECTION_LIMIT, MAX_RENAME_PREVIEW_EDITS, MCP_TOOLS, MAX_REFACTOR_PLAN_LIMIT, } from "./tools.js";
41
+ import { assertMcpSqliteQueryResourceBounded, DEFAULT_SQLITE_BYTE_LIMIT, normalizeSqliteRowLimit, } from "./sqliteGuard.js";
42
+ import { DEFAULT_CALL_HIERARCHY_LIMIT, MAX_CALL_HIERARCHY_LIMIT, DEFAULT_MCP_COLLECTION_LIMIT, DEFAULT_TYPE_HIERARCHY_LIMIT, listCodegraphMcpTools, MAX_TYPE_HIERARCHY_LIMIT, MAX_MCP_COLLECTION_LIMIT, MAX_RENAME_PREVIEW_EDITS, MCP_TOOL_REGISTRY, MAX_REFACTOR_PLAN_LIMIT, } from "./tools.js";
41
43
  import { buildAllowedHostHeaders, buildAllowedOriginHostnames, closeHttpServer, emptyAllowedHostHeaderRules, formatHostForUrl, getHeaderValue, getHttpServerPort, getRequestPath, isAllowedHostHeader, listenOnHttpServer, readJsonRequestBody, waitForHttpServerClose, writeJsonResponse, writeJsonRpcError, } from "./http.js";
42
44
  import { getCurrentNativeBindingOrigin } from "../native/runtime.js";
43
45
  import { captureCodegraphRuntimeIdentity, createInstalledVersionChecker, } from "../runtimeIdentity.js";
@@ -47,12 +49,34 @@ import { awaitStdioMcpLifecycle, DEFAULT_MCP_STDIO_IDLE_TIMEOUT_MS } from "./std
47
49
  export const DEFAULT_MCP_HTTP_SESSION_IDLE_MS = 30 * 60 * 1000;
48
50
  export const DEFAULT_MCP_HTTP_SESSION_MAX_COUNT = 32;
49
51
  export const DEFAULT_MCP_HTTP_SESSION_EVICTION_INTERVAL_MS = 60_000;
52
+ export const DEFAULT_MCP_HTTP_BODY_TIMEOUT_MS = 30_000;
53
+ export const DEFAULT_MCP_TOOL_TIMEOUT_MS = 30 * 60 * 1000;
54
+ const MAX_MCP_HTTP_BODY_TIMEOUT_MS = 2_147_483_647;
55
+ const MAX_MCP_TOOL_TIMEOUT_MS = 2_147_483_647;
56
+ export const DEFAULT_MCP_TOOL_CONCURRENCY = 4;
57
+ function normalizeMcpToolConcurrency(value) {
58
+ if (!Number.isFinite(value))
59
+ return DEFAULT_MCP_TOOL_CONCURRENCY;
60
+ return Math.max(1, Math.floor(value));
61
+ }
62
+ function assertMcpHttpBodyTimeout(value) {
63
+ if (!Number.isSafeInteger(value) || value < 1 || value > MAX_MCP_HTTP_BODY_TIMEOUT_MS) {
64
+ throw new RangeError(`httpBodyTimeoutMs must be a positive integer no greater than ${MAX_MCP_HTTP_BODY_TIMEOUT_MS}.`);
65
+ }
66
+ return value;
67
+ }
68
+ function assertMcpToolTimeout(value) {
69
+ if (!Number.isSafeInteger(value) || value < 0 || value > MAX_MCP_TOOL_TIMEOUT_MS) {
70
+ throw new RangeError(`mcpToolTimeoutMs must be a whole number from 0 through ${MAX_MCP_TOOL_TIMEOUT_MS}; 0 disables the deadline.`);
71
+ }
72
+ return value;
73
+ }
74
+ const legacyRequestAbortStorage = new AsyncLocalStorage();
50
75
  const MAX_MCP_FRESHNESS_CHANGED_FILES = 25;
76
+ const MAX_MCP_FRESHNESS_RETRIES = 3;
51
77
  const SQLITE_ARTIFACT_STAT_CONCURRENCY = 64;
52
78
  function assertMcpSessionOptions(options) {
53
- if (options.session !== undefined && options.buildOptions !== undefined) {
54
- throw new Error("MCP server options cannot combine a prebuilt session with buildOptions.");
55
- }
79
+ assertNoPrebuiltSessionWithBuildOptions(options, "MCP server options");
56
80
  }
57
81
  function createCodegraphMcpSession(options, root) {
58
82
  assertMcpSessionOptions(options);
@@ -72,7 +96,7 @@ function startCodegraphMcpWarmup(session, warmup) {
72
96
  }
73
97
  return undefined;
74
98
  }
75
- async function createWarmedCodegraphMcpHandlers(options) {
99
+ async function createWarmedCodegraphMcpResources(options) {
76
100
  const root = path.resolve(options.root);
77
101
  const session = createCodegraphMcpSession(options, root);
78
102
  await startCodegraphMcpWarmup(session, options.warmup);
@@ -81,7 +105,10 @@ async function createWarmedCodegraphMcpHandlers(options) {
81
105
  void host;
82
106
  void port;
83
107
  void onHttpListen;
84
- return createCodegraphMcpHandlersForSession({ ...handlerOptions, root }, session);
108
+ return {
109
+ handlers: createCodegraphMcpHandlersForSession({ ...handlerOptions, root }, session),
110
+ session,
111
+ };
85
112
  }
86
113
  const MCP_HTTP_PATH = "/mcp";
87
114
  const MAX_MCP_HTTP_BODY_BYTES = 1_000_000;
@@ -102,6 +129,8 @@ function createCodegraphMcpHandlersForSession(options, session) {
102
129
  let sqlitePath = configuredSqlitePath;
103
130
  let sqliteOutDir = configuredSqliteOutDir;
104
131
  let sqliteCanRefresh = configuredSqliteCanRefresh;
132
+ let refreshPromise;
133
+ let refreshEpoch = 0;
105
134
  const relative = (file) => toProjectDisplayPath(root, file);
106
135
  const boundedLimit = (limit, fallback, max) => {
107
136
  if (typeof limit !== "number" || !Number.isFinite(limit))
@@ -115,7 +144,7 @@ function createCodegraphMcpHandlersForSession(options, session) {
115
144
  state: "stale",
116
145
  changedFiles: boundedChangedFiles,
117
146
  changedFileCount: changedFiles.length,
118
- omittedChangedFileCount: Math.max(0, changedFiles.length - boundedChangedFiles.length),
147
+ omittedChangedFileCount: countOmitted(changedFiles.length, boundedChangedFiles.length),
119
148
  reason,
120
149
  };
121
150
  };
@@ -125,9 +154,16 @@ function createCodegraphMcpHandlersForSession(options, session) {
125
154
  return { state: "fresh" };
126
155
  };
127
156
  const withFreshness = async (run) => {
128
- const freshness = await checkMcpFreshness();
129
- const result = await run();
130
- return { ...result, freshness };
157
+ for (let attempt = 0; attempt < MAX_MCP_FRESHNESS_RETRIES; attempt += 1) {
158
+ if (refreshPromise)
159
+ await refreshPromise;
160
+ const epoch = refreshEpoch;
161
+ const freshness = await checkMcpFreshness();
162
+ const result = await run();
163
+ if (epoch === refreshEpoch && !refreshPromise)
164
+ return { ...result, freshness };
165
+ }
166
+ throw new Error("Workspace refresh changed repeatedly while serving the request; retry after refresh completes.");
131
167
  };
132
168
  const formatSqliteFreshnessError = (freshness) => {
133
169
  if (freshness.state === "fresh")
@@ -286,7 +322,7 @@ function createCodegraphMcpHandlersForSession(options, session) {
286
322
  // Probe one entry past the display limit so `truncated` is exact
287
323
  // rather than a `results.length === limit` heuristic (which cannot
288
324
  // tell "exactly limit reachable files" apart from "more exist"),
289
- // without re-walking the whole reachable graph for an exact total
325
+ // without re-walking the whole reachable graph for an exact total -
290
326
  // see finding #44.
291
327
  limit: limit + 1,
292
328
  };
@@ -302,13 +338,18 @@ function createCodegraphMcpHandlersForSession(options, session) {
302
338
  targetFile = await resolveProjectFile(await realRoot, root, request.file);
303
339
  }
304
340
  const collected = collectEntries(snapshot.fileGraph, targetFile, queryOptions);
305
- const totalSeen = collected.length;
306
- const truncated = totalSeen > limit;
307
- const entries = collected.slice(0, limit).map((dependency) => ({
341
+ const { items, omitted } = boundList(collected, limit);
342
+ const entries = items.map((dependency) => ({
308
343
  file: relative(dependency.file),
309
344
  depth: dependency.depth,
310
345
  }));
311
- return { entries, limit, totalSeen, truncated, omitted: truncated ? totalSeen - limit : 0 };
346
+ return {
347
+ entries,
348
+ limit,
349
+ totalSeen: collected.length,
350
+ truncated: Boolean(omitted),
351
+ omitted,
352
+ };
312
353
  };
313
354
  const calls = async (request) => {
314
355
  const findCalls = request.direction === "callers" ? findCallersWithSession : findCalleesWithSession;
@@ -333,12 +374,15 @@ function createCodegraphMcpHandlersForSession(options, session) {
333
374
  if (result.status !== "ok") {
334
375
  return { references: [], limit, totalSeen: 0, truncated: false, omitted: 0 };
335
376
  }
336
- const totalSeen = result.references.length;
337
- const truncated = totalSeen > limit;
338
- const references = result.references
339
- .slice(0, limit)
340
- .map((reference) => ({ file: relative(reference.file), range: reference.range }));
341
- return { references, limit, totalSeen, truncated, omitted: truncated ? totalSeen - limit : 0 };
377
+ const { items, omitted } = boundList(result.references, limit);
378
+ const references = items.map((reference) => ({ file: relative(reference.file), range: reference.range }));
379
+ return {
380
+ references,
381
+ limit,
382
+ totalSeen: result.references.length,
383
+ truncated: Boolean(omitted),
384
+ omitted,
385
+ };
342
386
  };
343
387
  const fileDeps = async (request) => await withFreshness(async () => {
344
388
  const { entries, ...meta } = await collectMcpDependencyEntries(request, request.direction === "deps" ? getDependencies : getReverseDependencies);
@@ -458,7 +502,7 @@ function createCodegraphMcpHandlersForSession(options, session) {
458
502
  if (parseQualifiedSymbolPath(handle)) {
459
503
  const snapshot = await session.loadProject({ symbolGraph: "skip" });
460
504
  const resolved = requireSemanticSymbol(snapshot, handle);
461
- // Probe one reference past the display limit so `truncated` is exact see
505
+ // Probe one reference past the display limit so `truncated` is exact - see
462
506
  // `collectMcpDependencyEntries` for the rationale (finding #44).
463
507
  const result = await findReferences(snapshot.index, { def: resolved.def }, { maxReferences: limit + 1 });
464
508
  return boundedReferencesFromResult(result, limit);
@@ -534,7 +578,7 @@ function createCodegraphMcpHandlersForSession(options, session) {
534
578
  // complete, unbounded report should call `buildReviewReport` directly.
535
579
  return boundReviewReportForTransport(report);
536
580
  }),
537
- query_sqlite: async (request) => {
581
+ query_sqlite: async (request, executionOptions) => {
538
582
  if (!sqlitePath) {
539
583
  throw new Error("No SQLite artifact is available. Run artifact_build first or pass artifactPath.");
540
584
  }
@@ -555,16 +599,32 @@ function createCodegraphMcpHandlersForSession(options, session) {
555
599
  }
556
600
  const result = await queryGraphSqliteRaw(realSqlitePath, request.query, request.params ?? [], {
557
601
  maxRows: normalizeSqliteRowLimit(request.limit),
602
+ maxBytes: DEFAULT_SQLITE_BYTE_LIMIT,
603
+ ...(executionOptions?.signal ? { signal: executionOptions.signal } : {}),
558
604
  });
559
- return { ...boundRawSqlResult(result, DEFAULT_SQLITE_BYTE_LIMIT), freshness: artifactFreshness };
605
+ return { ...result, truncated: Boolean(result.truncated), freshness: artifactFreshness };
560
606
  },
561
607
  refresh_index: async (request) => {
562
608
  const warmup = request.warmup ?? "off";
563
- session.invalidate();
564
- sqlitePath = configuredSqlitePath;
565
- sqliteOutDir = configuredSqliteOutDir;
566
- sqliteCanRefresh = configuredSqliteCanRefresh;
567
- await startCodegraphMcpWarmup(session, warmup);
609
+ const previousRefresh = refreshPromise;
610
+ const refresh = (async () => {
611
+ if (previousRefresh)
612
+ await previousRefresh.catch(() => undefined);
613
+ ++refreshEpoch;
614
+ session.invalidate();
615
+ sqlitePath = configuredSqlitePath;
616
+ sqliteOutDir = configuredSqliteOutDir;
617
+ sqliteCanRefresh = configuredSqliteCanRefresh;
618
+ await startCodegraphMcpWarmup(session, warmup);
619
+ })();
620
+ refreshPromise = refresh;
621
+ try {
622
+ await refresh;
623
+ }
624
+ finally {
625
+ if (refreshPromise === refresh)
626
+ refreshPromise = undefined;
627
+ }
568
628
  return { refreshed: true, warmup };
569
629
  },
570
630
  artifact_build: async (request) => {
@@ -602,15 +662,49 @@ function createCodegraphMcpHandlersForSession(options, session) {
602
662
  },
603
663
  };
604
664
  }
605
- export function createCodegraphMcpProtocolServer(handlers, runtimeIdentity = captureCodegraphRuntimeIdentity(getCurrentNativeBindingOrigin()), installedVersion = createInstalledVersionChecker(runtimeIdentity), toolCallState = { firstToolCallPending: true }) {
665
+ function createMcpToolOperationTracker() {
666
+ let accepting = true;
667
+ const operations = new Set();
668
+ return {
669
+ isAccepting: () => accepting,
670
+ track: (operation) => {
671
+ if (!accepting)
672
+ return undefined;
673
+ const tracked = operation();
674
+ operations.add(tracked);
675
+ void tracked.then(() => operations.delete(tracked), () => operations.delete(tracked));
676
+ return tracked;
677
+ },
678
+ stop: () => {
679
+ accepting = false;
680
+ },
681
+ drain: async () => {
682
+ accepting = false;
683
+ await Promise.allSettled([...operations]);
684
+ },
685
+ };
686
+ }
687
+ export function createCodegraphMcpProtocolServer(handlers, runtimeIdentity = captureCodegraphRuntimeIdentity(getCurrentNativeBindingOrigin()), installedVersion = createInstalledVersionChecker(runtimeIdentity), toolCallState = { firstToolCallPending: true }, maxConcurrentToolCalls = DEFAULT_MCP_TOOL_CONCURRENCY, mcpToolTimeoutMs = DEFAULT_MCP_TOOL_TIMEOUT_MS) {
688
+ return createCodegraphMcpProtocolServerWithTracker(handlers, runtimeIdentity, installedVersion, toolCallState, maxConcurrentToolCalls, assertMcpToolTimeout(mcpToolTimeoutMs), createMcpToolOperationTracker());
689
+ }
690
+ function createCodegraphMcpProtocolServerWithTracker(handlers, runtimeIdentity, installedVersion, toolCallState, maxConcurrentToolCalls, mcpToolTimeoutMs, toolOperations) {
606
691
  const server = new Server({
607
692
  name: "codegraph",
608
693
  version: runtimeIdentity.runningVersion,
609
694
  }, {
610
695
  capabilities: { tools: {}, logging: {} },
611
696
  });
612
- server.setRequestHandler("tools/list", () => ({ tools: MCP_TOOLS }));
697
+ let inFlightToolCalls = 0;
698
+ const toolConcurrency = normalizeMcpToolConcurrency(maxConcurrentToolCalls);
699
+ server.setRequestHandler("tools/list", () => ({ tools: listCodegraphMcpTools() }));
613
700
  server.setRequestHandler("tools/call", async (request, ctx) => {
701
+ if (!toolOperations.isAccepting()) {
702
+ throw new Error("MCP server is shutting down.");
703
+ }
704
+ if (inFlightToolCalls >= toolConcurrency) {
705
+ throw new Error("MCP tool execution is busy; retry shortly.");
706
+ }
707
+ inFlightToolCalls += 1;
614
708
  const isFirstToolCall = toolCallState.firstToolCallPending;
615
709
  toolCallState.firstToolCallPending = false;
616
710
  const progressToken = isFirstToolCall ? getToolCallProgressToken(request.params) : undefined;
@@ -622,12 +716,7 @@ export function createCodegraphMcpProtocolServer(handlers, runtimeIdentity = cap
622
716
  if (progressToken !== undefined) {
623
717
  await ctx.mcpReq.notify({
624
718
  method: "notifications/progress",
625
- params: {
626
- progressToken,
627
- progress,
628
- total: 1,
629
- message,
630
- },
719
+ params: { progressToken, progress, total: 1, message },
631
720
  });
632
721
  }
633
722
  }
@@ -643,9 +732,24 @@ export function createCodegraphMcpProtocolServer(handlers, runtimeIdentity = cap
643
732
  console.error(`[codegraph] installed-version check failed: ${errorMessage(error)}`);
644
733
  }
645
734
  try {
646
- const result = await callMcpTool(handlers, request.params.name, request.params.arguments ?? {});
647
- await emitFirstToolCallVisibility("info", 1, `Codegraph finished warming the first tool call for '${request.params.name}'.`);
648
- return toToolResult(result);
735
+ const toolCallAbort = createMcpToolAbortSignal([ctx.mcpReq.signal, legacyRequestAbortStorage.getStore()], request.params.name, mcpToolTimeoutMs);
736
+ const operation = toolOperations.track(() => callMcpTool(handlers, request.params.name, request.params.arguments ?? {}, toolCallAbort.signal));
737
+ if (operation === undefined) {
738
+ inFlightToolCalls -= 1;
739
+ toolCallAbort.dispose();
740
+ throw new Error("MCP server is shutting down.");
741
+ }
742
+ const releaseToolCall = () => {
743
+ inFlightToolCalls -= 1;
744
+ };
745
+ try {
746
+ const result = await awaitMcpToolOperation(toolCallAbort.signal, operation, releaseToolCall);
747
+ await emitFirstToolCallVisibility("info", 1, `Codegraph finished warming the first tool call for '${request.params.name}'.`);
748
+ return toToolResult(result);
749
+ }
750
+ finally {
751
+ toolCallAbort.dispose();
752
+ }
649
753
  }
650
754
  catch (error) {
651
755
  await emitFirstToolCallVisibility("error", 1, `Codegraph failed while warming the first tool call for '${request.params.name}'.`);
@@ -654,12 +758,20 @@ export function createCodegraphMcpProtocolServer(handlers, runtimeIdentity = cap
654
758
  });
655
759
  return server;
656
760
  }
657
- function createCodegraphMcpProtocolFactory(handlers, runtimeIdentity) {
761
+ function createCodegraphMcpProtocolFactory(handlers, runtimeIdentity, maxConcurrentToolCalls = DEFAULT_MCP_TOOL_CONCURRENCY, mcpToolTimeoutMs = DEFAULT_MCP_TOOL_TIMEOUT_MS) {
658
762
  const installedVersion = createInstalledVersionChecker(runtimeIdentity);
659
763
  const toolCallState = { firstToolCallPending: true };
660
- return () => createCodegraphMcpProtocolServer(handlers, runtimeIdentity, installedVersion, toolCallState);
764
+ const toolOperations = createMcpToolOperationTracker();
765
+ const timeout = assertMcpToolTimeout(mcpToolTimeoutMs);
766
+ return {
767
+ create: () => createCodegraphMcpProtocolServerWithTracker(handlers, runtimeIdentity, installedVersion, toolCallState, maxConcurrentToolCalls, timeout, toolOperations),
768
+ stop: () => toolOperations.stop(),
769
+ drain: () => toolOperations.drain(),
770
+ };
661
771
  }
662
772
  export async function serveCodegraphMcp(options) {
773
+ const configuredMcpToolTimeout = options.mcpToolTimeoutMs === undefined ? DEFAULT_MCP_TOOL_TIMEOUT_MS : options.mcpToolTimeoutMs;
774
+ const mcpToolTimeoutMs = assertMcpToolTimeout(configuredMcpToolTimeout);
663
775
  const port = options.port;
664
776
  if (port !== undefined) {
665
777
  const started = await startCodegraphMcpHttpServer({ ...options, port });
@@ -671,36 +783,46 @@ export async function serveCodegraphMcp(options) {
671
783
  await waitForHttpServerClose(started.server);
672
784
  return;
673
785
  }
674
- const handlers = await createWarmedCodegraphMcpHandlers(options);
786
+ const { handlers, session } = await createWarmedCodegraphMcpResources(options);
675
787
  const runtimeIdentity = options.runtimeIdentity ?? captureCodegraphRuntimeIdentity(getCurrentNativeBindingOrigin());
676
- const createProtocolServer = createCodegraphMcpProtocolFactory(handlers, runtimeIdentity);
677
- const handle = serveStdio(createProtocolServer, {
788
+ const protocolFactory = createCodegraphMcpProtocolFactory(handlers, runtimeIdentity, options.mcpToolConcurrency ?? DEFAULT_MCP_TOOL_CONCURRENCY, mcpToolTimeoutMs);
789
+ const handle = serveStdio(protocolFactory.create, {
678
790
  legacy: "serve",
679
791
  onerror: (error) => {
680
792
  console.error(`[codegraph] MCP stdio error: ${error.message}`);
681
793
  },
682
794
  });
683
795
  const idleTimeoutMs = options.idleTimeoutMs ?? DEFAULT_MCP_STDIO_IDLE_TIMEOUT_MS;
684
- await awaitStdioMcpLifecycle(handle, {
685
- idleTimeoutMs,
686
- onShutdown: (shutdownReason) => {
687
- console.error(`[codegraph] MCP stdio shutting down (${shutdownReason})`);
688
- },
689
- });
796
+ try {
797
+ await awaitStdioMcpLifecycle(handle, {
798
+ idleTimeoutMs,
799
+ onShutdown: (shutdownReason) => {
800
+ console.error(`[codegraph] MCP stdio shutting down (${shutdownReason})`);
801
+ },
802
+ });
803
+ }
804
+ finally {
805
+ protocolFactory.stop();
806
+ await protocolFactory.drain();
807
+ session.invalidate();
808
+ }
690
809
  // Ensure orphaned stdio servers do not linger after the client is gone.
691
810
  process.exitCode = 0;
692
811
  }
693
812
  export async function startCodegraphMcpHttpServer(options) {
813
+ const httpBodyTimeoutMs = assertMcpHttpBodyTimeout(options.httpBodyTimeoutMs === undefined ? DEFAULT_MCP_HTTP_BODY_TIMEOUT_MS : options.httpBodyTimeoutMs);
814
+ const configuredMcpToolTimeout = options.mcpToolTimeoutMs === undefined ? DEFAULT_MCP_TOOL_TIMEOUT_MS : options.mcpToolTimeoutMs;
815
+ const mcpToolTimeoutMs = assertMcpToolTimeout(configuredMcpToolTimeout);
694
816
  const host = options.host ?? "127.0.0.1";
695
- const handlers = await createWarmedCodegraphMcpHandlers(options);
817
+ const { handlers, session } = await createWarmedCodegraphMcpResources(options);
696
818
  const runtimeIdentity = options.runtimeIdentity ?? captureCodegraphRuntimeIdentity(getCurrentNativeBindingOrigin());
697
- const createProtocolServer = createCodegraphMcpProtocolFactory(handlers, runtimeIdentity);
819
+ const protocolFactory = createCodegraphMcpProtocolFactory(handlers, runtimeIdentity, options.mcpToolConcurrency ?? DEFAULT_MCP_TOOL_CONCURRENCY, mcpToolTimeoutMs);
698
820
  const sessionStore = createLegacyMcpSessionStore({
699
821
  idleMs: options.httpSessionIdleMs ?? DEFAULT_MCP_HTTP_SESSION_IDLE_MS,
700
822
  maxCount: options.httpSessionMaxCount ?? DEFAULT_MCP_HTTP_SESSION_MAX_COUNT,
701
823
  evictionIntervalMs: options.httpSessionEvictionIntervalMs ?? DEFAULT_MCP_HTTP_SESSION_EVICTION_INTERVAL_MS,
702
824
  });
703
- const modernHandler = createMcpHandler(createProtocolServer, {
825
+ const modernHandler = createMcpHandler(protocolFactory.create, {
704
826
  legacy: "reject",
705
827
  onerror: (error) => {
706
828
  console.error(`[codegraph] MCP HTTP error: ${error.message}`);
@@ -716,18 +838,31 @@ export async function startCodegraphMcpHttpServer(options) {
716
838
  let closeResourcesPromise;
717
839
  const closeResources = () => {
718
840
  closeResourcesPromise ??= (async () => {
841
+ protocolFactory.stop();
719
842
  sessionStore.stop();
720
- await closeMcpResources(sessionStore.sessions, modernHandler.close);
843
+ try {
844
+ await closeMcpResources(sessionStore.sessions, modernHandler.close);
845
+ }
846
+ finally {
847
+ await protocolFactory.drain();
848
+ session.invalidate();
849
+ }
721
850
  })();
722
851
  return closeResourcesPromise;
723
852
  };
724
853
  const server = createServer((request, response) => {
725
- void handleMcpHttpRequest(request, response, sessionStore, () => allowedHostHeaders, validateOrigin, modernNodeHandler, createProtocolServer);
854
+ void handleMcpHttpRequest(request, response, sessionStore, () => allowedHostHeaders, validateOrigin, modernNodeHandler, protocolFactory.create, httpBodyTimeoutMs);
726
855
  });
727
856
  server.on("close", () => {
728
857
  void closeResources();
729
858
  });
730
- await listenOnHttpServer(server, options.port, host);
859
+ try {
860
+ await listenOnHttpServer(server, options.port, host);
861
+ }
862
+ catch (error) {
863
+ await closeResources();
864
+ throw error;
865
+ }
731
866
  const address = server.address();
732
867
  const actualPort = getHttpServerPort(address);
733
868
  const urlHost = formatHostForUrl(host);
@@ -747,7 +882,11 @@ export async function startCodegraphMcpHttpServer(options) {
747
882
  },
748
883
  };
749
884
  }
750
- async function handleMcpHttpRequest(request, response, sessionStore, getAllowedHostHeaders, validateOrigin, modernNodeHandler, createProtocolServer) {
885
+ async function handleMcpHttpRequest(request, response, sessionStore, getAllowedHostHeaders, validateOrigin, modernNodeHandler, createProtocolServer, bodyTimeoutMs) {
886
+ const writeClosingJsonRpcError = (statusCode, message) => {
887
+ response.setHeader("connection", "close");
888
+ writeJsonRpcError(response, statusCode, message);
889
+ };
751
890
  const requestPath = getRequestPath(request);
752
891
  if (requestPath !== MCP_HTTP_PATH) {
753
892
  writeJsonResponse(response, 404, { error: "Not found" });
@@ -761,11 +900,15 @@ async function handleMcpHttpRequest(request, response, sessionStore, getAllowedH
761
900
  return;
762
901
  try {
763
902
  if (request.method === "POST") {
764
- const parsedBody = await readJsonRequestBody(request, MAX_MCP_HTTP_BODY_BYTES);
903
+ const parsedBody = await readJsonRequestBody(request, MAX_MCP_HTTP_BODY_BYTES, bodyTimeoutMs);
765
904
  if (parsedBody.status === "too_large") {
766
905
  writeJsonRpcError(response, 413, "MCP request body is too large");
767
906
  return;
768
907
  }
908
+ if (parsedBody.status === "timeout") {
909
+ writeClosingJsonRpcError(408, "MCP request body timed out");
910
+ return;
911
+ }
769
912
  if (parsedBody.status === "invalid_json") {
770
913
  writeJsonRpcError(response, 400, "Invalid JSON request body");
771
914
  return;
@@ -805,13 +948,7 @@ async function handleLegacyMcpHttpPost(request, response, body, sessionStore, cr
805
948
  return;
806
949
  }
807
950
  sessionStore.touch(sessionId);
808
- try {
809
- await handleLegacyMcpSessionRequest(session, request, response, body);
810
- }
811
- catch (error) {
812
- await sessionStore.delete(sessionId);
813
- throw error;
814
- }
951
+ await handleLegacyMcpSessionRequest(session, request, response, body);
815
952
  return;
816
953
  }
817
954
  if (!isInitializeRequest(body)) {
@@ -859,10 +996,16 @@ async function handleLegacyMcpHttpPost(request, response, body, sessionStore, cr
859
996
  openSseStreams: 0,
860
997
  };
861
998
  sessionRef.current = session;
999
+ // The SDK transport reports every per-request validation rejection through onerror
1000
+ // too (bad Accept header, wrong Content-Type, malformed JSON, an unsupported
1001
+ // protocol version, ...) - each of those already answered its own request with a
1002
+ // 4xx response and left the transport fully usable. Deleting the session here would
1003
+ // tear down an otherwise healthy session over one malformed follow-up request. Only
1004
+ // onclose reflects the transport actually shutting down (an explicit DELETE, an
1005
+ // eviction we triggered, or a real fatal failure), so session teardown is driven by
1006
+ // onclose alone; onerror only logs.
862
1007
  transport.onerror = (error) => {
863
1008
  console.error(`[codegraph] MCP HTTP session transport error: ${error.message}`);
864
- if (initializedSessionId !== undefined)
865
- void sessionStore.delete(initializedSessionId);
866
1009
  };
867
1010
  transport.onclose = () => {
868
1011
  if (initializedSessionId !== undefined)
@@ -871,6 +1014,14 @@ async function handleLegacyMcpHttpPost(request, response, body, sessionStore, cr
871
1014
  try {
872
1015
  await protocolServer.connect(transport);
873
1016
  await handleLegacyMcpSessionRequest(session, request, response, body);
1017
+ if (initializedSessionId === undefined) {
1018
+ // The transport answered a pre-session 4xx (invalid Accept header, wrong
1019
+ // Content-Type, malformed JSON, ...) without throwing and without ever reaching
1020
+ // onsessioninitialized, so nothing else releases this capacity reservation or
1021
+ // closes this ad hoc protocol server/transport pair.
1022
+ releaseCapacityReservation();
1023
+ await closeMcpSession(session);
1024
+ }
874
1025
  }
875
1026
  catch (error) {
876
1027
  if (initializedSessionId !== undefined) {
@@ -895,12 +1046,33 @@ async function handleExistingMcpSessionRequest(request, response, sessionStore)
895
1046
  return;
896
1047
  }
897
1048
  sessionStore.touch(sessionId);
1049
+ await handleLegacyMcpSessionRequest(session, request, response);
1050
+ }
1051
+ /**
1052
+ * Runs one legacy HTTP request with a signal that aborts when its connection closes.
1053
+ * The signal is scoped to this request and is available to nested MCP tool dispatch.
1054
+ */
1055
+ export async function runWithLegacyRequestAbortSignal(request, response, operation) {
1056
+ const abortController = new AbortController();
1057
+ let completed = false;
1058
+ const abortDisconnectedRequest = () => {
1059
+ if (completed)
1060
+ return;
1061
+ if (request.aborted || (!response.writableFinished && response.destroyed)) {
1062
+ abortController.abort(new Error("MCP HTTP request connection closed."));
1063
+ }
1064
+ };
1065
+ request.on("aborted", abortDisconnectedRequest);
1066
+ request.on("close", abortDisconnectedRequest);
1067
+ response.on("close", abortDisconnectedRequest);
898
1068
  try {
899
- await handleLegacyMcpSessionRequest(session, request, response);
1069
+ return await legacyRequestAbortStorage.run(abortController.signal, operation);
900
1070
  }
901
- catch (error) {
902
- await sessionStore.delete(sessionId);
903
- throw error;
1071
+ finally {
1072
+ completed = true;
1073
+ request.off("aborted", abortDisconnectedRequest);
1074
+ request.off("close", abortDisconnectedRequest);
1075
+ response.off("close", abortDisconnectedRequest);
904
1076
  }
905
1077
  }
906
1078
  async function handleLegacyMcpSessionRequest(session, request, response, body) {
@@ -909,7 +1081,9 @@ async function handleLegacyMcpSessionRequest(session, request, response, body) {
909
1081
  if (tracksSseStream)
910
1082
  session.openSseStreams += 1;
911
1083
  try {
912
- await session.transport.handleRequest(request, response, body);
1084
+ await runWithLegacyRequestAbortSignal(request, response, async () => {
1085
+ await session.transport.handleRequest(request, response, body);
1086
+ });
913
1087
  }
914
1088
  finally {
915
1089
  session.inFlightRequests -= 1;
@@ -1019,88 +1193,129 @@ async function closeMcpResources(sessions, closeModernHandler) {
1019
1193
  function isMcpNodeRequest(request) {
1020
1194
  return request.method !== undefined && request.url !== undefined;
1021
1195
  }
1022
- async function callMcpTool(handlers, name, input) {
1023
- switch (name) {
1196
+ function createMcpToolAbortSignal(requestSignals, toolName, timeoutMs) {
1197
+ const controller = new AbortController();
1198
+ const listeners = [];
1199
+ for (const requestSignal of requestSignals) {
1200
+ if (requestSignal === undefined)
1201
+ continue;
1202
+ const onAbort = () => {
1203
+ controller.abort(requestSignal.reason);
1204
+ };
1205
+ listeners.push({ signal: requestSignal, onAbort });
1206
+ if (requestSignal.aborted)
1207
+ onAbort();
1208
+ else
1209
+ requestSignal.addEventListener("abort", onAbort, { once: true });
1210
+ }
1211
+ const timeout = timeoutMs > 0
1212
+ ? setTimeout(() => {
1213
+ controller.abort(new Error(`MCP tool '${toolName}' exceeded the configured deadline of ${timeoutMs} ms.`));
1214
+ }, timeoutMs)
1215
+ : undefined;
1216
+ timeout?.unref?.();
1217
+ return {
1218
+ signal: controller.signal,
1219
+ dispose: () => {
1220
+ clearTimeout(timeout);
1221
+ for (const listener of listeners)
1222
+ listener.signal.removeEventListener("abort", listener.onAbort);
1223
+ },
1224
+ };
1225
+ }
1226
+ export function awaitMcpToolOperation(signal, operation, onSettled) {
1227
+ void operation.then(onSettled, onSettled);
1228
+ return withAbortSignal(signal, operation);
1229
+ }
1230
+ function withAbortSignal(signal, operation) {
1231
+ if (!signal)
1232
+ return operation;
1233
+ const cancellationError = () => {
1234
+ const reason = signal.reason;
1235
+ if (reason instanceof Error && reason.name !== "AbortError")
1236
+ return reason;
1237
+ return new Error("MCP tool call was cancelled.");
1238
+ };
1239
+ if (signal.aborted)
1240
+ return Promise.reject(cancellationError());
1241
+ const cancellation = Promise.withResolvers();
1242
+ const onAbort = () => cancellation.reject(cancellationError());
1243
+ signal.addEventListener("abort", onAbort, { once: true });
1244
+ return Promise.race([operation, cancellation.promise]).finally(() => signal.removeEventListener("abort", onAbort));
1245
+ }
1246
+ export async function callMcpTool(handlers, name, input, signal) {
1247
+ const tool = MCP_TOOL_REGISTRY.find((entry) => entry.name === name);
1248
+ if (!tool)
1249
+ throw new Error(`Unknown MCP tool: ${name}`);
1250
+ switch (tool.dispatch.handler) {
1024
1251
  case "search":
1025
- return await handlers.search(parseMcpToolInput(searchSchema, input, "search"));
1252
+ return await handlers.search(parseMcpToolInput(searchSchema, input, name), signal);
1026
1253
  case "workspace_symbols":
1027
- return await handlers.workspace_symbols(parseMcpToolInput(workspaceSymbolsSchema, input, "workspace_symbols"));
1254
+ return await handlers.workspace_symbols(parseMcpToolInput(workspaceSymbolsSchema, input, name), signal);
1028
1255
  case "rename_preview":
1029
- return await handlers.rename_preview(parseMcpToolInput(renamePreviewSchema, input, "rename_preview"));
1256
+ return await handlers.rename_preview(parseMcpToolInput(renamePreviewSchema, input, name), signal);
1030
1257
  case "refactor_plan":
1031
- return await handlers.refactor_plan(parseMcpToolInput(refactorPlanSchema, input, "refactor_plan"));
1258
+ return await handlers.refactor_plan(parseMcpToolInput(refactorPlanSchema, input, name), signal);
1032
1259
  case "calls":
1033
- return await handlers.calls(parseMcpToolInput(callsSchema, input, "calls"));
1034
- case "callers":
1035
- return await handlers.calls({ ...parseMcpToolInput(callHierarchySchema, input, name), direction: "callers" });
1036
- case "callees":
1037
- return await handlers.calls({ ...parseMcpToolInput(callHierarchySchema, input, name), direction: "callees" });
1260
+ if (tool.dispatch.direction) {
1261
+ return await handlers.calls({ ...parseMcpToolInput(callHierarchySchema, input, name), direction: tool.dispatch.direction }, signal);
1262
+ }
1263
+ return await handlers.calls(parseMcpToolInput(callsSchema, input, name), signal);
1038
1264
  case "type_hierarchy":
1039
- return await handlers.type_hierarchy(parseMcpToolInput(typeHierarchyUnifiedSchema, input, "type_hierarchy"));
1040
- case "supertypes":
1041
- return await handlers.type_hierarchy({
1042
- ...parseMcpToolInput(typeHierarchySchema, input, name),
1043
- direction: "supertypes",
1044
- });
1045
- case "subtypes":
1046
- return await handlers.type_hierarchy({
1047
- ...parseMcpToolInput(typeHierarchySchema, input, name),
1048
- direction: "subtypes",
1049
- });
1265
+ if (tool.dispatch.direction) {
1266
+ return await handlers.type_hierarchy({ ...parseMcpToolInput(typeHierarchySchema, input, name), direction: tool.dispatch.direction }, signal);
1267
+ }
1268
+ return await handlers.type_hierarchy(parseMcpToolInput(typeHierarchyUnifiedSchema, input, name), signal);
1050
1269
  case "implementations":
1051
- return await handlers.implementations(parseMcpToolInput(implementationsSchema, input, "implementations"));
1270
+ return await handlers.implementations(parseMcpToolInput(implementationsSchema, input, name), signal);
1052
1271
  case "explore":
1053
- return await handlers.explore(parseMcpToolInput(exploreSchema, input, "explore"));
1272
+ return await handlers.explore(parseMcpToolInput(exploreSchema, input, name), signal);
1054
1273
  case "orient":
1055
- return await handlers.orient(parseMcpToolInput(orientSchema, input, "orient"));
1274
+ return await handlers.orient(parseMcpToolInput(orientSchema, input, name), signal);
1056
1275
  case "packet_get":
1057
- return await handlers.packet_get(parseMcpToolInput(packetGetSchema, input, "packet_get"));
1276
+ return await handlers.packet_get(parseMcpToolInput(packetGetSchema, input, name), signal);
1058
1277
  case "get_file":
1059
- return await handlers.get_file(parseMcpToolInput(getFileSchema, input, "get_file"));
1278
+ return await handlers.get_file(parseMcpToolInput(getFileSchema, input, name), signal);
1060
1279
  case "get_symbol":
1061
- return await handlers.get_symbol(parseMcpToolInput(handleSchema, input, "get_symbol"));
1280
+ return await handlers.get_symbol(parseMcpToolInput(handleSchema, input, name), signal);
1062
1281
  case "goto":
1063
- return await callGotoTool(handlers, input);
1282
+ return await callGotoTool(handlers, input, signal);
1064
1283
  case "refs":
1065
- return await callRefsTool(handlers, input);
1284
+ return await callRefsTool(handlers, input, signal);
1066
1285
  case "file_deps":
1067
- return await handlers.file_deps(parseMcpToolInput(fileDepsUnifiedSchema, input, "file_deps"));
1068
- case "deps":
1069
- return await handlers.file_deps({ ...parseMcpToolInput(fileGraphSchema, input, name), direction: "deps" });
1070
- case "rdeps":
1071
- return await handlers.file_deps({ ...parseMcpToolInput(fileGraphSchema, input, name), direction: "rdeps" });
1286
+ if (tool.dispatch.direction) {
1287
+ return await handlers.file_deps({ ...parseMcpToolInput(fileGraphSchema, input, name), direction: tool.dispatch.direction }, signal);
1288
+ }
1289
+ return await handlers.file_deps(parseMcpToolInput(fileDepsUnifiedSchema, input, name), signal);
1072
1290
  case "path":
1073
- return await handlers.path(parseMcpToolInput(pathSchema, input, "path"));
1291
+ return await handlers.path(parseMcpToolInput(pathSchema, input, name), signal);
1074
1292
  case "impact":
1075
- return await handlers.impact(parseMcpToolInput(gitRangeSchema, input, name));
1293
+ return await handlers.impact(parseMcpToolInput(gitRangeSchema, input, name), signal);
1076
1294
  case "review":
1077
- return await handlers.review(parseMcpToolInput(reviewSchema, input, "review"));
1295
+ return await handlers.review(parseMcpToolInput(reviewSchema, input, name), signal);
1078
1296
  case "query_sqlite":
1079
- return await handlers.query_sqlite(parseMcpToolInput(querySqliteSchema, input, "query_sqlite"));
1297
+ return await handlers.query_sqlite(parseMcpToolInput(querySqliteSchema, input, name), {
1298
+ ...(signal ? { signal } : {}),
1299
+ });
1080
1300
  case "refresh_index":
1081
- return await handlers.refresh_index(parseMcpToolInput(refreshIndexSchema, input, "refresh_index"));
1301
+ return await handlers.refresh_index(parseMcpToolInput(refreshIndexSchema, input, name), signal);
1082
1302
  case "artifact_build":
1083
- return await handlers.artifact_build(parseMcpToolInput(artifactBuildSchema, input, "artifact_build"));
1084
- default:
1085
- throw new Error(`Unknown MCP tool: ${name}`);
1303
+ return await handlers.artifact_build(parseMcpToolInput(artifactBuildSchema, input, name), signal);
1086
1304
  }
1087
1305
  }
1088
- async function callGotoTool(handlers, input) {
1306
+ async function callGotoTool(handlers, input, signal) {
1089
1307
  const request = parseMcpToolInput(navigationSchema, input, "goto");
1090
1308
  if (request.handle !== undefined)
1091
- return await handlers.goto({ handle: request.handle });
1309
+ return await handlers.goto({ handle: request.handle }, signal);
1092
1310
  if (request.file === undefined || request.line === undefined || request.column === undefined) {
1093
1311
  throw new Error("goto requires either handle or file, line, and column.");
1094
1312
  }
1095
- return await handlers.goto({ file: request.file, line: request.line, column: request.column });
1313
+ return await handlers.goto({ file: request.file, line: request.line, column: request.column }, signal);
1096
1314
  }
1097
- async function callRefsTool(handlers, input) {
1315
+ async function callRefsTool(handlers, input, signal) {
1098
1316
  const request = parseMcpToolInput(refsSchema, input, "refs");
1099
1317
  if (request.handle !== undefined) {
1100
- return await handlers.refs({
1101
- handle: request.handle,
1102
- ...(request.limit !== undefined ? { limit: request.limit } : {}),
1103
- });
1318
+ return await handlers.refs({ handle: request.handle, ...(request.limit !== undefined ? { limit: request.limit } : {}) }, signal);
1104
1319
  }
1105
1320
  if (request.file === undefined || request.line === undefined || request.column === undefined) {
1106
1321
  throw new Error("refs requires either handle or file, line, and column.");
@@ -1110,7 +1325,7 @@ async function callRefsTool(handlers, input) {
1110
1325
  line: request.line,
1111
1326
  column: request.column,
1112
1327
  ...(request.limit !== undefined ? { limit: request.limit } : {}),
1113
- });
1328
+ }, signal);
1114
1329
  }
1115
1330
  function toToolResult(value) {
1116
1331
  return {