@ikarmic/forge-core 4.5.0 → 5.1.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 (643) hide show
  1. package/LICENSE +44 -21
  2. package/README.md +1 -1
  3. package/dist/agent/agent.d.ts +8 -1
  4. package/dist/agent/agent.js +143 -23
  5. package/dist/agent/architect.d.ts +0 -1
  6. package/dist/agent/architect.js +0 -1
  7. package/dist/agent/background.d.ts +58 -0
  8. package/dist/agent/background.js +139 -0
  9. package/dist/agent/cache-hints.d.ts +0 -1
  10. package/dist/agent/cache-hints.js +0 -1
  11. package/dist/agent/cost-router.d.ts +0 -1
  12. package/dist/agent/cost-router.js +0 -1
  13. package/dist/agent/enhance-prompt.d.ts +9 -0
  14. package/dist/agent/enhance-prompt.js +34 -0
  15. package/dist/agent/goal.d.ts +54 -0
  16. package/dist/agent/goal.js +65 -0
  17. package/dist/agent/index.d.ts +0 -1
  18. package/dist/agent/index.js +0 -1
  19. package/dist/agent/loop-guard.d.ts +21 -0
  20. package/dist/agent/loop-guard.js +41 -0
  21. package/dist/agent/prompts.d.ts +0 -1
  22. package/dist/agent/prompts.js +0 -1
  23. package/dist/agent/think-tags.d.ts +0 -1
  24. package/dist/agent/think-tags.js +0 -1
  25. package/dist/agent/verify.d.ts +0 -1
  26. package/dist/agent/verify.js +0 -1
  27. package/dist/agents/agent-files.d.ts +43 -0
  28. package/dist/agents/agent-files.js +109 -0
  29. package/dist/ai-comments/index.d.ts +0 -1
  30. package/dist/ai-comments/index.js +0 -1
  31. package/dist/attachments.d.ts +0 -1
  32. package/dist/attachments.js +0 -1
  33. package/dist/browser/cdp.d.ts +0 -1
  34. package/dist/browser/cdp.js +0 -1
  35. package/dist/browser/chrome.d.ts +0 -1
  36. package/dist/browser/chrome.js +0 -1
  37. package/dist/browser/session.d.ts +0 -1
  38. package/dist/browser/session.js +0 -1
  39. package/dist/checkpoints/index.d.ts +0 -1
  40. package/dist/checkpoints/index.js +0 -1
  41. package/dist/checkpoints/store.d.ts +0 -1
  42. package/dist/checkpoints/store.js +5 -2
  43. package/dist/checkpoints/types.d.ts +0 -1
  44. package/dist/checkpoints/types.js +0 -1
  45. package/dist/code-index/builder.d.ts +0 -1
  46. package/dist/code-index/builder.js +0 -1
  47. package/dist/code-index/index-store.d.ts +0 -1
  48. package/dist/code-index/index-store.js +0 -1
  49. package/dist/code-index/parser.d.ts +0 -1
  50. package/dist/code-index/parser.js +0 -1
  51. package/dist/code-index/types.d.ts +0 -1
  52. package/dist/code-index/types.js +0 -1
  53. package/dist/commands/custom-commands.d.ts +9 -5
  54. package/dist/commands/custom-commands.js +13 -3
  55. package/dist/config-file.d.ts +47 -1
  56. package/dist/config-file.js +249 -6
  57. package/dist/config-merge.d.ts +13 -0
  58. package/dist/config-merge.js +67 -0
  59. package/dist/config-schema.d.ts +340 -0
  60. package/dist/config-schema.js +126 -0
  61. package/dist/config.d.ts +0 -1
  62. package/dist/config.js +2 -2
  63. package/dist/context/compaction.d.ts +0 -1
  64. package/dist/context/compaction.js +10 -2
  65. package/dist/context/mask.d.ts +0 -1
  66. package/dist/context/mask.js +1 -2
  67. package/dist/credentials/index.d.ts +0 -1
  68. package/dist/credentials/index.js +0 -1
  69. package/dist/credentials/types.d.ts +0 -1
  70. package/dist/credentials/types.js +0 -1
  71. package/dist/custom-providers.d.ts +95 -0
  72. package/dist/custom-providers.js +120 -0
  73. package/dist/diff/index.d.ts +0 -1
  74. package/dist/diff/index.js +0 -1
  75. package/dist/diff/unified-diff.d.ts +0 -1
  76. package/dist/diff/unified-diff.js +0 -1
  77. package/dist/git/auto-commit.d.ts +3 -4
  78. package/dist/git/auto-commit.js +8 -7
  79. package/dist/git/index.d.ts +0 -1
  80. package/dist/git/index.js +0 -1
  81. package/dist/github/github-tools.d.ts +2 -3
  82. package/dist/github/github-tools.js +0 -1
  83. package/dist/hooks/agent-runner.d.ts +0 -1
  84. package/dist/hooks/agent-runner.js +0 -1
  85. package/dist/hooks/bus.d.ts +0 -1
  86. package/dist/hooks/bus.js +0 -1
  87. package/dist/hooks/config.d.ts +0 -1
  88. package/dist/hooks/config.js +0 -1
  89. package/dist/hooks/events.d.ts +0 -1
  90. package/dist/hooks/events.js +0 -1
  91. package/dist/hooks/index.d.ts +0 -1
  92. package/dist/hooks/index.js +0 -1
  93. package/dist/hooks/loader.d.ts +0 -1
  94. package/dist/hooks/loader.js +0 -1
  95. package/dist/hooks/runner.d.ts +0 -1
  96. package/dist/hooks/runner.js +3 -3
  97. package/dist/hooks/watch-coalescer.d.ts +0 -1
  98. package/dist/hooks/watch-coalescer.js +0 -1
  99. package/dist/hooks/watch-ignore.d.ts +0 -1
  100. package/dist/hooks/watch-ignore.js +0 -1
  101. package/dist/hooks/watcher.d.ts +0 -1
  102. package/dist/hooks/watcher.js +0 -1
  103. package/dist/import/claude-code.d.ts +39 -0
  104. package/dist/import/claude-code.js +254 -0
  105. package/dist/index.d.ts +37 -7
  106. package/dist/index.js +28 -5
  107. package/dist/lazy-model.d.ts +0 -1
  108. package/dist/lazy-model.js +0 -1
  109. package/dist/lint/auto-lint.d.ts +0 -1
  110. package/dist/lint/auto-lint.js +0 -1
  111. package/dist/lint/index.d.ts +0 -1
  112. package/dist/lint/index.js +0 -1
  113. package/dist/lsp/client.d.ts +5 -1
  114. package/dist/lsp/client.js +39 -4
  115. package/dist/lsp/diagnostics.d.ts +0 -1
  116. package/dist/lsp/diagnostics.js +0 -1
  117. package/dist/lsp/index.d.ts +0 -1
  118. package/dist/lsp/index.js +0 -1
  119. package/dist/mcp/catalog.d.ts +0 -1
  120. package/dist/mcp/catalog.js +0 -1
  121. package/dist/mcp/index.d.ts +5 -2
  122. package/dist/mcp/index.js +3 -2
  123. package/dist/mcp/json-schema-to-zod.d.ts +0 -1
  124. package/dist/mcp/json-schema-to-zod.js +0 -1
  125. package/dist/mcp/manager.d.ts +17 -4
  126. package/dist/mcp/manager.js +27 -3
  127. package/dist/mcp/marketplace-types.d.ts +0 -1
  128. package/dist/mcp/marketplace-types.js +0 -1
  129. package/dist/mcp/marketplace.d.ts +2 -1
  130. package/dist/mcp/marketplace.js +10 -5
  131. package/dist/mcp/mcp-client.d.ts +12 -3
  132. package/dist/mcp/mcp-client.js +74 -18
  133. package/dist/mcp/mcp-config.d.ts +2 -1
  134. package/dist/mcp/mcp-config.js +1 -1
  135. package/dist/mcp/oauth.d.ts +55 -0
  136. package/dist/mcp/oauth.js +197 -0
  137. package/dist/mcp/registry.d.ts +0 -1
  138. package/dist/mcp/registry.js +0 -1
  139. package/dist/mcp/resource-tools.d.ts +8 -0
  140. package/dist/mcp/resource-tools.js +56 -0
  141. package/dist/memory/memory-store.d.ts +0 -1
  142. package/dist/memory/memory-store.js +0 -1
  143. package/dist/memory/rank.d.ts +0 -1
  144. package/dist/memory/rank.js +0 -1
  145. package/dist/memory/session-digest.d.ts +12 -0
  146. package/dist/memory/session-digest.js +47 -0
  147. package/dist/memory/stale.d.ts +0 -1
  148. package/dist/memory/stale.js +2 -2
  149. package/dist/model-alias.d.ts +18 -3
  150. package/dist/model-alias.js +27 -4
  151. package/dist/model-catalog.d.ts +0 -1
  152. package/dist/model-catalog.js +0 -2
  153. package/dist/model-list.d.ts +0 -1
  154. package/dist/model-list.js +2 -2
  155. package/dist/model-overrides.d.ts +30 -0
  156. package/dist/model-overrides.js +48 -0
  157. package/dist/orchestrator/board-tools.d.ts +0 -1
  158. package/dist/orchestrator/board-tools.js +0 -1
  159. package/dist/orchestrator/board.d.ts +0 -1
  160. package/dist/orchestrator/board.js +0 -1
  161. package/dist/orchestrator/index.d.ts +0 -1
  162. package/dist/orchestrator/index.js +0 -1
  163. package/dist/orchestrator/orchestrator.d.ts +0 -1
  164. package/dist/orchestrator/orchestrator.js +0 -1
  165. package/dist/orchestrator/router.d.ts +0 -1
  166. package/dist/orchestrator/router.js +0 -1
  167. package/dist/orchestrator/specialists-registry.d.ts +0 -1
  168. package/dist/orchestrator/specialists-registry.js +2 -4
  169. package/dist/orchestrator/specialists.d.ts +0 -1
  170. package/dist/orchestrator/specialists.js +4 -5
  171. package/dist/orchestrator/types.d.ts +0 -1
  172. package/dist/orchestrator/types.js +0 -1
  173. package/dist/plugins/index.d.ts +0 -1
  174. package/dist/plugins/index.js +0 -1
  175. package/dist/plugins/install.d.ts +0 -1
  176. package/dist/plugins/install.js +0 -1
  177. package/dist/plugins/loader.d.ts +0 -1
  178. package/dist/plugins/loader.js +0 -1
  179. package/dist/policy/audit.d.ts +0 -1
  180. package/dist/policy/audit.js +0 -1
  181. package/dist/policy/ca-certs.d.ts +8 -0
  182. package/dist/policy/ca-certs.js +30 -0
  183. package/dist/policy/policy.d.ts +0 -1
  184. package/dist/policy/policy.js +0 -1
  185. package/dist/policy/proxy.d.ts +10 -4
  186. package/dist/policy/proxy.js +33 -7
  187. package/dist/pricing.d.ts +0 -1
  188. package/dist/pricing.js +4 -1
  189. package/dist/providers.d.ts +7 -1
  190. package/dist/providers.js +39 -6
  191. package/dist/repomap/index.d.ts +0 -1
  192. package/dist/repomap/index.js +0 -1
  193. package/dist/repomap/repo-map.d.ts +0 -1
  194. package/dist/repomap/repo-map.js +0 -1
  195. package/dist/semantic/chunker.d.ts +0 -1
  196. package/dist/semantic/chunker.js +0 -1
  197. package/dist/semantic/embedder.d.ts +15 -1
  198. package/dist/semantic/embedder.js +25 -1
  199. package/dist/semantic/semantic-index.d.ts +10 -3
  200. package/dist/semantic/semantic-index.js +16 -8
  201. package/dist/semantic/vector-store.d.ts +0 -1
  202. package/dist/semantic/vector-store.js +0 -1
  203. package/dist/sessions/index.d.ts +1 -1
  204. package/dist/sessions/index.js +1 -1
  205. package/dist/sessions/prune.d.ts +23 -0
  206. package/dist/sessions/prune.js +35 -0
  207. package/dist/sessions/search.d.ts +0 -1
  208. package/dist/sessions/search.js +0 -1
  209. package/dist/sessions/session-export.d.ts +0 -1
  210. package/dist/sessions/session-export.js +0 -1
  211. package/dist/sessions/session-store.d.ts +0 -1
  212. package/dist/sessions/session-store.js +2 -2
  213. package/dist/sessions/watch.d.ts +0 -1
  214. package/dist/sessions/watch.js +0 -1
  215. package/dist/settings-export.d.ts +0 -1
  216. package/dist/settings-export.js +0 -1
  217. package/dist/skills/activator.d.ts +0 -1
  218. package/dist/skills/activator.js +0 -1
  219. package/dist/skills/builtin.d.ts +2 -0
  220. package/dist/skills/builtin.js +68 -0
  221. package/dist/skills/index.d.ts +2 -1
  222. package/dist/skills/index.js +2 -1
  223. package/dist/skills/loader.d.ts +10 -4
  224. package/dist/skills/loader.js +20 -8
  225. package/dist/skills/marketplace-types.d.ts +0 -1
  226. package/dist/skills/marketplace-types.js +0 -1
  227. package/dist/skills/marketplace.d.ts +0 -1
  228. package/dist/skills/marketplace.js +2 -2
  229. package/dist/skills/parser.d.ts +0 -1
  230. package/dist/skills/parser.js +0 -1
  231. package/dist/skills/remote.d.ts +14 -0
  232. package/dist/skills/remote.js +131 -0
  233. package/dist/skills/types.d.ts +10 -1
  234. package/dist/skills/types.js +0 -1
  235. package/dist/specs/generate.d.ts +0 -1
  236. package/dist/specs/generate.js +0 -1
  237. package/dist/specs/index.d.ts +0 -1
  238. package/dist/specs/index.js +0 -1
  239. package/dist/specs/store.d.ts +0 -1
  240. package/dist/specs/store.js +0 -1
  241. package/dist/specs/sync.d.ts +0 -1
  242. package/dist/specs/sync.js +0 -1
  243. package/dist/specs/tasks-parser.d.ts +0 -1
  244. package/dist/specs/tasks-parser.js +0 -1
  245. package/dist/specs/types.d.ts +0 -1
  246. package/dist/specs/types.js +0 -1
  247. package/dist/steering/extra-instructions.d.ts +8 -0
  248. package/dist/steering/extra-instructions.js +104 -0
  249. package/dist/steering/folder-instructions.d.ts +8 -0
  250. package/dist/steering/folder-instructions.js +28 -0
  251. package/dist/steering/glob.d.ts +0 -1
  252. package/dist/steering/glob.js +0 -1
  253. package/dist/steering/index.d.ts +0 -1
  254. package/dist/steering/index.js +0 -1
  255. package/dist/steering/loader.d.ts +0 -1
  256. package/dist/steering/loader.js +0 -1
  257. package/dist/steering/project-instructions.d.ts +0 -1
  258. package/dist/steering/project-instructions.js +0 -1
  259. package/dist/steering/select.d.ts +0 -1
  260. package/dist/steering/select.js +2 -2
  261. package/dist/steering/types.d.ts +0 -1
  262. package/dist/steering/types.js +0 -1
  263. package/dist/structured/index.d.ts +0 -1
  264. package/dist/structured/index.js +0 -1
  265. package/dist/structured/retry.d.ts +0 -1
  266. package/dist/structured/retry.js +0 -1
  267. package/dist/structured/schema.d.ts +0 -1
  268. package/dist/structured/schema.js +0 -1
  269. package/dist/timed-fetch.d.ts +12 -0
  270. package/dist/timed-fetch.js +83 -0
  271. package/dist/tools/apply-patch.d.ts +52 -0
  272. package/dist/tools/apply-patch.js +197 -0
  273. package/dist/tools/ask-user.d.ts +27 -0
  274. package/dist/tools/ask-user.js +32 -0
  275. package/dist/tools/browser-tools.d.ts +6 -7
  276. package/dist/tools/browser-tools.js +3 -14
  277. package/dist/tools/codebase-search.d.ts +4 -3
  278. package/dist/tools/codebase-search.js +2 -3
  279. package/dist/tools/command-allow.d.ts +0 -1
  280. package/dist/tools/command-allow.js +0 -1
  281. package/dist/tools/edit-file.d.ts +0 -1
  282. package/dist/tools/edit-file.js +5 -4
  283. package/dist/tools/fetch-url.d.ts +7 -1
  284. package/dist/tools/fetch-url.js +52 -20
  285. package/dist/tools/find-references.d.ts +0 -1
  286. package/dist/tools/find-references.js +0 -1
  287. package/dist/tools/find-symbol.d.ts +2 -3
  288. package/dist/tools/find-symbol.js +0 -1
  289. package/dist/tools/ignore-rules.d.ts +0 -1
  290. package/dist/tools/ignore-rules.js +2 -2
  291. package/dist/tools/index.d.ts +5 -2
  292. package/dist/tools/index.js +10 -2
  293. package/dist/tools/list-files.d.ts +0 -1
  294. package/dist/tools/list-files.js +0 -1
  295. package/dist/tools/list-symbols.d.ts +0 -1
  296. package/dist/tools/list-symbols.js +0 -1
  297. package/dist/tools/memory.d.ts +6 -7
  298. package/dist/tools/memory.js +0 -1
  299. package/dist/tools/notebook.d.ts +2 -3
  300. package/dist/tools/notebook.js +0 -1
  301. package/dist/tools/permission-rules.d.ts +32 -0
  302. package/dist/tools/permission-rules.js +182 -0
  303. package/dist/tools/policy.d.ts +0 -1
  304. package/dist/tools/policy.js +0 -1
  305. package/dist/tools/read-file.d.ts +5 -1
  306. package/dist/tools/read-file.js +7 -3
  307. package/dist/tools/read-image.d.ts +0 -1
  308. package/dist/tools/read-image.js +0 -1
  309. package/dist/tools/read-only.d.ts +1 -2
  310. package/dist/tools/read-only.js +2 -1
  311. package/dist/tools/redact.d.ts +0 -1
  312. package/dist/tools/redact.js +0 -1
  313. package/dist/tools/result-cache.d.ts +0 -1
  314. package/dist/tools/result-cache.js +0 -1
  315. package/dist/tools/run-command.d.ts +4 -3
  316. package/dist/tools/run-command.js +12 -9
  317. package/dist/tools/sandbox-loader.d.ts +0 -1
  318. package/dist/tools/sandbox-loader.js +3 -14
  319. package/dist/tools/search-files.d.ts +8 -3
  320. package/dist/tools/search-files.js +43 -1
  321. package/dist/tools/shared.d.ts +5 -1
  322. package/dist/tools/shared.js +30 -3
  323. package/dist/tools/shell-env.d.ts +7 -0
  324. package/dist/tools/shell-env.js +9 -0
  325. package/dist/tools/sub-agent-wait.d.ts +29 -0
  326. package/dist/tools/sub-agent-wait.js +60 -0
  327. package/dist/tools/sub-agent.d.ts +50 -5
  328. package/dist/tools/sub-agent.js +210 -126
  329. package/dist/tools/text-encoding.d.ts +10 -0
  330. package/dist/tools/text-encoding.js +40 -0
  331. package/dist/tools/todo.d.ts +36 -0
  332. package/dist/tools/todo.js +42 -0
  333. package/dist/tools/web-search.d.ts +0 -1
  334. package/dist/tools/web-search.js +0 -1
  335. package/dist/tools/write-file.d.ts +0 -1
  336. package/dist/tools/write-file.js +15 -10
  337. package/dist/tools/write-tools.d.ts +12 -0
  338. package/dist/tools/write-tools.js +18 -0
  339. package/dist/types.d.ts +85 -2
  340. package/dist/types.js +0 -1
  341. package/dist/verify/detect.d.ts +0 -1
  342. package/dist/verify/detect.js +0 -1
  343. package/dist/verify/index.d.ts +0 -1
  344. package/dist/verify/index.js +0 -1
  345. package/dist/worktree/branch-ops.d.ts +0 -1
  346. package/dist/worktree/branch-ops.js +0 -1
  347. package/dist/worktree/index.d.ts +0 -1
  348. package/dist/worktree/index.js +0 -1
  349. package/dist/worktree/worktree.d.ts +3 -1
  350. package/dist/worktree/worktree.js +22 -1
  351. package/package.json +3 -2
  352. package/dist/agent/agent.d.ts.map +0 -1
  353. package/dist/agent/agent.js.map +0 -1
  354. package/dist/agent/architect.d.ts.map +0 -1
  355. package/dist/agent/architect.js.map +0 -1
  356. package/dist/agent/cache-hints.d.ts.map +0 -1
  357. package/dist/agent/cache-hints.js.map +0 -1
  358. package/dist/agent/cost-router.d.ts.map +0 -1
  359. package/dist/agent/cost-router.js.map +0 -1
  360. package/dist/agent/index.d.ts.map +0 -1
  361. package/dist/agent/index.js.map +0 -1
  362. package/dist/agent/prompts.d.ts.map +0 -1
  363. package/dist/agent/prompts.js.map +0 -1
  364. package/dist/agent/think-tags.d.ts.map +0 -1
  365. package/dist/agent/think-tags.js.map +0 -1
  366. package/dist/agent/verify.d.ts.map +0 -1
  367. package/dist/agent/verify.js.map +0 -1
  368. package/dist/ai-comments/index.d.ts.map +0 -1
  369. package/dist/ai-comments/index.js.map +0 -1
  370. package/dist/attachments.d.ts.map +0 -1
  371. package/dist/attachments.js.map +0 -1
  372. package/dist/browser/cdp.d.ts.map +0 -1
  373. package/dist/browser/cdp.js.map +0 -1
  374. package/dist/browser/chrome.d.ts.map +0 -1
  375. package/dist/browser/chrome.js.map +0 -1
  376. package/dist/browser/session.d.ts.map +0 -1
  377. package/dist/browser/session.js.map +0 -1
  378. package/dist/checkpoints/index.d.ts.map +0 -1
  379. package/dist/checkpoints/index.js.map +0 -1
  380. package/dist/checkpoints/store.d.ts.map +0 -1
  381. package/dist/checkpoints/store.js.map +0 -1
  382. package/dist/checkpoints/types.d.ts.map +0 -1
  383. package/dist/checkpoints/types.js.map +0 -1
  384. package/dist/code-index/builder.d.ts.map +0 -1
  385. package/dist/code-index/builder.js.map +0 -1
  386. package/dist/code-index/index-store.d.ts.map +0 -1
  387. package/dist/code-index/index-store.js.map +0 -1
  388. package/dist/code-index/parser.d.ts.map +0 -1
  389. package/dist/code-index/parser.js.map +0 -1
  390. package/dist/code-index/types.d.ts.map +0 -1
  391. package/dist/code-index/types.js.map +0 -1
  392. package/dist/commands/custom-commands.d.ts.map +0 -1
  393. package/dist/commands/custom-commands.js.map +0 -1
  394. package/dist/config-file.d.ts.map +0 -1
  395. package/dist/config-file.js.map +0 -1
  396. package/dist/config.d.ts.map +0 -1
  397. package/dist/config.js.map +0 -1
  398. package/dist/context/compaction.d.ts.map +0 -1
  399. package/dist/context/compaction.js.map +0 -1
  400. package/dist/context/mask.d.ts.map +0 -1
  401. package/dist/context/mask.js.map +0 -1
  402. package/dist/credentials/index.d.ts.map +0 -1
  403. package/dist/credentials/index.js.map +0 -1
  404. package/dist/credentials/types.d.ts.map +0 -1
  405. package/dist/credentials/types.js.map +0 -1
  406. package/dist/diff/index.d.ts.map +0 -1
  407. package/dist/diff/index.js.map +0 -1
  408. package/dist/diff/unified-diff.d.ts.map +0 -1
  409. package/dist/diff/unified-diff.js.map +0 -1
  410. package/dist/git/auto-commit.d.ts.map +0 -1
  411. package/dist/git/auto-commit.js.map +0 -1
  412. package/dist/git/index.d.ts.map +0 -1
  413. package/dist/git/index.js.map +0 -1
  414. package/dist/github/github-tools.d.ts.map +0 -1
  415. package/dist/github/github-tools.js.map +0 -1
  416. package/dist/hooks/agent-runner.d.ts.map +0 -1
  417. package/dist/hooks/agent-runner.js.map +0 -1
  418. package/dist/hooks/bus.d.ts.map +0 -1
  419. package/dist/hooks/bus.js.map +0 -1
  420. package/dist/hooks/config.d.ts.map +0 -1
  421. package/dist/hooks/config.js.map +0 -1
  422. package/dist/hooks/events.d.ts.map +0 -1
  423. package/dist/hooks/events.js.map +0 -1
  424. package/dist/hooks/index.d.ts.map +0 -1
  425. package/dist/hooks/index.js.map +0 -1
  426. package/dist/hooks/loader.d.ts.map +0 -1
  427. package/dist/hooks/loader.js.map +0 -1
  428. package/dist/hooks/runner.d.ts.map +0 -1
  429. package/dist/hooks/runner.js.map +0 -1
  430. package/dist/hooks/watch-coalescer.d.ts.map +0 -1
  431. package/dist/hooks/watch-coalescer.js.map +0 -1
  432. package/dist/hooks/watch-ignore.d.ts.map +0 -1
  433. package/dist/hooks/watch-ignore.js.map +0 -1
  434. package/dist/hooks/watcher.d.ts.map +0 -1
  435. package/dist/hooks/watcher.js.map +0 -1
  436. package/dist/index.d.ts.map +0 -1
  437. package/dist/index.js.map +0 -1
  438. package/dist/lazy-model.d.ts.map +0 -1
  439. package/dist/lazy-model.js.map +0 -1
  440. package/dist/lint/auto-lint.d.ts.map +0 -1
  441. package/dist/lint/auto-lint.js.map +0 -1
  442. package/dist/lint/index.d.ts.map +0 -1
  443. package/dist/lint/index.js.map +0 -1
  444. package/dist/lsp/client.d.ts.map +0 -1
  445. package/dist/lsp/client.js.map +0 -1
  446. package/dist/lsp/diagnostics.d.ts.map +0 -1
  447. package/dist/lsp/diagnostics.js.map +0 -1
  448. package/dist/lsp/index.d.ts.map +0 -1
  449. package/dist/lsp/index.js.map +0 -1
  450. package/dist/mcp/catalog.d.ts.map +0 -1
  451. package/dist/mcp/catalog.js.map +0 -1
  452. package/dist/mcp/index.d.ts.map +0 -1
  453. package/dist/mcp/index.js.map +0 -1
  454. package/dist/mcp/json-schema-to-zod.d.ts.map +0 -1
  455. package/dist/mcp/json-schema-to-zod.js.map +0 -1
  456. package/dist/mcp/manager.d.ts.map +0 -1
  457. package/dist/mcp/manager.js.map +0 -1
  458. package/dist/mcp/marketplace-types.d.ts.map +0 -1
  459. package/dist/mcp/marketplace-types.js.map +0 -1
  460. package/dist/mcp/marketplace.d.ts.map +0 -1
  461. package/dist/mcp/marketplace.js.map +0 -1
  462. package/dist/mcp/mcp-client.d.ts.map +0 -1
  463. package/dist/mcp/mcp-client.js.map +0 -1
  464. package/dist/mcp/mcp-config.d.ts.map +0 -1
  465. package/dist/mcp/mcp-config.js.map +0 -1
  466. package/dist/mcp/registry.d.ts.map +0 -1
  467. package/dist/mcp/registry.js.map +0 -1
  468. package/dist/memory/memory-store.d.ts.map +0 -1
  469. package/dist/memory/memory-store.js.map +0 -1
  470. package/dist/memory/rank.d.ts.map +0 -1
  471. package/dist/memory/rank.js.map +0 -1
  472. package/dist/memory/stale.d.ts.map +0 -1
  473. package/dist/memory/stale.js.map +0 -1
  474. package/dist/model-alias.d.ts.map +0 -1
  475. package/dist/model-alias.js.map +0 -1
  476. package/dist/model-catalog.d.ts.map +0 -1
  477. package/dist/model-catalog.js.map +0 -1
  478. package/dist/model-list.d.ts.map +0 -1
  479. package/dist/model-list.js.map +0 -1
  480. package/dist/orchestrator/board-tools.d.ts.map +0 -1
  481. package/dist/orchestrator/board-tools.js.map +0 -1
  482. package/dist/orchestrator/board.d.ts.map +0 -1
  483. package/dist/orchestrator/board.js.map +0 -1
  484. package/dist/orchestrator/index.d.ts.map +0 -1
  485. package/dist/orchestrator/index.js.map +0 -1
  486. package/dist/orchestrator/orchestrator.d.ts.map +0 -1
  487. package/dist/orchestrator/orchestrator.js.map +0 -1
  488. package/dist/orchestrator/router.d.ts.map +0 -1
  489. package/dist/orchestrator/router.js.map +0 -1
  490. package/dist/orchestrator/specialists-registry.d.ts.map +0 -1
  491. package/dist/orchestrator/specialists-registry.js.map +0 -1
  492. package/dist/orchestrator/specialists.d.ts.map +0 -1
  493. package/dist/orchestrator/specialists.js.map +0 -1
  494. package/dist/orchestrator/types.d.ts.map +0 -1
  495. package/dist/orchestrator/types.js.map +0 -1
  496. package/dist/plugins/index.d.ts.map +0 -1
  497. package/dist/plugins/index.js.map +0 -1
  498. package/dist/plugins/install.d.ts.map +0 -1
  499. package/dist/plugins/install.js.map +0 -1
  500. package/dist/plugins/loader.d.ts.map +0 -1
  501. package/dist/plugins/loader.js.map +0 -1
  502. package/dist/policy/audit.d.ts.map +0 -1
  503. package/dist/policy/audit.js.map +0 -1
  504. package/dist/policy/policy.d.ts.map +0 -1
  505. package/dist/policy/policy.js.map +0 -1
  506. package/dist/policy/proxy.d.ts.map +0 -1
  507. package/dist/policy/proxy.js.map +0 -1
  508. package/dist/pricing.d.ts.map +0 -1
  509. package/dist/pricing.js.map +0 -1
  510. package/dist/providers.d.ts.map +0 -1
  511. package/dist/providers.js.map +0 -1
  512. package/dist/repomap/index.d.ts.map +0 -1
  513. package/dist/repomap/index.js.map +0 -1
  514. package/dist/repomap/repo-map.d.ts.map +0 -1
  515. package/dist/repomap/repo-map.js.map +0 -1
  516. package/dist/semantic/chunker.d.ts.map +0 -1
  517. package/dist/semantic/chunker.js.map +0 -1
  518. package/dist/semantic/embedder.d.ts.map +0 -1
  519. package/dist/semantic/embedder.js.map +0 -1
  520. package/dist/semantic/semantic-index.d.ts.map +0 -1
  521. package/dist/semantic/semantic-index.js.map +0 -1
  522. package/dist/semantic/vector-store.d.ts.map +0 -1
  523. package/dist/semantic/vector-store.js.map +0 -1
  524. package/dist/sessions/index.d.ts.map +0 -1
  525. package/dist/sessions/index.js.map +0 -1
  526. package/dist/sessions/search.d.ts.map +0 -1
  527. package/dist/sessions/search.js.map +0 -1
  528. package/dist/sessions/session-export.d.ts.map +0 -1
  529. package/dist/sessions/session-export.js.map +0 -1
  530. package/dist/sessions/session-store.d.ts.map +0 -1
  531. package/dist/sessions/session-store.js.map +0 -1
  532. package/dist/sessions/watch.d.ts.map +0 -1
  533. package/dist/sessions/watch.js.map +0 -1
  534. package/dist/settings-export.d.ts.map +0 -1
  535. package/dist/settings-export.js.map +0 -1
  536. package/dist/skills/activator.d.ts.map +0 -1
  537. package/dist/skills/activator.js.map +0 -1
  538. package/dist/skills/index.d.ts.map +0 -1
  539. package/dist/skills/index.js.map +0 -1
  540. package/dist/skills/loader.d.ts.map +0 -1
  541. package/dist/skills/loader.js.map +0 -1
  542. package/dist/skills/marketplace-types.d.ts.map +0 -1
  543. package/dist/skills/marketplace-types.js.map +0 -1
  544. package/dist/skills/marketplace.d.ts.map +0 -1
  545. package/dist/skills/marketplace.js.map +0 -1
  546. package/dist/skills/parser.d.ts.map +0 -1
  547. package/dist/skills/parser.js.map +0 -1
  548. package/dist/skills/types.d.ts.map +0 -1
  549. package/dist/skills/types.js.map +0 -1
  550. package/dist/specs/generate.d.ts.map +0 -1
  551. package/dist/specs/generate.js.map +0 -1
  552. package/dist/specs/index.d.ts.map +0 -1
  553. package/dist/specs/index.js.map +0 -1
  554. package/dist/specs/store.d.ts.map +0 -1
  555. package/dist/specs/store.js.map +0 -1
  556. package/dist/specs/sync.d.ts.map +0 -1
  557. package/dist/specs/sync.js.map +0 -1
  558. package/dist/specs/tasks-parser.d.ts.map +0 -1
  559. package/dist/specs/tasks-parser.js.map +0 -1
  560. package/dist/specs/types.d.ts.map +0 -1
  561. package/dist/specs/types.js.map +0 -1
  562. package/dist/steering/glob.d.ts.map +0 -1
  563. package/dist/steering/glob.js.map +0 -1
  564. package/dist/steering/index.d.ts.map +0 -1
  565. package/dist/steering/index.js.map +0 -1
  566. package/dist/steering/loader.d.ts.map +0 -1
  567. package/dist/steering/loader.js.map +0 -1
  568. package/dist/steering/project-instructions.d.ts.map +0 -1
  569. package/dist/steering/project-instructions.js.map +0 -1
  570. package/dist/steering/select.d.ts.map +0 -1
  571. package/dist/steering/select.js.map +0 -1
  572. package/dist/steering/types.d.ts.map +0 -1
  573. package/dist/steering/types.js.map +0 -1
  574. package/dist/structured/index.d.ts.map +0 -1
  575. package/dist/structured/index.js.map +0 -1
  576. package/dist/structured/retry.d.ts.map +0 -1
  577. package/dist/structured/retry.js.map +0 -1
  578. package/dist/structured/schema.d.ts.map +0 -1
  579. package/dist/structured/schema.js.map +0 -1
  580. package/dist/tools/browser-tools.d.ts.map +0 -1
  581. package/dist/tools/browser-tools.js.map +0 -1
  582. package/dist/tools/codebase-search.d.ts.map +0 -1
  583. package/dist/tools/codebase-search.js.map +0 -1
  584. package/dist/tools/command-allow.d.ts.map +0 -1
  585. package/dist/tools/command-allow.js.map +0 -1
  586. package/dist/tools/edit-file.d.ts.map +0 -1
  587. package/dist/tools/edit-file.js.map +0 -1
  588. package/dist/tools/fetch-url.d.ts.map +0 -1
  589. package/dist/tools/fetch-url.js.map +0 -1
  590. package/dist/tools/find-references.d.ts.map +0 -1
  591. package/dist/tools/find-references.js.map +0 -1
  592. package/dist/tools/find-symbol.d.ts.map +0 -1
  593. package/dist/tools/find-symbol.js.map +0 -1
  594. package/dist/tools/ignore-rules.d.ts.map +0 -1
  595. package/dist/tools/ignore-rules.js.map +0 -1
  596. package/dist/tools/index.d.ts.map +0 -1
  597. package/dist/tools/index.js.map +0 -1
  598. package/dist/tools/list-files.d.ts.map +0 -1
  599. package/dist/tools/list-files.js.map +0 -1
  600. package/dist/tools/list-symbols.d.ts.map +0 -1
  601. package/dist/tools/list-symbols.js.map +0 -1
  602. package/dist/tools/memory.d.ts.map +0 -1
  603. package/dist/tools/memory.js.map +0 -1
  604. package/dist/tools/notebook.d.ts.map +0 -1
  605. package/dist/tools/notebook.js.map +0 -1
  606. package/dist/tools/policy.d.ts.map +0 -1
  607. package/dist/tools/policy.js.map +0 -1
  608. package/dist/tools/read-file.d.ts.map +0 -1
  609. package/dist/tools/read-file.js.map +0 -1
  610. package/dist/tools/read-image.d.ts.map +0 -1
  611. package/dist/tools/read-image.js.map +0 -1
  612. package/dist/tools/read-only.d.ts.map +0 -1
  613. package/dist/tools/read-only.js.map +0 -1
  614. package/dist/tools/redact.d.ts.map +0 -1
  615. package/dist/tools/redact.js.map +0 -1
  616. package/dist/tools/result-cache.d.ts.map +0 -1
  617. package/dist/tools/result-cache.js.map +0 -1
  618. package/dist/tools/run-command.d.ts.map +0 -1
  619. package/dist/tools/run-command.js.map +0 -1
  620. package/dist/tools/sandbox-loader.d.ts.map +0 -1
  621. package/dist/tools/sandbox-loader.js.map +0 -1
  622. package/dist/tools/search-files.d.ts.map +0 -1
  623. package/dist/tools/search-files.js.map +0 -1
  624. package/dist/tools/shared.d.ts.map +0 -1
  625. package/dist/tools/shared.js.map +0 -1
  626. package/dist/tools/sub-agent.d.ts.map +0 -1
  627. package/dist/tools/sub-agent.js.map +0 -1
  628. package/dist/tools/web-search.d.ts.map +0 -1
  629. package/dist/tools/web-search.js.map +0 -1
  630. package/dist/tools/write-file.d.ts.map +0 -1
  631. package/dist/tools/write-file.js.map +0 -1
  632. package/dist/types.d.ts.map +0 -1
  633. package/dist/types.js.map +0 -1
  634. package/dist/verify/detect.d.ts.map +0 -1
  635. package/dist/verify/detect.js.map +0 -1
  636. package/dist/verify/index.d.ts.map +0 -1
  637. package/dist/verify/index.js.map +0 -1
  638. package/dist/worktree/branch-ops.d.ts.map +0 -1
  639. package/dist/worktree/branch-ops.js.map +0 -1
  640. package/dist/worktree/index.d.ts.map +0 -1
  641. package/dist/worktree/index.js.map +0 -1
  642. package/dist/worktree/worktree.d.ts.map +0 -1
  643. package/dist/worktree/worktree.js.map +0 -1
