beth-copilot 1.0.18 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (429) hide show
  1. package/CHANGELOG.md +79 -28
  2. package/README.md +127 -298
  3. package/assets/beth-questioning.png +0 -0
  4. package/assets/yellowstone-beth.png +0 -0
  5. package/bin/cli.js +124 -715
  6. package/dist/__tests__/inject-skills.test.d.ts +9 -0
  7. package/dist/__tests__/inject-skills.test.d.ts.map +1 -0
  8. package/dist/__tests__/inject-skills.test.js +143 -0
  9. package/dist/__tests__/inject-skills.test.js.map +1 -0
  10. package/dist/__tests__/skills/disambiguation.test.d.ts +10 -0
  11. package/dist/__tests__/skills/disambiguation.test.d.ts.map +1 -0
  12. package/dist/__tests__/skills/disambiguation.test.js +192 -0
  13. package/dist/__tests__/skills/disambiguation.test.js.map +1 -0
  14. package/dist/__tests__/skills/hook-injection.test.d.ts +11 -0
  15. package/dist/__tests__/skills/hook-injection.test.d.ts.map +1 -0
  16. package/dist/__tests__/skills/hook-injection.test.js +173 -0
  17. package/dist/__tests__/skills/hook-injection.test.js.map +1 -0
  18. package/dist/__tests__/skills/mapping-completeness.test.d.ts +17 -0
  19. package/dist/__tests__/skills/mapping-completeness.test.d.ts.map +1 -0
  20. package/dist/__tests__/skills/mapping-completeness.test.js +281 -0
  21. package/dist/__tests__/skills/mapping-completeness.test.js.map +1 -0
  22. package/dist/__tests__/skills/pipeline-integration.test.d.ts +18 -0
  23. package/dist/__tests__/skills/pipeline-integration.test.d.ts.map +1 -0
  24. package/dist/__tests__/skills/pipeline-integration.test.js +234 -0
  25. package/dist/__tests__/skills/pipeline-integration.test.js.map +1 -0
  26. package/dist/__tests__/skills/skill-routing.test.d.ts +15 -0
  27. package/dist/__tests__/skills/skill-routing.test.d.ts.map +1 -0
  28. package/dist/__tests__/skills/skill-routing.test.js +723 -0
  29. package/dist/__tests__/skills/skill-routing.test.js.map +1 -0
  30. package/dist/__tests__/skills/trigger-coverage.test.d.ts +24 -0
  31. package/dist/__tests__/skills/trigger-coverage.test.d.ts.map +1 -0
  32. package/dist/__tests__/skills/trigger-coverage.test.js +746 -0
  33. package/dist/__tests__/skills/trigger-coverage.test.js.map +1 -0
  34. package/dist/__tests__/smoke.test.d.ts +8 -0
  35. package/dist/__tests__/smoke.test.d.ts.map +1 -0
  36. package/dist/__tests__/smoke.test.js +62 -0
  37. package/dist/__tests__/smoke.test.js.map +1 -0
  38. package/dist/__tests__/verify-skills.test.d.ts +9 -0
  39. package/dist/__tests__/verify-skills.test.d.ts.map +1 -0
  40. package/dist/__tests__/verify-skills.test.js +78 -0
  41. package/dist/__tests__/verify-skills.test.js.map +1 -0
  42. package/dist/cli/commands/beads.e2e.test.d.ts +15 -0
  43. package/dist/cli/commands/beads.e2e.test.d.ts.map +1 -0
  44. package/dist/cli/commands/beads.e2e.test.js +585 -0
  45. package/dist/cli/commands/beads.e2e.test.js.map +1 -0
  46. package/dist/cli/commands/cli-edge-cases.e2e.test.d.ts +32 -0
  47. package/dist/cli/commands/cli-edge-cases.e2e.test.d.ts.map +1 -0
  48. package/dist/cli/commands/cli-edge-cases.e2e.test.js +162 -0
  49. package/dist/cli/commands/cli-edge-cases.e2e.test.js.map +1 -0
  50. package/dist/cli/commands/close.d.ts +54 -0
  51. package/dist/cli/commands/close.d.ts.map +1 -0
  52. package/dist/cli/commands/close.e2e.test.d.ts +11 -0
  53. package/dist/cli/commands/close.e2e.test.d.ts.map +1 -0
  54. package/dist/cli/commands/close.e2e.test.js +71 -0
  55. package/dist/cli/commands/close.e2e.test.js.map +1 -0
  56. package/dist/cli/commands/close.js +95 -0
  57. package/dist/cli/commands/close.js.map +1 -0
  58. package/dist/cli/commands/close.test.d.ts +13 -0
  59. package/dist/cli/commands/close.test.d.ts.map +1 -0
  60. package/dist/cli/commands/close.test.js +254 -0
  61. package/dist/cli/commands/close.test.js.map +1 -0
  62. package/dist/cli/commands/doctor.d.ts +7 -1
  63. package/dist/cli/commands/doctor.d.ts.map +1 -1
  64. package/dist/cli/commands/doctor.e2e.test.js +3 -59
  65. package/dist/cli/commands/doctor.e2e.test.js.map +1 -1
  66. package/dist/cli/commands/doctor.js +38 -18
  67. package/dist/cli/commands/doctor.js.map +1 -1
  68. package/dist/cli/commands/doctor.test.js +32 -25
  69. package/dist/cli/commands/doctor.test.js.map +1 -1
  70. package/dist/cli/commands/framework-isolation.test.d.ts +30 -0
  71. package/dist/cli/commands/framework-isolation.test.d.ts.map +1 -0
  72. package/dist/cli/commands/framework-isolation.test.js +118 -0
  73. package/dist/cli/commands/framework-isolation.test.js.map +1 -0
  74. package/dist/cli/commands/help.e2e.test.js +5 -9
  75. package/dist/cli/commands/help.e2e.test.js.map +1 -1
  76. package/dist/cli/commands/init-logic.e2e.test.d.ts +37 -0
  77. package/dist/cli/commands/init-logic.e2e.test.d.ts.map +1 -0
  78. package/dist/cli/commands/init-logic.e2e.test.js +315 -0
  79. package/dist/cli/commands/init-logic.e2e.test.js.map +1 -0
  80. package/dist/cli/commands/init.test.js +4 -21
  81. package/dist/cli/commands/init.test.js.map +1 -1
  82. package/dist/cli/commands/land.d.ts +130 -0
  83. package/dist/cli/commands/land.d.ts.map +1 -0
  84. package/dist/cli/commands/land.js +592 -0
  85. package/dist/cli/commands/land.js.map +1 -0
  86. package/dist/cli/commands/land.test.d.ts +19 -0
  87. package/dist/cli/commands/land.test.d.ts.map +1 -0
  88. package/dist/cli/commands/land.test.js +567 -0
  89. package/dist/cli/commands/land.test.js.map +1 -0
  90. package/dist/cli/commands/mcp.e2e.test.js +24 -31
  91. package/dist/cli/commands/mcp.e2e.test.js.map +1 -1
  92. package/dist/cli/commands/pipeline.e2e.test.js +28 -31
  93. package/dist/cli/commands/pipeline.e2e.test.js.map +1 -1
  94. package/dist/cli/commands/pre-push-guard.d.ts +74 -0
  95. package/dist/cli/commands/pre-push-guard.d.ts.map +1 -0
  96. package/dist/cli/commands/pre-push-guard.e2e.test.d.ts +24 -0
  97. package/dist/cli/commands/pre-push-guard.e2e.test.d.ts.map +1 -0
  98. package/dist/cli/commands/pre-push-guard.e2e.test.js +171 -0
  99. package/dist/cli/commands/pre-push-guard.e2e.test.js.map +1 -0
  100. package/dist/cli/commands/pre-push-guard.js +212 -0
  101. package/dist/cli/commands/pre-push-guard.js.map +1 -0
  102. package/dist/cli/commands/pre-push-guard.test.d.ts +14 -0
  103. package/dist/cli/commands/pre-push-guard.test.d.ts.map +1 -0
  104. package/dist/cli/commands/pre-push-guard.test.js +314 -0
  105. package/dist/cli/commands/pre-push-guard.test.js.map +1 -0
  106. package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts +23 -0
  107. package/dist/cli/commands/quickstart-expanded.e2e.test.d.ts.map +1 -0
  108. package/dist/cli/commands/quickstart-expanded.e2e.test.js +152 -0
  109. package/dist/cli/commands/quickstart-expanded.e2e.test.js.map +1 -0
  110. package/dist/cli/commands/quickstart.d.ts +0 -1
  111. package/dist/cli/commands/quickstart.d.ts.map +1 -1
  112. package/dist/cli/commands/quickstart.js +9 -83
  113. package/dist/cli/commands/quickstart.js.map +1 -1
  114. package/dist/cli/commands/quickstart.test.js +8 -129
  115. package/dist/cli/commands/quickstart.test.js.map +1 -1
  116. package/dist/cli/commands/update.d.ts +35 -0
  117. package/dist/cli/commands/update.d.ts.map +1 -0
  118. package/dist/cli/commands/update.e2e.test.d.ts +24 -0
  119. package/dist/cli/commands/update.e2e.test.d.ts.map +1 -0
  120. package/dist/cli/commands/update.e2e.test.js +240 -0
  121. package/dist/cli/commands/update.e2e.test.js.map +1 -0
  122. package/dist/cli/commands/update.js +255 -0
  123. package/dist/cli/commands/update.js.map +1 -0
  124. package/dist/core/agents/frontmatter.test.js +1 -1
  125. package/dist/core/agents/frontmatter.test.js.map +1 -1
  126. package/dist/core/agents/handoffs.test.js +1 -1
  127. package/dist/core/agents/handoffs.test.js.map +1 -1
  128. package/dist/core/agents/loader.d.ts +4 -2
  129. package/dist/core/agents/loader.d.ts.map +1 -1
  130. package/dist/core/agents/loader.js +5 -3
  131. package/dist/core/agents/loader.js.map +1 -1
  132. package/dist/core/agents/loader.test.js +42 -4
  133. package/dist/core/agents/loader.test.js.map +1 -1
  134. package/dist/core/agents/suite.test.js +12 -9
  135. package/dist/core/agents/suite.test.js.map +1 -1
  136. package/dist/core/agents/tools.test.js +15 -9
  137. package/dist/core/agents/tools.test.js.map +1 -1
  138. package/dist/core/agents/types.test.js +1 -1
  139. package/dist/core/agents/types.test.js.map +1 -1
  140. package/dist/core/skills/loader.test.js +1 -1
  141. package/dist/core/skills/loader.test.js.map +1 -1
  142. package/dist/index.d.ts +3 -11
  143. package/dist/index.d.ts.map +1 -1
  144. package/dist/index.js +5 -12
  145. package/dist/index.js.map +1 -1
  146. package/dist/lib/pathValidation.d.ts +0 -5
  147. package/dist/lib/pathValidation.d.ts.map +1 -1
  148. package/dist/lib/pathValidation.js +0 -11
  149. package/dist/lib/pathValidation.js.map +1 -1
  150. package/dist/lib/pathValidation.test.js +2 -14
  151. package/dist/lib/pathValidation.test.js.map +1 -1
  152. package/package.json +13 -10
  153. package/sbom.json +1927 -847
  154. package/templates/.github/agents/beth.agent.md +331 -105
  155. package/templates/.github/agents/developer.agent.md +73 -102
  156. package/templates/.github/agents/product-manager.agent.md +24 -68
  157. package/templates/.github/agents/researcher.agent.md +21 -69
  158. package/templates/.github/agents/security-reviewer.agent.md +39 -82
  159. package/templates/.github/agents/tester.agent.md +44 -65
  160. package/templates/.github/agents/ux-designer.agent.md +25 -76
  161. package/templates/.github/copilot-instructions.md +246 -225
  162. package/templates/.github/copilot-mcp-config.json +12 -0
  163. package/templates/.github/dependabot.yml +68 -0
  164. package/templates/.github/hooks/scripts/inject-skills.mjs +139 -0
  165. package/templates/.github/hooks/scripts/verify-skills.mjs +47 -0
  166. package/templates/.github/hooks/skill-enforcement.json +18 -0
  167. package/templates/.github/pull_request_template.md +48 -0
  168. package/templates/.github/skills/framer-components/SKILL.md +0 -0
  169. package/templates/.github/skills/prd/SKILL.md +0 -0
  170. package/templates/.github/skills/security-analysis/SKILL.md +798 -798
  171. package/templates/.github/skills/shadcn-ui/SKILL.md +561 -561
  172. package/templates/.github/skills/vercel-react-best-practices/AGENTS.md +0 -0
  173. package/templates/.github/skills/vercel-react-best-practices/SKILL.md +0 -0
  174. package/templates/.github/skills/vercel-react-best-practices/rules/advanced-event-handler-refs.md +0 -0
  175. package/templates/.github/skills/vercel-react-best-practices/rules/advanced-use-latest.md +0 -0
  176. package/templates/.github/skills/vercel-react-best-practices/rules/async-api-routes.md +0 -0
  177. package/templates/.github/skills/vercel-react-best-practices/rules/async-defer-await.md +0 -0
  178. package/templates/.github/skills/vercel-react-best-practices/rules/async-dependencies.md +0 -0
  179. package/templates/.github/skills/vercel-react-best-practices/rules/async-parallel.md +0 -0
  180. package/templates/.github/skills/vercel-react-best-practices/rules/async-suspense-boundaries.md +0 -0
  181. package/templates/.github/skills/vercel-react-best-practices/rules/bundle-barrel-imports.md +0 -0
  182. package/templates/.github/skills/vercel-react-best-practices/rules/bundle-conditional.md +0 -0
  183. package/templates/.github/skills/vercel-react-best-practices/rules/bundle-defer-third-party.md +0 -0
  184. package/templates/.github/skills/vercel-react-best-practices/rules/bundle-dynamic-imports.md +0 -0
  185. package/templates/.github/skills/vercel-react-best-practices/rules/bundle-preload.md +0 -0
  186. package/templates/.github/skills/vercel-react-best-practices/rules/client-event-listeners.md +0 -0
  187. package/templates/.github/skills/vercel-react-best-practices/rules/client-localstorage-schema.md +0 -0
  188. package/templates/.github/skills/vercel-react-best-practices/rules/client-passive-event-listeners.md +0 -0
  189. package/templates/.github/skills/vercel-react-best-practices/rules/client-swr-dedup.md +0 -0
  190. package/templates/.github/skills/vercel-react-best-practices/rules/js-batch-dom-css.md +0 -0
  191. package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-function-results.md +0 -0
  192. package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-property-access.md +0 -0
  193. package/templates/.github/skills/vercel-react-best-practices/rules/js-cache-storage.md +0 -0
  194. package/templates/.github/skills/vercel-react-best-practices/rules/js-combine-iterations.md +0 -0
  195. package/templates/.github/skills/vercel-react-best-practices/rules/js-early-exit.md +0 -0
  196. package/templates/.github/skills/vercel-react-best-practices/rules/js-hoist-regexp.md +0 -0
  197. package/templates/.github/skills/vercel-react-best-practices/rules/js-index-maps.md +0 -0
  198. package/templates/.github/skills/vercel-react-best-practices/rules/js-length-check-first.md +0 -0
  199. package/templates/.github/skills/vercel-react-best-practices/rules/js-min-max-loop.md +0 -0
  200. package/templates/.github/skills/vercel-react-best-practices/rules/js-set-map-lookups.md +0 -0
  201. package/templates/.github/skills/vercel-react-best-practices/rules/js-tosorted-immutable.md +0 -0
  202. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-activity.md +0 -0
  203. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +0 -0
  204. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-conditional-render.md +0 -0
  205. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-content-visibility.md +0 -0
  206. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-hoist-jsx.md +0 -0
  207. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +0 -0
  208. package/templates/.github/skills/vercel-react-best-practices/rules/rendering-svg-precision.md +0 -0
  209. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-defer-reads.md +0 -0
  210. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-dependencies.md +0 -0
  211. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-derived-state.md +0 -0
  212. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-functional-setstate.md +0 -0
  213. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-lazy-state-init.md +0 -0
  214. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-memo.md +0 -0
  215. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +0 -0
  216. package/templates/.github/skills/vercel-react-best-practices/rules/rerender-transitions.md +0 -0
  217. package/templates/.github/skills/vercel-react-best-practices/rules/server-after-nonblocking.md +0 -0
  218. package/templates/.github/skills/vercel-react-best-practices/rules/server-auth-actions.md +0 -0
  219. package/templates/.github/skills/vercel-react-best-practices/rules/server-cache-lru.md +0 -0
  220. package/templates/.github/skills/vercel-react-best-practices/rules/server-cache-react.md +0 -0
  221. package/templates/.github/skills/vercel-react-best-practices/rules/server-dedup-props.md +0 -0
  222. package/templates/.github/skills/vercel-react-best-practices/rules/server-parallel-fetching.md +0 -0
  223. package/templates/.github/skills/vercel-react-best-practices/rules/server-serialization.md +0 -0
  224. package/templates/.github/skills/web-design-guidelines/SKILL.md +0 -0
  225. package/templates/.vscode/settings.json +16 -16
  226. package/templates/AGENTS.md +103 -54
  227. package/templates/Backlog.md +80 -80
  228. package/templates/mcp.json.example +0 -3
  229. package/assets/beth-portrait-small.txt +0 -13
  230. package/assets/beth-portrait.txt +0 -60
  231. package/bin/beth-animation.sh +0 -155
  232. package/bin/lib/animation.js +0 -189
  233. package/bin/lib/pathValidation.js +0 -233
  234. package/bin/lib/pathValidation.test.js +0 -280
  235. package/dist/cli/commands/client-config.d.ts +0 -31
  236. package/dist/cli/commands/client-config.d.ts.map +0 -1
  237. package/dist/cli/commands/client-config.e2e.test.d.ts +0 -15
  238. package/dist/cli/commands/client-config.e2e.test.d.ts.map +0 -1
  239. package/dist/cli/commands/client-config.e2e.test.js +0 -556
  240. package/dist/cli/commands/client-config.e2e.test.js.map +0 -1
  241. package/dist/cli/commands/client-config.js +0 -73
  242. package/dist/cli/commands/client-config.js.map +0 -1
  243. package/dist/cli/commands/client-config.test.d.ts +0 -6
  244. package/dist/cli/commands/client-config.test.d.ts.map +0 -1
  245. package/dist/cli/commands/client-config.test.js +0 -133
  246. package/dist/cli/commands/client-config.test.js.map +0 -1
  247. package/dist/cli/commands/init-quickstart.e2e.test.d.ts +0 -11
  248. package/dist/cli/commands/init-quickstart.e2e.test.d.ts.map +0 -1
  249. package/dist/cli/commands/init-quickstart.e2e.test.js +0 -221
  250. package/dist/cli/commands/init-quickstart.e2e.test.js.map +0 -1
  251. package/dist/core/context.d.ts +0 -171
  252. package/dist/core/context.d.ts.map +0 -1
  253. package/dist/core/context.js +0 -353
  254. package/dist/core/context.js.map +0 -1
  255. package/dist/core/context.test.d.ts +0 -8
  256. package/dist/core/context.test.d.ts.map +0 -1
  257. package/dist/core/context.test.js +0 -253
  258. package/dist/core/context.test.js.map +0 -1
  259. package/dist/core/handoffs.d.ts +0 -151
  260. package/dist/core/handoffs.d.ts.map +0 -1
  261. package/dist/core/handoffs.js +0 -220
  262. package/dist/core/handoffs.js.map +0 -1
  263. package/dist/core/handoffs.test.d.ts +0 -8
  264. package/dist/core/handoffs.test.d.ts.map +0 -1
  265. package/dist/core/handoffs.test.js +0 -231
  266. package/dist/core/handoffs.test.js.map +0 -1
  267. package/dist/core/orchestrator.d.ts +0 -246
  268. package/dist/core/orchestrator.d.ts.map +0 -1
  269. package/dist/core/orchestrator.js +0 -514
  270. package/dist/core/orchestrator.js.map +0 -1
  271. package/dist/core/orchestrator.test.d.ts +0 -8
  272. package/dist/core/orchestrator.test.d.ts.map +0 -1
  273. package/dist/core/orchestrator.test.js +0 -517
  274. package/dist/core/orchestrator.test.js.map +0 -1
  275. package/dist/core/router.d.ts +0 -102
  276. package/dist/core/router.d.ts.map +0 -1
  277. package/dist/core/router.js +0 -178
  278. package/dist/core/router.js.map +0 -1
  279. package/dist/core/router.test.d.ts +0 -8
  280. package/dist/core/router.test.d.ts.map +0 -1
  281. package/dist/core/router.test.js +0 -215
  282. package/dist/core/router.test.js.map +0 -1
  283. package/dist/init.test.js +0 -288
  284. package/dist/providers/azure.d.ts +0 -147
  285. package/dist/providers/azure.d.ts.map +0 -1
  286. package/dist/providers/azure.js +0 -491
  287. package/dist/providers/azure.js.map +0 -1
  288. package/dist/providers/azure.test.d.ts +0 -11
  289. package/dist/providers/azure.test.d.ts.map +0 -1
  290. package/dist/providers/azure.test.js +0 -330
  291. package/dist/providers/azure.test.js.map +0 -1
  292. package/dist/providers/config.d.ts +0 -87
  293. package/dist/providers/config.d.ts.map +0 -1
  294. package/dist/providers/config.js +0 -193
  295. package/dist/providers/config.js.map +0 -1
  296. package/dist/providers/config.test.d.ts +0 -7
  297. package/dist/providers/config.test.d.ts.map +0 -1
  298. package/dist/providers/config.test.js +0 -370
  299. package/dist/providers/config.test.js.map +0 -1
  300. package/dist/providers/index.d.ts +0 -18
  301. package/dist/providers/index.d.ts.map +0 -1
  302. package/dist/providers/index.js +0 -14
  303. package/dist/providers/index.js.map +0 -1
  304. package/dist/providers/interface.d.ts +0 -191
  305. package/dist/providers/interface.d.ts.map +0 -1
  306. package/dist/providers/interface.js +0 -94
  307. package/dist/providers/interface.js.map +0 -1
  308. package/dist/providers/retry.d.ts +0 -128
  309. package/dist/providers/retry.d.ts.map +0 -1
  310. package/dist/providers/retry.js +0 -205
  311. package/dist/providers/retry.js.map +0 -1
  312. package/dist/providers/retry.test.d.ts +0 -7
  313. package/dist/providers/retry.test.d.ts.map +0 -1
  314. package/dist/providers/retry.test.js +0 -439
  315. package/dist/providers/retry.test.js.map +0 -1
  316. package/dist/providers/streaming.d.ts +0 -157
  317. package/dist/providers/streaming.d.ts.map +0 -1
  318. package/dist/providers/streaming.js +0 -233
  319. package/dist/providers/streaming.js.map +0 -1
  320. package/dist/providers/streaming.test.d.ts +0 -7
  321. package/dist/providers/streaming.test.d.ts.map +0 -1
  322. package/dist/providers/streaming.test.js +0 -372
  323. package/dist/providers/streaming.test.js.map +0 -1
  324. package/dist/providers/types.d.ts +0 -209
  325. package/dist/providers/types.d.ts.map +0 -1
  326. package/dist/providers/types.js +0 -53
  327. package/dist/providers/types.js.map +0 -1
  328. package/dist/providers/types.test.d.ts +0 -7
  329. package/dist/providers/types.test.d.ts.map +0 -1
  330. package/dist/providers/types.test.js +0 -141
  331. package/dist/providers/types.test.js.map +0 -1
  332. package/dist/tools/cli/beads.d.ts +0 -27
  333. package/dist/tools/cli/beads.d.ts.map +0 -1
  334. package/dist/tools/cli/beads.js +0 -172
  335. package/dist/tools/cli/beads.js.map +0 -1
  336. package/dist/tools/cli/beads.test.d.ts +0 -8
  337. package/dist/tools/cli/beads.test.d.ts.map +0 -1
  338. package/dist/tools/cli/beads.test.js +0 -264
  339. package/dist/tools/cli/beads.test.js.map +0 -1
  340. package/dist/tools/cli/editFile.d.ts +0 -17
  341. package/dist/tools/cli/editFile.d.ts.map +0 -1
  342. package/dist/tools/cli/editFile.js +0 -125
  343. package/dist/tools/cli/editFile.js.map +0 -1
  344. package/dist/tools/cli/editFile.test.d.ts +0 -8
  345. package/dist/tools/cli/editFile.test.d.ts.map +0 -1
  346. package/dist/tools/cli/editFile.test.js +0 -177
  347. package/dist/tools/cli/editFile.test.js.map +0 -1
  348. package/dist/tools/cli/readFile.d.ts +0 -25
  349. package/dist/tools/cli/readFile.d.ts.map +0 -1
  350. package/dist/tools/cli/readFile.js +0 -118
  351. package/dist/tools/cli/readFile.js.map +0 -1
  352. package/dist/tools/cli/readFile.test.d.ts +0 -8
  353. package/dist/tools/cli/readFile.test.d.ts.map +0 -1
  354. package/dist/tools/cli/readFile.test.js +0 -194
  355. package/dist/tools/cli/readFile.test.js.map +0 -1
  356. package/dist/tools/cli/search.d.ts +0 -16
  357. package/dist/tools/cli/search.d.ts.map +0 -1
  358. package/dist/tools/cli/search.js +0 -261
  359. package/dist/tools/cli/search.js.map +0 -1
  360. package/dist/tools/cli/search.test.d.ts +0 -8
  361. package/dist/tools/cli/search.test.d.ts.map +0 -1
  362. package/dist/tools/cli/search.test.js +0 -172
  363. package/dist/tools/cli/search.test.js.map +0 -1
  364. package/dist/tools/cli/subagent.d.ts +0 -43
  365. package/dist/tools/cli/subagent.d.ts.map +0 -1
  366. package/dist/tools/cli/subagent.js +0 -99
  367. package/dist/tools/cli/subagent.js.map +0 -1
  368. package/dist/tools/cli/subagent.test.d.ts +0 -8
  369. package/dist/tools/cli/subagent.test.d.ts.map +0 -1
  370. package/dist/tools/cli/subagent.test.js +0 -190
  371. package/dist/tools/cli/subagent.test.js.map +0 -1
  372. package/dist/tools/cli/terminal.d.ts +0 -19
  373. package/dist/tools/cli/terminal.d.ts.map +0 -1
  374. package/dist/tools/cli/terminal.js +0 -164
  375. package/dist/tools/cli/terminal.js.map +0 -1
  376. package/dist/tools/cli/terminal.test.d.ts +0 -8
  377. package/dist/tools/cli/terminal.test.d.ts.map +0 -1
  378. package/dist/tools/cli/terminal.test.js +0 -161
  379. package/dist/tools/cli/terminal.test.js.map +0 -1
  380. package/dist/tools/index.d.ts +0 -25
  381. package/dist/tools/index.d.ts.map +0 -1
  382. package/dist/tools/index.js +0 -41
  383. package/dist/tools/index.js.map +0 -1
  384. package/dist/tools/interface.d.ts +0 -64
  385. package/dist/tools/interface.d.ts.map +0 -1
  386. package/dist/tools/interface.js +0 -37
  387. package/dist/tools/interface.js.map +0 -1
  388. package/dist/tools/interface.test.d.ts +0 -7
  389. package/dist/tools/interface.test.d.ts.map +0 -1
  390. package/dist/tools/interface.test.js +0 -179
  391. package/dist/tools/interface.test.js.map +0 -1
  392. package/dist/tools/mcp/bridge.d.ts +0 -48
  393. package/dist/tools/mcp/bridge.d.ts.map +0 -1
  394. package/dist/tools/mcp/bridge.js +0 -128
  395. package/dist/tools/mcp/bridge.js.map +0 -1
  396. package/dist/tools/mcp/bridge.test.d.ts +0 -8
  397. package/dist/tools/mcp/bridge.test.d.ts.map +0 -1
  398. package/dist/tools/mcp/bridge.test.js +0 -300
  399. package/dist/tools/mcp/bridge.test.js.map +0 -1
  400. package/dist/tools/mcp/client.d.ts +0 -135
  401. package/dist/tools/mcp/client.d.ts.map +0 -1
  402. package/dist/tools/mcp/client.js +0 -263
  403. package/dist/tools/mcp/client.js.map +0 -1
  404. package/dist/tools/mcp/client.test.d.ts +0 -8
  405. package/dist/tools/mcp/client.test.d.ts.map +0 -1
  406. package/dist/tools/mcp/client.test.js +0 -390
  407. package/dist/tools/mcp/client.test.js.map +0 -1
  408. package/dist/tools/registry.d.ts +0 -82
  409. package/dist/tools/registry.d.ts.map +0 -1
  410. package/dist/tools/registry.js +0 -99
  411. package/dist/tools/registry.js.map +0 -1
  412. package/dist/tools/registry.test.d.ts +0 -7
  413. package/dist/tools/registry.test.d.ts.map +0 -1
  414. package/dist/tools/registry.test.js +0 -199
  415. package/dist/tools/registry.test.js.map +0 -1
  416. package/dist/tools/suite.test.d.ts +0 -11
  417. package/dist/tools/suite.test.d.ts.map +0 -1
  418. package/dist/tools/suite.test.js +0 -119
  419. package/dist/tools/suite.test.js.map +0 -1
  420. package/dist/tools/types.d.ts +0 -75
  421. package/dist/tools/types.d.ts.map +0 -1
  422. package/dist/tools/types.js +0 -30
  423. package/dist/tools/types.js.map +0 -1
  424. package/dist/tools/types.test.d.ts +0 -7
  425. package/dist/tools/types.test.d.ts.map +0 -1
  426. package/dist/tools/types.test.js +0 -178
  427. package/dist/tools/types.test.js.map +0 -1
  428. package/templates/.vscode/mcp.json +0 -20
  429. package/templates/CLAUDE.md +0 -129
