@machina.ai/cell-cli-core 1.0.13-rc9 → 1.0.21-rc1

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 (484) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.js +3 -0
  3. package/dist/index.js.map +1 -1
  4. package/dist/package.json +12 -4
  5. package/dist/src/code_assist/converter.d.ts +6 -3
  6. package/dist/src/code_assist/converter.js +4 -2
  7. package/dist/src/code_assist/converter.js.map +1 -1
  8. package/dist/src/code_assist/converter.test.js +61 -11
  9. package/dist/src/code_assist/converter.test.js.map +1 -1
  10. package/dist/src/code_assist/oauth2.d.ts +1 -0
  11. package/dist/src/code_assist/oauth2.js +43 -18
  12. package/dist/src/code_assist/oauth2.js.map +1 -1
  13. package/dist/src/code_assist/oauth2.test.js +142 -9
  14. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  15. package/dist/src/code_assist/server.d.ts +2 -2
  16. package/dist/src/code_assist/server.js +5 -5
  17. package/dist/src/code_assist/server.js.map +1 -1
  18. package/dist/src/code_assist/server.test.js +13 -10
  19. package/dist/src/code_assist/server.test.js.map +1 -1
  20. package/dist/src/code_assist/setup.js +49 -18
  21. package/dist/src/code_assist/setup.js.map +1 -1
  22. package/dist/src/code_assist/setup.test.js +115 -9
  23. package/dist/src/code_assist/setup.test.js.map +1 -1
  24. package/dist/src/config/config.d.ts +71 -13
  25. package/dist/src/config/config.js +154 -41
  26. package/dist/src/config/config.js.map +1 -1
  27. package/dist/src/config/config.test.js +206 -21
  28. package/dist/src/config/config.test.js.map +1 -1
  29. package/dist/src/config/flashFallback.test.js +19 -47
  30. package/dist/src/config/flashFallback.test.js.map +1 -1
  31. package/dist/src/config/models.d.ts +1 -0
  32. package/dist/src/config/models.js +1 -0
  33. package/dist/src/config/models.js.map +1 -1
  34. package/dist/src/core/client.d.ts +15 -16
  35. package/dist/src/core/client.js +247 -104
  36. package/dist/src/core/client.js.map +1 -1
  37. package/dist/src/core/client.test.js +798 -49
  38. package/dist/src/core/client.test.js.map +1 -1
  39. package/dist/src/core/contentGenerator.d.ts +2 -2
  40. package/dist/src/core/contentGenerator.js +23 -21
  41. package/dist/src/core/contentGenerator.js.map +1 -1
  42. package/dist/src/core/contentGenerator.test.js +30 -126
  43. package/dist/src/core/contentGenerator.test.js.map +1 -1
  44. package/dist/src/core/coreToolScheduler.d.ts +23 -10
  45. package/dist/src/core/coreToolScheduler.js +201 -77
  46. package/dist/src/core/coreToolScheduler.js.map +1 -1
  47. package/dist/src/core/coreToolScheduler.test.js +322 -94
  48. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  49. package/dist/src/core/geminiChat.d.ts +8 -6
  50. package/dist/src/core/geminiChat.js +49 -51
  51. package/dist/src/core/geminiChat.js.map +1 -1
  52. package/dist/src/core/geminiChat.test.js +2 -2
  53. package/dist/src/core/geminiChat.test.js.map +1 -1
  54. package/dist/src/core/geminiRequest.js +2 -37
  55. package/dist/src/core/geminiRequest.js.map +1 -1
  56. package/dist/src/core/logger.d.ts +24 -1
  57. package/dist/src/core/logger.js +128 -4
  58. package/dist/src/core/logger.js.map +1 -1
  59. package/dist/src/core/logger.test.js +157 -11
  60. package/dist/src/core/logger.test.js.map +1 -1
  61. package/dist/src/core/loggingContentGenerator.d.ts +25 -0
  62. package/dist/src/core/loggingContentGenerator.js +95 -0
  63. package/dist/src/core/loggingContentGenerator.js.map +1 -0
  64. package/dist/src/core/nonInteractiveToolExecutor.js +39 -4
  65. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  66. package/dist/src/core/nonInteractiveToolExecutor.test.js +85 -62
  67. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  68. package/dist/src/core/prompts.js +43 -19
  69. package/dist/src/core/prompts.js.map +1 -1
  70. package/dist/src/core/prompts.test.js +118 -1
  71. package/dist/src/core/prompts.test.js.map +1 -1
  72. package/dist/src/core/subagent.d.ts +230 -0
  73. package/dist/src/core/subagent.js +447 -0
  74. package/dist/src/core/subagent.js.map +1 -0
  75. package/dist/src/core/subagent.test.js +515 -0
  76. package/dist/src/core/subagent.test.js.map +1 -0
  77. package/dist/src/core/tokenLimits.js +1 -0
  78. package/dist/src/core/tokenLimits.js.map +1 -1
  79. package/dist/src/core/turn.d.ts +3 -0
  80. package/dist/src/core/turn.js +4 -0
  81. package/dist/src/core/turn.js.map +1 -1
  82. package/dist/src/core/turn.test.js +4 -0
  83. package/dist/src/core/turn.test.js.map +1 -1
  84. package/dist/src/generated/git-commit.d.ts +7 -0
  85. package/dist/src/generated/git-commit.js +10 -0
  86. package/dist/src/generated/git-commit.js.map +1 -0
  87. package/dist/src/ide/constants.d.ts +6 -0
  88. package/dist/src/ide/constants.js +7 -0
  89. package/dist/src/ide/constants.js.map +1 -0
  90. package/dist/src/ide/detect-ide.d.ts +20 -0
  91. package/dist/src/ide/detect-ide.js +86 -0
  92. package/dist/src/ide/detect-ide.js.map +1 -0
  93. package/dist/src/ide/detect-ide.test.js +65 -0
  94. package/dist/src/ide/detect-ide.test.js.map +1 -0
  95. package/dist/src/ide/ide-client.d.ts +63 -0
  96. package/dist/src/ide/ide-client.js +320 -0
  97. package/dist/src/ide/ide-client.js.map +1 -0
  98. package/dist/src/ide/ide-client.test.d.ts +6 -0
  99. package/dist/src/ide/ide-client.test.js +43 -0
  100. package/dist/src/ide/ide-client.test.js.map +1 -0
  101. package/dist/src/ide/ide-installer.d.ts +14 -0
  102. package/dist/src/ide/ide-installer.js +98 -0
  103. package/dist/src/ide/ide-installer.js.map +1 -0
  104. package/dist/src/ide/ide-installer.test.d.ts +6 -0
  105. package/dist/src/ide/ide-installer.test.js +53 -0
  106. package/dist/src/ide/ide-installer.test.js.map +1 -0
  107. package/dist/src/ide/ideContext.d.ts +374 -0
  108. package/dist/src/ide/ideContext.js +147 -0
  109. package/dist/src/ide/ideContext.js.map +1 -0
  110. package/dist/src/ide/ideContext.test.d.ts +6 -0
  111. package/dist/src/ide/ideContext.test.js +265 -0
  112. package/dist/src/ide/ideContext.test.js.map +1 -0
  113. package/dist/src/ide/process-utils.d.ts +14 -0
  114. package/dist/src/ide/process-utils.js +57 -0
  115. package/dist/src/ide/process-utils.js.map +1 -0
  116. package/dist/src/index.d.ts +17 -1
  117. package/dist/src/index.js +20 -1
  118. package/dist/src/index.js.map +1 -1
  119. package/dist/src/mcp/google-auth-provider.d.ts +23 -0
  120. package/dist/src/mcp/google-auth-provider.js +72 -0
  121. package/dist/src/mcp/google-auth-provider.js.map +1 -0
  122. package/dist/src/mcp/google-auth-provider.test.d.ts +6 -0
  123. package/dist/src/mcp/google-auth-provider.test.js +89 -0
  124. package/dist/src/mcp/google-auth-provider.test.js.map +1 -0
  125. package/dist/src/mcp/oauth-provider.d.ts +6 -2
  126. package/dist/src/mcp/oauth-provider.js +208 -53
  127. package/dist/src/mcp/oauth-provider.js.map +1 -1
  128. package/dist/src/mcp/oauth-provider.test.js +222 -70
  129. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  130. package/dist/src/mcp/oauth-token-storage.d.ts +3 -1
  131. package/dist/src/mcp/oauth-token-storage.js +3 -1
  132. package/dist/src/mcp/oauth-token-storage.js.map +1 -1
  133. package/dist/src/mcp/oauth-utils.d.ts +3 -1
  134. package/dist/src/mcp/oauth-utils.js +52 -14
  135. package/dist/src/mcp/oauth-utils.js.map +1 -1
  136. package/dist/src/mcp/oauth-utils.test.js +18 -3
  137. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  138. package/dist/src/mocks/msw.d.ts +6 -0
  139. package/dist/src/mocks/msw.js +8 -0
  140. package/dist/src/mocks/msw.js.map +1 -0
  141. package/dist/src/prompts/mcp-prompts.d.ts +8 -0
  142. package/dist/src/prompts/mcp-prompts.js +13 -0
  143. package/dist/src/prompts/mcp-prompts.js.map +1 -0
  144. package/dist/src/prompts/prompt-registry.d.ts +34 -0
  145. package/dist/src/prompts/prompt-registry.js +63 -0
  146. package/dist/src/prompts/prompt-registry.js.map +1 -0
  147. package/dist/src/services/chatRecordingService.d.ts +150 -0
  148. package/dist/src/services/chatRecordingService.js +318 -0
  149. package/dist/src/services/chatRecordingService.js.map +1 -0
  150. package/dist/src/services/chatRecordingService.test.d.ts +6 -0
  151. package/dist/src/services/chatRecordingService.test.js +288 -0
  152. package/dist/src/services/chatRecordingService.test.js.map +1 -0
  153. package/dist/src/services/fileDiscoveryService.test.js +101 -60
  154. package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
  155. package/dist/src/services/fileSystemService.d.ts +31 -0
  156. package/dist/src/services/fileSystemService.js +18 -0
  157. package/dist/src/services/fileSystemService.js.map +1 -0
  158. package/dist/src/services/fileSystemService.test.d.ts +6 -0
  159. package/dist/src/services/fileSystemService.test.js +41 -0
  160. package/dist/src/services/fileSystemService.test.js.map +1 -0
  161. package/dist/src/services/gitService.test.js +67 -86
  162. package/dist/src/services/gitService.test.js.map +1 -1
  163. package/dist/src/services/loopDetectionService.d.ts +51 -5
  164. package/dist/src/services/loopDetectionService.js +152 -45
  165. package/dist/src/services/loopDetectionService.js.map +1 -1
  166. package/dist/src/services/loopDetectionService.test.js +286 -89
  167. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  168. package/dist/src/services/shellExecutionService.d.ts +70 -0
  169. package/dist/src/services/shellExecutionService.js +175 -0
  170. package/dist/src/services/shellExecutionService.js.map +1 -0
  171. package/dist/src/services/shellExecutionService.test.d.ts +6 -0
  172. package/dist/src/services/shellExecutionService.test.js +282 -0
  173. package/dist/src/services/shellExecutionService.test.js.map +1 -0
  174. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +81 -9
  175. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +356 -182
  176. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  177. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +17 -0
  178. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +342 -0
  179. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -0
  180. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +19 -2
  181. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +51 -9
  182. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  183. package/dist/src/telemetry/constants.d.ts +4 -0
  184. package/dist/src/telemetry/constants.js +4 -0
  185. package/dist/src/telemetry/constants.js.map +1 -1
  186. package/dist/src/telemetry/file-exporters.d.ts +28 -0
  187. package/dist/src/telemetry/file-exporters.js +62 -0
  188. package/dist/src/telemetry/file-exporters.js.map +1 -0
  189. package/dist/src/telemetry/index.d.ts +2 -2
  190. package/dist/src/telemetry/index.js +2 -2
  191. package/dist/src/telemetry/index.js.map +1 -1
  192. package/dist/src/telemetry/integration.test.circular.js +1 -0
  193. package/dist/src/telemetry/integration.test.circular.js.map +1 -1
  194. package/dist/src/telemetry/loggers.d.ts +6 -1
  195. package/dist/src/telemetry/loggers.js +87 -6
  196. package/dist/src/telemetry/loggers.js.map +1 -1
  197. package/dist/src/telemetry/loggers.test.circular.js +9 -2
  198. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  199. package/dist/src/telemetry/loggers.test.js +51 -11
  200. package/dist/src/telemetry/loggers.test.js.map +1 -1
  201. package/dist/src/telemetry/metrics.d.ts +7 -2
  202. package/dist/src/telemetry/metrics.js +26 -6
  203. package/dist/src/telemetry/metrics.js.map +1 -1
  204. package/dist/src/telemetry/metrics.test.js +81 -1
  205. package/dist/src/telemetry/metrics.test.js.map +1 -1
  206. package/dist/src/telemetry/sdk.d.ts +1 -1
  207. package/dist/src/telemetry/sdk.js +77 -30
  208. package/dist/src/telemetry/sdk.js.map +1 -1
  209. package/dist/src/telemetry/sdk.test.d.ts +6 -0
  210. package/dist/src/telemetry/sdk.test.js +82 -0
  211. package/dist/src/telemetry/sdk.test.js.map +1 -0
  212. package/dist/src/telemetry/telemetry.test.js +2 -2
  213. package/dist/src/telemetry/telemetry.test.js.map +1 -1
  214. package/dist/src/telemetry/tool-call-decision.d.ts +13 -0
  215. package/dist/src/telemetry/tool-call-decision.js +29 -0
  216. package/dist/src/telemetry/tool-call-decision.js.map +1 -0
  217. package/dist/src/telemetry/types.d.ts +74 -18
  218. package/dist/src/telemetry/types.js +110 -32
  219. package/dist/src/telemetry/types.js.map +1 -1
  220. package/dist/src/telemetry/uiTelemetry.d.ts +8 -1
  221. package/dist/src/telemetry/uiTelemetry.js +17 -2
  222. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  223. package/dist/src/telemetry/uiTelemetry.test.js +60 -10
  224. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  225. package/dist/src/test-utils/config.d.ts +16 -0
  226. package/dist/src/test-utils/config.js +32 -0
  227. package/dist/src/test-utils/config.js.map +1 -0
  228. package/dist/src/test-utils/mockWorkspaceContext.d.ts +13 -0
  229. package/dist/src/test-utils/mockWorkspaceContext.js +24 -0
  230. package/dist/src/test-utils/mockWorkspaceContext.js.map +1 -0
  231. package/dist/src/test-utils/tools.d.ts +44 -0
  232. package/dist/src/test-utils/tools.js +105 -0
  233. package/dist/src/test-utils/tools.js.map +1 -0
  234. package/dist/src/tools/diffOptions.d.ts +2 -0
  235. package/dist/src/tools/diffOptions.js +28 -0
  236. package/dist/src/tools/diffOptions.js.map +1 -1
  237. package/dist/src/tools/diffOptions.test.d.ts +6 -0
  238. package/dist/src/tools/diffOptions.test.js +119 -0
  239. package/dist/src/tools/diffOptions.test.js.map +1 -0
  240. package/dist/src/tools/edit.d.ts +10 -34
  241. package/dist/src/tools/edit.js +171 -131
  242. package/dist/src/tools/edit.js.map +1 -1
  243. package/dist/src/tools/edit.test.js +220 -43
  244. package/dist/src/tools/edit.test.js.map +1 -1
  245. package/dist/src/tools/glob.d.ts +4 -11
  246. package/dist/src/tools/glob.js +129 -97
  247. package/dist/src/tools/glob.js.map +1 -1
  248. package/dist/src/tools/glob.test.js +73 -17
  249. package/dist/src/tools/glob.test.js.map +1 -1
  250. package/dist/src/tools/grep.d.ts +5 -37
  251. package/dist/src/tools/grep.js +175 -100
  252. package/dist/src/tools/grep.js.map +1 -1
  253. package/dist/src/tools/grep.test.js +112 -28
  254. package/dist/src/tools/grep.test.js.map +1 -1
  255. package/dist/src/tools/ls.d.ts +4 -23
  256. package/dist/src/tools/ls.js +77 -78
  257. package/dist/src/tools/ls.js.map +1 -1
  258. package/dist/src/tools/ls.test.d.ts +6 -0
  259. package/dist/src/tools/ls.test.js +384 -0
  260. package/dist/src/tools/ls.test.js.map +1 -0
  261. package/dist/src/tools/mcp-client-manager.d.ts +38 -0
  262. package/dist/src/tools/mcp-client-manager.js +74 -0
  263. package/dist/src/tools/mcp-client-manager.js.map +1 -0
  264. package/dist/src/tools/mcp-client-manager.test.d.ts +6 -0
  265. package/dist/src/tools/mcp-client-manager.test.js +39 -0
  266. package/dist/src/tools/mcp-client-manager.test.js.map +1 -0
  267. package/dist/src/tools/mcp-client.d.ts +86 -4
  268. package/dist/src/tools/mcp-client.js +730 -59
  269. package/dist/src/tools/mcp-client.js.map +1 -1
  270. package/dist/src/tools/mcp-client.test.js +295 -22
  271. package/dist/src/tools/mcp-client.test.js.map +1 -1
  272. package/dist/src/tools/mcp-tool.d.ts +6 -13
  273. package/dist/src/tools/mcp-tool.js +163 -76
  274. package/dist/src/tools/mcp-tool.js.map +1 -1
  275. package/dist/src/tools/mcp-tool.test.js +400 -29
  276. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  277. package/dist/src/tools/memoryTool.d.ts +14 -3
  278. package/dist/src/tools/memoryTool.js +159 -40
  279. package/dist/src/tools/memoryTool.js.map +1 -1
  280. package/dist/src/tools/memoryTool.test.js +116 -11
  281. package/dist/src/tools/memoryTool.test.js.map +1 -1
  282. package/dist/src/tools/modifiable-tool.d.ts +9 -6
  283. package/dist/src/tools/modifiable-tool.js +6 -3
  284. package/dist/src/tools/modifiable-tool.js.map +1 -1
  285. package/dist/src/tools/modifiable-tool.test.js +63 -74
  286. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  287. package/dist/src/tools/read-file.d.ts +4 -6
  288. package/dist/src/tools/read-file.js +100 -53
  289. package/dist/src/tools/read-file.js.map +1 -1
  290. package/dist/src/tools/read-file.test.js +238 -111
  291. package/dist/src/tools/read-file.test.js.map +1 -1
  292. package/dist/src/tools/read-many-files.d.ts +3 -6
  293. package/dist/src/tools/read-many-files.js +232 -157
  294. package/dist/src/tools/read-many-files.js.map +1 -1
  295. package/dist/src/tools/read-many-files.test.js +231 -34
  296. package/dist/src/tools/read-many-files.test.js.map +1 -1
  297. package/dist/src/tools/shell.d.ts +6 -28
  298. package/dist/src/tools/shell.js +249 -366
  299. package/dist/src/tools/shell.js.map +1 -1
  300. package/dist/src/tools/shell.test.js +305 -384
  301. package/dist/src/tools/shell.test.js.map +1 -1
  302. package/dist/src/tools/tool-error.d.ts +27 -0
  303. package/dist/src/tools/tool-error.js +32 -0
  304. package/dist/src/tools/tool-error.js.map +1 -0
  305. package/dist/src/tools/tool-registry.d.ts +38 -23
  306. package/dist/src/tools/tool-registry.js +127 -99
  307. package/dist/src/tools/tool-registry.js.map +1 -1
  308. package/dist/src/tools/tool-registry.test.js +37 -212
  309. package/dist/src/tools/tool-registry.test.js.map +1 -1
  310. package/dist/src/tools/tools.d.ts +145 -92
  311. package/dist/src/tools/tools.js +188 -61
  312. package/dist/src/tools/tools.js.map +1 -1
  313. package/dist/src/tools/tools.test.d.ts +6 -0
  314. package/dist/src/tools/tools.test.js +206 -0
  315. package/dist/src/tools/tools.test.js.map +1 -0
  316. package/dist/src/tools/web-fetch.d.ts +4 -7
  317. package/dist/src/tools/web-fetch.js +58 -64
  318. package/dist/src/tools/web-fetch.js.map +1 -1
  319. package/dist/src/tools/web-fetch.test.js +8 -4
  320. package/dist/src/tools/web-fetch.test.js.map +1 -1
  321. package/dist/src/tools/web-search.d.ts +4 -5
  322. package/dist/src/tools/web-search.js +47 -51
  323. package/dist/src/tools/web-search.js.map +1 -1
  324. package/dist/src/tools/web-search.test.d.ts +6 -0
  325. package/dist/src/tools/web-search.test.js +139 -0
  326. package/dist/src/tools/web-search.test.js.map +1 -0
  327. package/dist/src/tools/write-file.d.ts +20 -11
  328. package/dist/src/tools/write-file.js +198 -141
  329. package/dist/src/tools/write-file.js.map +1 -1
  330. package/dist/src/tools/write-file.test.js +190 -76
  331. package/dist/src/tools/write-file.test.js.map +1 -1
  332. package/dist/src/utils/bfsFileSearch.js +51 -27
  333. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  334. package/dist/src/utils/bfsFileSearch.test.js +137 -136
  335. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  336. package/dist/src/utils/browser.js +4 -3
  337. package/dist/src/utils/browser.js.map +1 -1
  338. package/dist/src/utils/editCorrector.js +23 -24
  339. package/dist/src/utils/editCorrector.js.map +1 -1
  340. package/dist/src/utils/editor.d.ts +2 -2
  341. package/dist/src/utils/editor.js +23 -6
  342. package/dist/src/utils/editor.js.map +1 -1
  343. package/dist/src/utils/editor.test.js +67 -15
  344. package/dist/src/utils/editor.test.js.map +1 -1
  345. package/dist/src/utils/environmentContext.d.ts +21 -0
  346. package/dist/src/utils/environmentContext.js +90 -0
  347. package/dist/src/utils/environmentContext.js.map +1 -0
  348. package/dist/src/utils/environmentContext.test.d.ts +6 -0
  349. package/dist/src/utils/environmentContext.test.js +140 -0
  350. package/dist/src/utils/environmentContext.test.js.map +1 -0
  351. package/dist/src/utils/errorParsing.d.ts +8 -0
  352. package/dist/src/utils/errorParsing.js +93 -0
  353. package/dist/src/utils/errorParsing.js.map +1 -0
  354. package/dist/src/utils/errorParsing.test.d.ts +6 -0
  355. package/dist/src/utils/errorParsing.test.js +172 -0
  356. package/dist/src/utils/errorParsing.test.js.map +1 -0
  357. package/dist/src/utils/errorReporting.d.ts +1 -1
  358. package/dist/src/utils/errorReporting.js +2 -2
  359. package/dist/src/utils/errorReporting.js.map +1 -1
  360. package/dist/src/utils/errorReporting.test.js +44 -38
  361. package/dist/src/utils/errorReporting.test.js.map +1 -1
  362. package/dist/src/utils/fileUtils.d.ts +9 -1
  363. package/dist/src/utils/fileUtils.js +27 -13
  364. package/dist/src/utils/fileUtils.js.map +1 -1
  365. package/dist/src/utils/fileUtils.test.js +61 -18
  366. package/dist/src/utils/fileUtils.test.js.map +1 -1
  367. package/dist/src/utils/filesearch/crawlCache.d.ts +25 -0
  368. package/dist/src/utils/filesearch/crawlCache.js +57 -0
  369. package/dist/src/utils/filesearch/crawlCache.js.map +1 -0
  370. package/dist/src/utils/filesearch/crawlCache.test.d.ts +6 -0
  371. package/dist/src/utils/filesearch/crawlCache.test.js +103 -0
  372. package/dist/src/utils/filesearch/crawlCache.test.js.map +1 -0
  373. package/dist/src/utils/filesearch/crawler.d.ts +15 -0
  374. package/dist/src/utils/filesearch/crawler.js +50 -0
  375. package/dist/src/utils/filesearch/crawler.js.map +1 -0
  376. package/dist/src/utils/filesearch/crawler.test.d.ts +6 -0
  377. package/dist/src/utils/filesearch/crawler.test.js +468 -0
  378. package/dist/src/utils/filesearch/crawler.test.js.map +1 -0
  379. package/dist/src/utils/filesearch/fileSearch.d.ts +37 -0
  380. package/dist/src/utils/filesearch/fileSearch.js +186 -0
  381. package/dist/src/utils/filesearch/fileSearch.js.map +1 -0
  382. package/dist/src/utils/filesearch/fileSearch.test.d.ts +6 -0
  383. package/dist/src/utils/filesearch/fileSearch.test.js +552 -0
  384. package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -0
  385. package/dist/src/utils/filesearch/ignore.d.ts +42 -0
  386. package/dist/src/utils/filesearch/ignore.js +106 -0
  387. package/dist/src/utils/filesearch/ignore.js.map +1 -0
  388. package/dist/src/utils/filesearch/ignore.test.d.ts +6 -0
  389. package/dist/src/utils/filesearch/ignore.test.js +144 -0
  390. package/dist/src/utils/filesearch/ignore.test.js.map +1 -0
  391. package/dist/src/utils/filesearch/result-cache.d.ts +33 -0
  392. package/dist/src/utils/filesearch/result-cache.js +59 -0
  393. package/dist/src/utils/filesearch/result-cache.js.map +1 -0
  394. package/dist/src/utils/filesearch/result-cache.test.d.ts +6 -0
  395. package/dist/src/utils/filesearch/result-cache.test.js +46 -0
  396. package/dist/src/utils/filesearch/result-cache.test.js.map +1 -0
  397. package/dist/src/utils/flashFallback.integration.test.js +6 -0
  398. package/dist/src/utils/flashFallback.integration.test.js.map +1 -1
  399. package/dist/src/utils/formatters.d.ts +6 -0
  400. package/dist/src/utils/formatters.js +16 -0
  401. package/dist/src/utils/formatters.js.map +1 -0
  402. package/dist/src/utils/getFolderStructure.test.js +11 -13
  403. package/dist/src/utils/getFolderStructure.test.js.map +1 -1
  404. package/dist/src/utils/gitIgnoreParser.js +5 -11
  405. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  406. package/dist/src/utils/gitIgnoreParser.test.js +58 -61
  407. package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
  408. package/dist/src/utils/memoryDiscovery.d.ts +1 -1
  409. package/dist/src/utils/memoryDiscovery.js +76 -83
  410. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  411. package/dist/src/utils/memoryDiscovery.test.js +122 -372
  412. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  413. package/dist/src/utils/memoryImportProcessor.d.ts +19 -12
  414. package/dist/src/utils/memoryImportProcessor.js +240 -85
  415. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  416. package/dist/src/utils/memoryImportProcessor.test.js +593 -51
  417. package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
  418. package/dist/src/utils/nextSpeakerChecker.js +4 -25
  419. package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
  420. package/dist/src/utils/partUtils.d.ts +14 -0
  421. package/dist/src/utils/partUtils.js +65 -0
  422. package/dist/src/utils/partUtils.js.map +1 -0
  423. package/dist/src/utils/partUtils.test.d.ts +6 -0
  424. package/dist/src/utils/partUtils.test.js +130 -0
  425. package/dist/src/utils/partUtils.test.js.map +1 -0
  426. package/dist/src/utils/paths.d.ts +18 -2
  427. package/dist/src/utils/paths.js +39 -7
  428. package/dist/src/utils/paths.js.map +1 -1
  429. package/dist/src/utils/paths.test.d.ts +6 -0
  430. package/dist/src/utils/paths.test.js +225 -0
  431. package/dist/src/utils/paths.test.js.map +1 -0
  432. package/dist/src/utils/quotaErrorDetection.d.ts +1 -5
  433. package/dist/src/utils/quotaErrorDetection.js.map +1 -1
  434. package/dist/src/utils/retry.d.ts +3 -0
  435. package/dist/src/utils/retry.js.map +1 -1
  436. package/dist/src/utils/retry.test.js.map +1 -1
  437. package/dist/src/utils/schemaValidator.d.ts +1 -8
  438. package/dist/src/utils/schemaValidator.js +1 -32
  439. package/dist/src/utils/schemaValidator.js.map +1 -1
  440. package/dist/src/utils/secure-browser-launcher.d.ts +23 -0
  441. package/dist/src/utils/secure-browser-launcher.js +165 -0
  442. package/dist/src/utils/secure-browser-launcher.js.map +1 -0
  443. package/dist/src/utils/secure-browser-launcher.test.d.ts +6 -0
  444. package/dist/src/utils/secure-browser-launcher.test.js +149 -0
  445. package/dist/src/utils/secure-browser-launcher.test.js.map +1 -0
  446. package/dist/src/utils/shell-utils.d.ts +117 -0
  447. package/dist/src/utils/shell-utils.js +376 -0
  448. package/dist/src/utils/shell-utils.js.map +1 -0
  449. package/dist/src/utils/shell-utils.test.d.ts +6 -0
  450. package/dist/src/utils/shell-utils.test.js +328 -0
  451. package/dist/src/utils/shell-utils.test.js.map +1 -0
  452. package/dist/src/utils/summarizer.js +3 -32
  453. package/dist/src/utils/summarizer.js.map +1 -1
  454. package/dist/src/utils/systemEncoding.js +1 -1
  455. package/dist/src/utils/systemEncoding.js.map +1 -1
  456. package/dist/src/utils/systemEncoding.test.js +23 -23
  457. package/dist/src/utils/systemEncoding.test.js.map +1 -1
  458. package/dist/src/utils/textUtils.d.ts +13 -0
  459. package/dist/src/utils/textUtils.js +28 -0
  460. package/dist/src/utils/textUtils.js.map +1 -0
  461. package/dist/src/utils/user_account.js +58 -48
  462. package/dist/src/utils/user_account.js.map +1 -1
  463. package/dist/src/utils/user_account.test.js +76 -9
  464. package/dist/src/utils/user_account.test.js.map +1 -1
  465. package/dist/src/utils/workspaceContext.d.ts +66 -0
  466. package/dist/src/utils/workspaceContext.js +165 -0
  467. package/dist/src/utils/workspaceContext.js.map +1 -0
  468. package/dist/src/utils/workspaceContext.test.d.ts +6 -0
  469. package/dist/src/utils/workspaceContext.test.js +293 -0
  470. package/dist/src/utils/workspaceContext.test.js.map +1 -0
  471. package/dist/tsconfig.tsbuildinfo +1 -1
  472. package/package.json +14 -3
  473. package/dist/src/core/geminiRequest.test.js +0 -72
  474. package/dist/src/core/geminiRequest.test.js.map +0 -1
  475. package/dist/src/core/modelCheck.d.ts +0 -14
  476. package/dist/src/core/modelCheck.js +0 -62
  477. package/dist/src/core/modelCheck.js.map +0 -1
  478. package/dist/src/services/ideContext.d.ts +0 -178
  479. package/dist/src/services/ideContext.js +0 -105
  480. package/dist/src/services/ideContext.js.map +0 -1
  481. package/dist/src/services/ideContext.test.js +0 -111
  482. package/dist/src/services/ideContext.test.js.map +0 -1
  483. /package/dist/src/core/{geminiRequest.test.d.ts → subagent.test.d.ts} +0 -0
  484. /package/dist/src/{services/ideContext.test.d.ts → ide/detect-ide.test.d.ts} +0 -0