@@ -1,8 +1,9 @@
1
1
  import type { ToolDefinition } from '../types.js';
2
- import { type ConnectedMcpServer } from './mcp-client.js';
2
+ import { type ConnectOptions, type ConnectedMcpServer } from './mcp-client.js';
3
+ import type { McpOAuthOptions } from './oauth.js';
3
4
  import type { McpServerSpec } from './mcp-config.js';
4
5
  import { type OrgPolicy } from '../policy/policy.js';
5
- export type McpServerState = 'connected' | 'failed' | 'disabled';
6
+ export type McpServerState = 'connected' | 'failed' | 'disabled' | 'needs-auth';
6
7
  export interface McpServerStatus {
7
8
  name: string;
8
9
  state: McpServerState;
@@ -24,8 +25,13 @@ export interface McpManagerOptions {
24
25
  connectTimeoutMs?: number;
25
26
  /** Organization policy for the MCP allowlist. Unset = the managed policy file; null = none. */
26
27
  policy?: OrgPolicy | null;
28
+ /**
29
+ * OAuth sign-in for HTTP servers that want it. Without it such a server is simply "failed" (401). With it, saved
30
+ * tokens are used and a server without them is listed as "needs-auth" until {@link McpManager.signIn} runs.
31
+ */
32
+ oauth?: Omit<McpOAuthOptions, 'interactive'>;
27
33
  /** Test seam. */
28
- connect?: (name: string, spec: McpServerSpec) => Promise<ConnectedMcpServer>;
34
+ connect?: (name: string, spec: McpServerSpec, options?: ConnectOptions) => Promise<ConnectedMcpServer>;
29
35
  }
30
36
  /** Replace `${workspaceFolder}` in args, env values, url and headers. */
31
37
  export declare function expandSpec(spec: McpServerSpec, cwd: string): McpServerSpec;
@@ -41,11 +47,18 @@ export declare class McpManager {
41
47
  ensureConnected(): Promise<void>;
42
48
  /** Tools from all connected servers (call {@link ensureConnected} first). */
43
49
  tools(): ToolDefinition[];
50
+ /** The servers that are connected right now (call {@link ensureConnected} first). */
51
+ servers(): readonly ConnectedMcpServer[];
44
52
  status(): McpServerStatus[];
45
53
  /** Drop connections and re-read the config files. */
54
+ private readonly specs;
55
+ /**
56
+ * Sign in to a server listed as `needs-auth`: opens the user's browser, waits for them to finish (up to the sign-in
57
+ * timeout), saves the tokens, then reconnects everything so the server's tools appear.
58
+ */
59
+ signIn(name: string): Promise<void>;
46
60
  reload(): Promise<void>;
47
61
  dispose(): Promise<void>;
48
62
  private readScope;
49
63
  private load;
50
64
  }
51
- //# sourceMappingURL=manager.d.ts.map
@@ -5,7 +5,7 @@
5
5
  * reported in `status()` instead of only written to stderr.
6
6
  */
7
7
  import path from 'node:path';
8
- import { closeAll, connectOne } from './mcp-client.js';
8
+ import { McpAuthRequiredError, closeAll, connectOne } from './mcp-client.js';
9
9
  import { loadMcpConfig } from './mcp-config.js';
10
10
  import { defaultUserMcpPath } from './marketplace.js';
11
11
  import { filterMcpServers, getOrgPolicy } from '../policy/policy.js';
@@ -50,10 +50,32 @@ export class McpManager {
50
50
  tools() {
51
51
  return this.connected.flatMap((s) => s.tools);
52
52
  }
53
+ /** The servers that are connected right now (call {@link ensureConnected} first). */
54
+ servers() {
55
+ return this.connected;
56
+ }
53
57
  status() {
54
58
  return [...this.statuses];
55
59
  }
56
60
  /** Drop connections and re-read the config files. */
61
+ specs = new Map();
62
+ /**
63
+ * Sign in to a server listed as `needs-auth`: opens the user's browser, waits for them to finish (up to the sign-in
64
+ * timeout), saves the tokens, then reconnects everything so the server's tools appear.
65
+ */
66
+ async signIn(name) {
67
+ const oauth = this.options.oauth;
68
+ const spec = this.specs.get(name);
69
+ if (!oauth)
70
+ throw new Error('sign-in is not available here');
71
+ if (!spec)
72
+ throw new Error(`no MCP server named "${name}"`);
73
+ const connect = this.options.connect ?? connectOne;
74
+ const wait = oauth.signInTimeoutMs ?? 5 * 60_000;
75
+ const server = await withTimeout(connect(name, expandSpec(spec, this.options.cwd), { oauth: { ...oauth, interactive: true } }), wait + (this.options.connectTimeoutMs ?? 30_000), `Signing in to MCP server "${name}"`);
76
+ await closeAll([server]);
77
+ await this.reload();
78
+ }
57
79
  async reload() {
58
80
  await this.dispose();
59
81
  await this.ensureConnected();
@@ -110,10 +132,13 @@ export class McpManager {
110
132
  if (spec.disabled)
111
133
  return { status: { name, state: 'disabled', scope, toolCount: 0 } };
112
134
  try {
113
- const server = await withTimeout(connect(name, expandSpec(spec, cwd)), timeoutMs, `MCP server "${name}"`);
135
+ this.specs.set(name, spec);
136
+ const server = await withTimeout(connect(name, expandSpec(spec, cwd), this.options.oauth ? { oauth: { ...this.options.oauth, interactive: false } } : undefined), timeoutMs, `MCP server "${name}"`);
114
137
  return { server, status: { name, state: 'connected', scope, toolCount: server.tools.length } };
115
138
  }
116
139
  catch (err) {
140
+ if (err instanceof McpAuthRequiredError)
141
+ return { status: { name, state: 'needs-auth', scope, toolCount: 0, error: err.message } };
117
142
  return { status: { name, state: 'failed', scope, toolCount: 0, error: err.message } };
118
143
  }
119
144
  }));
@@ -121,4 +146,3 @@ export class McpManager {
121
146
  this.statuses = [...statuses, ...results.map((r) => r.status)];
122
147
  }
123
148
  }