@@ -1,263 +0,0 @@
1
- /**
2
- * MCP Client
3
- *
4
- * Minimal Model Context Protocol client that communicates with
5
- * MCP servers over stdio transport using JSON-RPC 2.0.
6
- */
7
- import { spawn } from 'node:child_process';
8
- import { createInterface } from 'node:readline';
9
- /** Default timeout for MCP requests in milliseconds */
10
- const DEFAULT_TIMEOUT_MS = 10_000;
11
- /** MCP protocol version */
12
- const PROTOCOL_VERSION = '2024-11-05';
13
- /** Client info sent during initialization */
14
- const CLIENT_INFO = { name: 'beth-cli', version: '1.0.15' };
15
- // =============================================================================
16
- // MCP Client
17
- // =============================================================================
18
- /**
19
- * MCP protocol client for stdio-based MCP servers.
20
- *
21
- * Handles the JSON-RPC 2.0 transport, initialization handshake,
22
- * tool listing, and tool invocation.
23
- *
24
- * @example
25
- * ```typescript
26
- * const client = new MCPClient('shadcn', {
27
- * command: 'npx',
28
- * args: ['shadcn@3.7.0', 'mcp'],
29
- * });
30
- * await client.connect();
31
- * const tools = await client.listTools();
32
- * const result = await client.callTool('search', { query: 'button' });
33
- * await client.disconnect();
34
- * ```
35
- */
36
- export class MCPClient {
37
- /** Server name (for logging/namespacing) */
38
- name;
39
- /** Server configuration */
40
- config;
41
- /** Spawn function (injectable for testing) */
42
- spawnFn;
43
- /** Request timeout in milliseconds */
44
- timeoutMs;
45
- /** The spawned server process */
46
- process = null;
47
- /** Readline interface for reading stdout line by line */
48
- reader = null;
49
- /** Incrementing request ID counter */
50
- nextId = 1;
51
- /** Whether the initialization handshake has completed */
52
- initialized = false;
53
- /** Pending request resolvers keyed by request ID */
54
- pending = new Map();
55
- constructor(name, config, options) {
56
- this.name = name;
57
- this.config = config;
58
- this.spawnFn = options?.spawnFn ?? spawn;
59
- this.timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
60
- }
61
- /**
62
- * Whether the client is connected and initialized.
63
- */
64
- get connected() {
65
- return this.initialized && this.process !== null;
66
- }
67
- /**
68
- * Start the MCP server process and perform the initialization handshake.
69
- *
70
- * @throws Error if the process fails to start or initialization times out
71
- */
72
- async connect() {
73
- if (this.process) {
74
- throw new Error(`MCP client "${this.name}" is already connected`);
75
- }
76
- const env = this.config.env
77
- ? { ...process.env, ...this.config.env }
78
- : process.env;
79
- this.process = this.spawnFn(this.config.command, this.config.args, {
80
- stdio: ['pipe', 'pipe', 'pipe'],
81
- env,
82
- });
83
- // Handle unexpected process exit
84
- this.process.on('error', (err) => {
85
- this.rejectAllPending(new Error(`MCP server "${this.name}" process error: ${err.message}`));
86
- this.cleanup();
87
- });
88
- this.process.on('close', () => {
89
- this.rejectAllPending(new Error(`MCP server "${this.name}" process exited unexpectedly`));
90
- this.cleanup();
91
- });
92
- // Set up line-delimited JSON reader on stdout
93
- if (!this.process.stdout) {
94
- throw new Error(`MCP server "${this.name}" has no stdout`);
95
- }
96
- this.reader = createInterface({ input: this.process.stdout });
97
- this.reader.on('line', (line) => this.handleLine(line));
98
- // Perform initialization handshake
99
- await this.sendRequest('initialize', {
100
- protocolVersion: PROTOCOL_VERSION,
101
- capabilities: {},
102
- clientInfo: CLIENT_INFO,
103
- });
104
- this.sendNotification('notifications/initialized');
105
- this.initialized = true;
106
- }
107
- /**
108
- * List available tools from the MCP server.
109
- *
110
- * @returns Array of tool information
111
- * @throws Error if not connected
112
- */
113
- async listTools() {
114
- this.ensureConnected();
115
- const result = await this.sendRequest('tools/list', {});
116
- const tools = result.tools;
117
- if (!Array.isArray(tools)) {
118
- return [];
119
- }
120
- return tools.map((t) => ({
121
- name: String(t.name ?? ''),
122
- description: String(t.description ?? ''),
123
- inputSchema: t.inputSchema ?? {},
124
- }));
125
- }
126
- /**
127
- * Call a tool on the MCP server.
128
- *
129
- * @param toolName - Name of the tool to call
130
- * @param args - Arguments to pass to the tool
131
- * @returns Tool execution result
132
- * @throws Error if not connected or the tool call fails
133
- */
134
- async callTool(toolName, args) {
135
- this.ensureConnected();
136
- return this.sendRequest('tools/call', {
137
- name: toolName,
138
- arguments: args,
139
- });
140
- }
141
- /**
142
- * Shut down the MCP server process.
143
- */
144
- async disconnect() {
145
- this.rejectAllPending(new Error(`MCP client "${this.name}" disconnecting`));
146
- this.cleanup();
147
- }
148
- // ===========================================================================
149
- // Internal: JSON-RPC transport
150
- // ===========================================================================
151
- /**
152
- * Send a JSON-RPC request and wait for the matching response.
153
- */
154
- sendRequest(method, params) {
155
- const id = this.nextId++;
156
- const message = {
157
- jsonrpc: '2.0',
158
- id,
159
- method,
160
- params,
161
- };
162
- return new Promise((resolve, reject) => {
163
- // Set up timeout
164
- const timer = setTimeout(() => {
165
- this.pending.delete(id);
166
- reject(new Error(`MCP request "${method}" timed out after ${this.timeoutMs}ms`));
167
- }, this.timeoutMs);
168
- this.pending.set(id, {
169
- resolve: (value) => {
170
- clearTimeout(timer);
171
- resolve(value);
172
- },
173
- reject: (reason) => {
174
- clearTimeout(timer);
175
- reject(reason);
176
- },
177
- });
178
- this.writeMessage(JSON.stringify(message));
179
- });
180
- }
181
- /**
182
- * Send a JSON-RPC notification (no response expected).
183
- */
184
- sendNotification(method, params) {
185
- const message = {
186
- jsonrpc: '2.0',
187
- method,
188
- ...(params !== undefined ? { params } : {}),
189
- };
190
- this.writeMessage(JSON.stringify(message));
191
- }
192
- /**
193
- * Write a line-delimited JSON message to the process stdin.
194
- */
195
- writeMessage(json) {
196
- if (!this.process?.stdin?.writable) {
197
- throw new Error(`MCP server "${this.name}" stdin is not writable`);
198
- }
199
- this.process.stdin.write(json + '\n');
200
- }
201
- /**
202
- * Handle a line of JSON from the server's stdout.
203
- */
204
- handleLine(line) {
205
- const trimmed = line.trim();
206
- if (!trimmed)
207
- return;
208
- let parsed;
209
- try {
210
- parsed = JSON.parse(trimmed);
211
- }
212
- catch {
213
- // Ignore malformed lines (e.g., server logging to stdout)
214
- return;
215
- }
216
- // Only handle responses with an id that we're waiting for
217
- if (parsed.id === undefined || parsed.id === null)
218
- return;
219
- const pending = this.pending.get(parsed.id);
220
- if (!pending)
221
- return;
222
- this.pending.delete(parsed.id);
223
- if (parsed.error) {
224
- pending.reject(new Error(`MCP error (${parsed.error.code}): ${parsed.error.message}`));
225
- }
226
- else {
227
- pending.resolve(parsed.result);
228
- }
229
- }
230
- /**
231
- * Assert that the client is connected.
232
- */
233
- ensureConnected() {
234
- if (!this.connected) {
235
- throw new Error(`MCP client "${this.name}" is not connected`);
236
- }
237
- }
238
- /**
239
- * Reject all pending requests.
240
- */
241
- rejectAllPending(error) {
242
- for (const [id, pending] of this.pending) {
243
- pending.reject(error);
244
- this.pending.delete(id);
245
- }
246
- }
247
- /**
248
- * Clean up the process and reader.
249
- */
250
- cleanup() {
251
- this.initialized = false;
252
- if (this.reader) {
253
- this.reader.close();
254
- this.reader = null;
255
- }
256
- if (this.process) {
257
- this.process.stdin?.end();
258
- this.process.kill();
259
- this.process = null;
260
- }
261
- }
262
- }
263
- //# sourceMappingURL=client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/tools/mcp/client.ts"],"names":[],"mappings":"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"}
@@ -1,8 +0,0 @@
1
- /**
2
- * MCP Client Tests
3
- *
4
- * Tests for the MCP protocol client including JSON-RPC message
5
- * formatting, request lifecycle, and timeout handling.
6
- */
7
- export {};
8
- //# sourceMappingURL=client.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.test.d.ts","sourceRoot":"","sources":["../../../src/tools/mcp/client.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,390 +0,0 @@
1
- /**
2
- * MCP Client Tests
3
- *
4
- * Tests for the MCP protocol client including JSON-RPC message
5
- * formatting, request lifecycle, and timeout handling.
6
- */
7
- import { describe, it } from 'node:test';
8
- import assert from 'node:assert';
9
- import { EventEmitter } from 'node:events';
10
- import { PassThrough } from 'node:stream';
11
- import { MCPClient } from './client.js';
12
- /**
13
- * Create a mock child process with controllable stdin/stdout.
14
- */
15
- function createMockProcess() {
16
- const proc = new EventEmitter();
17
- proc.stdin = new PassThrough();
18
- proc.stdout = new PassThrough();
19
- proc.stderr = new PassThrough();
20
- proc.killed = false;
21
- proc.kill = () => { proc.killed = true; };
22
- return proc;
23
- }
24
- /**
25
- * Collect all messages written to a PassThrough stream as parsed JSON-RPC.
26
- */
27
- function collectMessages(stream) {
28
- const messages = [];
29
- let buffer = '';
30
- stream.on('data', (chunk) => {
31
- buffer += chunk.toString();
32
- const lines = buffer.split('\n');
33
- // Keep the last incomplete line in the buffer
34
- buffer = lines.pop() ?? '';
35
- for (const line of lines) {
36
- if (line.trim()) {
37
- messages.push(JSON.parse(line));
38
- }
39
- }
40
- });
41
- return messages;
42
- }
43
- /**
44
- * Create a spawn function that returns the given mock process.
45
- */
46
- function createMockSpawn(proc) {
47
- return (() => proc);
48
- }
49
- /**
50
- * Respond to pending requests on a mock process's stdout.
51
- * Reads from stdin, auto-responds with matching id.
52
- */
53
- function autoRespond(proc, handler) {
54
- let buffer = '';
55
- proc.stdin.on('data', (chunk) => {
56
- buffer += chunk.toString();
57
- const lines = buffer.split('\n');
58
- buffer = lines.pop() ?? '';
59
- for (const line of lines) {
60
- if (!line.trim())
61
- continue;
62
- const msg = JSON.parse(line);
63
- // Only respond to requests (those with an id), not notifications
64
- if (msg.id !== undefined) {
65
- const result = handler(msg);
66
- const response = JSON.stringify({ jsonrpc: '2.0', id: msg.id, result });
67
- proc.stdout.push(response + '\n');
68
- }
69
- }
70
- });
71
- }
72
- // =============================================================================
73
- // Tests
74
- // =============================================================================
75
- describe('MCPClient', () => {
76
- describe('construction', () => {
77
- it('should create a client with name and config', () => {
78
- const client = new MCPClient('test-server', {
79
- command: 'npx',
80
- args: ['-y', 'some-server'],
81
- });
82
- assert.strictEqual(client.name, 'test-server');
83
- assert.strictEqual(client.connected, false);
84
- });
85
- it('should accept custom timeout', () => {
86
- const client = new MCPClient('test', { command: 'node', args: [] }, {
87
- timeoutMs: 5000,
88
- });
89
- assert.strictEqual(client.name, 'test');
90
- });
91
- });
92
- describe('connect', () => {
93
- it('should spawn the server process and perform handshake', async () => {
94
- const proc = createMockProcess();
95
- let spawnCalled = false;
96
- let spawnCmd = '';
97
- let spawnArgs = [];
98
- const mockSpawn = ((cmd, args) => {
99
- spawnCalled = true;
100
- spawnCmd = cmd;
101
- spawnArgs = args;
102
- return proc;
103
- });
104
- autoRespond(proc, (msg) => {
105
- if (msg.method === 'initialize') {
106
- return { protocolVersion: '2024-11-05', capabilities: {} };
107
- }
108
- return {};
109
- });
110
- const client = new MCPClient('test', {
111
- command: 'npx',
112
- args: ['-y', 'test-server'],
113
- }, { spawnFn: mockSpawn });
114
- await client.connect();
115
- assert.strictEqual(spawnCalled, true);
116
- assert.strictEqual(spawnCmd, 'npx');
117
- assert.deepStrictEqual(spawnArgs, ['-y', 'test-server']);
118
- assert.strictEqual(client.connected, true);
119
- await client.disconnect();
120
- });
121
- it('should throw if already connected', async () => {
122
- const proc = createMockProcess();
123
- autoRespond(proc, () => ({ protocolVersion: '2024-11-05', capabilities: {} }));
124
- const client = new MCPClient('test', { command: 'node', args: [] }, {
125
- spawnFn: createMockSpawn(proc),
126
- });
127
- await client.connect();
128
- await assert.rejects(() => client.connect(), (err) => {
129
- assert.ok(err.message.includes('already connected'));
130
- return true;
131
- });
132
- await client.disconnect();
133
- });
134
- it('should send initialize request with correct params', async () => {
135
- const proc = createMockProcess();
136
- const messages = collectMessages(proc.stdin);
137
- autoRespond(proc, () => ({ protocolVersion: '2024-11-05', capabilities: {} }));
138
- const client = new MCPClient('test', { command: 'node', args: [] }, {
139
- spawnFn: createMockSpawn(proc),
140
- });
141
- await client.connect();
142
- // First message should be the initialize request
143
- const initMsg = messages[0];
144
- assert.strictEqual(initMsg.jsonrpc, '2.0');
145
- assert.strictEqual(initMsg.method, 'initialize');
146
- assert.strictEqual(initMsg.id, 1);
147
- const params = initMsg.params;
148
- assert.strictEqual(params.protocolVersion, '2024-11-05');
149
- assert.deepStrictEqual(params.clientInfo, { name: 'beth-cli', version: '1.0.15' });
150
- await client.disconnect();
151
- });
152
- it('should send initialized notification after handshake', async () => {
153
- const proc = createMockProcess();
154
- const messages = collectMessages(proc.stdin);
155
- autoRespond(proc, () => ({ protocolVersion: '2024-11-05', capabilities: {} }));
156
- const client = new MCPClient('test', { command: 'node', args: [] }, {
157
- spawnFn: createMockSpawn(proc),
158
- });
159
- await client.connect();
160
- // Second message should be the initialized notification (no id)
161
- const notifMsg = messages[1];
162
- assert.strictEqual(notifMsg.jsonrpc, '2.0');
163
- assert.strictEqual(notifMsg.method, 'notifications/initialized');
164
- assert.strictEqual(notifMsg.id, undefined);
165
- await client.disconnect();
166
- });
167
- });
168
- describe('request IDs', () => {
169
- it('should increment request IDs', async () => {
170
- const proc = createMockProcess();
171
- const messages = collectMessages(proc.stdin);
172
- autoRespond(proc, () => ({ protocolVersion: '2024-11-05', capabilities: {}, tools: [] }));
173
- const client = new MCPClient('test', { command: 'node', args: [] }, {
174
- spawnFn: createMockSpawn(proc),
175
- });
176
- await client.connect(); // id: 1 (initialize)
177
- await client.listTools(); // id: 2 (tools/list)
178
- const initMsg = messages[0];
179
- assert.strictEqual(initMsg.id, 1);
180
- // messages[1] is the notification (no id), messages[2] is tools/list
181
- const listMsg = messages[2];
182
- assert.strictEqual(listMsg.id, 2);
183
- await client.disconnect();
184
- });
185
- });
186
- describe('listTools', () => {
187
- it('should return tool info from server', async () => {
188
- const proc = createMockProcess();
189
- autoRespond(proc, (msg) => {
190
- if (msg.method === 'initialize') {
191
- return { protocolVersion: '2024-11-05', capabilities: {} };
192
- }
193
- if (msg.method === 'tools/list') {
194
- return {
195
- tools: [
196
- {
197
- name: 'search',
198
- description: 'Search for components',
199
- inputSchema: { type: 'object', properties: { query: { type: 'string' } } },
200
- },
201
- {
202
- name: 'install',
203
- description: 'Install a component',
204
- inputSchema: { type: 'object', properties: { name: { type: 'string' } } },
205
- },
206
- ],
207
- };
208
- }
209
- return {};
210
- });
211
- const client = new MCPClient('test', { command: 'node', args: [] }, {
212
- spawnFn: createMockSpawn(proc),
213
- });
214
- await client.connect();
215
- const tools = await client.listTools();
216
- assert.strictEqual(tools.length, 2);
217
- assert.strictEqual(tools[0].name, 'search');
218
- assert.strictEqual(tools[0].description, 'Search for components');
219
- assert.deepStrictEqual(tools[0].inputSchema, {
220
- type: 'object',
221
- properties: { query: { type: 'string' } },
222
- });
223
- assert.strictEqual(tools[1].name, 'install');
224
- await client.disconnect();
225
- });
226
- it('should return empty array when server returns no tools', async () => {
227
- const proc = createMockProcess();
228
- autoRespond(proc, (msg) => {
229
- if (msg.method === 'initialize') {
230
- return { protocolVersion: '2024-11-05', capabilities: {} };
231
- }
232
- return { tools: [] };
233
- });
234
- const client = new MCPClient('test', { command: 'node', args: [] }, {
235
- spawnFn: createMockSpawn(proc),
236
- });
237
- await client.connect();
238
- const tools = await client.listTools();
239
- assert.deepStrictEqual(tools, []);
240
- await client.disconnect();
241
- });
242
- it('should throw if not connected', async () => {
243
- const client = new MCPClient('test', { command: 'node', args: [] });
244
- await assert.rejects(() => client.listTools(), (err) => {
245
- assert.ok(err.message.includes('not connected'));
246
- return true;
247
- });
248
- });
249
- });
250
- describe('callTool', () => {
251
- it('should send tools/call request with name and arguments', async () => {
252
- const proc = createMockProcess();
253
- const messages = collectMessages(proc.stdin);
254
- autoRespond(proc, (msg) => {
255
- if (msg.method === 'initialize') {
256
- return { protocolVersion: '2024-11-05', capabilities: {} };
257
- }
258
- if (msg.method === 'tools/call') {
259
- return { content: [{ type: 'text', text: 'result data' }] };
260
- }
261
- return {};
262
- });
263
- const client = new MCPClient('test', { command: 'node', args: [] }, {
264
- spawnFn: createMockSpawn(proc),
265
- });
266
- await client.connect();
267
- const result = await client.callTool('search', { query: 'button' });
268
- // Verify the request format (messages[2] is the callTool request)
269
- const callMsg = messages[2];
270
- assert.strictEqual(callMsg.method, 'tools/call');
271
- const params = callMsg.params;
272
- assert.strictEqual(params.name, 'search');
273
- assert.deepStrictEqual(params.arguments, { query: 'button' });
274
- // Verify the result
275
- assert.deepStrictEqual(result, { content: [{ type: 'text', text: 'result data' }] });
276
- await client.disconnect();
277
- });
278
- it('should throw if not connected', async () => {
279
- const client = new MCPClient('test', { command: 'node', args: [] });
280
- await assert.rejects(() => client.callTool('search', {}), (err) => {
281
- assert.ok(err.message.includes('not connected'));
282
- return true;
283
- });
284
- });
285
- });
286
- describe('disconnect', () => {
287
- it('should set connected to false', async () => {
288
- const proc = createMockProcess();
289
- autoRespond(proc, () => ({ protocolVersion: '2024-11-05', capabilities: {} }));
290
- const client = new MCPClient('test', { command: 'node', args: [] }, {
291
- spawnFn: createMockSpawn(proc),
292
- });
293
- await client.connect();
294
- assert.strictEqual(client.connected, true);
295
- await client.disconnect();
296
- assert.strictEqual(client.connected, false);
297
- });
298
- it('should be safe to call when not connected', async () => {
299
- const client = new MCPClient('test', { command: 'node', args: [] });
300
- // Should not throw
301
- await client.disconnect();
302
- assert.strictEqual(client.connected, false);
303
- });
304
- });
305
- describe('timeout handling', () => {
306
- it('should reject request on timeout', async () => {
307
- const proc = createMockProcess();
308
- // Don't auto-respond to anything — let it time out
309
- const client = new MCPClient('test', { command: 'node', args: [] }, {
310
- spawnFn: createMockSpawn(proc),
311
- timeoutMs: 50, // Very short timeout for test
312
- });
313
- await assert.rejects(() => client.connect(), // initialize will time out
314
- (err) => {
315
- assert.ok(err.message.includes('timed out'));
316
- return true;
317
- });
318
- await client.disconnect();
319
- });
320
- });
321
- describe('error responses', () => {
322
- it('should reject on JSON-RPC error response', async () => {
323
- const proc = createMockProcess();
324
- let initDone = false;
325
- // Custom handler: respond to initialize, error on tools/list
326
- let buffer = '';
327
- proc.stdin.on('data', (chunk) => {
328
- buffer += chunk.toString();
329
- const lines = buffer.split('\n');
330
- buffer = lines.pop() ?? '';
331
- for (const line of lines) {
332
- if (!line.trim())
333
- continue;
334
- const msg = JSON.parse(line);
335
- if (msg.id === undefined)
336
- continue;
337
- if (msg.method === 'initialize') {
338
- const resp = JSON.stringify({
339
- jsonrpc: '2.0',
340
- id: msg.id,
341
- result: { protocolVersion: '2024-11-05', capabilities: {} },
342
- });
343
- proc.stdout.push(resp + '\n');
344
- initDone = true;
345
- }
346
- else if (msg.method === 'tools/list' && initDone) {
347
- const resp = JSON.stringify({
348
- jsonrpc: '2.0',
349
- id: msg.id,
350
- error: { code: -32600, message: 'Not supported' },
351
- });
352
- proc.stdout.push(resp + '\n');
353
- }
354
- }
355
- });
356
- const client = new MCPClient('test', { command: 'node', args: [] }, {
357
- spawnFn: createMockSpawn(proc),
358
- });
359
- await client.connect();
360
- await assert.rejects(() => client.listTools(), (err) => {
361
- assert.ok(err.message.includes('Not supported'));
362
- return true;
363
- });
364
- await client.disconnect();
365
- });
366
- });
367
- describe('malformed responses', () => {
368
- it('should ignore non-JSON lines from server', async () => {
369
- const proc = createMockProcess();
370
- // Send garbage before the real response
371
- autoRespond(proc, (msg) => {
372
- if (msg.method === 'initialize') {
373
- // Push garbage first
374
- proc.stdout.push('This is not JSON\n');
375
- proc.stdout.push('DEBUG: server starting\n');
376
- return { protocolVersion: '2024-11-05', capabilities: {} };
377
- }
378
- return {};
379
- });
380
- const client = new MCPClient('test', { command: 'node', args: [] }, {
381
- spawnFn: createMockSpawn(proc),
382
- });
383
- // Should not throw despite garbage lines
384
- await client.connect();
385
- assert.strictEqual(client.connected, true);
386
- await client.disconnect();
387
- });
388
- });
389
- });
390
- //# sourceMappingURL=client.test.js.map