@descryy/mcp 0.11.5 → 0.11.6

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 (445) hide show
  1. package/dist/action-handshake.d.ts +38 -0
  2. package/dist/action-handshake.d.ts.map +1 -0
  3. package/dist/action-handshake.js +127 -0
  4. package/dist/action-handshake.js.map +1 -0
  5. package/dist/bin/descry-mcp.d.ts +7 -0
  6. package/dist/bin/descry-mcp.d.ts.map +1 -0
  7. package/dist/bin/descry-mcp.js +73 -0
  8. package/dist/bin/descry-mcp.js.map +1 -0
  9. package/dist/browser/auth.d.ts +84 -0
  10. package/dist/browser/auth.d.ts.map +1 -0
  11. package/dist/browser/auth.js +233 -0
  12. package/dist/browser/auth.js.map +1 -0
  13. package/dist/browser/capability-probe.d.ts +109 -0
  14. package/dist/browser/capability-probe.d.ts.map +1 -0
  15. package/dist/browser/capability-probe.js +201 -0
  16. package/dist/browser/capability-probe.js.map +1 -0
  17. package/dist/browser/driver.d.ts +591 -0
  18. package/dist/browser/driver.d.ts.map +1 -0
  19. package/dist/browser/driver.js +116 -0
  20. package/dist/browser/driver.js.map +1 -0
  21. package/dist/browser/evidence.d.ts +28 -0
  22. package/dist/browser/evidence.d.ts.map +1 -0
  23. package/dist/browser/evidence.js +82 -0
  24. package/dist/browser/evidence.js.map +1 -0
  25. package/dist/browser/fake-driver.d.ts +116 -0
  26. package/dist/browser/fake-driver.d.ts.map +1 -0
  27. package/dist/browser/fake-driver.js +416 -0
  28. package/dist/browser/fake-driver.js.map +1 -0
  29. package/dist/browser/fault-attribution.d.ts +178 -0
  30. package/dist/browser/fault-attribution.d.ts.map +1 -0
  31. package/dist/browser/fault-attribution.js +266 -0
  32. package/dist/browser/fault-attribution.js.map +1 -0
  33. package/dist/browser/graph-write.d.ts +45 -0
  34. package/dist/browser/graph-write.d.ts.map +1 -0
  35. package/dist/browser/graph-write.js +103 -0
  36. package/dist/browser/graph-write.js.map +1 -0
  37. package/dist/browser/identity-graph-write.d.ts +55 -0
  38. package/dist/browser/identity-graph-write.d.ts.map +1 -0
  39. package/dist/browser/identity-graph-write.js +45 -0
  40. package/dist/browser/identity-graph-write.js.map +1 -0
  41. package/dist/browser/page-probe.d.ts +81 -0
  42. package/dist/browser/page-probe.d.ts.map +1 -0
  43. package/dist/browser/page-probe.js +202 -0
  44. package/dist/browser/page-probe.js.map +1 -0
  45. package/dist/browser/playwright-driver.d.ts +115 -0
  46. package/dist/browser/playwright-driver.d.ts.map +1 -0
  47. package/dist/browser/playwright-driver.js +1545 -0
  48. package/dist/browser/playwright-driver.js.map +1 -0
  49. package/dist/browser/provider.d.ts +26 -0
  50. package/dist/browser/provider.d.ts.map +1 -0
  51. package/dist/browser/provider.js +14 -0
  52. package/dist/browser/provider.js.map +1 -0
  53. package/dist/browser/reach-recording-session.d.ts +44 -0
  54. package/dist/browser/reach-recording-session.d.ts.map +1 -0
  55. package/dist/browser/reach-recording-session.js +151 -0
  56. package/dist/browser/reach-recording-session.js.map +1 -0
  57. package/dist/browser/reachability.d.ts +168 -0
  58. package/dist/browser/reachability.d.ts.map +1 -0
  59. package/dist/browser/reachability.js +294 -0
  60. package/dist/browser/reachability.js.map +1 -0
  61. package/dist/browser/registry.d.ts +126 -0
  62. package/dist/browser/registry.d.ts.map +1 -0
  63. package/dist/browser/registry.js +177 -0
  64. package/dist/browser/registry.js.map +1 -0
  65. package/dist/browser/scenario-provenance.d.ts +23 -0
  66. package/dist/browser/scenario-provenance.d.ts.map +1 -0
  67. package/dist/browser/scenario-provenance.js +73 -0
  68. package/dist/browser/scenario-provenance.js.map +1 -0
  69. package/dist/browser/scenario-resolve.d.ts +28 -0
  70. package/dist/browser/scenario-resolve.d.ts.map +1 -0
  71. package/dist/browser/scenario-resolve.js +96 -0
  72. package/dist/browser/scenario-resolve.js.map +1 -0
  73. package/dist/browser/scenario-runner.d.ts +72 -0
  74. package/dist/browser/scenario-runner.d.ts.map +1 -0
  75. package/dist/browser/scenario-runner.js +353 -0
  76. package/dist/browser/scenario-runner.js.map +1 -0
  77. package/dist/browser/stack-parser.d.ts +19 -0
  78. package/dist/browser/stack-parser.d.ts.map +1 -0
  79. package/dist/browser/stack-parser.js +85 -0
  80. package/dist/browser/stack-parser.js.map +1 -0
  81. package/dist/browser/tool-support.d.ts +71 -0
  82. package/dist/browser/tool-support.d.ts.map +1 -0
  83. package/dist/browser/tool-support.js +216 -0
  84. package/dist/browser/tool-support.js.map +1 -0
  85. package/dist/browser/url-scheme.d.ts +14 -0
  86. package/dist/browser/url-scheme.d.ts.map +1 -0
  87. package/dist/browser/url-scheme.js +38 -0
  88. package/dist/browser/url-scheme.js.map +1 -0
  89. package/dist/browser/wait-target.d.ts +37 -0
  90. package/dist/browser/wait-target.d.ts.map +1 -0
  91. package/dist/browser/wait-target.js +54 -0
  92. package/dist/browser/wait-target.js.map +1 -0
  93. package/dist/cancellation.d.ts +20 -0
  94. package/dist/cancellation.d.ts.map +1 -0
  95. package/dist/cancellation.js +41 -0
  96. package/dist/cancellation.js.map +1 -0
  97. package/dist/capped.d.ts +39 -0
  98. package/dist/capped.d.ts.map +1 -0
  99. package/dist/capped.js +43 -0
  100. package/dist/capped.js.map +1 -0
  101. package/dist/credential-store.d.ts +22 -0
  102. package/dist/credential-store.d.ts.map +1 -0
  103. package/dist/credential-store.js +33 -0
  104. package/dist/credential-store.js.map +1 -0
  105. package/dist/disclosure-ledger.d.ts +14 -0
  106. package/dist/disclosure-ledger.d.ts.map +1 -0
  107. package/dist/disclosure-ledger.js +18 -0
  108. package/dist/disclosure-ledger.js.map +1 -0
  109. package/dist/evidence/observed-route-evidence.d.ts +25 -0
  110. package/dist/evidence/observed-route-evidence.d.ts.map +1 -0
  111. package/dist/evidence/observed-route-evidence.js +76 -0
  112. package/dist/evidence/observed-route-evidence.js.map +1 -0
  113. package/dist/heap.d.ts +61 -0
  114. package/dist/heap.d.ts.map +1 -0
  115. package/dist/heap.js +82 -0
  116. package/dist/heap.js.map +1 -0
  117. package/dist/heartbeat.d.ts +46 -0
  118. package/dist/heartbeat.d.ts.map +1 -0
  119. package/dist/heartbeat.js +66 -0
  120. package/dist/heartbeat.js.map +1 -0
  121. package/dist/index.d.ts +32 -0
  122. package/dist/index.d.ts.map +1 -0
  123. package/dist/index.js +19 -0
  124. package/dist/index.js.map +1 -0
  125. package/dist/module-trust.d.ts +37 -0
  126. package/dist/module-trust.d.ts.map +1 -0
  127. package/dist/module-trust.js +77 -0
  128. package/dist/module-trust.js.map +1 -0
  129. package/dist/path-confinement.d.ts +31 -0
  130. package/dist/path-confinement.d.ts.map +1 -0
  131. package/dist/path-confinement.js +44 -0
  132. package/dist/path-confinement.js.map +1 -0
  133. package/dist/planner/predict-then-propose.d.ts +134 -0
  134. package/dist/planner/predict-then-propose.d.ts.map +1 -0
  135. package/dist/planner/predict-then-propose.js +138 -0
  136. package/dist/planner/predict-then-propose.js.map +1 -0
  137. package/dist/planner/propose-journey.d.ts +75 -0
  138. package/dist/planner/propose-journey.d.ts.map +1 -0
  139. package/dist/planner/propose-journey.js +96 -0
  140. package/dist/planner/propose-journey.js.map +1 -0
  141. package/dist/protocol.d.ts +57 -0
  142. package/dist/protocol.d.ts.map +1 -0
  143. package/dist/protocol.js +90 -0
  144. package/dist/protocol.js.map +1 -0
  145. package/dist/ready-checks.d.ts +12 -0
  146. package/dist/ready-checks.d.ts.map +1 -0
  147. package/dist/ready-checks.js +43 -0
  148. package/dist/ready-checks.js.map +1 -0
  149. package/dist/registry.d.ts +103 -0
  150. package/dist/registry.d.ts.map +1 -0
  151. package/dist/registry.js +327 -0
  152. package/dist/registry.js.map +1 -0
  153. package/dist/render.d.ts +623 -0
  154. package/dist/render.d.ts.map +1 -0
  155. package/dist/render.js +968 -0
  156. package/dist/render.js.map +1 -0
  157. package/dist/runtime-registry.d.ts +22 -0
  158. package/dist/runtime-registry.d.ts.map +1 -0
  159. package/dist/runtime-registry.js +142 -0
  160. package/dist/runtime-registry.js.map +1 -0
  161. package/dist/sandbox-defaults.d.ts +41 -0
  162. package/dist/sandbox-defaults.d.ts.map +1 -0
  163. package/dist/sandbox-defaults.js +14 -0
  164. package/dist/sandbox-defaults.js.map +1 -0
  165. package/dist/scenarios/browser-run-plan-projection.d.ts +161 -0
  166. package/dist/scenarios/browser-run-plan-projection.d.ts.map +1 -0
  167. package/dist/scenarios/browser-run-plan-projection.js +264 -0
  168. package/dist/scenarios/browser-run-plan-projection.js.map +1 -0
  169. package/dist/scenarios/credential-ref.d.ts +102 -0
  170. package/dist/scenarios/credential-ref.d.ts.map +1 -0
  171. package/dist/scenarios/credential-ref.js +148 -0
  172. package/dist/scenarios/credential-ref.js.map +1 -0
  173. package/dist/scenarios/index.d.ts +7 -0
  174. package/dist/scenarios/index.d.ts.map +1 -0
  175. package/dist/scenarios/index.js +7 -0
  176. package/dist/scenarios/index.js.map +1 -0
  177. package/dist/scenarios/parse.d.ts +18 -0
  178. package/dist/scenarios/parse.d.ts.map +1 -0
  179. package/dist/scenarios/parse.js +212 -0
  180. package/dist/scenarios/parse.js.map +1 -0
  181. package/dist/scenarios/scenario.d.ts +93 -0
  182. package/dist/scenarios/scenario.d.ts.map +1 -0
  183. package/dist/scenarios/scenario.js +27 -0
  184. package/dist/scenarios/scenario.js.map +1 -0
  185. package/dist/scenarios/secret-ref.d.ts +86 -0
  186. package/dist/scenarios/secret-ref.d.ts.map +1 -0
  187. package/dist/scenarios/secret-ref.js +125 -0
  188. package/dist/scenarios/secret-ref.js.map +1 -0
  189. package/dist/scenarios/storage.d.ts +21 -0
  190. package/dist/scenarios/storage.d.ts.map +1 -0
  191. package/dist/scenarios/storage.js +103 -0
  192. package/dist/scenarios/storage.js.map +1 -0
  193. package/dist/server.d.ts +61 -0
  194. package/dist/server.d.ts.map +1 -0
  195. package/dist/server.js +642 -0
  196. package/dist/server.js.map +1 -0
  197. package/dist/session.d.ts +356 -0
  198. package/dist/session.d.ts.map +1 -0
  199. package/dist/session.js +779 -0
  200. package/dist/session.js.map +1 -0
  201. package/dist/tools/alias-kit.d.ts +29 -0
  202. package/dist/tools/alias-kit.d.ts.map +1 -0
  203. package/dist/tools/alias-kit.js +21 -0
  204. package/dist/tools/alias-kit.js.map +1 -0
  205. package/dist/tools/aliases.d.ts +42 -0
  206. package/dist/tools/aliases.d.ts.map +1 -0
  207. package/dist/tools/aliases.js +52 -0
  208. package/dist/tools/aliases.js.map +1 -0
  209. package/dist/tools/analyze-workspace.d.ts +52 -0
  210. package/dist/tools/analyze-workspace.d.ts.map +1 -0
  211. package/dist/tools/analyze-workspace.js +207 -0
  212. package/dist/tools/analyze-workspace.js.map +1 -0
  213. package/dist/tools/analyze.d.ts +163 -0
  214. package/dist/tools/analyze.d.ts.map +1 -0
  215. package/dist/tools/analyze.js +724 -0
  216. package/dist/tools/analyze.js.map +1 -0
  217. package/dist/tools/browser-click.d.ts +18 -0
  218. package/dist/tools/browser-click.d.ts.map +1 -0
  219. package/dist/tools/browser-click.js +110 -0
  220. package/dist/tools/browser-click.js.map +1 -0
  221. package/dist/tools/browser-close-session.d.ts +39 -0
  222. package/dist/tools/browser-close-session.d.ts.map +1 -0
  223. package/dist/tools/browser-close-session.js +120 -0
  224. package/dist/tools/browser-close-session.js.map +1 -0
  225. package/dist/tools/browser-fill.d.ts +18 -0
  226. package/dist/tools/browser-fill.d.ts.map +1 -0
  227. package/dist/tools/browser-fill.js +117 -0
  228. package/dist/tools/browser-fill.js.map +1 -0
  229. package/dist/tools/browser-navigate.d.ts +15 -0
  230. package/dist/tools/browser-navigate.d.ts.map +1 -0
  231. package/dist/tools/browser-navigate.js +106 -0
  232. package/dist/tools/browser-navigate.js.map +1 -0
  233. package/dist/tools/browser-read.d.ts +33 -0
  234. package/dist/tools/browser-read.d.ts.map +1 -0
  235. package/dist/tools/browser-read.js +105 -0
  236. package/dist/tools/browser-read.js.map +1 -0
  237. package/dist/tools/browser-run-scenario.d.ts +28 -0
  238. package/dist/tools/browser-run-scenario.d.ts.map +1 -0
  239. package/dist/tools/browser-run-scenario.js +238 -0
  240. package/dist/tools/browser-run-scenario.js.map +1 -0
  241. package/dist/tools/browser-save-scenario.d.ts +19 -0
  242. package/dist/tools/browser-save-scenario.d.ts.map +1 -0
  243. package/dist/tools/browser-save-scenario.js +447 -0
  244. package/dist/tools/browser-save-scenario.js.map +1 -0
  245. package/dist/tools/browser-select.d.ts +20 -0
  246. package/dist/tools/browser-select.d.ts.map +1 -0
  247. package/dist/tools/browser-select.js +120 -0
  248. package/dist/tools/browser-select.js.map +1 -0
  249. package/dist/tools/browser-snapshot.d.ts +46 -0
  250. package/dist/tools/browser-snapshot.d.ts.map +1 -0
  251. package/dist/tools/browser-snapshot.js +127 -0
  252. package/dist/tools/browser-snapshot.js.map +1 -0
  253. package/dist/tools/browser-start-session.d.ts +24 -0
  254. package/dist/tools/browser-start-session.d.ts.map +1 -0
  255. package/dist/tools/browser-start-session.js +653 -0
  256. package/dist/tools/browser-start-session.js.map +1 -0
  257. package/dist/tools/browser-submit.d.ts +18 -0
  258. package/dist/tools/browser-submit.d.ts.map +1 -0
  259. package/dist/tools/browser-submit.js +106 -0
  260. package/dist/tools/browser-submit.js.map +1 -0
  261. package/dist/tools/browser-type.d.ts +18 -0
  262. package/dist/tools/browser-type.d.ts.map +1 -0
  263. package/dist/tools/browser-type.js +115 -0
  264. package/dist/tools/browser-type.js.map +1 -0
  265. package/dist/tools/browser-wait-for.d.ts +45 -0
  266. package/dist/tools/browser-wait-for.d.ts.map +1 -0
  267. package/dist/tools/browser-wait-for.js +164 -0
  268. package/dist/tools/browser-wait-for.js.map +1 -0
  269. package/dist/tools/browser.d.ts +69 -0
  270. package/dist/tools/browser.d.ts.map +1 -0
  271. package/dist/tools/browser.js +326 -0
  272. package/dist/tools/browser.js.map +1 -0
  273. package/dist/tools/chain.d.ts +41 -0
  274. package/dist/tools/chain.d.ts.map +1 -0
  275. package/dist/tools/chain.js +101 -0
  276. package/dist/tools/chain.js.map +1 -0
  277. package/dist/tools/change-scope.d.ts +25 -0
  278. package/dist/tools/change-scope.d.ts.map +1 -0
  279. package/dist/tools/change-scope.js +103 -0
  280. package/dist/tools/change-scope.js.map +1 -0
  281. package/dist/tools/code-context.d.ts +83 -0
  282. package/dist/tools/code-context.d.ts.map +1 -0
  283. package/dist/tools/code-context.js +432 -0
  284. package/dist/tools/code-context.js.map +1 -0
  285. package/dist/tools/contracts.d.ts +74 -0
  286. package/dist/tools/contracts.d.ts.map +1 -0
  287. package/dist/tools/contracts.js +214 -0
  288. package/dist/tools/contracts.js.map +1 -0
  289. package/dist/tools/cross-pr.d.ts +178 -0
  290. package/dist/tools/cross-pr.d.ts.map +1 -0
  291. package/dist/tools/cross-pr.js +362 -0
  292. package/dist/tools/cross-pr.js.map +1 -0
  293. package/dist/tools/disclosure.d.ts +75 -0
  294. package/dist/tools/disclosure.d.ts.map +1 -0
  295. package/dist/tools/disclosure.js +325 -0
  296. package/dist/tools/disclosure.js.map +1 -0
  297. package/dist/tools/draw-conclusion.d.ts +55 -0
  298. package/dist/tools/draw-conclusion.d.ts.map +1 -0
  299. package/dist/tools/draw-conclusion.js +243 -0
  300. package/dist/tools/draw-conclusion.js.map +1 -0
  301. package/dist/tools/git-context.d.ts +39 -0
  302. package/dist/tools/git-context.d.ts.map +1 -0
  303. package/dist/tools/git-context.js +374 -0
  304. package/dist/tools/git-context.js.map +1 -0
  305. package/dist/tools/git-diff.d.ts +45 -0
  306. package/dist/tools/git-diff.d.ts.map +1 -0
  307. package/dist/tools/git-diff.js +338 -0
  308. package/dist/tools/git-diff.js.map +1 -0
  309. package/dist/tools/git-history.d.ts +16 -0
  310. package/dist/tools/git-history.d.ts.map +1 -0
  311. package/dist/tools/git-history.js +106 -0
  312. package/dist/tools/git-history.js.map +1 -0
  313. package/dist/tools/history.d.ts +34 -0
  314. package/dist/tools/history.d.ts.map +1 -0
  315. package/dist/tools/history.js +121 -0
  316. package/dist/tools/history.js.map +1 -0
  317. package/dist/tools/impact.d.ts +46 -0
  318. package/dist/tools/impact.d.ts.map +1 -0
  319. package/dist/tools/impact.js +225 -0
  320. package/dist/tools/impact.js.map +1 -0
  321. package/dist/tools/index.d.ts +59 -0
  322. package/dist/tools/index.d.ts.map +1 -0
  323. package/dist/tools/index.js +70 -0
  324. package/dist/tools/index.js.map +1 -0
  325. package/dist/tools/kit.d.ts +165 -0
  326. package/dist/tools/kit.d.ts.map +1 -0
  327. package/dist/tools/kit.js +153 -0
  328. package/dist/tools/kit.js.map +1 -0
  329. package/dist/tools/link-workspace.d.ts +24 -0
  330. package/dist/tools/link-workspace.d.ts.map +1 -0
  331. package/dist/tools/link-workspace.js +131 -0
  332. package/dist/tools/link-workspace.js.map +1 -0
  333. package/dist/tools/lookup.d.ts +19 -0
  334. package/dist/tools/lookup.d.ts.map +1 -0
  335. package/dist/tools/lookup.js +63 -0
  336. package/dist/tools/lookup.js.map +1 -0
  337. package/dist/tools/mark-incident.d.ts +28 -0
  338. package/dist/tools/mark-incident.d.ts.map +1 -0
  339. package/dist/tools/mark-incident.js +171 -0
  340. package/dist/tools/mark-incident.js.map +1 -0
  341. package/dist/tools/merged-browser.d.ts +11 -0
  342. package/dist/tools/merged-browser.d.ts.map +1 -0
  343. package/dist/tools/merged-browser.js +20 -0
  344. package/dist/tools/merged-browser.js.map +1 -0
  345. package/dist/tools/merged-context.d.ts +11 -0
  346. package/dist/tools/merged-context.d.ts.map +1 -0
  347. package/dist/tools/merged-context.js +21 -0
  348. package/dist/tools/merged-context.js.map +1 -0
  349. package/dist/tools/merged-observe.d.ts +13 -0
  350. package/dist/tools/merged-observe.d.ts.map +1 -0
  351. package/dist/tools/merged-observe.js +21 -0
  352. package/dist/tools/merged-observe.js.map +1 -0
  353. package/dist/tools/merged-workspace.d.ts +14 -0
  354. package/dist/tools/merged-workspace.d.ts.map +1 -0
  355. package/dist/tools/merged-workspace.js +21 -0
  356. package/dist/tools/merged-workspace.js.map +1 -0
  357. package/dist/tools/observe-runtime.d.ts +262 -0
  358. package/dist/tools/observe-runtime.d.ts.map +1 -0
  359. package/dist/tools/observe-runtime.js +1966 -0
  360. package/dist/tools/observe-runtime.js.map +1 -0
  361. package/dist/tools/observe-tests.d.ts +57 -0
  362. package/dist/tools/observe-tests.d.ts.map +1 -0
  363. package/dist/tools/observe-tests.js +391 -0
  364. package/dist/tools/observe-tests.js.map +1 -0
  365. package/dist/tools/observe.d.ts +28 -0
  366. package/dist/tools/observe.d.ts.map +1 -0
  367. package/dist/tools/observe.js +291 -0
  368. package/dist/tools/observe.js.map +1 -0
  369. package/dist/tools/pr-analysis.d.ts +189 -0
  370. package/dist/tools/pr-analysis.d.ts.map +1 -0
  371. package/dist/tools/pr-analysis.js +365 -0
  372. package/dist/tools/pr-analysis.js.map +1 -0
  373. package/dist/tools/pre-push.d.ts +168 -0
  374. package/dist/tools/pre-push.d.ts.map +1 -0
  375. package/dist/tools/pre-push.js +416 -0
  376. package/dist/tools/pre-push.js.map +1 -0
  377. package/dist/tools/predict-reach.d.ts +57 -0
  378. package/dist/tools/predict-reach.d.ts.map +1 -0
  379. package/dist/tools/predict-reach.js +183 -0
  380. package/dist/tools/predict-reach.js.map +1 -0
  381. package/dist/tools/propagation.d.ts +37 -0
  382. package/dist/tools/propagation.d.ts.map +1 -0
  383. package/dist/tools/propagation.js +162 -0
  384. package/dist/tools/propagation.js.map +1 -0
  385. package/dist/tools/propose-journey.d.ts +16 -0
  386. package/dist/tools/propose-journey.d.ts.map +1 -0
  387. package/dist/tools/propose-journey.js +132 -0
  388. package/dist/tools/propose-journey.js.map +1 -0
  389. package/dist/tools/prove-reach.d.ts +74 -0
  390. package/dist/tools/prove-reach.d.ts.map +1 -0
  391. package/dist/tools/prove-reach.js +274 -0
  392. package/dist/tools/prove-reach.js.map +1 -0
  393. package/dist/tools/questions.d.ts +30 -0
  394. package/dist/tools/questions.d.ts.map +1 -0
  395. package/dist/tools/questions.js +230 -0
  396. package/dist/tools/questions.js.map +1 -0
  397. package/dist/tools/refusal-fetch.d.ts +35 -0
  398. package/dist/tools/refusal-fetch.d.ts.map +1 -0
  399. package/dist/tools/refusal-fetch.js +123 -0
  400. package/dist/tools/refusal-fetch.js.map +1 -0
  401. package/dist/tools/runtime-incident.d.ts +33 -0
  402. package/dist/tools/runtime-incident.d.ts.map +1 -0
  403. package/dist/tools/runtime-incident.js +67 -0
  404. package/dist/tools/runtime-incident.js.map +1 -0
  405. package/dist/tools/runtime-journey-drive.d.ts +102 -0
  406. package/dist/tools/runtime-journey-drive.d.ts.map +1 -0
  407. package/dist/tools/runtime-journey-drive.js +247 -0
  408. package/dist/tools/runtime-journey-drive.js.map +1 -0
  409. package/dist/tools/scope.d.ts +45 -0
  410. package/dist/tools/scope.d.ts.map +1 -0
  411. package/dist/tools/scope.js +217 -0
  412. package/dist/tools/scope.js.map +1 -0
  413. package/dist/tools/similar-incidents.d.ts +43 -0
  414. package/dist/tools/similar-incidents.d.ts.map +1 -0
  415. package/dist/tools/similar-incidents.js +190 -0
  416. package/dist/tools/similar-incidents.js.map +1 -0
  417. package/dist/tools/validate.d.ts +133 -0
  418. package/dist/tools/validate.d.ts.map +1 -0
  419. package/dist/tools/validate.js +488 -0
  420. package/dist/tools/validate.js.map +1 -0
  421. package/dist/tools/verb.d.ts +46 -0
  422. package/dist/tools/verb.d.ts.map +1 -0
  423. package/dist/tools/verb.js +78 -0
  424. package/dist/tools/verb.js.map +1 -0
  425. package/dist/tools/verification-status.d.ts +38 -0
  426. package/dist/tools/verification-status.d.ts.map +1 -0
  427. package/dist/tools/verification-status.js +203 -0
  428. package/dist/tools/verification-status.js.map +1 -0
  429. package/dist/tools/verify-claim.d.ts +29 -0
  430. package/dist/tools/verify-claim.d.ts.map +1 -0
  431. package/dist/tools/verify-claim.js +218 -0
  432. package/dist/tools/verify-claim.js.map +1 -0
  433. package/dist/tools/workspace.d.ts +28 -0
  434. package/dist/tools/workspace.d.ts.map +1 -0
  435. package/dist/tools/workspace.js +94 -0
  436. package/dist/tools/workspace.js.map +1 -0
  437. package/dist/transport.d.ts +32 -0
  438. package/dist/transport.d.ts.map +1 -0
  439. package/dist/transport.js +85 -0
  440. package/dist/transport.js.map +1 -0
  441. package/dist/workspace-index.d.ts +164 -0
  442. package/dist/workspace-index.d.ts.map +1 -0
  443. package/dist/workspace-index.js +381 -0
  444. package/dist/workspace-index.js.map +1 -0
  445. package/package.json +3 -3