124
- //# sourceMappingURL=manager.js.map
@@ -80,4 +80,3 @@ export interface InstalledServerMetadata {
80
80
  installedAt: string;
81
81
  displayName?: string;
82
82
  }
83
- //# sourceMappingURL=marketplace-types.d.ts.map
@@ -10,4 +10,3 @@
10
10
  */
11
11
  /** Version of the catalog JSON format. Bumped on backwards-incompatible changes. */
12
12
  export const MARKETPLACE_CATALOG_VERSION = 1;
13
- //# sourceMappingURL=marketplace-types.js.map
@@ -55,6 +55,8 @@ export declare function installDirNameFor(source: {
55
55
  * server" message instead of silently registering nothing.
56
56
  */
57
57
  export declare function probeRepoForServer(repoPath: string, subdir?: string): Promise<McpServerSpec>;
58
+ /** `--` ends git's option parsing: a source that starts with `-` (`--upload-pack=…`) must never be read as an option. */
59
+ export declare function gitCloneArgs(url: string, target: string): string[];
58
60
  /**
59
61
  * Install an MCP server from a catalog entry or a raw GitHub URL.
60
62
  * Returns the {@link InstalledMcpServer} describing what was installed.
@@ -95,4 +97,3 @@ export declare function listInstalledServers(params?: {
95
97
  cacheRoot?: string;
96
98
  userMcpPath?: string;
97
99
  }): Promise<InstalledMcpServer[]>;
98
- //# sourceMappingURL=marketplace.d.ts.map
@@ -27,6 +27,8 @@ import { homedir } from 'node:os';
27
27
  import path from 'node:path';
28
28
  import { promisify } from 'node:util';
29
29
  import { parseMcpConfig } from './mcp-config.js';
30
+ import { isOutsideRel } from '../tools/shared.js';
31
+ import { updateJsonFile } from '../config-file.js';
30
32
  const execFileP = promisify(execFile);
31
33
  /** Path to the cache root (caller-controlled so tests can inject a temp dir). */
32
34
  export function defaultCacheRoot() {
@@ -152,10 +154,14 @@ export async function probeRepoForServer(repoPath, subdir) {
152
154
  }
153
155
  /** Side-effect: clone the source into the cache dir. */
154
156
  async function gitClone(url, target) {
155
- await execFileP('git', ['clone', '--depth', '1', '--quiet', url, target], {
157
+ await execFileP('git', gitCloneArgs(url, target), {
156
158
  windowsHide: true,
157
159
  });
158
160
  }
161
+ /** `--` ends git's option parsing: a source that starts with `-` (`--upload-pack=…`) must never be read as an option. */
162
+ export function gitCloneArgs(url, target) {
163
+ return ['clone', '--depth', '1', '--quiet', '--', url, target];
164
+ }
159
165
  /**
160
166
  * Install an MCP server from a catalog entry or a raw GitHub URL.
161
167
  * Returns the {@link InstalledMcpServer} describing what was installed.
@@ -197,7 +203,7 @@ export async function installMcpServer(params) {
197
203
  // consequences of a bypass (arbitrary recursive delete) are severe.
198
204
  const installPath = path.join(cacheRoot, name);
199
205
  const relInstall = path.relative(cacheRoot, installPath);
200
- if (relInstall.startsWith('..') || path.isAbsolute(relInstall)) {
206
+ if (isOutsideRel(relInstall)) {
201
207
  throw new Error(`Refusing to install "${name}": resolved path escapes the cache root.`);
202
208
  }
203
209
  if (existsSync(installPath)) {
@@ -260,8 +266,8 @@ export async function readUserMcpRegistry(userMcpPath) {
260
266
  }
261
267
  /** Write the user's MCP registry, creating parent directories as needed. */
262
268
  export async function writeUserMcpRegistry(userMcpPath, config) {
263
- await mkdir(path.dirname(userMcpPath), { recursive: true });
264
- await writeFile(userMcpPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
269
+ // Atomic, and one writer at a time (see updateJsonFile).
270
+ await updateJsonFile(userMcpPath, () => config);
265
271
  }
266
272
  /** Remove an installed MCP server by name. Idempotent: succeeds even when absent. */
267
273
  export async function uninstallMcpServer(params) {
@@ -319,4 +325,3 @@ export async function listInstalledServers(params) {
319
325
  }
320
326
  return out;
321
327
  }
322
- //# sourceMappingURL=marketplace.js.map
@@ -1,4 +1,5 @@
1
1
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { type McpOAuthOptions } from './oauth.js';
2
3
  import type { McpConfigFile, McpServerSpec } from './mcp-config.js';
3
4
  import type { ToolDefinition } from '../types.js';
4
5
  /**
@@ -9,11 +10,20 @@ export interface ConnectedMcpServer {
9
10
  name: string;
10
11
  client: Client;
11
12
  tools: ToolDefinition[];
13
+ /** What the server says about using it (from `initialize`); shown to the model next to its tools. */
14
+ instructions?: string | undefined;
12
15
  }
13
16
  /** Connect to every server in a parsed MCP config. Failed connections are skipped with a warning. */
14
- export declare function connectAll(config: McpConfigFile): Promise<ConnectedMcpServer[]>;
17
+ export declare function connectAll(config: McpConfigFile, options?: ConnectOptions): Promise<ConnectedMcpServer[]>;
18
+ export { McpAuthRequiredError } from './oauth.js';
19
+ export interface ConnectOptions {
20
+ /** Let an HTTP server that wants OAuth sign-in use saved tokens, and (with `interactive`) ask the user to sign in. */
21
+ oauth?: McpOAuthOptions;
22
+ }
15
23
  /** Connect to a single server and pull its tools. */
16
- export declare function connectOne(name: string, spec: McpServerSpec): Promise<ConnectedMcpServer>;
24
+ export declare function connectOne(name: string, spec: McpServerSpec, options?: ConnectOptions): Promise<ConnectedMcpServer>;
25
+ /** The instructions servers sent with `initialize`, as one prompt block (empty when none sent any). */
26
+ export declare function mcpInstructionsBlock(servers: readonly ConnectedMcpServer[]): string;
17
27
  /** Close all clients and their underlying transports. */
18
28
  export declare function closeAll(servers: ConnectedMcpServer[]): Promise<void>;
19
29
  /**
@@ -24,4 +34,3 @@ export declare function closeAll(servers: ConnectedMcpServer[]): Promise<void>;
24
34
  * single string and keep the structured content for any embedded resources.
25
35
  */
26
36
  export declare function mcpResultToValue(result: unknown): unknown;
27
- //# sourceMappingURL=mcp-client.d.ts.map
@@ -24,12 +24,14 @@
24
24
  import { readFileSync } from 'node:fs';
25
25
  import { dirname, join } from 'node:path';
26
26
  import { fileURLToPath } from 'node:url';
27
+ import { UnauthorizedError } from '@modelcontextprotocol/sdk/client/auth.js';
27
28
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
28
29
  import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
29
30
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
30
31
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
31
32
  import { filterMcpServers, getOrgPolicy } from '../policy/policy.js';
32
33
  import { jsonSchemaToZod } from './json-schema-to-zod.js';
34
+ import { ForgeOAuthProvider, McpAuthRequiredError, defaultMcpAuthDir, readSavedAuth } from './oauth.js';
33
35
  /**
34
36
  * Self-identifying info we send to every MCP server during the `initialize`
35
37
  * handshake. Version is read from our own package.json so it stays in sync
@@ -53,7 +55,7 @@ function readPackageVersion() {
53
55
  }
54
56
  }
55
57
  /** Connect to every server in a parsed MCP config. Failed connections are skipped with a warning. */
56
- export async function connectAll(config) {
58
+ export async function connectAll(config, options = {}) {
57
59
  const { allowed, blocked } = filterMcpServers(config.mcpServers, getOrgPolicy()?.policy);
58
60
  for (const name of blocked) {
59
61
  process.stderr.write(`forge: MCP server "${name}" is blocked by organization policy
@@ -65,10 +67,14 @@ export async function connectAll(config) {
65
67
  if (spec.disabled)
66
68
  continue;
67
69
  try {
68
- const server = await connectOne(name, spec);
70
+ const server = await connectOne(name, spec, options);
69
71
  results.push(server);
70
72
  }
71
73
  catch (err) {
74
+ if (err instanceof McpAuthRequiredError) {
75
+ process.stderr.write(`forge: MCP server "${name}" needs you to sign in. Run: forge mcp login ${name}\n`);
76
+ continue;
77
+ }
72
78
  // Skip failed servers so one bad entry doesn't take down the whole
73
79
  // session; surface the error so the caller can log it.
74
80
  process.stderr.write(`forge: MCP server "${name}" failed to connect: ${err.message}\n`);
@@ -76,21 +82,68 @@ export async function connectAll(config) {
76
82
  }
77
83
  return results;
78
84
  }
85
+ export { McpAuthRequiredError } from './oauth.js';
86
+ /** A 401 from a server we connected to without credentials. */
87
+ function isUnauthorized(err) {
88
+ const e = err;
89
+ return err instanceof UnauthorizedError || e?.code === 401 || (typeof e?.message === 'string' && /\b401\b/.test(e.message));
90
+ }
79
91
  /** Connect to a single server and pull its tools. */
80
- export async function connectOne(name, spec) {
81
- const transport = buildTransport(spec);
82
- const client = new Client(CLIENT_INFO, { capabilities: {} });
83
- await client.connect(transport);
84
- const { tools: mcpTools } = await client.listTools();
85
- const tools = mcpTools.map((t) => mcpToolToForgeTool(name, t, client));
86
- return { name, client, tools };
92
+ export async function connectOne(name, spec, options = {}) {
93
+ const timeout = spec.timeout ? { timeout: spec.timeout } : undefined;
94
+ let client = new Client(CLIENT_INFO, { capabilities: {} });
95
+ const oauth = options.oauth;
96
+ // A static Authorization header is the user's own choice of credentials: leave OAuth out of it.
97
+ const hasStaticAuth = Object.keys(spec.headers ?? {}).some((h) => h.toLowerCase() === 'authorization');
98
+ const wantsOAuth = Boolean(oauth && spec.url && !spec.command && !hasStaticAuth);
99
+ if (!wantsOAuth) {
100
+ await client.connect(buildTransport(spec), timeout);
101
+ }
102
+ else {
103
+ const url = spec.url;
104
+ const haveTokens = Boolean((await readSavedAuth(oauth.storeDir ?? defaultMcpAuthDir(), url))?.tokens);
105
+ let provider;
106
+ if (haveTokens || oauth.interactive) {
107
+ provider = await ForgeOAuthProvider.create(name, url, oauth);
108
+ }
109
+ let transport = buildTransport(spec, provider);
110
+ try {
111
+ await client.connect(transport, timeout);
112
+ }
113
+ catch (err) {
114
+ if (!provider) {
115
+ // Tried without credentials and the server refused: it needs a sign-in the user has not done yet.
116
+ if (isUnauthorized(err))
117
+ throw new McpAuthRequiredError(name);
118
+ throw err;
119
+ }
120
+ if (!(err instanceof UnauthorizedError))
121
+ throw err;
122
+ // The SDK started the sign-in (the browser is open); wait for the user, then connect again with the tokens.
123
+ try {
124
+ const code = await provider.waitForCode();
125
+ await transport.finishAuth(code);
126
+ }
127
+ catch (signInErr) {
128
+ provider.cancel();
129
+ throw signInErr;
130
+ }
131
+ await client.close().catch(() => undefined);
132
+ client = new Client(CLIENT_INFO, { capabilities: {} });
133
+ transport = buildTransport(spec, provider);
134
+ await client.connect(transport, timeout);
135
+ }
136
+ }
137
+ const { tools: mcpTools } = await client.listTools(undefined, spec.timeout ? { timeout: spec.timeout } : undefined);
138
+ const tools = mcpTools.map((t) => mcpToolToForgeTool(name, t, client, spec.timeout));
139
+ return { name, client, tools, instructions: client.getInstructions()?.trim() || undefined };
87
140
  }
88
141
  /**
89
142
  * Pick the right SDK transport for the server spec. The transport type is
90
143
  * either explicit (`type: 'sse'` etc.) or inferred from the shape of the
91
144
  * spec: `command` present ⇒ stdio, `url` present ⇒ SSE.
92
145
  */
93
- function buildTransport(spec) {
146
+ function buildTransport(spec, authProvider) {
94
147
  const explicit = spec.type;
95
148
  const isStdio = explicit === 'stdio' || (!explicit && Boolean(spec.command));
96
149
  const isSse = explicit === 'sse' || (!explicit && Boolean(spec.url) && !explicit);
@@ -118,10 +171,17 @@ function buildTransport(spec) {
118
171
  const headers = spec.headers ?? {};
119
172
  const requestInit = headers ? { headers } : {};
120
173
  if (explicit === 'streamable-http') {
121
- return new StreamableHTTPClientTransport(new URL(spec.url), { requestInit });
174
+ return new StreamableHTTPClientTransport(new URL(spec.url), { requestInit, ...(authProvider ? { authProvider } : {}) });
122
175
  }
123
176
  // Default for HTTP-transport specs: SSE (preserves prior behavior).
124
- return new SSEClientTransport(new URL(spec.url), { requestInit });
177
+ return new SSEClientTransport(new URL(spec.url), { requestInit, ...(authProvider ? { authProvider } : {}) });
178
+ }
179
+ /** The instructions servers sent with `initialize`, as one prompt block (empty when none sent any). */
180
+ export function mcpInstructionsBlock(servers) {
181
+ return servers
182
+ .filter((s) => s.instructions)
183
+ .map((s) => `<mcp-server-instructions server="${s.name.replace(/"/g, '')}">\n${s.instructions}\n</mcp-server-instructions>`)
184
+ .join('\n\n');
125
185
  }
126
186
  /** Close all clients and their underlying transports. */
127
187
  export async function closeAll(servers) {
@@ -133,7 +193,7 @@ export async function closeAll(servers) {
133
193
  * namespace of the built-in tools and tells the model which server a tool
134
194
  * came from at a glance.
135
195
  */
136
- function mcpToolToForgeTool(serverName, mcpTool, client) {
196
+ function mcpToolToForgeTool(serverName, mcpTool, client, timeout) {
137
197
  const fullName = `mcp__${serverName}__${mcpTool.name}`;
138
198
  const description = [
139
199
  mcpTool.description ?? '',
@@ -150,10 +210,7 @@ function mcpToolToForgeTool(serverName, mcpTool, client) {
150
210
  // destructive so the user gets a confirmation prompt unless --auto.
151
211
  destructive: true,
152
212
  execute: async (args) => {
153
- const result = await client.callTool({
154
- name: mcpTool.name,
155
- arguments: args,
156
- });
213
+ const result = await client.callTool({ name: mcpTool.name, arguments: args }, undefined, timeout ? { timeout } : undefined);
157
214
  return mcpResultToValue(result);
158
215
  },
159
216
  };
@@ -185,4 +242,3 @@ export function mcpResultToValue(result) {
185
242
  }
186
243
  return { text, content: r.content, isError: r.isError };
187
244
  }
188
- //# sourceMappingURL=mcp-client.js.map
@@ -45,6 +45,8 @@ export interface McpServerSpec {
45
45
  headers?: Record<string, string>;
46
46
  /** Keep the entry but do not connect it. */
47
47
  disabled?: boolean;
48
+ /** Milliseconds to wait for a connection or a tool call before giving up (default: the SDK's 60 s). */
49
+ timeout?: number;
48
50
  }
49
51
  /**
50
52
  * Load and validate a `forge.mcp.json` file. Throws if the file is missing,
@@ -56,4 +58,3 @@ export declare function loadMcpConfig(configPath: string): Promise<McpConfigFile
56
58
  * that already have the file contents (e.g. embedded configs).
57
59
  */
58
60
  export declare function parseMcpConfig(raw: string, sourcePath?: string): McpConfigFile;
59
- //# sourceMappingURL=mcp-config.d.ts.map
@@ -9,6 +9,7 @@ const serverSchema = z
9
9
  url: z.string().optional(),
10
10
  headers: z.record(z.string(), z.string()).optional(),
11
11
  disabled: z.boolean().optional(),
12
+ timeout: z.number().int().positive().max(3_600_000).optional(),
12
13
  })
13
14
  .refine((s) => Boolean(s.command) || Boolean(s.url), {
14
15
  message: 'Each MCP server must have either `command` (stdio) or `url` (sse/streamable-http).',
@@ -60,4 +61,3 @@ export function parseMcpConfig(raw, sourcePath = '<inline>') {
60
61
  }
61
62
  return result.data;
62
63
  }
63
- //# sourceMappingURL=mcp-config.js.map
@@ -0,0 +1,55 @@
1
+ import type { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
2
+ import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
3
+ export interface McpOAuthOptions {
4
+ /** Defaults to `~/.forge/mcp-auth`. */
5
+ storeDir?: string;
6
+ /** Show the authorization page to the user (their browser). Throw to refuse. */
7
+ openUrl: (url: string) => void | Promise<void>;
8
+ /** True: may open the browser and wait for the user. False: only use tokens already saved. */
9
+ interactive?: boolean;
10
+ /** How long to wait for the user to finish in the browser. Default five minutes. */
11
+ signInTimeoutMs?: number;
12
+ }
13
+ /** The server needs the user to sign in, and this connection was not allowed to ask. */
14
+ export declare class McpAuthRequiredError extends Error {
15
+ readonly server: string;
16
+ constructor(server: string);
17
+ }
18
+ interface SavedAuth {
19
+ url: string;
20
+ port?: number;
21
+ clientInformation?: OAuthClientInformationMixed;
22
+ tokens?: OAuthTokens;
23
+ }
24
+ export declare function defaultMcpAuthDir(): string;
25
+ export declare function readSavedAuth(dir: string, serverUrl: string): Promise<SavedAuth | undefined>;
26
+ export declare function forgetSavedAuth(dir: string, serverUrl: string): Promise<void>;
27
+ export declare class ForgeOAuthProvider implements OAuthClientProvider {
28
+ readonly serverName: string;
29
+ private readonly serverUrl;
30
+ private readonly dir;
31
+ private readonly port;
32
+ private readonly options;
33
+ private verifier;
34
+ private expectedState;
35
+ private receiver;
36
+ private constructor();
37
+ static create(serverName: string, serverUrl: string, options: McpOAuthOptions): Promise<ForgeOAuthProvider>;
38
+ get redirectUrl(): string;
39
+ get clientMetadata(): OAuthClientMetadata;
40
+ state(): string;
41
+ private saved;
42
+ clientInformation(): Promise<OAuthClientInformationMixed | undefined>;
43
+ saveClientInformation(info: OAuthClientInformationMixed): Promise<void>;
44
+ tokens(): Promise<OAuthTokens | undefined>;
45
+ saveTokens(tokens: OAuthTokens): Promise<void>;
46
+ saveCodeVerifier(v: string): void;
47
+ codeVerifier(): string;
48
+ invalidateCredentials(scope: 'all' | 'client' | 'tokens' | 'verifier' | 'discovery'): Promise<void>;
49
+ /** Called by the SDK once it has the authorization URL. Without `interactive` this is where the connection stops. */
50
+ redirectToAuthorization(url: URL): Promise<void>;
51
+ /** After the SDK reported the sign-in as started: the code the browser brings back. */
52
+ waitForCode(): Promise<string>;
53
+ cancel(): void;
54
+ }
55
+ export {};
@@ -0,0 +1,197 @@
1
+ /**
2
+ * OAuth sign-in for MCP servers behind it (authorization code with PKCE, dynamic client registration).
3
+ * The SDK does the protocol; this file supplies what it leaves to the application: where tokens are kept,
4
+ * where the browser returns to (a one-shot page on 127.0.0.1), and a state value that must come back unchanged.
5
+ *
6
+ * Tokens live in `~/.forge/mcp-auth/<server>.json`, readable by the user only, one file per server URL.
7
+ * Signing in is always the user's act: a server that needs it is reported as such, and the browser opens only
8
+ * when `interactive` is set. A URL that is not http or https is never opened.
9
+ */
10
+ import { randomBytes, createHash } from 'node:crypto';
11
+ import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
12
+ import http from 'node:http';
13
+ import { homedir } from 'node:os';
14
+ import path from 'node:path';
15
+ /** The server needs the user to sign in, and this connection was not allowed to ask. */
16
+ export class McpAuthRequiredError extends Error {
17
+ server;
18
+ constructor(server) {
19
+ super(`MCP server "${server}" needs you to sign in`);
20
+ this.server = server;
21
+ this.name = 'McpAuthRequiredError';
22
+ }
23
+ }
24
+ export function defaultMcpAuthDir() {
25
+ return path.join(homedir(), '.forge', 'mcp-auth');
26
+ }
27
+ function fileFor(dir, serverUrl) {
28
+ return path.join(dir, `${createHash('sha256').update(serverUrl).digest('hex').slice(0, 32)}.json`);
29
+ }
30
+ export async function readSavedAuth(dir, serverUrl) {
31
+ try {
32
+ return JSON.parse(await readFile(fileFor(dir, serverUrl), 'utf8'));
33
+ }
34
+ catch {
35
+ return undefined;
36
+ }
37
+ }
38
+ async function writeSavedAuth(dir, auth) {
39
+ await mkdir(dir, { recursive: true, mode: 0o700 });
40
+ await writeFile(fileFor(dir, auth.url), JSON.stringify(auth, null, 2), { encoding: 'utf8', mode: 0o600 });
41
+ }
42
+ export async function forgetSavedAuth(dir, serverUrl) {
43
+ await rm(fileFor(dir, serverUrl), { force: true });
44
+ }
45
+ /** A port on 127.0.0.1: the one used last time if it is free (so a registered redirect URL keeps working), else any. */
46
+ async function freePort(preferred) {
47
+ const tryListen = (port) => new Promise((resolve) => {
48
+ const s = http.createServer();
49
+ s.once('error', () => resolve(undefined));
50
+ s.listen(port, '127.0.0.1', () => {
51
+ const got = s.address().port;
52
+ s.close(() => resolve(got));
53
+ });
54
+ });
55
+ return (preferred ? await tryListen(preferred) : undefined) ?? (await tryListen(0)) ?? 0;
56
+ }
57
+ /** A one-shot page the browser returns to. Resolves with the code; a wrong `state` is ignored, an `error` rejects. */
58
+ async function receiveCode(port, expectedState, timeoutMs) {
59
+ let resolveCode;
60
+ let rejectCode;
61
+ const code = new Promise((resolve, reject) => {
62
+ resolveCode = resolve;
63
+ rejectCode = reject;
64
+ });
65
+ const page = (title) => `<!doctype html><meta charset="utf-8"><title>${title}</title><body style="font-family:sans-serif;margin:3em"><h2>${title}</h2><p>You can close this tab and go back to your editor.</p>`;
66
+ const server = http.createServer((req, res) => {
67
+ const url = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);
68
+ if (url.pathname !== '/callback') {
69
+ res.writeHead(404).end();
70
+ return;
71
+ }
72
+ if (url.searchParams.get('state') !== expectedState) {
73
+ res.writeHead(400, { 'content-type': 'text/html' }).end(page('This sign-in link is not for this session'));
74
+ return;
75
+ }
76
+ const error = url.searchParams.get('error');
77
+ const got = url.searchParams.get('code');
78
+ if (error || !got) {
79
+ res.writeHead(400, { 'content-type': 'text/html' }).end(page('Sign-in was not completed'));
80
+ rejectCode(new Error(`sign-in failed: ${error ?? 'no code returned'}`));
81
+ return;
82
+ }
83
+ res.writeHead(200, { 'content-type': 'text/html' }).end(page('Signed in to Forge'));
84
+ resolveCode(got);
85
+ });
86
+ await new Promise((resolve, reject) => {
87
+ server.once('error', reject);
88
+ server.listen(port, '127.0.0.1', resolve);
89
+ });
90
+ const timer = setTimeout(() => rejectCode(new Error('sign-in timed out')), timeoutMs);
91
+ const close = () => {
92
+ clearTimeout(timer);
93
+ server.closeAllConnections();
94
+ server.close();
95
+ };
96
+ code.then(close, close);
97
+ return { code, close };
98
+ }
99
+ export class ForgeOAuthProvider {
100
+ serverName;
101
+ serverUrl;
102
+ dir;
103
+ port;
104
+ options;
105
+ verifier = '';
106
+ expectedState = '';
107
+ receiver;
108
+ constructor(serverName, serverUrl, dir, port, options) {
109
+ this.serverName = serverName;
110
+ this.serverUrl = serverUrl;
111
+ this.dir = dir;
112
+ this.port = port;
113
+ this.options = options;
114
+ }
115
+ static async create(serverName, serverUrl, options) {
116
+ const dir = options.storeDir ?? defaultMcpAuthDir();
117
+ const saved = await readSavedAuth(dir, serverUrl);
118
+ const port = await freePort(saved?.port);
119
+ await writeSavedAuth(dir, { ...(saved ?? { url: serverUrl }), url: serverUrl, port });
120
+ return new ForgeOAuthProvider(serverName, serverUrl, dir, port, options);
121
+ }
122
+ get redirectUrl() {
123
+ return `http://127.0.0.1:${this.port}/callback`;
124
+ }
125
+ get clientMetadata() {
126
+ return {
127
+ client_name: 'Ikarmic Forge',
128
+ redirect_uris: [this.redirectUrl],
129
+ grant_types: ['authorization_code', 'refresh_token'],
130
+ response_types: ['code'],
131
+ token_endpoint_auth_method: 'none',
132
+ };
133
+ }
134
+ state() {
135
+ this.expectedState = randomBytes(16).toString('hex');
136
+ return this.expectedState;
137
+ }
138
+ async saved() {
139
+ return (await readSavedAuth(this.dir, this.serverUrl)) ?? { url: this.serverUrl };
140
+ }
141
+ async clientInformation() {
142
+ const info = (await this.saved()).clientInformation;
143
+ // A registration made for another redirect URL cannot be used here: register again.
144
+ if (info?.redirect_uris && !info.redirect_uris.includes(this.redirectUrl))
145
+ return undefined;
146
+ return info;
147
+ }
148
+ async saveClientInformation(info) {
149
+ await writeSavedAuth(this.dir, { ...(await this.saved()), clientInformation: info });
150
+ }
151
+ async tokens() {
152
+ return (await this.saved()).tokens;
153
+ }
154
+ async saveTokens(tokens) {
155
+ await writeSavedAuth(this.dir, { ...(await this.saved()), tokens });
156
+ }
157
+ saveCodeVerifier(v) {
158
+ this.verifier = v;
159
+ }
160
+ codeVerifier() {
161
+ return this.verifier;
162
+ }
163
+ async invalidateCredentials(scope) {
164
+ const s = await this.saved();
165
+ if (scope === 'all' || scope === 'tokens')
166
+ delete s.tokens;
167
+ if (scope === 'all' || scope === 'client')
168
+ delete s.clientInformation;
169
+ await writeSavedAuth(this.dir, s);
170
+ }
171
+ /** Called by the SDK once it has the authorization URL. Without `interactive` this is where the connection stops. */
172
+ async redirectToAuthorization(url) {
173
+ if (!this.options.interactive)
174
+ throw new McpAuthRequiredError(this.serverName);
175
+ if (url.protocol !== 'https:' && url.protocol !== 'http:') {
176
+ throw new Error(`MCP server "${this.serverName}" gave a sign-in address that is not a web page (${url.protocol}); refused`);
177
+ }
178
+ this.receiver?.close();
179
+ this.receiver = await receiveCode(this.port, this.expectedState, this.options.signInTimeoutMs ?? 5 * 60_000);
180
+ await this.options.openUrl(url.href);
181
+ }
182
+ /** After the SDK reported the sign-in as started: the code the browser brings back. */
183
+ async waitForCode() {
184
+ if (!this.receiver)
185
+ throw new Error('no sign-in is waiting');
186
+ try {
187
+ return await this.receiver.code;
188
+ }
189
+ finally {
190
+ this.receiver = undefined;
191
+ }
192
+ }
193
+ cancel() {
194
+ this.receiver?.close();
195
+ this.receiver = undefined;
196
+ }
197
+ }