@@ -7,11 +7,18 @@ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
7
7
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
8
8
  import { SSEClientTransport, } from '@modelcontextprotocol/sdk/client/sse.js';
9
9
  import { StreamableHTTPClientTransport, } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
10
+ import { ListPromptsResultSchema, GetPromptResultSchema, ListRootsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
10
11
  import { parse } from 'shell-quote';
12
+ import { AuthProviderType } from '../config/config.js';
13
+ import { GoogleCredentialProvider } from '../mcp/google-auth-provider.js';
11
14
  import { DiscoveredMCPTool } from './mcp-tool.js';
12
15
  import { mcpToTool } from '@google/genai';
13
- import { OpenFilesNotificationSchema, IDE_SERVER_NAME, ideContext, } from '../services/ideContext.js';
16
+ import { MCPOAuthProvider } from '../mcp/oauth-provider.js';
17
+ import { OAuthUtils } from '../mcp/oauth-utils.js';
18
+ import { MCPOAuthTokenStorage } from '../mcp/oauth-token-storage.js';
14
19
  import { getErrorMessage } from '../utils/errors.js';
20
+ import { basename } from 'node:path';
21
+ import { pathToFileURL } from 'node:url';
15
22
  export const MCP_DEFAULT_TIMEOUT_MSEC = 10 * 60 * 1000; // default to 10 minutes
16
23
  /**
17
24
  * Enum representing the connection status of an MCP server
@@ -37,14 +44,134 @@ export var MCPDiscoveryState;
37
44
  /** Discovery has completed (with or without errors) */
38
45
  MCPDiscoveryState["COMPLETED"] = "completed";
39
46
  })(MCPDiscoveryState || (MCPDiscoveryState = {}));