package/dist/server.js ADDED
@@ -0,0 +1,642 @@
1
+ /**
2
+ * The MCP server: handshake, tool listing, tool calls, streaming narration.
3
+ *
4
+ * ## The layering that makes this testable without a pipe
5
+ *
6
+ * `dispatch` takes a line of text and a `send`, and that is the whole surface.
7
+ * The stdio transport is a loop around it; a test is a call to it. So the
8
+ * handshake, the error frames and the progress notifications are all covered by
9
+ * ordinary unit tests rather than by spawning a process and hoping.
10
+ *
11
+ * ## Streaming narration — §22.2's primary UX, at the protocol level
12
+ *
13
+ * A developer asking a question in their editor and watching the work happen is
14
+ * the most-used delivery path in the architecture. MCP's mechanism is
15
+ * `notifications/progress`, sent only when the request carried a
16
+ * `_meta.progressToken`. Tools call `ctx.progress(...)` unconditionally and this
17
+ * layer decides whether anyone is listening — the alternative, tools checking
18
+ * first, is how narration ends up in some code paths and not others.
19
+ *
20
+ * ## Every tool failure is a *tool* result, not a protocol error
21
+ *
22
+ * The spec is explicit and the reason is practical: a JSON-RPC error is for a
23
+ * malformed request, and an agent that receives one has nothing to reason about.
24
+ * A bad argument, a missing graph, an unreadable repository — those come back as
25
+ * content with `isError`, which the model can read and act on. Only genuinely
26
+ * broken protocol produces an error frame.
27
+ */
28
+ import { randomUUID } from "node:crypto";
29
+ import { resolveActionDispatch } from "./action-handshake.js";
30
+ import { TOOL_ALIASES } from "./tools/aliases.js";
31
+ import { fail, isRequest, negotiateVersion, ok, parseMessage, ProtocolError, RPC_INTERNAL_ERROR, RPC_INVALID_PARAMS, RPC_METHOD_NOT_FOUND, } from "./protocol.js";
32
+ import { renderAnswer, renderFailed, renderHandshake, renderRefusedInput, renderTimedOut, renderToolError, TOOL_OUTPUT_SCHEMA, } from "./render.js";
33
+ import { createDisclosureLedger } from "./disclosure-ledger.js";
34
+ import { AUTO_REFRESH_BUDGET_MS, checkConfigDrift, checkFreshness, ConfigError } from "./session.js";
35
+ import { TOOLS, TOOLS_BY_NAME, ToolInputError, } from "./tools/index.js";
36
+ import { analyzeTool } from "./tools/analyze.js";
37
+ /** Every call's declared budget (§6). Fixed today; per-trigger budgets are P26/P28 work. */
38
+ const CALL_BUDGET_MS = 15 * 60 * 1000;
39
+ function isAbort(error) {
40
+ return ((error instanceof Error && error.name === "AbortError") ||
41
+ (typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "TimeoutError"));
42
+ }
43
+ /**
44
+ * The stored graph's stamp, for a caller that has no `result` to read it from
45
+ * — a refusal, a failure, a timeout, or a handshake mint (F3, UAT Phase 5).
46
+ *
47
+ * Read defensively, never folded into `renderOptions()` unconditionally: a
48
+ * graph in a state `baseStamp()` cannot read (a stale schema version, MK-4)
49
+ * must not turn a graceful refusal into a thrown error. `try`/`catch` to
50
+ * `undefined` here, exactly as `renderHandshake`'s call site already did
51
+ * before this helper existed, so `renderRefusedInput`/`renderFailed`/
52
+ * `renderTimedOut` can stop hardcoding "no graph" regardless of what is
53
+ * actually stored, without reopening that already-reverted failure mode.
54
+ */
55
+ function readGraphStampSafely(session) {
56
+ try {
57
+ return session.provider().baseStamp();
58
+ }
59
+ catch {
60
+ return undefined;
61
+ }
62
+ }
63
+ const NO_FRESHNESS_OUTCOME = { freshness: undefined, autoNotes: [] };
64
+ function elapsedSeconds(startedAt) {
65
+ return ((Date.now() - startedAt) / 1000).toFixed(1);
66
+ }
67
+ /**
68
+ * Lane "map-freshness" items 1-3, run once per call, ahead of `tool.run` —
69
+ * the one shared place this happens, rather than 29 separate tools each
70
+ * growing their own copy (the lane's own instruction). Builds the graph when
71
+ * it is empty, refreshes it (within a budget) when it is `behind`, and
72
+ * either way reads the freshness this call should report.
73
+ *
74
+ * Skipped entirely for `workspace`: its `analyze`/`index` verbs already are
75
+ * the build/refresh mechanism (so running this ahead of them would be a
76
+ * second, redundant build) and `link` only declares repositories. The retired
77
+ * `analyze`/`analyze_workspace` names are aliases that resolve to `workspace`
78
+ * before this runs, so they are covered by the same check. `analyzeTool` is
79
+ * imported directly: it is not registered in `TOOLS_BY_NAME` under its own
80
+ * name any more, so a by-name lookup finds nothing.
81
+ *
82
+ * Never throws: an auto-build/refresh that fails (a `ConfigError` needing
83
+ * input this call can't default, an aborted refresh, anything else) is
84
+ * caught and treated as "did not run" — the real tool call proceeds exactly
85
+ * as it would have if this had never been attempted, per the lane's own
86
+ * "keep today's named refusal" instruction. An empty graph that stays empty
87
+ * after a failed auto-build still reports `freshness: null` (never `unknown`
88
+ * or a fabricated `current`) via `freshnessField` in `render.ts`, from the
89
+ * real `commitSha` this function reads again after the attempt.
90
+ */
91
+ async function ensureFreshGraph(session, tool, ctx) {
92
+ if (tool.name === "workspace")
93
+ return NO_FRESHNESS_OUTCOME;
94
+ let stamp;
95
+ try {
96
+ stamp = session.provider().baseStamp();
97
+ }
98
+ catch {
99
+ return NO_FRESHNESS_OUTCOME;
100
+ }
101
+ // Item 2: an empty graph is built with defaults before this call answers.
102
+ // `analyzeTool.run` already calls `ctx.progress(...)` as it works, so
103
+ // reusing this call's real `ctx` (rather than a stand-in) is what "sends
104
+ // progress notifications" means here — nothing extra to wire.
105
+ if (stamp.commitSha === null) {
106
+ const startedAt = Date.now();
107
+ try {
108
+ await analyzeTool.run({}, ctx);
109
+ }
110
+ catch {
111
+ // Needs input `analyze`'s own defaults can't supply (not a git
112
+ // repository, for instance) — leave the graph empty and let the real
113
+ // tool call's own "graph is empty" refusal stand, unchanged.
114
+ }
115
+ const rebuilt = readGraphStampSafely(session);
116
+ if (rebuilt === undefined || rebuilt.commitSha === null)
117
+ return NO_FRESHNESS_OUTCOME;
118
+ return {
119
+ freshness: await checkFreshness(session),
120
+ autoNotes: [`Code map built automatically for this answer (took ${elapsedSeconds(startedAt)}s).`],
121
+ };
122
+ }
123
+ const freshness = await checkFreshness(session);
124
+ if (freshness === undefined || freshness.status !== "behind")
125
+ return { freshness, autoNotes: [] };
126
+ // Item 3: refresh within a budget. `AbortSignal.any` combines the caller's
127
+ // signal with a timeout for this attempt, and `analyze` hands it to every
128
+ // source's `prepare()`. That is the whole reach of the budget: a source
129
+ // that checks the signal abandons the refresh, one that does not (git
130
+ // history does not) runs to completion, so the budget bounds a slow
131
+ // adapter, not the refresh as a whole. It is not raced against a timer:
132
+ // an abandoned refresh left running would write the graph while the real
133
+ // tool reads it. A budget of 0 or less skips the refresh outright.
134
+ const budgetMs = session.autoRefreshBudgetMs ?? AUTO_REFRESH_BUDGET_MS;
135
+ if (budgetMs <= 0)
136
+ return { freshness, autoNotes: [] };
137
+ const refreshCtx = { ...ctx, signal: AbortSignal.any([ctx.signal, AbortSignal.timeout(budgetMs)]) };
138
+ const startedAt = Date.now();
139
+ try {
140
+ await analyzeTool.run({}, refreshCtx);
141
+ }
142
+ catch {
143
+ // Timed out, or failed outright — answer from the graph as it stood
144
+ // before this attempt. `freshness` (still `behind`) already carries its
145
+ // own disclosure downstream (`freshnessDisclosure` in `render.ts`), so
146
+ // the caller learns the map is stale even though the refresh did not run.
147
+ return { freshness, autoNotes: [] };
148
+ }
149
+ return {
150
+ freshness: await checkFreshness(session),
151
+ autoNotes: [`Code map refreshed automatically for this answer (took ${elapsedSeconds(startedAt)}s).`],
152
+ };
153
+ }
154
+ /** A schema's own declared top-level argument names — empty when it has none, or when the
155
+ * schema isn't the `{ properties: {...} }` shape every tool's `inputSchema` actually is. */
156
+ function declaredTopLevelProperties(schema) {
157
+ const props = schema["properties"];
158
+ return typeof props === "object" && props !== null ? Object.keys(props) : [];
159
+ }
160
+ /** UAT phase 5, F12: which top-level keys in `args` this schema does not declare. Only meaningful
161
+ * when the schema opts into `additionalProperties: false` — the promise every tool's `SCHEMA`
162
+ * already makes (asserted across the registry by `tool-input-schema-gate.test.ts`) and that
163
+ * nothing enforced before this check existed. Shape only: whether a key exists, never what it
164
+ * means — a tool's own `requiredString`/`optionalEnum`/etc. still reads and validates the value. */
165
+ function unknownArgumentKeys(schema, args) {
166
+ if (schema["additionalProperties"] !== false)
167
+ return [];
168
+ const known = new Set(declaredTopLevelProperties(schema));
169
+ return Object.keys(args).filter((key) => !known.has(key));
170
+ }
171
+ /**
172
+ * Does this frame have to jump the transport's ordering queue?
173
+ *
174
+ * True for `notifications/cancelled` and nothing else. Exported because the
175
+ * stdio runner needs the answer and the knowledge of what MCP methods mean
176
+ * belongs here, not in a module that otherwise only knows about bytes. Never
177
+ * throws — a line that will not parse is the dispatcher's to reject, with the
178
+ * error frame it already knows how to build.
179
+ */
180
+ export function isOutOfBand(line) {
181
+ try {
182
+ const message = JSON.parse(line);
183
+ if (typeof message !== "object" || message === null || Array.isArray(message))
184
+ return false;
185
+ const frame = message;
186
+ // A *request* named `notifications/cancelled` is malformed, not a
187
+ // cancellation. Letting it jump the queue would answer it out of order,
188
+ // which is the exact hazard the ordering exists to prevent.
189
+ return frame["method"] === "notifications/cancelled" && frame["id"] === undefined;
190
+ }
191
+ catch {
192
+ return false;
193
+ }
194
+ }
195
+ const SERVER_INSTRUCTIONS = "Descry reads the repository's source into a code graph and answers questions about it. A " +
196
+ "graph-reading tool builds the graph itself the first time it finds one empty, and refreshes " +
197
+ "it when it is behind the code — both disclosed in the reply. Call `workspace` yourself only " +
198
+ "to control timing directly (`{verb: \"analyze\"}` to force a rebuild now, `{verb: \"link\"}` " +
199
+ "to declare a shared workspace).\n\n" +
200
+ "Every reply has a `state`, one of five, and they are different claims: `ok` (found " +
201
+ "something), `empty` (looked completely, found nothing — a fact about your code), `refused` " +
202
+ "(could not look — a fact about Descry, never about your code), `failed` (something broke) " +
203
+ "and `timed_out` (ran out of its time budget, partial answer). Never read `refused` as " +
204
+ "\"clean\" or `empty` as \"broken\".\n\n" +
205
+ "One case is not an answer at all and has its own shape: a call naming no tool this server " +
206
+ "has comes back with `isError: true` and `{ tool, status: \"error\", message }`, carrying no " +
207
+ "`state`. A *resolved* tool given bad input instead comes back as a real `state: \"refused\"` " +
208
+ "reply, with `disclosures` naming what was wrong. Branch on `isError` before reading " +
209
+ "`state`.\n\n" +
210
+ "Every reply also carries a `disclosures` list, a `resolutionFloor` and a `reliabilityCap` " +
211
+ "(A, B or C) inside `graph`. `resolutionFloor` is the weakest resolution behind the answer, " +
212
+ "R0 through R4: R0 is syntax only; R1 adds module/import resolution; R2 adds cross-file " +
213
+ "reference resolution (which symbol a name refers to, no type checker); R3 adds a type " +
214
+ "checker, so claims about shapes are provable; R4 means the fact was observed at runtime " +
215
+ "rather than inferred. `reliabilityCap` is what that floor permits: C means the claim is an " +
216
+ "unconfirmed behavioural prediction. B means the claim rests on structural or reference " +
217
+ "resolution — a name, an import, a call target — real evidence, not yet confirmed behaviour. " +
218
+ "A means the claim is as strong as this graph can make it: a name-level fact at R2 or better, " +
219
+ "a shape-level fact backed by a type checker (R3), or anything witnessed at runtime (R4). " +
220
+ "Read the disclosures before summarising — they say what the answer does not cover.\n\n" +
221
+ "Coverage is separate from confidence: call `disclosure` with `{verb: \"coverage\", refs: " +
222
+ "[...]}` and node ids or file paths from an earlier reply to learn which of them the graph " +
223
+ "actually reached, rather than assuming silence means untested. `disclosure`'s " +
224
+ "`{verb: \"unresolved\"}` gives the graph's full ledger of things an adapter could not " +
225
+ "resolve — call with no `handle` for a one-line summary and a handle, then again with that " +
226
+ "handle to page through every row.\n\n" +
227
+ "`class` on each tool (`read`, `stateful-read` or `action`) says whether it is safe to retry. " +
228
+ "Some `action`-class tools gate a write behind a two-call handshake: the first call performs " +
229
+ "nothing and returns a `confirmToken` describing what it would do; a second call presenting " +
230
+ "that exact token performs the write, with the arguments frozen at the first call — a changed " +
231
+ "argument on the second call is discarded and disclosed.\n\n" +
232
+ "`tier` on each tool is `conclusion` for the tools that already state a verdict about your " +
233
+ "code (`validate`, `contracts`, `cross_pr` — quote their `headline` verbatim rather than " +
234
+ "rephrasing it) or `evidence` for every other tool, which returns graph facts for you to " +
235
+ "reason over yourself. Every reply also carries `reportCategory` — one of `confirmed`, " +
236
+ "`strongly supported`, `unconfirmed`, `not analysable`, `unsupported`, or `null` where no " +
237
+ "claim applies. It is `null` on every `conclusion`-tier reply (the `headline` already states " +
238
+ "the verdict). On an `evidence`-tier reply it follows that reply's own `resolutionFloor`: " +
239
+ "`unconfirmed` below R4, and `strongly supported` at R4, where every hop behind the answer " +
240
+ "was witnessed in a real run — `observe`'s `runtime`/`tests` verbs and the browser tools are " +
241
+ "what write those edges. `confirmed` never appears here — that word is reserved for results " +
242
+ "that passed the full governance pipeline, and its absence is honest, not a bug.\n\n" +
243
+ "Beside it, `existenceCategory` answers a different question. `reportCategory` says how " +
244
+ "strongly the cause may be stated, capped by how well the code resolved; `existenceCategory` " +
245
+ "says how strongly the evidence shows the failure is real, never reading the resolution at " +
246
+ "all. A reply that witnessed a failure on several channels but resolved no code path reports " +
247
+ "`unconfirmed` for the cause and `strongly supported` for the failure — read that as " +
248
+ "*something is wrong and we could not tell you where*, not as *nothing is wrong*. It is " +
249
+ "`null` wherever no evidence reading was taken: conclusion-tier replies, faults, and " +
250
+ "refusals. `provenance` names this surface explicitly (`adjudicatedBy: \"descry\"`, " +
251
+ "`presentedBy: \"host-agent\"`) so a reply from here is never mistaken for one the app itself " +
252
+ "adjudicated and presented.\n\n" +
253
+ "In agent mode, Descry gives you high-reliability facts about your code. It does not give " +
254
+ "you confirmed behaviour, because it did not run your application — at any resolution level, " +
255
+ "however careful the static analysis was. `confirmed` and `strongly supported` are the " +
256
+ "desktop app's differentiator, not this surface's; treat every reply here as a strong lead to " +
257
+ "verify, never as a closed case.\n\n" +
258
+ "Descry cannot enforce any of this once you leave this server: nothing stops you from adding " +
259
+ "your own claims on top of what a tool returned, and nothing stops you from investigating " +
260
+ "paths no tool surfaced or suggested. The fields above exist so you do not have to guess.";
261
+ export function createMcpServer(options) {
262
+ const session = options.session;
263
+ const serverName = options.name ?? "descry";
264
+ const serverVersion = options.version ?? "0.0.0";
265
+ // One per connection, living exactly as long as this server — see
266
+ // `disclosure-ledger.ts` for why it is not shared across connections.
267
+ const disclosureLedger = createDisclosureLedger();
268
+ let initialized = false;
269
+ const tools = options.tools ?? TOOLS;
270
+ const toolsByName = options.tools === undefined
271
+ ? TOOLS_BY_NAME
272
+ : new Map(options.tools.map((tool) => [tool.name, tool]));
273
+ /**
274
+ * In-flight `tools/call`s, by request id, so `notifications/cancelled` has
275
+ * something to act on. Entries live exactly as long as the call: added
276
+ * before `tool.run`, removed in the `finally` that also drops the call's
277
+ * progress tick.
278
+ */
279
+ const pending = new Map();
280
+ async function handleRequest(request, transport) {
281
+ const { id, method } = request;
282
+ const params = request.params ?? {};
283
+ switch (method) {
284
+ case "initialize": {
285
+ transport.send(ok(id, {
286
+ protocolVersion: negotiateVersion(params["protocolVersion"]),
287
+ // `listChanged: false` is honest: the tool set is fixed at startup,
288
+ // so the server will never send a list-changed notification and
289
+ // should not claim it might.
290
+ capabilities: { tools: { listChanged: false } },
291
+ serverInfo: { name: serverName, version: serverVersion },
292
+ instructions: SERVER_INSTRUCTIONS,
293
+ }));
294
+ return;
295
+ }
296
+ case "ping": {
297
+ transport.send(ok(id, {}));
298
+ return;
299
+ }
300
+ case "tools/list": {
301
+ transport.send(ok(id, {
302
+ tools: tools.map((tool) => ({
303
+ name: tool.name,
304
+ title: tool.title,
305
+ description: tool.description,
306
+ inputSchema: tool.inputSchema,
307
+ // ai-tool-contract.md §8: every endpoint declares a class, and an
308
+ // external client has no other way to read it — §6's retry table
309
+ // (read=retryable, stateful-read=idempotent-retryable,
310
+ // action=no-retry+handshake-required) is meaningless without this
311
+ // on the wire.
312
+ class: tool.class,
313
+ // MK-5: whether this tool's output is a conclusion about the
314
+ // user's code or a fact about the graph — same "no other way to
315
+ // read it" reasoning as `class`, one line up.
316
+ tier: tool.tier,
317
+ toolVersion: tool.version,
318
+ // Every reply this server sends carries a `structuredContent`
319
+ // envelope, and without this a host has no way to validate one.
320
+ // Shared across all tools because the envelope is: see
321
+ // `TOOL_OUTPUT_SCHEMA`, including why `data` is left open.
322
+ outputSchema: TOOL_OUTPUT_SCHEMA,
323
+ })),
324
+ }));
325
+ return;
326
+ }
327
+ case "tools/call": {
328
+ const result = await callTool(id, params, transport);
329
+ // `null` means the call was cancelled while it ran. MCP forbids a
330
+ // response to a cancelled request, so the only correct frame here is
331
+ // no frame at all.
332
+ if (result !== null)
333
+ transport.send(ok(id, result));
334
+ return;
335
+ }
336
+ default:
337
+ transport.send(fail(id, RPC_METHOD_NOT_FOUND, `unknown method: ${method}`));
338
+ }
339
+ }
340
+ async function callTool(id, params, transport) {
341
+ const name = params["name"];
342
+ if (typeof name !== "string") {
343
+ return renderToolError("tools/call", '"name" must be a string');
344
+ }
345
+ // A retired name is resolved here and nowhere else: `tools/list` never
346
+ // offered it (see `tools/aliases.ts`), so only a caller holding an old
347
+ // name in a config or a script can arrive with one. `aliasedTo` is
348
+ // threaded into `renderOptions` so the reply says which name answered.
349
+ const direct = toolsByName.get(name);
350
+ const alias = direct === undefined ? TOOL_ALIASES.get(name) : undefined;
351
+ const tool = direct ?? (alias === undefined ? undefined : toolsByName.get(alias.to));
352
+ if (tool === undefined) {
353
+ return renderToolError(name, `no such tool. Available: ${tools.map((t) => t.name).join(", ")}.`);
354
+ }
355
+ // `tool` is resolved from here on, so any input failure below has a real
356
+ // `ToolDefinition` to render a `state: "refused"` envelope from
357
+ // (`renderRefusedInput`) rather than `renderToolError`'s bare shape —
358
+ // minted here, ahead of the args check, so both that check and a
359
+ // `ToolInputError` thrown later out of `tool.run` share the one
360
+ // `renderOptions()`. Same precedent as B10's `callId`: a call that never
361
+ // reaches `tool.run` still gets one minted (`renderFailed`/`renderTimedOut`
362
+ // already do this for every call but `verify_claim`), and is never passed
363
+ // to `session.recordCallWithId` below, so no gap opens in what a citation
364
+ // can resolve.
365
+ const started = Date.now();
366
+ const callId = name === "verify_claim" ? randomUUID() : session.allocateCallId();
367
+ // 13.3.16 (N2) steps 2-3: checked once per call, ahead of dispatch, so every
368
+ // reply this call produces — ok, refused, failed or timed out — carries the
369
+ // same disclosure and the same `configStale` flag, not only `analyze`'s.
370
+ const configDrift = await checkConfigDrift(session);
371
+ // Lane "map-freshness": set for real just before `tool.run` (once `ctx`
372
+ // exists), by `ensureFreshGraph`. Declared here, ahead of every early
373
+ // `renderOptions()` call below (an `"arguments"`-shape refusal, an
374
+ // unknown-argument refusal), so those calls see the same
375
+ // `NO_FRESHNESS_OUTCOME` default `configDrift` above already reads —
376
+ // never a "used before declaration" on a call site that runs before
377
+ // `ctx` does.
378
+ let freshnessOutcome = NO_FRESHNESS_OUTCOME;
379
+ const renderOptions = () => ({
380
+ toolVersion: tool.version,
381
+ toolClass: tool.class,
382
+ toolTier: tool.tier,
383
+ elapsedMs: Date.now() - started,
384
+ limitMs: CALL_BUDGET_MS,
385
+ disclosureLedger,
386
+ callId,
387
+ configDrift,
388
+ ...(freshnessOutcome.freshness === undefined ? {} : { freshness: freshnessOutcome.freshness }),
389
+ ...(freshnessOutcome.autoNotes.length === 0 ? {} : { autoNotes: freshnessOutcome.autoNotes }),
390
+ ...(alias === undefined ? {} : { aliasedFrom: name, aliasedTo: tool.name }),
391
+ });
392
+ const rawArgs = params["arguments"];
393
+ if (rawArgs !== undefined && (typeof rawArgs !== "object" || rawArgs === null || Array.isArray(rawArgs))) {
394
+ const graphStamp = readGraphStampSafely(session);
395
+ return renderRefusedInput(name, '"arguments" must be an object', {
396
+ ...renderOptions(),
397
+ ...(graphStamp === undefined ? {} : { graphStamp }),
398
+ });
399
+ }
400
+ const rewritten = (rawArgs ?? {});
401
+ // The old call shape becomes the new one before any gate reads it, so the
402
+ // schema check below is run against the tool that will actually answer.
403
+ const args = alias?.args === undefined ? rewritten : alias.args(rewritten);
404
+ // UAT phase 5, F12: `inputSchema` is advertised in `tools/list` and never read
405
+ // again — every tool hand-reads the keys it knows, so an unknown argument was
406
+ // silently ignored rather than refused (`contracts({ symbol: ... })` returning
407
+ // the whole-repo report; `browser_start_session({ profile: ... })` issuing the
408
+ // wrong consent because the tool reads `environment`). Checked here, once, for
409
+ // every tool that declares `additionalProperties: false` — which is all of
410
+ // them (asserted by tool-input-schema-gate.test.ts) — before dispatch, so a
411
+ // typo'd or misremembered key refuses loudly instead of vanishing. This is
412
+ // shape only: which keys exist, not what they mean — each tool's own
413
+ // `requiredString`/`optionalEnum`/etc. still checks that.
414
+ const unknownArgs = unknownArgumentKeys(tool.inputSchema, args);
415
+ if (unknownArgs.length > 0) {
416
+ const known = declaredTopLevelProperties(tool.inputSchema);
417
+ return renderRefusedInput(name, `unknown argument(s): ${unknownArgs.map((k) => `"${k}"`).join(", ")}. ` +
418
+ (known.length > 0 ? `${name} accepts: ${known.join(", ")}.` : `${name} takes no arguments.`), renderOptions());
419
+ }
420
+ const meta = params["_meta"];
421
+ const token = typeof meta === "object" && meta !== null
422
+ ? meta["progressToken"]
423
+ : undefined;
424
+ const progress = typeof token === "string" || typeof token === "number"
425
+ ? (message, current, total) => {
426
+ transport.send({
427
+ jsonrpc: "2.0",
428
+ method: "notifications/progress",
429
+ params: {
430
+ progressToken: token,
431
+ // `progress` is required by the spec and must increase. When a
432
+ // tool narrates without a count, the message is the payload and
433
+ // the number is a monotonic tick rather than a fake percentage.
434
+ progress: current ?? nextTick(id),
435
+ ...(total === undefined ? {} : { total }),
436
+ message,
437
+ },
438
+ });
439
+ }
440
+ : () => { };
441
+ // Two ways a call ends early, composed into the one signal the tool sees:
442
+ // its own budget running out, and the client asking for it to stop.
443
+ //
444
+ // **What this does and does not buy.** Aborting here stops the *server*
445
+ // waiting and suppresses the response the client is no longer listening
446
+ // for, which is the protocol's requirement and is met. It stops the actual
447
+ // work only in a tool that reads the signal it is handed, and today that is
448
+ // exactly one of thirty-three — `analyze`, which passes `ctx.signal` down. The
449
+ // other thirty-two, `browser_run_scenario` and `observe_runtime` among
450
+ // them, take the signal and never look at it, so a cancelled call there
451
+ // leaves a real browser or a real application process running until it
452
+ // finishes on its own. That is a disclosed gap, filed as
453
+ // `DEC-NEXT-cancellation-reaches-one-tool-in-thirty.md`, not something this
454
+ // layer can fix from here — threading the signal is each tool's own work.
455
+ const controller = new AbortController();
456
+ pending.set(id, controller);
457
+ const ctx = {
458
+ session,
459
+ progress,
460
+ signal: AbortSignal.any([controller.signal, AbortSignal.timeout(CALL_BUDGET_MS)]),
461
+ };
462
+ // B10: `started`/`callId`/`renderOptions` are minted above, ahead of the
463
+ // `arguments` shape check, so every envelope this call can produce
464
+ // (refused, handshake, failed, timed-out, or a real answer) carries the
465
+ // exact id `recordCallWithId` will file the record under below — a
466
+ // caller reading `callId` off the reply and citing it in `verify_claim`
467
+ // is citing the id that call is actually recorded as.
468
+ //
469
+ // `verify_claim` itself is the one exception, on the same reasoning as
470
+ // its exclusion from recording just below: it produces no fact for a
471
+ // later claim to cite, so its own `callId` is not drawn from the
472
+ // session's call-id sequence at all — `session.allocateCallId()` is
473
+ // reserved for calls that will actually be recorded under the id it
474
+ // returns. Reusing it here would consume a real id `verify_claim` never
475
+ // gets recorded under, opening a gap in the sequence a caller relies on
476
+ // corresponding exactly to recorded calls.
477
+ try {
478
+ // §7's two-call handshake. Decided before any real work starts — a mint
479
+ // has no I/O to time out on — so this sits outside the try/catch's
480
+ // failure/timeout handling below, which is for `tool.run` alone.
481
+ const dispatch = await resolveActionDispatch(tool, args, ctx);
482
+ if (dispatch.kind === "handshake") {
483
+ // A handshake mint has done no I/O yet, so falling back to "no stamp
484
+ // known" on a read failure is exactly `renderHandshake`'s original,
485
+ // already-correct behaviour, not a new silent failure — see
486
+ // `readGraphStampSafely`'s own doc for why this is never folded into
487
+ // `renderOptions()` unconditionally.
488
+ const graphStamp = readGraphStampSafely(session);
489
+ return renderHandshake(name, dispatch.token, dispatch.willDo, {
490
+ ...renderOptions(),
491
+ ...(graphStamp === undefined ? {} : { graphStamp }),
492
+ });
493
+ }
494
+ // Lane "map-freshness" items 1-3: build an empty graph, refresh a
495
+ // `behind` one within budget, and read the freshness this call should
496
+ // report — once, here, ahead of the real work, not inside `tool.run`
497
+ // itself. After the handshake check (a mint does no I/O, so nothing to
498
+ // ensure yet) and before `tool.run` (which is what needs a fresh graph
499
+ // to answer from).
500
+ freshnessOutcome = await ensureFreshGraph(session, tool, ctx);
501
+ const outcome = await tool.run(dispatch.args, ctx);
502
+ // Cancelled while it was running, and it finished anyway — the client
503
+ // stopped listening for this id, so the answer is dropped rather than
504
+ // sent late. Not recorded on the session either: a fact the caller never
505
+ // received must not become one a later `verify_claim` can cite.
506
+ if (controller.signal.aborted)
507
+ return null;
508
+ // Re-checked here, not reused from the `configDrift` captured before
509
+ // dispatch: `tool.run` is the one place `session.reloadConfig()` can be
510
+ // called (§0 gap 2's `analyze({ reload: true })`), and a call that just
511
+ // reloaded must not still report itself as stale — the drift it would
512
+ // be reporting no longer exists by the time this line runs.
513
+ const rendered = renderAnswer(name, outcome, {
514
+ ...renderOptions(),
515
+ configDrift: await checkConfigDrift(session),
516
+ // Rule 7 on the redemption path: the handshake decided which arguments ran, so it is the
517
+ // only thing that knows which of the caller's were dropped. Omitted entirely when nothing
518
+ // was, so a correct two-call redemption reads exactly as it did before.
519
+ ...(dispatch.discardedArgs === undefined ? {} : { discardedArgs: dispatch.discardedArgs }),
520
+ });
521
+ // MK-12: recorded after rendering, from the exact structuredContent the
522
+ // host receives — not the pre-render outcome, which the host never
523
+ // sees. `verify_claim` itself is excluded: it produces no fact for a
524
+ // later claim to cite, only a verdict about other calls' facts.
525
+ //
526
+ // Recorded under `callId` — the same id `rendered.structuredContent`
527
+ // already carries as `callId` — rather than a freshly minted one
528
+ // (B10): the two must be the same value for a citation read off this
529
+ // reply to resolve.
530
+ if (name !== "verify_claim") {
531
+ // B1: a tool that can be handed a credential says how it wants to be
532
+ // remembered (`ToolDefinition.redactArgs`). Every other tool is
533
+ // recorded exactly as it was called, as before.
534
+ session.recordCallWithId(callId, name, tool.redactArgs === undefined ? args : tool.redactArgs(args), rendered.structuredContent);
535
+ }
536
+ return rendered;
537
+ }
538
+ catch (error) {
539
+ // Cancellation is checked before anything else, including
540
+ // `ToolInputError`: whatever the tool threw on its way out, the client
541
+ // has told us it is not listening, and the spec is explicit that a
542
+ // cancelled request gets no response at all.
543
+ if (controller.signal.aborted)
544
+ return null;
545
+ const graphStamp = readGraphStampSafely(session);
546
+ const optionsWithStamp = () => ({
547
+ ...renderOptions(),
548
+ ...(graphStamp === undefined ? {} : { graphStamp }),
549
+ });
550
+ if (error instanceof ToolInputError)
551
+ return renderRefusedInput(name, error.message, optionsWithStamp());
552
+ if (isAbort(error) || ctx.signal.aborted)
553
+ return renderTimedOut(name, optionsWithStamp());
554
+ // Anything else is a bug or an environment failure. It still comes back as
555
+ // a tool result: an agent can retry or tell the user, whereas a protocol
556
+ // error just ends the call with nothing it can use.
557
+ const failureMessage = error instanceof Error ? error.message : String(error);
558
+ // 13.3.5 Half A: a `ConfigError` is thrown with a full written reason
559
+ // specifically so a caller can read it — giving it the generic
560
+ // "X failed." headline and burying that reason in `disclosures` says
561
+ // less than the error already said. An unexplained fault keeps the
562
+ // opaque default `renderFailed` falls back to.
563
+ return renderFailed(name, failureMessage, optionsWithStamp(), error instanceof ConfigError ? `${name} could not run: ${failureMessage}` : undefined);
564
+ }
565
+ finally {
566
+ pending.delete(id);
567
+ }
568
+ }
569
+ /**
570
+ * Act on `notifications/cancelled`: abort the named call if it is still ours
571
+ * and still running.
572
+ *
573
+ * Silence in every other case is deliberate and is what the spec asks for. A
574
+ * cancellation racing a call that has already returned is ordinary client
575
+ * behaviour, not an error — the client sent it before our response reached
576
+ * it — and a notification cannot be answered anyway, so there is nowhere to
577
+ * report a bad `requestId` even if one were worth reporting.
578
+ */
579
+ function cancel(params) {
580
+ const requestId = params["requestId"];
581
+ if (typeof requestId !== "string" && typeof requestId !== "number")
582
+ return;
583
+ const controller = pending.get(requestId);
584
+ if (controller === undefined)
585
+ return;
586
+ const reason = params["reason"];
587
+ controller.abort(new Error(typeof reason === "string" && reason !== ""
588
+ ? `cancelled by client: ${reason}`
589
+ : "cancelled by client"));
590
+ }
591
+ // Monotonic per-request tick for narration with no natural count.
592
+ const ticks = new Map();
593
+ function nextTick(id) {
594
+ const next = (ticks.get(id) ?? 0) + 1;
595
+ ticks.set(id, next);
596
+ return next;
597
+ }
598
+ return {
599
+ get initialized() {
600
+ return initialized;
601
+ },
602
+ async dispatch(line, transport) {
603
+ let message;
604
+ try {
605
+ message = parseMessage(line);
606
+ }
607
+ catch (error) {
608
+ if (error instanceof ProtocolError) {
609
+ // No usable id means no response is possible: JSON-RPC has nowhere to
610
+ // put the answer, and inventing an id would put a frame on the wire
611
+ // the client cannot correlate to anything it sent.
612
+ if (error.id !== null)
613
+ transport.send(fail(error.id, error.code, error.message));
614
+ return;
615
+ }
616
+ throw error;
617
+ }
618
+ if (!isRequest(message)) {
619
+ if (message.method === "notifications/initialized")
620
+ initialized = true;
621
+ else if (message.method === "notifications/cancelled")
622
+ cancel(message.params ?? {});
623
+ // Anything else — roots changed, and every notification a future spec
624
+ // adds — is accepted and ignored. A notification must never be
625
+ // answered, so silence on the wire is the protocol; silence *in
626
+ // response* is what cancellation could not afford, which is why it is
627
+ // the one handled above.
628
+ return;
629
+ }
630
+ try {
631
+ await handleRequest(message, transport);
632
+ }
633
+ catch (error) {
634
+ transport.send(fail(message.id, error instanceof ToolInputError ? RPC_INVALID_PARAMS : RPC_INTERNAL_ERROR, error instanceof Error ? error.message : String(error)));
635
+ }
636
+ finally {
637
+ ticks.delete(message.id);
638
+ }
639
+ },
640
+ };
641
+ }
642
+ //# sourceMappingURL=server.js.map