47
+ /**
48
+ * A client for a single MCP server.
49
+ *
50
+ * This class is responsible for connecting to, discovering tools from, and
51
+ * managing the state of a single MCP server.
52
+ */
53
+ export class McpClient {
54
+ serverName;
55
+ serverConfig;
56
+ toolRegistry;
57
+ promptRegistry;
58
+ workspaceContext;
59
+ debugMode;
60
+ client;
61
+ transport;
62
+ status = MCPServerStatus.DISCONNECTED;
63
+ isDisconnecting = false;
64
+ constructor(serverName, serverConfig, toolRegistry, promptRegistry, workspaceContext, debugMode) {
65
+ this.serverName = serverName;
66
+ this.serverConfig = serverConfig;
67
+ this.toolRegistry = toolRegistry;
68
+ this.promptRegistry = promptRegistry;
69
+ this.workspaceContext = workspaceContext;
70
+ this.debugMode = debugMode;
71
+ this.client = new Client({
72
+ name: `gemini-cli-mcp-client-${this.serverName}`,
73
+ version: '0.0.1',
74
+ });
75
+ }
76
+ /**
77
+ * Connects to the MCP server.
78
+ */
79
+ async connect() {
80
+ this.isDisconnecting = false;
81
+ this.updateStatus(MCPServerStatus.CONNECTING);
82
+ try {
83
+ this.transport = await this.createTransport();
84
+ this.client.onerror = (error) => {
85
+ if (this.isDisconnecting) {
86
+ return;
87
+ }
88
+ console.error(`MCP ERROR (${this.serverName}):`, error.toString());
89
+ this.updateStatus(MCPServerStatus.DISCONNECTED);
90
+ };
91
+ this.client.registerCapabilities({
92
+ roots: {},
93
+ });
94
+ this.client.setRequestHandler(ListRootsRequestSchema, async () => {
95
+ const roots = [];
96
+ for (const dir of this.workspaceContext.getDirectories()) {
97
+ roots.push({
98
+ uri: pathToFileURL(dir).toString(),
99
+ name: basename(dir),
100
+ });
101
+ }
102
+ return {
103
+ roots,
104
+ };
105
+ });
106
+ await this.client.connect(this.transport, {
107
+ timeout: this.serverConfig.timeout,
108
+ });
109
+ this.updateStatus(MCPServerStatus.CONNECTED);
110
+ }
111
+ catch (error) {
112
+ this.updateStatus(MCPServerStatus.DISCONNECTED);
113
+ throw error;
114
+ }
115
+ }
116
+ /**
117
+ * Discovers tools and prompts from the MCP server.
118
+ */
119
+ async discover() {
120
+ if (this.status !== MCPServerStatus.CONNECTED) {
121
+ throw new Error('Client is not connected.');
122
+ }
123
+ const prompts = await this.discoverPrompts();
124
+ const tools = await this.discoverTools();
125
+ if (prompts.length === 0 && tools.length === 0) {
126
+ throw new Error('No prompts or tools found on the server.');
127
+ }
128
+ for (const tool of tools) {
129
+ this.toolRegistry.registerTool(tool);
130
+ }
131
+ }
132
+ /**
133
+ * Disconnects from the MCP server.
134
+ */
135
+ async disconnect() {
136
+ this.isDisconnecting = true;
137
+ if (this.transport) {
138
+ await this.transport.close();
139
+ }
140
+ this.client.close();
141
+ this.updateStatus(MCPServerStatus.DISCONNECTED);
142
+ }
143
+ /**
144
+ * Returns the current status of the client.
145
+ */
146
+ getStatus() {
147
+ return this.status;
148
+ }
149
+ updateStatus(status) {
150
+ this.status = status;
151
+ updateMCPServerStatus(this.serverName, status);
152
+ }
153
+ async createTransport() {
154
+ return createTransport(this.serverName, this.serverConfig, this.debugMode);
155
+ }
156
+ async discoverTools() {
157
+ return discoverTools(this.serverName, this.serverConfig, this.client);
158
+ }
159
+ async discoverPrompts() {
160
+ return discoverPrompts(this.serverName, this.client, this.promptRegistry);
161
+ }
162
+ }
40
163
  /**
41
164
  * Map to track the status of each MCP server within the core package
42
165
  */
43
- const mcpServerStatusesInternal = new Map();
166
+ const serverStatuses = new Map();
44
167
  /**
45
168
  * Track the overall MCP discovery state
46
169
  */
47
170
  let mcpDiscoveryState = MCPDiscoveryState.NOT_STARTED;
171
+ /**
172
+ * Map to track which MCP servers have been discovered to require OAuth
173
+ */
174
+ export const mcpServerRequiresOAuth = new Map();
48
175
  const statusChangeListeners = [];
49
176
  /**
50
177
  * Add a listener for MCP server status changes
@@ -64,8 +191,8 @@ export function removeMCPStatusChangeListener(listener) {
64
191
  /**
65
192
  * Update the status of an MCP server
66
193
  */
67
- function updateMCPServerStatus(serverName, status) {
68
- mcpServerStatusesInternal.set(serverName, status);
194
+ export function updateMCPServerStatus(serverName, status) {
195
+ serverStatuses.set(serverName, status);
69
196
  // Notify all listeners
70
197
  for (const listener of statusChangeListeners) {
71
198
  listener(serverName, status);
@@ -75,13 +202,13 @@ function updateMCPServerStatus(serverName, status) {
75
202
  * Get the current status of an MCP server
76
203
  */
77
204
  export function getMCPServerStatus(serverName) {
78
- return (mcpServerStatusesInternal.get(serverName) || MCPServerStatus.DISCONNECTED);
205
+ return serverStatuses.get(serverName) || MCPServerStatus.DISCONNECTED;
79
206
  }
80
207
  /**
81
208
  * Get all MCP server statuses
82
209
  */
83
210
  export function getAllMCPServerStatuses() {
84
- return new Map(mcpServerStatusesInternal);
211
+ return new Map(serverStatuses);
85
212
  }
86
213
  /**
87
214
  * Get the current MCP discovery state
@@ -89,6 +216,123 @@ export function getAllMCPServerStatuses() {
89
216
  export function getMCPDiscoveryState() {
90
217
  return mcpDiscoveryState;
91
218
  }
219
+ /**
220
+ * Extract WWW-Authenticate header from error message string.
221
+ * This is a more robust approach than regex matching.
222
+ *
223
+ * @param errorString The error message string
224
+ * @returns The www-authenticate header value if found, null otherwise
225
+ */
226
+ function extractWWWAuthenticateHeader(errorString) {
227
+ // Try multiple patterns to extract the header
228
+ const patterns = [
229
+ /www-authenticate:\s*([^\n\r]+)/i,
230
+ /WWW-Authenticate:\s*([^\n\r]+)/i,
231
+ /"www-authenticate":\s*"([^"]+)"/i,
232
+ /'www-authenticate':\s*'([^']+)'/i,
233
+ ];
234
+ for (const pattern of patterns) {
235
+ const match = errorString.match(pattern);
236
+ if (match) {
237
+ return match[1].trim();
238
+ }
239
+ }
240
+ return null;
241
+ }
242
+ /**
243
+ * Handle automatic OAuth discovery and authentication for a server.
244
+ *
245
+ * @param mcpServerName The name of the MCP server
246
+ * @param mcpServerConfig The MCP server configuration
247
+ * @param wwwAuthenticate The www-authenticate header value
248
+ * @returns True if OAuth was successfully configured and authenticated, false otherwise
249
+ */
250
+ async function handleAutomaticOAuth(mcpServerName, mcpServerConfig, wwwAuthenticate) {
251
+ try {
252
+ console.log(`🔐 '${mcpServerName}' requires OAuth authentication`);
253
+ // Always try to parse the resource metadata URI from the www-authenticate header
254
+ let oauthConfig;
255
+ const resourceMetadataUri = OAuthUtils.parseWWWAuthenticateHeader(wwwAuthenticate);
256
+ if (resourceMetadataUri) {
257
+ oauthConfig = await OAuthUtils.discoverOAuthConfig(resourceMetadataUri);
258
+ }
259
+ else if (mcpServerConfig.url) {
260
+ // Fallback: try to discover OAuth config from the base URL for SSE
261
+ const sseUrl = new URL(mcpServerConfig.url);
262
+ const baseUrl = `${sseUrl.protocol}//${sseUrl.host}`;
263
+ oauthConfig = await OAuthUtils.discoverOAuthConfig(baseUrl);
264
+ }
265
+ else if (mcpServerConfig.httpUrl) {
266
+ // Fallback: try to discover OAuth config from the base URL for HTTP
267
+ const httpUrl = new URL(mcpServerConfig.httpUrl);
268
+ const baseUrl = `${httpUrl.protocol}//${httpUrl.host}`;
269
+ oauthConfig = await OAuthUtils.discoverOAuthConfig(baseUrl);
270
+ }
271
+ if (!oauthConfig) {
272
+ console.error(`❌ Could not configure OAuth for '${mcpServerName}' - please authenticate manually with /mcp auth ${mcpServerName}`);
273
+ return false;
274
+ }
275
+ // OAuth configuration discovered - proceed with authentication
276
+ // Create OAuth configuration for authentication
277
+ const oauthAuthConfig = {
278
+ enabled: true,
279
+ authorizationUrl: oauthConfig.authorizationUrl,
280
+ tokenUrl: oauthConfig.tokenUrl,
281
+ scopes: oauthConfig.scopes || [],
282
+ };
283
+ // Perform OAuth authentication
284
+ // Pass the server URL for proper discovery
285
+ const serverUrl = mcpServerConfig.httpUrl || mcpServerConfig.url;
286
+ console.log(`Starting OAuth authentication for server '${mcpServerName}'...`);
287
+ await MCPOAuthProvider.authenticate(mcpServerName, oauthAuthConfig, serverUrl);
288
+ console.log(`OAuth authentication successful for server '${mcpServerName}'`);
289
+ return true;
290
+ }
291
+ catch (error) {
292
+ console.error(`Failed to handle automatic OAuth for server '${mcpServerName}': ${getErrorMessage(error)}`);
293
+ return false;
294
+ }
295
+ }
296
+ /**
297
+ * Create a transport with OAuth token for the given server configuration.
298
+ *
299
+ * @param mcpServerName The name of the MCP server
300
+ * @param mcpServerConfig The MCP server configuration
301
+ * @param accessToken The OAuth access token
302
+ * @returns The transport with OAuth token, or null if creation fails
303
+ */
304
+ async function createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken) {
305
+ try {
306
+ if (mcpServerConfig.httpUrl) {
307
+ // Create HTTP transport with OAuth token
308
+ const oauthTransportOptions = {
309
+ requestInit: {
310
+ headers: {
311
+ ...mcpServerConfig.headers,
312
+ Authorization: `Bearer ${accessToken}`,
313
+ },
314
+ },
315
+ };
316
+ return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), oauthTransportOptions);
317
+ }
318
+ else if (mcpServerConfig.url) {
319
+ // Create SSE transport with OAuth token in Authorization header
320
+ return new SSEClientTransport(new URL(mcpServerConfig.url), {
321
+ requestInit: {
322
+ headers: {
323
+ ...mcpServerConfig.headers,
324
+ Authorization: `Bearer ${accessToken}`,
325
+ },
326
+ },
327
+ });
328
+ }
329
+ return null;
330
+ }
331
+ catch (error) {
332
+ console.error(`Failed to create OAuth transport for server '${mcpServerName}': ${getErrorMessage(error)}`);
333
+ return null;
334
+ }
335
+ }
92
336
  /**
93
337
  * Discovers tools from all configured MCP servers and registers them with the tool registry.
94
338
  * It orchestrates the connection and discovery process for each server defined in the
@@ -99,11 +343,11 @@ export function getMCPDiscoveryState() {
99
343
  * @param toolRegistry The central registry where discovered tools will be registered.
100
344
  * @returns A promise that resolves when the discovery process has been attempted for all servers.
101
345
  */
102
- export async function discoverMcpTools(mcpServers, mcpServerCommand, toolRegistry, debugMode) {
346
+ export async function discoverMcpTools(mcpServers, mcpServerCommand, toolRegistry, promptRegistry, debugMode, workspaceContext) {
103
347
  mcpDiscoveryState = MCPDiscoveryState.IN_PROGRESS;
104
348
  try {
105
349
  mcpServers = populateMcpServerCommand(mcpServers, mcpServerCommand);
106
- const discoveryPromises = Object.entries(mcpServers).map(([mcpServerName, mcpServerConfig]) => connectAndDiscover(mcpServerName, mcpServerConfig, toolRegistry, debugMode));
350
+ const discoveryPromises = Object.entries(mcpServers).map(([mcpServerName, mcpServerConfig]) => connectAndDiscover(mcpServerName, mcpServerConfig, toolRegistry, promptRegistry, debugMode, workspaceContext));
107
351
  await Promise.all(discoveryPromises);
108
352
  }
109
353
  finally {
@@ -136,39 +380,90 @@ export function populateMcpServerCommand(mcpServers, mcpServerCommand) {
136
380
  * @param toolRegistry The registry to register discovered tools with
137
381
  * @returns Promise that resolves when discovery is complete
138
382
  */
139
- export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolRegistry, debugMode) {
383
+ export async function connectAndDiscover(mcpServerName, mcpServerConfig, toolRegistry, promptRegistry, debugMode, workspaceContext) {
140
384
  updateMCPServerStatus(mcpServerName, MCPServerStatus.CONNECTING);
385
+ let mcpClient;
141
386
  try {
142
- const mcpClient = await connectToMcpServer(mcpServerName, mcpServerConfig, debugMode);
143
- try {
144
- updateMCPServerStatus(mcpServerName, MCPServerStatus.CONNECTED);
145
- mcpClient.onerror = (error) => {
146
- console.error(`MCP ERROR (${mcpServerName}):`, error.toString());
147
- updateMCPServerStatus(mcpServerName, MCPServerStatus.DISCONNECTED);
148
- if (mcpServerName === IDE_SERVER_NAME) {
149
- ideContext.clearOpenFilesContext();
150
- }
151
- };
152
- if (mcpServerName === IDE_SERVER_NAME) {
153
- mcpClient.setNotificationHandler(OpenFilesNotificationSchema, (notification) => {
154
- ideContext.setOpenFilesContext(notification.params);
155
- });
156
- }
157
- const tools = await discoverTools(mcpServerName, mcpServerConfig, mcpClient);
158
- for (const tool of tools) {
159
- toolRegistry.registerTool(tool);
160
- }
387
+ mcpClient = await connectToMcpServer(mcpServerName, mcpServerConfig, debugMode, workspaceContext);
388
+ mcpClient.onerror = (error) => {
389
+ console.error(`MCP ERROR (${mcpServerName}):`, error.toString());
390
+ updateMCPServerStatus(mcpServerName, MCPServerStatus.DISCONNECTED);
391
+ };
392
+ // Attempt to discover both prompts and tools
393
+ const prompts = await discoverPrompts(mcpServerName, mcpClient, promptRegistry);
394
+ const tools = await discoverTools(mcpServerName, mcpServerConfig, mcpClient);
395
+ // If we have neither prompts nor tools, it's a failed discovery
396
+ if (prompts.length === 0 && tools.length === 0) {
397
+ throw new Error('No prompts or tools found on the server.');
161
398
  }
162
- catch (error) {
163
- mcpClient.close();
164
- throw error;
399
+ // If we found anything, the server is connected
400
+ updateMCPServerStatus(mcpServerName, MCPServerStatus.CONNECTED);
401
+ // Register any discovered tools
402
+ for (const tool of tools) {
403
+ toolRegistry.registerTool(tool);
165
404
  }
166
405
  }
167
406
  catch (error) {
407
+ if (mcpClient) {
408
+ mcpClient.close();
409
+ }
168
410
  console.error(`Error connecting to MCP server '${mcpServerName}': ${getErrorMessage(error)}`);
169
411
  updateMCPServerStatus(mcpServerName, MCPServerStatus.DISCONNECTED);
170
412
  }
171
413
  }
414
+ /**
415
+ * Recursively validates that a JSON schema and all its nested properties and
416
+ * items have a `type` defined.
417
+ *
418
+ * @param schema The JSON schema to validate.
419
+ * @returns `true` if the schema is valid, `false` otherwise.
420
+ *
421
+ * @visiblefortesting
422
+ */
423
+ export function hasValidTypes(schema) {
424
+ if (typeof schema !== 'object' || schema === null) {
425
+ // Not a schema object we can validate, or not a schema at all.
426
+ // Treat as valid as it has no properties to be invalid.
427
+ return true;
428
+ }
429
+ const s = schema;
430
+ if (!s['type']) {
431
+ // These keywords contain an array of schemas that should be validated.
432
+ //
433
+ // If no top level type was given, then they must each have a type.
434
+ let hasSubSchema = false;
435
+ const schemaArrayKeywords = ['anyOf', 'allOf', 'oneOf'];
436
+ for (const keyword of schemaArrayKeywords) {
437
+ const subSchemas = s[keyword];
438
+ if (Array.isArray(subSchemas)) {
439
+ hasSubSchema = true;
440
+ for (const subSchema of subSchemas) {
441
+ if (!hasValidTypes(subSchema)) {
442
+ return false;
443
+ }
444
+ }
445
+ }
446
+ }
447
+ // If the node itself is missing a type and had no subschemas, then it isn't valid.
448
+ if (!hasSubSchema)
449
+ return false;
450
+ }
451
+ if (s['type'] === 'object' && s['properties']) {
452
+ if (typeof s['properties'] === 'object' && s['properties'] !== null) {
453
+ for (const prop of Object.values(s['properties'])) {
454
+ if (!hasValidTypes(prop)) {
455
+ return false;
456
+ }
457
+ }
458
+ }
459
+ }
460
+ if (s['type'] === 'array' && s['items']) {
461
+ if (!hasValidTypes(s['items'])) {
462
+ return false;
463
+ }
464
+ }
465
+ return true;
466
+ }
172
467
  /**
173
468
  * Discovers and sanitizes tools from a connected MCP client.
174
469
  * It retrieves function declarations from the client, filters out disabled tools,
@@ -185,22 +480,95 @@ export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient) {
185
480
  const mcpCallableTool = mcpToTool(mcpClient);
186
481
  const tool = await mcpCallableTool.tool();
187
482
  if (!Array.isArray(tool.functionDeclarations)) {
188
- throw new Error(`Server did not return valid function declarations.`);
483
+ // This is a valid case for a prompt-only server
484
+ return [];
189
485
  }
190
486
  const discoveredTools = [];
191
487
  for (const funcDecl of tool.functionDeclarations) {
192
- if (!isEnabled(funcDecl, mcpServerName, mcpServerConfig)) {
193
- continue;
488
+ try {
489
+ if (!isEnabled(funcDecl, mcpServerName, mcpServerConfig)) {
490
+ continue;
491
+ }
492
+ if (!hasValidTypes(funcDecl.parametersJsonSchema)) {
493
+ console.warn(`Skipping tool '${funcDecl.name}' from MCP server '${mcpServerName}' ` +
494
+ `because it has missing types in its parameter schema. Please file an ` +
495
+ `issue with the owner of the MCP server.`);
496
+ continue;
497
+ }
498
+ discoveredTools.push(new DiscoveredMCPTool(mcpCallableTool, mcpServerName, funcDecl.name, funcDecl.description ?? '', funcDecl.parametersJsonSchema ?? { type: 'object', properties: {} }, mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC, mcpServerConfig.trust));
499
+ }
500
+ catch (error) {
501
+ console.error(`Error discovering tool: '${funcDecl.name}' from MCP server '${mcpServerName}': ${error.message}`);
194
502
  }
195
- discoveredTools.push(new DiscoveredMCPTool(mcpCallableTool, mcpServerName, funcDecl.name, funcDecl.description ?? '', funcDecl.parametersJsonSchema ?? { type: 'object', properties: {} }, mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC, mcpServerConfig.trust));
196
- }
197
- if (discoveredTools.length === 0) {
198
- throw Error('No enabled tools found');
199
503
  }
200
504
  return discoveredTools;
201
505
  }
202
506
  catch (error) {
203
- throw new Error(`Error discovering tools: ${error}`);
507
+ if (error instanceof Error &&
508
+ !error.message?.includes('Method not found')) {
509
+ console.error(`Error discovering tools from ${mcpServerName}: ${getErrorMessage(error)}`);
510
+ }
511
+ return [];
512
+ }
513
+ }
514
+ /**
515
+ * Discovers and logs prompts from a connected MCP client.
516
+ * It retrieves prompt declarations from the client and logs their names.
517
+ *
518
+ * @param mcpServerName The name of the MCP server.
519
+ * @param mcpClient The active MCP client instance.
520
+ */
521
+ export async function discoverPrompts(mcpServerName, mcpClient, promptRegistry) {
522
+ try {
523
+ // Only request prompts if the server supports them.
524
+ if (mcpClient.getServerCapabilities()?.prompts == null)
525
+ return [];
526
+ const response = await mcpClient.request({ method: 'prompts/list', params: {} }, ListPromptsResultSchema);
527
+ for (const prompt of response.prompts) {
528
+ promptRegistry.registerPrompt({
529
+ ...prompt,
530
+ serverName: mcpServerName,
531
+ invoke: (params) => invokeMcpPrompt(mcpServerName, mcpClient, prompt.name, params),
532
+ });
533
+ }
534
+ return response.prompts;
535
+ }
536
+ catch (error) {
537
+ // It's okay if this fails, not all servers will have prompts.
538
+ // Don't log an error if the method is not found, which is a common case.
539
+ if (error instanceof Error &&
540
+ !error.message?.includes('Method not found')) {
541
+ console.error(`Error discovering prompts from ${mcpServerName}: ${getErrorMessage(error)}`);
542
+ }
543
+ return [];
544
+ }
545
+ }
546
+ /**
547
+ * Invokes a prompt on a connected MCP client.
548
+ *
549
+ * @param mcpServerName The name of the MCP server.
550
+ * @param mcpClient The active MCP client instance.
551
+ * @param promptName The name of the prompt to invoke.
552
+ * @param promptParams The parameters to pass to the prompt.
553
+ * @returns A promise that resolves to the result of the prompt invocation.
554
+ */
555
+ export async function invokeMcpPrompt(mcpServerName, mcpClient, promptName, promptParams) {
556
+ try {
557
+ const response = await mcpClient.request({
558
+ method: 'prompts/get',
559
+ params: {
560
+ name: promptName,
561
+ arguments: promptParams,
562
+ },
563
+ }, GetPromptResultSchema);
564
+ return response;
565
+ }
566
+ catch (error) {
567
+ if (error instanceof Error &&
568
+ !error.message?.includes('Method not found')) {
569
+ console.error(`Error invoking prompt '${promptName}' from ${mcpServerName} ${promptParams}: ${getErrorMessage(error)}`);
570
+ }
571
+ throw error;
204
572
  }
205
573
  }
206
574
  /**
@@ -213,11 +581,52 @@ export async function discoverTools(mcpServerName, mcpServerConfig, mcpClient) {
213
581
  * @returns A promise that resolves to a connected MCP `Client` instance.
214
582
  * @throws An error if the connection fails or the configuration is invalid.
215
583
  */
216
- export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMode) {
584
+ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMode, workspaceContext) {
217
585
  const mcpClient = new Client({
218
586
  name: 'gemini-cli-mcp-client',
219
587
  version: '0.0.1',
220
588
  });
589
+ mcpClient.registerCapabilities({
590
+ roots: {
591
+ listChanged: true,
592
+ },
593
+ });
594
+ mcpClient.setRequestHandler(ListRootsRequestSchema, async () => {
595
+ const roots = [];
596
+ for (const dir of workspaceContext.getDirectories()) {
597
+ roots.push({
598
+ uri: pathToFileURL(dir).toString(),
599
+ name: basename(dir),
600
+ });
601
+ }
602
+ return {
603
+ roots,
604
+ };
605
+ });
606
+ let unlistenDirectories = workspaceContext.onDirectoriesChanged(async () => {
607
+ try {
608
+ await mcpClient.notification({
609
+ method: 'notifications/roots/list_changed',
610
+ });
611
+ }
612
+ catch (_) {
613
+ // If this fails, its almost certainly because the connection was closed
614
+ // and we should just stop listening for future directory changes.
615
+ unlistenDirectories?.();
616
+ unlistenDirectories = undefined;
617
+ }
618
+ });
619
+ // Attempt to pro-actively unsubscribe if the mcp client closes. This API is
620
+ // very brittle though so we don't have any guarantees, hence the try/catch
621
+ // above as well.
622
+ //
623
+ // Be a good steward and don't just bash over onclose.
624
+ const oldOnClose = mcpClient.onclose;
625
+ mcpClient.onclose = () => {
626
+ oldOnClose?.();
627
+ unlistenDirectories?.();
628
+ unlistenDirectories = undefined;
629
+ };
221
630
  // patch Client.callTool to use request timeout as genai McpCallTool.callTool does not do it
222
631
  // TODO: remove this hack once GenAI SDK does callTool with request options
223
632
  if ('callTool' in mcpClient) {
@@ -230,7 +639,7 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
230
639
  };
231
640
  }
232
641
  try {
233
- const transport = createTransport(mcpServerName, mcpServerConfig, debugMode);
642
+ const transport = await createTransport(mcpServerName, mcpServerConfig, debugMode);
234
643
  try {
235
644
  await mcpClient.connect(transport, {
236
645
  timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
@@ -243,29 +652,282 @@ export async function connectToMcpServer(mcpServerName, mcpServerConfig, debugMo
243
652
  }
244
653
  }
245
654
  catch (error) {
246
- // Create a safe config object that excludes sensitive information
247
- const safeConfig = {
248
- command: mcpServerConfig.command,
249
- url: mcpServerConfig.url,
250
- httpUrl: mcpServerConfig.httpUrl,
251
- cwd: mcpServerConfig.cwd,
252
- timeout: mcpServerConfig.timeout,
253
- trust: mcpServerConfig.trust,
254
- // Exclude args, env, and headers which may contain sensitive data
255
- };
256
- let errorString = `failed to start or connect to MCP server '${mcpServerName}' ` +
257
- `${JSON.stringify(safeConfig)}; \n${error}`;
258
- if (process.env.SANDBOX) {
259
- errorString += `\nMake sure it is available in the sandbox`;
655
+ // Check if this is a 401 error that might indicate OAuth is required
656
+ const errorString = String(error);
657
+ if (errorString.includes('401') &&
658
+ (mcpServerConfig.httpUrl || mcpServerConfig.url)) {
659
+ mcpServerRequiresOAuth.set(mcpServerName, true);
660
+ // Only trigger automatic OAuth discovery for HTTP servers or when OAuth is explicitly configured
661
+ // For SSE servers, we should not trigger new OAuth flows automatically
662
+ const shouldTriggerOAuth = mcpServerConfig.httpUrl || mcpServerConfig.oauth?.enabled;
663
+ if (!shouldTriggerOAuth) {
664
+ // For SSE servers without explicit OAuth config, if a token was found but rejected, report it accurately.
665
+ const credentials = await MCPOAuthTokenStorage.getToken(mcpServerName);
666
+ if (credentials) {
667
+ const hasStoredTokens = await MCPOAuthProvider.getValidToken(mcpServerName, {
668
+ // Pass client ID if available
669
+ clientId: credentials.clientId,
670
+ });
671
+ if (hasStoredTokens) {
672
+ console.log(`Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
673
+ `Please re-authenticate using: /mcp auth ${mcpServerName}`);
674
+ }
675
+ else {
676
+ console.log(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
677
+ `Please authenticate using: /mcp auth ${mcpServerName}`);
678
+ }
679
+ }
680
+ throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
681
+ `Please authenticate using: /mcp auth ${mcpServerName}`);
682
+ }
683
+ // Try to extract www-authenticate header from the error
684
+ let wwwAuthenticate = extractWWWAuthenticateHeader(errorString);
685
+ // If we didn't get the header from the error string, try to get it from the server
686
+ if (!wwwAuthenticate && mcpServerConfig.url) {
687
+ console.log(`No www-authenticate header in error, trying to fetch it from server...`);
688
+ try {
689
+ const response = await fetch(mcpServerConfig.url, {
690
+ method: 'HEAD',
691
+ headers: {
692
+ Accept: 'text/event-stream',
693
+ },
694
+ signal: AbortSignal.timeout(5000),
695
+ });
696
+ if (response.status === 401) {
697
+ wwwAuthenticate = response.headers.get('www-authenticate');
698
+ if (wwwAuthenticate) {
699
+ console.log(`Found www-authenticate header from server: ${wwwAuthenticate}`);
700
+ }
701
+ }
702
+ }
703
+ catch (fetchError) {
704
+ console.debug(`Failed to fetch www-authenticate header: ${getErrorMessage(fetchError)}`);
705
+ }
706
+ }
707
+ if (wwwAuthenticate) {
708
+ console.log(`Received 401 with www-authenticate header: ${wwwAuthenticate}`);
709
+ // Try automatic OAuth discovery and authentication
710
+ const oauthSuccess = await handleAutomaticOAuth(mcpServerName, mcpServerConfig, wwwAuthenticate);
711
+ if (oauthSuccess) {
712
+ // Retry connection with OAuth token
713
+ console.log(`Retrying connection to '${mcpServerName}' with OAuth token...`);
714
+ // Get the valid token - we need to create a proper OAuth config
715
+ // The token should already be available from the authentication process
716
+ const credentials = await MCPOAuthTokenStorage.getToken(mcpServerName);
717
+ if (credentials) {
718
+ const accessToken = await MCPOAuthProvider.getValidToken(mcpServerName, {
719
+ // Pass client ID if available
720
+ clientId: credentials.clientId,
721
+ });
722
+ if (accessToken) {
723
+ // Create transport with OAuth token
724
+ const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
725
+ if (oauthTransport) {
726
+ try {
727
+ await mcpClient.connect(oauthTransport, {
728
+ timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
729
+ });
730
+ // Connection successful with OAuth
731
+ return mcpClient;
732
+ }
733
+ catch (retryError) {
734
+ console.error(`Failed to connect with OAuth token: ${getErrorMessage(retryError)}`);
735
+ throw retryError;
736
+ }
737
+ }
738
+ else {
739
+ console.error(`Failed to create OAuth transport for server '${mcpServerName}'`);
740
+ throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
741
+ }
742
+ }
743
+ else {
744
+ console.error(`Failed to get OAuth token for server '${mcpServerName}'`);
745
+ throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
746
+ }
747
+ }
748
+ else {
749
+ console.error(`Failed to get credentials for server '${mcpServerName}' after successful OAuth authentication`);
750
+ throw new Error(`Failed to get credentials for server '${mcpServerName}' after successful OAuth authentication`);
751
+ }
752
+ }
753
+ else {
754
+ console.error(`Failed to handle automatic OAuth for server '${mcpServerName}'`);
755
+ throw new Error(`Failed to handle automatic OAuth for server '${mcpServerName}'`);
756
+ }
757
+ }
758
+ else {
759
+ // No www-authenticate header found, but we got a 401
760
+ // Only try OAuth discovery for HTTP servers or when OAuth is explicitly configured
761
+ // For SSE servers, we should not trigger new OAuth flows automatically
762
+ const shouldTryDiscovery = mcpServerConfig.httpUrl || mcpServerConfig.oauth?.enabled;
763
+ if (!shouldTryDiscovery) {
764
+ const credentials = await MCPOAuthTokenStorage.getToken(mcpServerName);
765
+ if (credentials) {
766
+ const hasStoredTokens = await MCPOAuthProvider.getValidToken(mcpServerName, {
767
+ // Pass client ID if available
768
+ clientId: credentials.clientId,
769
+ });
770
+ if (hasStoredTokens) {
771
+ console.log(`Stored OAuth token for SSE server '${mcpServerName}' was rejected. ` +
772
+ `Please re-authenticate using: /mcp auth ${mcpServerName}`);
773
+ }
774
+ else {
775
+ console.log(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
776
+ `Please authenticate using: /mcp auth ${mcpServerName}`);
777
+ }
778
+ }
779
+ throw new Error(`401 error received for SSE server '${mcpServerName}' without OAuth configuration. ` +
780
+ `Please authenticate using: /mcp auth ${mcpServerName}`);
781
+ }
782
+ // For SSE servers, try to discover OAuth configuration from the base URL
783
+ console.log(`🔍 Attempting OAuth discovery for '${mcpServerName}'...`);
784
+ if (mcpServerConfig.url) {
785
+ const sseUrl = new URL(mcpServerConfig.url);
786
+ const baseUrl = `${sseUrl.protocol}//${sseUrl.host}`;
787
+ try {
788
+ // Try to discover OAuth configuration from the base URL
789
+ const oauthConfig = await OAuthUtils.discoverOAuthConfig(baseUrl);
790
+ if (oauthConfig) {
791
+ console.log(`Discovered OAuth configuration from base URL for server '${mcpServerName}'`);
792
+ // Create OAuth configuration for authentication
793
+ const oauthAuthConfig = {
794
+ enabled: true,
795
+ authorizationUrl: oauthConfig.authorizationUrl,
796
+ tokenUrl: oauthConfig.tokenUrl,
797
+ scopes: oauthConfig.scopes || [],
798
+ };
799
+ // Perform OAuth authentication
800
+ // Pass the server URL for proper discovery
801
+ const serverUrl = mcpServerConfig.httpUrl || mcpServerConfig.url;
802
+ console.log(`Starting OAuth authentication for server '${mcpServerName}'...`);
803
+ await MCPOAuthProvider.authenticate(mcpServerName, oauthAuthConfig, serverUrl);
804
+ // Retry connection with OAuth token
805
+ const credentials = await MCPOAuthTokenStorage.getToken(mcpServerName);
806
+ if (credentials) {
807
+ const accessToken = await MCPOAuthProvider.getValidToken(mcpServerName, {
808
+ // Pass client ID if available
809
+ clientId: credentials.clientId,
810
+ });
811
+ if (accessToken) {
812
+ // Create transport with OAuth token
813
+ const oauthTransport = await createTransportWithOAuth(mcpServerName, mcpServerConfig, accessToken);
814
+ if (oauthTransport) {
815
+ try {
816
+ await mcpClient.connect(oauthTransport, {
817
+ timeout: mcpServerConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
818
+ });
819
+ // Connection successful with OAuth
820
+ return mcpClient;
821
+ }
822
+ catch (retryError) {
823
+ console.error(`Failed to connect with OAuth token: ${getErrorMessage(retryError)}`);
824
+ throw retryError;
825
+ }
826
+ }
827
+ else {
828
+ console.error(`Failed to create OAuth transport for server '${mcpServerName}'`);
829
+ throw new Error(`Failed to create OAuth transport for server '${mcpServerName}'`);
830
+ }
831
+ }
832
+ else {
833
+ console.error(`Failed to get OAuth token for server '${mcpServerName}'`);
834
+ throw new Error(`Failed to get OAuth token for server '${mcpServerName}'`);
835
+ }
836
+ }
837
+ else {
838
+ console.error(`Failed to get stored credentials for server '${mcpServerName}'`);
839
+ throw new Error(`Failed to get stored credentials for server '${mcpServerName}'`);
840
+ }
841
+ }
842
+ else {
843
+ console.error(`❌ Could not configure OAuth for '${mcpServerName}' - please authenticate manually with /mcp auth ${mcpServerName}`);
844
+ throw new Error(`OAuth configuration failed for '${mcpServerName}'. Please authenticate manually with /mcp auth ${mcpServerName}`);
845
+ }
846
+ }
847
+ catch (discoveryError) {
848
+ console.error(`❌ OAuth discovery failed for '${mcpServerName}' - please authenticate manually with /mcp auth ${mcpServerName}`);
849
+ throw discoveryError;
850
+ }
851
+ }
852
+ else {
853
+ console.error(`❌ '${mcpServerName}' requires authentication but no OAuth configuration found`);
854
+ throw new Error(`MCP server '${mcpServerName}' requires authentication. Please configure OAuth or check server settings.`);
855
+ }
856
+ }
857
+ }
858
+ else {
859
+ // Handle other connection errors
860
+ // Create a concise error message
861
+ const errorMessage = error.message || String(error);
862
+ const isNetworkError = errorMessage.includes('ENOTFOUND') ||
863
+ errorMessage.includes('ECONNREFUSED');
864
+ let conciseError;
865
+ if (isNetworkError) {
866
+ conciseError = `Cannot connect to '${mcpServerName}' - server may be down or URL incorrect`;
867
+ }
868
+ else {
869
+ conciseError = `Connection failed for '${mcpServerName}': ${errorMessage}`;
870
+ }
871
+ if (process.env['SANDBOX']) {
872
+ conciseError += ` (check sandbox availability)`;
873
+ }
874
+ throw new Error(conciseError);
260
875
  }
261
- throw new Error(errorString);
262
876
  }
263
877
  }
264
878
  /** Visible for Testing */
265
- export function createTransport(mcpServerName, mcpServerConfig, debugMode) {
879
+ export async function createTransport(mcpServerName, mcpServerConfig, debugMode) {
880
+ if (mcpServerConfig.authProviderType === AuthProviderType.GOOGLE_CREDENTIALS) {
881
+ const provider = new GoogleCredentialProvider(mcpServerConfig);
882
+ const transportOptions = {
883
+ authProvider: provider,
884
+ };
885
+ if (mcpServerConfig.httpUrl) {
886
+ return new StreamableHTTPClientTransport(new URL(mcpServerConfig.httpUrl), transportOptions);
887
+ }
888
+ else if (mcpServerConfig.url) {
889
+ return new SSEClientTransport(new URL(mcpServerConfig.url), transportOptions);
890
+ }
891
+ throw new Error('No URL configured for Google Credentials MCP server');
892
+ }
893
+ // Check if we have OAuth configuration or stored tokens
894
+ let accessToken = null;
895
+ let hasOAuthConfig = mcpServerConfig.oauth?.enabled;
896
+ if (hasOAuthConfig && mcpServerConfig.oauth) {
897
+ accessToken = await MCPOAuthProvider.getValidToken(mcpServerName, mcpServerConfig.oauth);
898
+ if (!accessToken) {
899
+ console.error(`MCP server '${mcpServerName}' requires OAuth authentication. ` +
900
+ `Please authenticate using the /mcp auth command.`);
901
+ throw new Error(`MCP server '${mcpServerName}' requires OAuth authentication. ` +
902
+ `Please authenticate using the /mcp auth command.`);
903
+ }
904
+ }
905
+ else {
906
+ // Check if we have stored OAuth tokens for this server (from previous authentication)
907
+ const credentials = await MCPOAuthTokenStorage.getToken(mcpServerName);
908
+ if (credentials) {
909
+ accessToken = await MCPOAuthProvider.getValidToken(mcpServerName, {
910
+ // Pass client ID if available
911
+ clientId: credentials.clientId,
912
+ });
913
+ if (accessToken) {
914
+ hasOAuthConfig = true;
915
+ console.log(`Found stored OAuth token for server '${mcpServerName}'`);
916
+ }
917
+ }
918
+ }
266
919
  if (mcpServerConfig.httpUrl) {
267
920
  const transportOptions = {};
268
- if (mcpServerConfig.headers) {
921
+ // Set up headers with OAuth token if available
922
+ if (hasOAuthConfig && accessToken) {
923
+ transportOptions.requestInit = {
924
+ headers: {
925
+ ...mcpServerConfig.headers,
926
+ Authorization: `Bearer ${accessToken}`,
927
+ },
928
+ };
929
+ }
930
+ else if (mcpServerConfig.headers) {
269
931
  transportOptions.requestInit = {
270
932
  headers: mcpServerConfig.headers,
271
933
  };
@@ -274,7 +936,16 @@ export function createTransport(mcpServerName, mcpServerConfig, debugMode) {
274
936
  }
275
937
  if (mcpServerConfig.url) {
276
938
  const transportOptions = {};
277
- if (mcpServerConfig.headers) {
939
+ // Set up headers with OAuth token if available
940
+ if (hasOAuthConfig && accessToken) {
941
+ transportOptions.requestInit = {
942
+ headers: {
943
+ ...mcpServerConfig.headers,
944
+ Authorization: `Bearer ${accessToken}`,
945
+ },
946
+ };
947
+ }
948
+ else if (mcpServerConfig.headers) {
278
949
  transportOptions.requestInit = {
279
950
  headers: mcpServerConfig.headers,
280
951
  };