@herbertgao/pi-extensions 2026.9.17 → 2026.9.19

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 (307) hide show
  1. package/README.md +31 -33
  2. package/THIRD_PARTY_NOTICES.md +1 -1
  3. package/node_modules/@herbertgao/pi-bark/package.json +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +4 -1
  5. package/node_modules/@herbertgao/pi-cc-extensions/README.md +4 -1
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/shell/working-message.ts +21 -6
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/index.ts +15 -4
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/index.ts +43 -7
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +7 -2
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +1 -1
  11. package/node_modules/@herbertgao/pi-cc-extensions/package.json +75 -75
  12. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  13. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  14. package/node_modules/@herbertgao/resume-from/package.json +4 -2
  15. package/node_modules/@herbertgao/sol-pi/package.json +6 -6
  16. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +99 -99
  17. package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
  18. package/node_modules/@tifan/pi-handoff/package.json +1 -1
  19. package/node_modules/@tifan/pi-handoff/src/index.ts +56 -26
  20. package/node_modules/@tifan/pi-mermaid-open/package.json +1 -1
  21. package/node_modules/@tifan/pi-preferred-thinking/package.json +1 -1
  22. package/node_modules/@tifan/pi-recap/package.json +1 -1
  23. package/node_modules/@tifan/pi-rename/package.json +1 -1
  24. package/node_modules/pi-antigravity/README.md +29 -6
  25. package/node_modules/pi-antigravity/package.json +14 -9
  26. package/node_modules/pi-antigravity/src/auth/accounts.ts +327 -0
  27. package/node_modules/pi-antigravity/src/auth/index.ts +9 -0
  28. package/node_modules/pi-antigravity/src/client/client.ts +1 -1
  29. package/node_modules/pi-antigravity/src/image/image.ts +4 -4
  30. package/node_modules/pi-antigravity/src/index.ts +203 -13
  31. package/node_modules/pi-antigravity/src/search/index.ts +1 -0
  32. package/node_modules/pi-antigravity/src/search/search.ts +325 -0
  33. package/node_modules/pi-antigravity/src/stream/stream.ts +191 -14
  34. package/node_modules/pi-antigravity/src/types/enums.ts +45 -36
  35. package/node_modules/pi-antigravity/src/types/types.ts +5 -12
  36. package/node_modules/pi-antigravity/src/utils/http.ts +7 -2
  37. package/node_modules/pi-antigravity/src/utils/util.ts +31 -3
  38. package/node_modules/pi-lens/package.json +158 -158
  39. package/node_modules/pi-multi-account/package.json +2 -2
  40. package/node_modules/pi-typesafe/README.md +3 -1
  41. package/node_modules/pi-typesafe/dist/auth.d.ts +9 -5
  42. package/node_modules/pi-typesafe/dist/auth.js +7 -3
  43. package/node_modules/pi-typesafe/dist/backends.d.ts +33 -3
  44. package/node_modules/pi-typesafe/dist/backends.js +95 -1
  45. package/node_modules/pi-typesafe/dist/client.d.ts +5 -5
  46. package/node_modules/pi-typesafe/dist/client.js +12 -9
  47. package/node_modules/pi-typesafe/dist/credentials.d.ts +14 -8
  48. package/node_modules/pi-typesafe/dist/credentials.js +10 -7
  49. package/node_modules/pi-typesafe/dist/errors.d.ts +2 -2
  50. package/node_modules/pi-typesafe/dist/index.d.ts +2 -2
  51. package/node_modules/pi-typesafe/dist/index.js +1 -1
  52. package/node_modules/pi-typesafe/dist/login.d.ts +2 -2
  53. package/node_modules/pi-typesafe/dist/login.js +2 -2
  54. package/node_modules/pi-typesafe/package.json +6 -5
  55. package/node_modules/pi-web-access/CHANGELOG.md +72 -0
  56. package/node_modules/pi-web-access/README.md +34 -13
  57. package/node_modules/pi-web-access/chrome-cookies.ts +79 -25
  58. package/node_modules/pi-web-access/curator-page.ts +5 -1
  59. package/node_modules/pi-web-access/curator-server.ts +2 -0
  60. package/node_modules/pi-web-access/dist/index.js +1337 -1009
  61. package/node_modules/pi-web-access/exa.ts +20 -52
  62. package/node_modules/pi-web-access/extract.ts +41 -4
  63. package/node_modules/pi-web-access/gemini-search.ts +12 -4
  64. package/node_modules/pi-web-access/index.ts +29 -37
  65. package/node_modules/pi-web-access/openai-search.ts +35 -7
  66. package/node_modules/pi-web-access/package.json +8 -7
  67. package/node_modules/pi-web-access/page-query.ts +2 -2
  68. package/node_modules/pi-web-access/query-rewrite.ts +2 -3
  69. package/node_modules/pi-web-access/ssrf-protection.ts +27 -10
  70. package/node_modules/pi-web-access/storage.ts +48 -77
  71. package/node_modules/pi-web-access/summary-model-scope.ts +6 -77
  72. package/node_modules/pi-web-access/summary-review.ts +3 -4
  73. package/node_modules/pi-web-access/tavily.ts +67 -20
  74. package/node_modules/pi-web-access/tool-activation.ts +53 -33
  75. package/node_modules/pi-web-access/utils.ts +1 -1
  76. package/node_modules/pi-web-access/you.ts +164 -0
  77. package/node_modules/pi-web-access/zai.ts +161 -0
  78. package/node_modules/remote-pi/package.json +5 -1
  79. package/package.json +19 -31
  80. package/node_modules/pi-mcp-adapter/CHANGELOG.md +0 -1013
  81. package/node_modules/pi-mcp-adapter/LICENSE +0 -21
  82. package/node_modules/pi-mcp-adapter/OAUTH.md +0 -369
  83. package/node_modules/pi-mcp-adapter/README.md +0 -1021
  84. package/node_modules/pi-mcp-adapter/abort.ts +0 -34
  85. package/node_modules/pi-mcp-adapter/agent-dir.ts +0 -68
  86. package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +0 -416
  87. package/node_modules/pi-mcp-adapter/agent-plugin-provenance.ts +0 -36
  88. package/node_modules/pi-mcp-adapter/app-bridge.bundle.js +0 -67
  89. package/node_modules/pi-mcp-adapter/banner.png +0 -0
  90. package/node_modules/pi-mcp-adapter/bearer-command-resolver.ts +0 -193
  91. package/node_modules/pi-mcp-adapter/claude-plugin-loader.ts +0 -365
  92. package/node_modules/pi-mcp-adapter/cli.js +0 -454
  93. package/node_modules/pi-mcp-adapter/commands.ts +0 -861
  94. package/node_modules/pi-mcp-adapter/config.ts +0 -1565
  95. package/node_modules/pi-mcp-adapter/consent-manager.ts +0 -95
  96. package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +0 -244
  97. package/node_modules/pi-mcp-adapter/direct-tools.ts +0 -428
  98. package/node_modules/pi-mcp-adapter/dist/abort.d.ts +0 -2
  99. package/node_modules/pi-mcp-adapter/dist/abort.js +0 -36
  100. package/node_modules/pi-mcp-adapter/dist/abort.js.map +0 -1
  101. package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +0 -10
  102. package/node_modules/pi-mcp-adapter/dist/agent-dir.js +0 -63
  103. package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +0 -1
  104. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +0 -8
  105. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +0 -398
  106. package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +0 -1
  107. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.d.ts +0 -1
  108. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js +0 -31
  109. package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js.map +0 -1
  110. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.d.ts +0 -6
  111. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js +0 -194
  112. package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js.map +0 -1
  113. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.d.ts +0 -9
  114. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js +0 -362
  115. package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js.map +0 -1
  116. package/node_modules/pi-mcp-adapter/dist/config.d.ts +0 -134
  117. package/node_modules/pi-mcp-adapter/dist/config.js +0 -1361
  118. package/node_modules/pi-mcp-adapter/dist/config.js.map +0 -1
  119. package/node_modules/pi-mcp-adapter/dist/consent-manager.d.ts +0 -18
  120. package/node_modules/pi-mcp-adapter/dist/consent-manager.js +0 -88
  121. package/node_modules/pi-mcp-adapter/dist/consent-manager.js.map +0 -1
  122. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.d.ts +0 -17
  123. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js +0 -316
  124. package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js.map +0 -1
  125. package/node_modules/pi-mcp-adapter/dist/errors.d.ts +0 -131
  126. package/node_modules/pi-mcp-adapter/dist/errors.js +0 -278
  127. package/node_modules/pi-mcp-adapter/dist/errors.js.map +0 -1
  128. package/node_modules/pi-mcp-adapter/dist/http-ca.d.ts +0 -8
  129. package/node_modules/pi-mcp-adapter/dist/http-ca.js +0 -88
  130. package/node_modules/pi-mcp-adapter/dist/http-ca.js.map +0 -1
  131. package/node_modules/pi-mcp-adapter/dist/jev-client.d.ts +0 -14
  132. package/node_modules/pi-mcp-adapter/dist/jev-client.js +0 -367
  133. package/node_modules/pi-mcp-adapter/dist/jev-client.js.map +0 -1
  134. package/node_modules/pi-mcp-adapter/dist/jev-contracts.d.ts +0 -77
  135. package/node_modules/pi-mcp-adapter/dist/jev-contracts.js +0 -2
  136. package/node_modules/pi-mcp-adapter/dist/jev-contracts.js.map +0 -1
  137. package/node_modules/pi-mcp-adapter/dist/jev-key-store.d.ts +0 -51
  138. package/node_modules/pi-mcp-adapter/dist/jev-key-store.js +0 -205
  139. package/node_modules/pi-mcp-adapter/dist/jev-key-store.js.map +0 -1
  140. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.d.ts +0 -2
  141. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +0 -68
  142. package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +0 -1
  143. package/node_modules/pi-mcp-adapter/dist/lifecycle.d.ts +0 -56
  144. package/node_modules/pi-mcp-adapter/dist/lifecycle.js +0 -410
  145. package/node_modules/pi-mcp-adapter/dist/lifecycle.js.map +0 -1
  146. package/node_modules/pi-mcp-adapter/dist/logger.d.ts +0 -51
  147. package/node_modules/pi-mcp-adapter/dist/logger.js +0 -131
  148. package/node_modules/pi-mcp-adapter/dist/logger.js.map +0 -1
  149. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.d.ts +0 -26
  150. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js +0 -103
  151. package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js.map +0 -1
  152. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.d.ts +0 -118
  153. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js +0 -1097
  154. package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js.map +0 -1
  155. package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +0 -170
  156. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +0 -1142
  157. package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +0 -1
  158. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.d.ts +0 -24
  159. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js +0 -203
  160. package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js.map +0 -1
  161. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.d.ts +0 -53
  162. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js +0 -441
  163. package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js.map +0 -1
  164. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.d.ts +0 -148
  165. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js +0 -689
  166. package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js.map +0 -1
  167. package/node_modules/pi-mcp-adapter/dist/mcp-probe.d.ts +0 -6
  168. package/node_modules/pi-mcp-adapter/dist/mcp-probe.js +0 -166
  169. package/node_modules/pi-mcp-adapter/dist/mcp-probe.js.map +0 -1
  170. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.d.ts +0 -102
  171. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js +0 -369
  172. package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js.map +0 -1
  173. package/node_modules/pi-mcp-adapter/dist/mcp-trace.d.ts +0 -95
  174. package/node_modules/pi-mcp-adapter/dist/mcp-trace.js +0 -242
  175. package/node_modules/pi-mcp-adapter/dist/mcp-trace.js.map +0 -1
  176. package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +0 -19
  177. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +0 -301
  178. package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +0 -1
  179. package/node_modules/pi-mcp-adapter/dist/npx-resolver.d.ts +0 -6
  180. package/node_modules/pi-mcp-adapter/dist/npx-resolver.js +0 -505
  181. package/node_modules/pi-mcp-adapter/dist/npx-resolver.js.map +0 -1
  182. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +0 -2
  183. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +0 -144
  184. package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +0 -1
  185. package/node_modules/pi-mcp-adapter/dist/request-headers-command.d.ts +0 -10
  186. package/node_modules/pi-mcp-adapter/dist/request-headers-command.js +0 -312
  187. package/node_modules/pi-mcp-adapter/dist/request-headers-command.js.map +0 -1
  188. package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +0 -1
  189. package/node_modules/pi-mcp-adapter/dist/resource-tools.js +0 -15
  190. package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +0 -1
  191. package/node_modules/pi-mcp-adapter/dist/runtime-owner.d.ts +0 -13
  192. package/node_modules/pi-mcp-adapter/dist/runtime-owner.js +0 -97
  193. package/node_modules/pi-mcp-adapter/dist/runtime-owner.js.map +0 -1
  194. package/node_modules/pi-mcp-adapter/dist/sampling-handler.d.ts +0 -17
  195. package/node_modules/pi-mcp-adapter/dist/sampling-handler.js +0 -203
  196. package/node_modules/pi-mcp-adapter/dist/sampling-handler.js.map +0 -1
  197. package/node_modules/pi-mcp-adapter/dist/secure-keyring.d.ts +0 -11
  198. package/node_modules/pi-mcp-adapter/dist/secure-keyring.js +0 -172
  199. package/node_modules/pi-mcp-adapter/dist/secure-keyring.js.map +0 -1
  200. package/node_modules/pi-mcp-adapter/dist/server-manager.d.ts +0 -157
  201. package/node_modules/pi-mcp-adapter/dist/server-manager.js +0 -1745
  202. package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +0 -1
  203. package/node_modules/pi-mcp-adapter/dist/session-approvals.d.ts +0 -34
  204. package/node_modules/pi-mcp-adapter/dist/session-approvals.js +0 -140
  205. package/node_modules/pi-mcp-adapter/dist/session-approvals.js.map +0 -1
  206. package/node_modules/pi-mcp-adapter/dist/session-recovery.d.ts +0 -26
  207. package/node_modules/pi-mcp-adapter/dist/session-recovery.js +0 -142
  208. package/node_modules/pi-mcp-adapter/dist/session-recovery.js.map +0 -1
  209. package/node_modules/pi-mcp-adapter/dist/state.d.ts +0 -73
  210. package/node_modules/pi-mcp-adapter/dist/state.js +0 -2
  211. package/node_modules/pi-mcp-adapter/dist/state.js.map +0 -1
  212. package/node_modules/pi-mcp-adapter/dist/types.d.ts +0 -642
  213. package/node_modules/pi-mcp-adapter/dist/types.js +0 -331
  214. package/node_modules/pi-mcp-adapter/dist/types.js.map +0 -1
  215. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +0 -6
  216. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +0 -37
  217. package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +0 -1
  218. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.d.ts +0 -17
  219. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js +0 -219
  220. package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js.map +0 -1
  221. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +0 -104
  222. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +0 -59
  223. package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +0 -1
  224. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +0 -4
  225. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +0 -27
  226. package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +0 -1
  227. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.d.ts +0 -15
  228. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js +0 -85
  229. package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js.map +0 -1
  230. package/node_modules/pi-mcp-adapter/dist/utils.d.ts +0 -41
  231. package/node_modules/pi-mcp-adapter/dist/utils.js +0 -417
  232. package/node_modules/pi-mcp-adapter/dist/utils.js.map +0 -1
  233. package/node_modules/pi-mcp-adapter/elicitation-handler.ts +0 -358
  234. package/node_modules/pi-mcp-adapter/error-signal.ts +0 -32
  235. package/node_modules/pi-mcp-adapter/errors.ts +0 -364
  236. package/node_modules/pi-mcp-adapter/examples/jev-accessibility-loop.mjs +0 -85
  237. package/node_modules/pi-mcp-adapter/examples/jev-semantic-filter.mjs +0 -34
  238. package/node_modules/pi-mcp-adapter/failure-backoff.ts +0 -23
  239. package/node_modules/pi-mcp-adapter/glimpse-ui.ts +0 -80
  240. package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -515
  241. package/node_modules/pi-mcp-adapter/http-ca.ts +0 -84
  242. package/node_modules/pi-mcp-adapter/index.ts +0 -2106
  243. package/node_modules/pi-mcp-adapter/init.ts +0 -721
  244. package/node_modules/pi-mcp-adapter/jev-client.ts +0 -300
  245. package/node_modules/pi-mcp-adapter/jev-contracts.ts +0 -53
  246. package/node_modules/pi-mcp-adapter/jev-key-store.ts +0 -192
  247. package/node_modules/pi-mcp-adapter/json-schema-validator.ts +0 -83
  248. package/node_modules/pi-mcp-adapter/lazy-loader.ts +0 -7
  249. package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -457
  250. package/node_modules/pi-mcp-adapter/logger.ts +0 -169
  251. package/node_modules/pi-mcp-adapter/mcp-auth-fetch.ts +0 -113
  252. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +0 -1296
  253. package/node_modules/pi-mcp-adapter/mcp-auth.ts +0 -1287
  254. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +0 -250
  255. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +0 -534
  256. package/node_modules/pi-mcp-adapter/mcp-code.ts +0 -495
  257. package/node_modules/pi-mcp-adapter/mcp-install.ts +0 -60
  258. package/node_modules/pi-mcp-adapter/mcp-keyring-helper.cjs +0 -89
  259. package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +0 -819
  260. package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +0 -511
  261. package/node_modules/pi-mcp-adapter/mcp-panel-theme.ts +0 -104
  262. package/node_modules/pi-mcp-adapter/mcp-panel.ts +0 -1099
  263. package/node_modules/pi-mcp-adapter/mcp-probe.ts +0 -201
  264. package/node_modules/pi-mcp-adapter/mcp-references.ts +0 -373
  265. package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +0 -137
  266. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +0 -747
  267. package/node_modules/pi-mcp-adapter/mcp-status.ts +0 -105
  268. package/node_modules/pi-mcp-adapter/mcp-tasks.ts +0 -467
  269. package/node_modules/pi-mcp-adapter/mcp-trace.ts +0 -306
  270. package/node_modules/pi-mcp-adapter/metadata-cache.ts +0 -362
  271. package/node_modules/pi-mcp-adapter/namespace-tools.ts +0 -334
  272. package/node_modules/pi-mcp-adapter/npx-resolver.ts +0 -543
  273. package/node_modules/pi-mcp-adapter/oauth-handler.ts +0 -30
  274. package/node_modules/pi-mcp-adapter/oauth.ts +0 -52
  275. package/node_modules/pi-mcp-adapter/onboarding-state.ts +0 -76
  276. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +0 -156
  277. package/node_modules/pi-mcp-adapter/package.json +0 -219
  278. package/node_modules/pi-mcp-adapter/panel-keys.ts +0 -53
  279. package/node_modules/pi-mcp-adapter/prompts.ts +0 -385
  280. package/node_modules/pi-mcp-adapter/proxy-modes.ts +0 -1735
  281. package/node_modules/pi-mcp-adapter/request-headers-command.ts +0 -333
  282. package/node_modules/pi-mcp-adapter/resource-tools.ts +0 -17
  283. package/node_modules/pi-mcp-adapter/runtime-owner.ts +0 -106
  284. package/node_modules/pi-mcp-adapter/sampling-handler.ts +0 -261
  285. package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +0 -144
  286. package/node_modules/pi-mcp-adapter/search-ranking.ts +0 -309
  287. package/node_modules/pi-mcp-adapter/secure-keyring.ts +0 -170
  288. package/node_modules/pi-mcp-adapter/semantic-search.ts +0 -186
  289. package/node_modules/pi-mcp-adapter/server-manager.ts +0 -2088
  290. package/node_modules/pi-mcp-adapter/session-approvals.ts +0 -201
  291. package/node_modules/pi-mcp-adapter/session-recovery.ts +0 -158
  292. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +0 -49
  293. package/node_modules/pi-mcp-adapter/state.ts +0 -71
  294. package/node_modules/pi-mcp-adapter/tool-approval.ts +0 -205
  295. package/node_modules/pi-mcp-adapter/tool-metadata.ts +0 -302
  296. package/node_modules/pi-mcp-adapter/tool-registrar.ts +0 -255
  297. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +0 -573
  298. package/node_modules/pi-mcp-adapter/ts-shape.ts +0 -149
  299. package/node_modules/pi-mcp-adapter/types.ts +0 -1120
  300. package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +0 -40
  301. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +0 -266
  302. package/node_modules/pi-mcp-adapter/ui-server.ts +0 -993
  303. package/node_modules/pi-mcp-adapter/ui-session.ts +0 -624
  304. package/node_modules/pi-mcp-adapter/ui-stream-types.ts +0 -89
  305. package/node_modules/pi-mcp-adapter/ui-tool-visibility.ts +0 -25
  306. package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +0 -85
  307. package/node_modules/pi-mcp-adapter/utils.ts +0 -464
@@ -1,819 +0,0 @@
1
- /**
2
- * MCP OAuth Provider
3
- *
4
- * Implementation of the MCP SDK's OAuthClientProvider interface.
5
- * Handles OAuth client registration, token storage, and authorization redirection.
6
- */
7
-
8
- import {
9
- UnauthorizedError,
10
- type FetchLike,
11
- type AddClientAuthentication,
12
- type OAuthClientInformationContext,
13
- type OAuthClientProvider,
14
- type OAuthDiscoveryState,
15
- } from "@modelcontextprotocol/client"
16
- import type {
17
- OAuthClientInformationMixed,
18
- OAuthClientMetadata,
19
- OAuthTokens,
20
- } from "@modelcontextprotocol/client"
21
- import {
22
- getAuthForUrl,
23
- updateTokens,
24
- updateClientInfo,
25
- clearAllCredentials,
26
- clearCodeVerifier,
27
- invalidateAuthEntryCache,
28
- captureOAuthAuthority,
29
- type AuthEntry,
30
- type AuthStorageOptions,
31
- type OAuthAuthority,
32
- type StoredTokens,
33
- type StoredClientInfo,
34
- } from "./mcp-auth.ts"
35
- import { OAuthMetadataSchema, OpenIdProviderDiscoveryMetadataSchema } from "@modelcontextprotocol/core"
36
- import { createOAuthFetch, type OAuthFetch } from "./mcp-auth-fetch.ts"
37
- import { resolveCommandSecret } from "./utils.ts"
38
- import { getAppClientUri, getAppName } from "./agent-dir.ts"
39
-
40
- /**
41
- * Client name advertised during Dynamic Client Registration.
42
- *
43
- * A distribution that rebrands pi (arc, tau, …) should register under its own
44
- * name — otherwise every consent screen its users see asks them to authorize
45
- * an app they have never run. Stock pi keeps the long-standing
46
- * "Pi Coding Agent" so existing registrations are unaffected.
47
- */
48
- function defaultClientName(): string {
49
- const app = getAppName()
50
- return app === "pi" ? "Pi Coding Agent" : app
51
- }
52
-
53
- /**
54
- * Client homepage advertised during Dynamic Client Registration.
55
- *
56
- * RFC 7591 defines client_uri as the home page *of the client*. Under a
57
- * rebranded pi the client is that distribution, not this adapter, so pointing
58
- * at the adapter's repository misidentifies it on the consent screen. There is
59
- * no way to guess the right URL and a wrong one is worse than none, so the
60
- * field is omitted unless a server config supplies oauth.clientUri.
61
- *
62
- * Stock pi keeps the historical value.
63
- */
64
- function defaultClientUri(): string | undefined {
65
- const declared = getAppClientUri()
66
- if (declared) return declared
67
- return getAppName() === "pi" ? "https://github.com/nicobailon/pi-mcp-adapter" : undefined
68
- }
69
-
70
- type IssuerBoundClientInformation = OAuthClientInformationMixed & { issuer?: string }
71
- type IssuerBoundTokens = OAuthTokens & { issuer?: string }
72
-
73
- function issuersMatch(first: string, second: string): boolean {
74
- return first === second
75
- || (first.endsWith("/") && first.slice(0, -1) === second)
76
- || (second.endsWith("/") && second.slice(0, -1) === first)
77
- }
78
-
79
- function toOAuthTokens(tokens: StoredTokens): IssuerBoundTokens {
80
- const result: IssuerBoundTokens = {
81
- access_token: tokens.accessToken,
82
- token_type: "Bearer",
83
- }
84
- if (tokens.refreshToken !== undefined) result.refresh_token = tokens.refreshToken
85
- if (tokens.expiresAt !== undefined) result.expires_in = Math.max(0, Math.floor(tokens.expiresAt - Date.now() / 1000))
86
- if (tokens.scope !== undefined) result.scope = tokens.scope
87
- if (tokens.issuer !== undefined) result.issuer = tokens.issuer
88
- return result
89
- }
90
-
91
- // Callback server configuration
92
- const DEFAULT_OAUTH_CALLBACK_PORT = 19876
93
- const DEFAULT_OAUTH_CALLBACK_PATH = "/callback"
94
-
95
- let configuredOAuthCallbackPort = DEFAULT_OAUTH_CALLBACK_PORT
96
-
97
- if (process.env.MCP_OAUTH_CALLBACK_PORT) {
98
- const parsedPort = Number.parseInt(process.env.MCP_OAUTH_CALLBACK_PORT, 10)
99
- if (Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535) {
100
- configuredOAuthCallbackPort = parsedPort
101
- }
102
- }
103
-
104
- let oauthCallbackPort = configuredOAuthCallbackPort
105
- let oauthCallbackPath = DEFAULT_OAUTH_CALLBACK_PATH
106
-
107
- export function getConfiguredOAuthCallbackPort(): number {
108
- return configuredOAuthCallbackPort
109
- }
110
-
111
- export function getOAuthCallbackPort(): number {
112
- return oauthCallbackPort
113
- }
114
-
115
- export function setOAuthCallbackPort(port: number): void {
116
- oauthCallbackPort = port
117
- }
118
-
119
- export function getOAuthCallbackPath(): string {
120
- return oauthCallbackPath
121
- }
122
-
123
- export function setOAuthCallbackPath(path: string): void {
124
- oauthCallbackPath = path.startsWith("/") ? path : `/${path}`
125
- }
126
-
127
- /** Configuration options for OAuth */
128
- export interface McpOAuthConfig {
129
- grantType?: "authorization_code" | "client_credentials"
130
- clientId?: string
131
- clientSecret?: string
132
- clientMetadataUrl?: string
133
- scope?: string
134
- authorizationParams?: Record<string, string>
135
- redirectUri?: string
136
- clientName?: string
137
- clientUri?: string
138
- logoUri?: string
139
- authServerMetadataUrl?: string
140
- skipIssuerMetadataValidation?: boolean
141
- }
142
-
143
- const reservedAuthorizationParams = new Set([
144
- "client_id",
145
- "code_challenge",
146
- "code_challenge_method",
147
- "redirect_uri",
148
- "resource",
149
- "response_type",
150
- "scope",
151
- "state",
152
- ])
153
-
154
- function addAuthorizationParams(authorizationUrl: URL, params: Record<string, string> | undefined): URL {
155
- if (!params) return authorizationUrl
156
- const nextUrl = new URL(authorizationUrl.toString())
157
- for (const [key, value] of Object.entries(params)) {
158
- if (reservedAuthorizationParams.has(key) || nextUrl.searchParams.has(key)) {
159
- throw new Error(`OAuth authorizationParams.${key} cannot override an authorization flow parameter`)
160
- }
161
- nextUrl.searchParams.set(key, value)
162
- }
163
- return nextUrl
164
- }
165
-
166
- /** Callbacks for OAuth flow interactions */
167
- export interface McpOAuthCallbacks {
168
- onRedirect: (url: URL) => void | Promise<void>
169
- }
170
-
171
- function inferIssuerFromMetadataUrl(metadataUrl: string): string | undefined {
172
- const url = new URL(metadataUrl)
173
- const pathname = url.pathname.replace(/\/+$/, "") || "/"
174
- const oauthPrefix = "/.well-known/oauth-authorization-server"
175
- if (pathname === oauthPrefix || pathname.startsWith(`${oauthPrefix}/`)) {
176
- const issuerPath = pathname.slice(oauthPrefix.length) || "/"
177
- return new URL(issuerPath, url.origin).toString()
178
- }
179
-
180
- const oidcPath = "/.well-known/openid-configuration"
181
- if (pathname === oidcPath || pathname.startsWith(`${oidcPath}/`)) {
182
- const issuerPath = pathname.slice(oidcPath.length) || "/"
183
- return new URL(issuerPath, url.origin).toString()
184
- }
185
- if (pathname.endsWith(oidcPath)) {
186
- const issuerPath = pathname.slice(0, -oidcPath.length) || "/"
187
- return new URL(issuerPath, url.origin).toString()
188
- }
189
- return undefined
190
- }
191
-
192
- function validateConfiguredIssuer(metadataUrl: string, issuer: string, skipIssuerValidation: boolean): void {
193
- let parsedIssuer: URL
194
- try {
195
- parsedIssuer = new URL(issuer)
196
- } catch (error) {
197
- throw new Error("OAuth authorization-server metadata issuer must be an absolute URL", { cause: error })
198
- }
199
- if (parsedIssuer.protocol !== "http:" && parsedIssuer.protocol !== "https:") {
200
- throw new Error("OAuth authorization-server metadata issuer must use http:// or https://")
201
- }
202
-
203
- const expectedIssuer = inferIssuerFromMetadataUrl(metadataUrl)
204
- if (skipIssuerValidation) return
205
- if (expectedIssuer !== undefined && !issuersMatch(expectedIssuer, issuer)) {
206
- throw new Error(
207
- `OAuth authorization-server metadata issuer does not match authServerMetadataUrl: expected ${expectedIssuer}`,
208
- )
209
- }
210
- if (expectedIssuer === undefined && !issuersMatch(new URL(metadataUrl).origin, issuer)) {
211
- throw new Error(
212
- `OAuth authorization-server metadata issuer does not match authServerMetadataUrl origin: expected ${new URL(metadataUrl).origin}`,
213
- )
214
- }
215
- }
216
-
217
- async function loadConfiguredDiscoveryState(
218
- metadataUrl: string,
219
- serverUrl: string,
220
- skipIssuerValidation: boolean,
221
- fetchFn: FetchLike,
222
- ): Promise<OAuthDiscoveryState> {
223
- const response = await fetchFn(metadataUrl, {
224
- headers: { accept: "application/json" },
225
- })
226
- if (!response.ok) {
227
- await response.text().catch(() => {})
228
- throw new Error(`OAuth authServerMetadataUrl request failed with HTTP ${response.status}`)
229
- }
230
-
231
- const payload = await response.json()
232
- const oauthResult = OAuthMetadataSchema.safeParse(payload)
233
- const metadata = oauthResult.success
234
- ? oauthResult.data
235
- : OpenIdProviderDiscoveryMetadataSchema.parse(payload)
236
- validateConfiguredIssuer(metadataUrl, metadata.issuer, skipIssuerValidation)
237
-
238
- const resource = new URL(serverUrl)
239
- resource.hash = ""
240
- return {
241
- authorizationServerUrl: metadata.issuer,
242
- authorizationServerMetadata: metadata,
243
- // The configured AS document is authoritative, so avoid a second PRM
244
- // lookup while still binding the token request to the configured resource.
245
- resourceMetadata: { resource: resource.toString() },
246
- }
247
- }
248
-
249
- /**
250
- * OAuth provider implementation for MCP servers.
251
- * Implements the OAuthClientProvider interface from the MCP SDK.
252
- */
253
- export class McpOAuthProvider implements OAuthClientProvider {
254
- readonly clientMetadataUrl?: string
255
- private readonly redirectUrlSnapshot: string | undefined
256
- private authFetch: OAuthFetch
257
- private active = true
258
- private flowClientInfo: StoredClientInfo | undefined
259
- private flowCodeVerifier: string | undefined
260
- private flowDiscoveryState: OAuthDiscoveryState | undefined
261
- private flowIssuerMismatch = false
262
- private flowState: string | undefined
263
- private invalidatedAccessToken: string | undefined
264
- private invalidatedClientId: string | undefined
265
- private staleRedirectClientId: string | undefined
266
- private lastObservedClientId: string | undefined
267
- private lastSavedAccessToken: string | undefined
268
- private pendingAuthAccessToken: string | undefined
269
- private readonly assertAuthority: OAuthAuthority
270
-
271
- constructor(
272
- private serverName: string,
273
- private serverUrl: string,
274
- private config: McpOAuthConfig,
275
- private callbacks: McpOAuthCallbacks,
276
- private storageOptions: AuthStorageOptions = {},
277
- private runtimeSignal?: AbortSignal,
278
- initialState?: string,
279
- authority?: OAuthAuthority,
280
- ) {
281
- this.assertAuthority = authority ?? captureOAuthAuthority(serverName)
282
- this.assertAuthority()
283
- if (config.clientId === undefined && config.clientMetadataUrl !== undefined) {
284
- this.clientMetadataUrl = config.clientMetadataUrl
285
- }
286
- this.authFetch = createOAuthFetch(serverUrl, undefined, runtimeSignal)
287
- this.flowState = initialState
288
- this.redirectUrlSnapshot = config.grantType === "client_credentials"
289
- ? undefined
290
- : config.redirectUri ?? `http://localhost:${getOAuthCallbackPort()}${getOAuthCallbackPath()}`
291
- }
292
-
293
- setAuthFetch(fetchFn: OAuthFetch): void {
294
- this.authFetch = fetchFn
295
- }
296
-
297
- private get usesClientCredentials(): boolean {
298
- return this.config.grantType === "client_credentials"
299
- }
300
-
301
- private get discoveredIssuer(): string | undefined {
302
- return this.flowDiscoveryState?.authorizationServerMetadata?.issuer
303
- ?? this.flowDiscoveryState?.authorizationServerUrl
304
- }
305
-
306
- deactivate(): void {
307
- this.active = false
308
- this.invalidatedAccessToken = undefined
309
- this.invalidatedClientId = undefined
310
- this.staleRedirectClientId = undefined
311
- this.lastObservedClientId = undefined
312
- this.lastSavedAccessToken = undefined
313
- this.pendingAuthAccessToken = undefined
314
- }
315
-
316
- private assertStoredIssuerBindings(entry: AuthEntry | undefined, issuer: string | undefined): void {
317
- if (this.flowIssuerMismatch) {
318
- throw new Error(
319
- `OAuth authorization server issuer changed for ${this.serverName}; clear credentials before authenticating again`,
320
- )
321
- }
322
- if (!entry || !issuer) return
323
-
324
- const storedIssuers = [entry.clientInfo?.issuer, entry.tokens?.issuer]
325
- .filter((storedIssuer): storedIssuer is string => storedIssuer !== undefined)
326
- if (storedIssuers.some(storedIssuer => !issuersMatch(storedIssuer, issuer))) {
327
- this.flowIssuerMismatch = true
328
- throw new Error(
329
- `OAuth authorization server issuer changed for ${this.serverName}; clear credentials before authenticating again`,
330
- )
331
- }
332
- }
333
-
334
- private throwIfInactive(): void {
335
- if (!this.active) throw new Error("OAuth flow is no longer active")
336
- this.assertAuthority()
337
- this.runtimeSignal?.throwIfAborted()
338
- // The SDK can swallow refresh fetch errors and attempt browser authorization.
339
- // A failed service credential must stop that fallback and token persistence.
340
- this.authFetch.throwIfHeaderResolutionFailed()
341
- }
342
-
343
- /**
344
- * The redirect URL for OAuth callbacks.
345
- * This must match the redirect_uri in client metadata.
346
- */
347
- get redirectUrl(): string | undefined {
348
- return this.redirectUrlSnapshot
349
- }
350
-
351
- /** Configured homepage, else the historical default on stock pi, else nothing. */
352
- private get clientUri(): string | undefined {
353
- return this.config.clientUri ?? defaultClientUri()
354
- }
355
-
356
- /**
357
- * Client metadata for dynamic registration.
358
- * Describes this client to the OAuth authorization server.
359
- */
360
- get clientMetadata(): OAuthClientMetadata {
361
- if (this.usesClientCredentials) {
362
- return {
363
- client_name: this.config.clientName ?? defaultClientName(),
364
- ...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),
365
- ...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),
366
- redirect_uris: [],
367
- grant_types: ["client_credentials"],
368
- token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
369
- }
370
- }
371
-
372
- const redirectUrl = this.redirectUrl
373
- if (!redirectUrl) {
374
- throw new Error("redirectUrl is required for authorization_code flow")
375
- }
376
-
377
- return {
378
- redirect_uris: [redirectUrl],
379
- client_name: this.config.clientName ?? defaultClientName(),
380
- ...(this.clientUri !== undefined ? { client_uri: this.clientUri } : {}),
381
- ...(this.config.logoUri !== undefined ? { logo_uri: this.config.logoUri } : {}),
382
- grant_types: ["authorization_code", "refresh_token"],
383
- response_types: ["code"],
384
- token_endpoint_auth_method: this.config.clientSecret ? "client_secret_post" : "none",
385
- ...(this.config.scope !== undefined ? { scope: this.config.scope } : {}),
386
- }
387
- }
388
-
389
- /**
390
- * Get client information (for pre-registered or dynamically registered clients).
391
- * Returns undefined if no client info exists or if the server URL has changed.
392
- */
393
- async clientInformation(): Promise<OAuthClientInformationMixed | undefined> {
394
- this.throwIfInactive()
395
- if (this.invalidatedClientId !== undefined) {
396
- invalidateAuthEntryCache(this.serverName)
397
- }
398
- const issuer = this.discoveredIssuer
399
- const stored = await getAuthForUrl(this.serverName, this.serverUrl, this.storageOptions)
400
- this.throwIfInactive()
401
- this.assertStoredIssuerBindings(stored, issuer)
402
-
403
- // Check config first (pre-registered client). Store only its issuer binding.
404
- // The configured secret stays in config and never enters the credential store.
405
- if (this.config.clientId) {
406
- const storedClient = stored?.clientInfo?.clientId === this.config.clientId
407
- ? stored.clientInfo
408
- : undefined
409
- if (issuer && (storedClient?.issuer !== issuer || storedClient.configPreRegistered !== true)) {
410
- this.throwIfInactive()
411
- updateClientInfo(
412
- this.serverName,
413
- { clientId: this.config.clientId, issuer, configPreRegistered: true },
414
- this.serverUrl,
415
- this.storageOptions,
416
- )
417
- }
418
- const clientSecret = this.config.clientSecret?.startsWith("!")
419
- ? resolveCommandSecret(
420
- this.config.clientSecret,
421
- `MCP server "${this.serverName}" OAuth clientSecret`,
422
- )
423
- : this.config.clientSecret
424
- return {
425
- client_id: this.config.clientId,
426
- client_secret: clientSecret,
427
- ...(issuer !== undefined ? { issuer } : {}),
428
- } as IssuerBoundClientInformation
429
- }
430
-
431
- // Keep client registration associated with this in-flight flow even if
432
- // another runtime writes the shared persistent entry for the same name.
433
- const clientInfo = this.flowClientInfo ?? stored?.clientInfo
434
- if (clientInfo?.clientId === this.invalidatedClientId) return undefined
435
-
436
- const clientMetadataUrl = this.clientMetadataUrl
437
- const supportsClientMetadataDocument = this.flowDiscoveryState
438
- ?.authorizationServerMetadata?.client_id_metadata_document_supported
439
- if (clientMetadataUrl !== undefined && supportsClientMetadataDocument !== undefined) {
440
- if (supportsClientMetadataDocument === true
441
- && clientInfo?.clientId !== clientMetadataUrl
442
- && (stored?.tokens?.refreshToken === undefined || this.invalidatedAccessToken !== undefined)) {
443
- // With no DCR refresh pair to preserve, let the SDK select CIMD now.
444
- return undefined
445
- }
446
- if (supportsClientMetadataDocument !== true && clientInfo?.clientId === clientMetadataUrl) {
447
- return undefined
448
- }
449
- }
450
-
451
- if (clientInfo) {
452
- this.invalidatedClientId = undefined
453
- // A stored SEP-2352 issuer stub for a config-pre-registered client
454
- // (identified by the explicit marker, or by the legacy stub shape of
455
- // {clientId, issuer} with no registration metadata) is only meaningful
456
- // when the config supplies the matching client secret. Since we reach
457
- // this branch only when config.clientId is absent, serving the stub
458
- // would let a token refresh go out with a client_id but no secret,
459
- // causing invalid_client and credential invalidation. Return undefined
460
- // so callers treat this as "no client info".
461
- const isConfiguredCimd = clientMetadataUrl !== undefined
462
- && clientInfo.clientId === clientMetadataUrl
463
- const isConfigStub = clientInfo.configPreRegistered === true
464
- || (clientInfo.clientSecret === undefined
465
- && clientInfo.clientIdIssuedAt === undefined
466
- && clientInfo.clientSecretExpiresAt === undefined
467
- && clientInfo.redirectUris === undefined)
468
- if (isConfigStub && !isConfiguredCimd) {
469
- return undefined
470
- }
471
- // Check if client secret has expired
472
- if (clientInfo.clientSecretExpiresAt && clientInfo.clientSecretExpiresAt < Date.now() / 1000) {
473
- return undefined
474
- }
475
- if (issuer && clientInfo.issuer && !issuersMatch(clientInfo.issuer, issuer)) {
476
- return undefined
477
- }
478
- if (issuer && clientInfo.issuer === undefined) {
479
- clientInfo.issuer = issuer
480
- this.flowClientInfo = clientInfo
481
- this.throwIfInactive()
482
- updateClientInfo(this.serverName, clientInfo, this.serverUrl, this.storageOptions)
483
- }
484
- // Keep a stale dynamic registration available for its refresh attempt,
485
- // but suppress it if that attempt invalidates the token and auth falls
486
- // back to an interactive flow. The next clientInformation() call then
487
- // makes the SDK register the current callback URI.
488
- const redirectUriIsStale = this.redirectUrl !== undefined
489
- && (!Array.isArray(clientInfo.redirectUris) || !clientInfo.redirectUris.includes(this.redirectUrl))
490
- this.staleRedirectClientId = redirectUriIsStale ? clientInfo.clientId : undefined
491
- // Return all registration metadata and the local issuer extension.
492
- // This keeps the SDK OAuth view and the stored issuer binding consistent.
493
- this.lastObservedClientId = clientInfo.clientId
494
- return {
495
- client_id: clientInfo.clientId,
496
- client_secret: clientInfo.clientSecret,
497
- ...(clientInfo.clientIdIssuedAt !== undefined
498
- ? { client_id_issued_at: clientInfo.clientIdIssuedAt }
499
- : {}),
500
- ...(clientInfo.clientSecretExpiresAt !== undefined
501
- ? { client_secret_expires_at: clientInfo.clientSecretExpiresAt }
502
- : {}),
503
- ...(clientInfo.redirectUris !== undefined
504
- ? { redirect_uris: clientInfo.redirectUris }
505
- : {}),
506
- ...(clientInfo.issuer !== undefined ? { issuer: clientInfo.issuer } : {}),
507
- } as IssuerBoundClientInformation
508
- }
509
-
510
- // No client info or URL changed - will trigger dynamic registration
511
- return undefined
512
- }
513
-
514
- /**
515
- * Save client information from dynamic registration.
516
- */
517
- async saveClientInformation(info: OAuthClientInformationMixed): Promise<void> {
518
- this.throwIfInactive()
519
- const issuer = this.discoveredIssuer ?? (info as IssuerBoundClientInformation).issuer
520
- if (this.config.clientId && info.client_id === this.config.clientId) {
521
- updateClientInfo(
522
- this.serverName,
523
- {
524
- clientId: info.client_id,
525
- ...(issuer !== undefined ? { issuer } : {}),
526
- configPreRegistered: true,
527
- },
528
- this.serverUrl,
529
- this.storageOptions,
530
- )
531
- return
532
- }
533
-
534
- const redirectUris = ("redirect_uris" in info ? info.redirect_uris : undefined)
535
- ?? (this.redirectUrl ? [this.redirectUrl] : undefined)
536
- const clientInfo: StoredClientInfo = {
537
- clientId: info.client_id,
538
- ...(info.client_secret !== undefined ? { clientSecret: info.client_secret } : {}),
539
- ...(info.client_id_issued_at !== undefined ? { clientIdIssuedAt: info.client_id_issued_at } : {}),
540
- ...(info.client_secret_expires_at !== undefined ? { clientSecretExpiresAt: info.client_secret_expires_at } : {}),
541
- ...(redirectUris !== undefined ? { redirectUris } : {}),
542
- ...(issuer !== undefined ? { issuer } : {}),
543
- }
544
- this.flowClientInfo = clientInfo
545
- this.invalidatedClientId = undefined
546
- this.lastObservedClientId = clientInfo.clientId
547
- updateClientInfo(this.serverName, clientInfo, this.serverUrl, this.storageOptions)
548
- }
549
-
550
- /**
551
- * Get stored OAuth tokens.
552
- * Returns undefined if no tokens exist or if the server URL has changed.
553
- */
554
- async tokens(ctx?: OAuthClientInformationContext): Promise<OAuthTokens | undefined> {
555
- this.throwIfInactive()
556
- // Once this provider rejects a token, bypass its process-local cache until
557
- // another process replaces that token in shared secure storage.
558
- if (this.invalidatedAccessToken !== undefined) {
559
- invalidateAuthEntryCache(this.serverName)
560
- }
561
-
562
- // Use getAuthForUrl to validate tokens are for the current server URL.
563
- const entry = await getAuthForUrl(this.serverName, this.serverUrl, this.storageOptions)
564
- this.throwIfInactive()
565
- if (!entry?.tokens || entry.tokens.accessToken === this.invalidatedAccessToken) return undefined
566
- this.invalidatedAccessToken = undefined
567
- const issuer = this.discoveredIssuer
568
- this.assertStoredIssuerBindings(entry, issuer)
569
- if (issuer && entry.tokens.issuer === undefined) {
570
- entry.tokens.issuer = issuer
571
- this.throwIfInactive()
572
- updateTokens(this.serverName, entry.tokens, this.serverUrl, this.storageOptions)
573
- }
574
- if (ctx !== undefined) {
575
- this.pendingAuthAccessToken = entry.tokens.accessToken
576
- }
577
-
578
- return toOAuthTokens(entry.tokens)
579
- }
580
-
581
- /**
582
- * Save OAuth tokens.
583
- */
584
- async saveTokens(tokens: OAuthTokens): Promise<void> {
585
- const issuer = this.discoveredIssuer ?? (tokens as IssuerBoundTokens).issuer
586
- const storedTokens: StoredTokens = {
587
- accessToken: tokens.access_token,
588
- ...(tokens.refresh_token !== undefined ? { refreshToken: tokens.refresh_token } : {}),
589
- // Preserve expiry even when expires_in is 0 (e.g. the SDK re-saving an
590
- // already-expired token) so expired tokens stay expired instead of
591
- // being persisted as never-expiring.
592
- ...(tokens.expires_in !== undefined ? { expiresAt: Date.now() / 1000 + tokens.expires_in } : {}),
593
- ...(tokens.scope !== undefined ? { scope: tokens.scope } : {}),
594
- ...(issuer !== undefined ? { issuer } : {}),
595
- }
596
- this.throwIfInactive()
597
- updateTokens(this.serverName, storedTokens, this.serverUrl, this.storageOptions)
598
- this.invalidatedAccessToken = undefined
599
- this.lastSavedAccessToken = storedTokens.accessToken
600
- // Discovery must survive the browser redirect so the callback can verify
601
- // the authorization server that minted the code. Once token issuance
602
- // succeeds, clear it so a later 401 re-reads PRM and can observe an
603
- // authorization-server migration.
604
- this.flowDiscoveryState = undefined
605
- }
606
-
607
- /**
608
- * Redirect the user to the authorization URL.
609
- * This opens the browser for the user to authenticate.
610
- *
611
- * Throws UnauthorizedError when called outside of a user-initiated flow
612
- * (no oauthState saved by startAuth). That path is reached when the SDK
613
- * falls through from a failed refresh into a fresh authorization_code
614
- * flow, which library hosts cannot complete in-process.
615
- */
616
- async redirectToAuthorization(authorizationUrl: URL): Promise<void> {
617
- if (this.usesClientCredentials) {
618
- throw new Error("redirectToAuthorization is not used for client_credentials flow")
619
- }
620
- // No flow-local state means we're on the post-refresh authorize fallback.
621
- this.throwIfInactive()
622
- if (!this.flowState) {
623
- throw new UnauthorizedError(
624
- `Re-authentication required for MCP server: ${this.serverName}`,
625
- )
626
- }
627
- // URL is passed to callback, not logged (may contain sensitive params)
628
- await this.callbacks.onRedirect(addAuthorizationParams(authorizationUrl, this.config.authorizationParams))
629
- }
630
-
631
- /**
632
- * Save the PKCE code verifier.
633
- */
634
- async saveCodeVerifier(codeVerifier: string): Promise<void> {
635
- this.throwIfInactive()
636
- this.flowCodeVerifier = codeVerifier
637
- }
638
-
639
- /**
640
- * Get the stored PKCE code verifier.
641
- * @throws Error if no code verifier is stored
642
- */
643
- async codeVerifier(): Promise<string> {
644
- if (this.usesClientCredentials) {
645
- throw new Error("codeVerifier is not used for client_credentials flow")
646
- }
647
- this.throwIfInactive()
648
- if (!this.flowCodeVerifier) {
649
- throw new Error(`No code verifier saved for MCP server: ${this.serverName}`)
650
- }
651
- return this.flowCodeVerifier
652
- }
653
-
654
- /**
655
- * Keep discovery with the in-flight PKCE verifier. The callback leg uses it
656
- * to validate the authorization response issuer before token exchange.
657
- */
658
- async saveDiscoveryState(state: OAuthDiscoveryState): Promise<void> {
659
- this.throwIfInactive()
660
- this.flowDiscoveryState = structuredClone(state)
661
- }
662
-
663
- async discoveryState(): Promise<OAuthDiscoveryState | undefined> {
664
- this.throwIfInactive()
665
- if (!this.flowDiscoveryState && this.config.authServerMetadataUrl !== undefined) {
666
- const discoveryState = await loadConfiguredDiscoveryState(
667
- this.config.authServerMetadataUrl,
668
- this.serverUrl,
669
- this.config.skipIssuerMetadataValidation === true,
670
- this.authFetch,
671
- )
672
- this.throwIfInactive()
673
- this.flowDiscoveryState = discoveryState
674
- }
675
- this.throwIfInactive()
676
- return this.flowDiscoveryState ? structuredClone(this.flowDiscoveryState) : undefined
677
- }
678
-
679
- /** Internal connection-attempt identity check for manager cleanup. */
680
- /**
681
- * Save the OAuth state parameter for CSRF protection.
682
- */
683
- async saveState(state: string): Promise<void> {
684
- this.throwIfInactive()
685
- this.flowState = state
686
- }
687
-
688
- /**
689
- * Get the stored OAuth state parameter.
690
- * @throws UnauthorizedError if no flow is in progress (see redirectToAuthorization)
691
- */
692
- async state(): Promise<string> {
693
- if (this.usesClientCredentials) {
694
- throw new Error("state is not used for client_credentials flow")
695
- }
696
- this.throwIfInactive()
697
- if (!this.flowState) {
698
- throw new UnauthorizedError(
699
- `Re-authentication required for MCP server: ${this.serverName}`,
700
- )
701
- }
702
- return this.flowState
703
- }
704
-
705
- /**
706
- * Invalidate credentials when authentication fails.
707
- * Clears tokens, client info, or all credentials based on the type.
708
- */
709
- async invalidateCredentials(type: "all" | "client" | "tokens" | "verifier" | "discovery"): Promise<void> {
710
- this.throwIfInactive()
711
- switch (type) {
712
- case "all":
713
- this.flowClientInfo = undefined
714
- this.flowCodeVerifier = undefined
715
- this.flowDiscoveryState = undefined
716
- this.flowIssuerMismatch = false
717
- this.flowState = undefined
718
- this.invalidatedAccessToken = undefined
719
- this.invalidatedClientId = undefined
720
- this.staleRedirectClientId = undefined
721
- this.lastObservedClientId = undefined
722
- this.lastSavedAccessToken = undefined
723
- this.pendingAuthAccessToken = undefined
724
- clearAllCredentials(this.serverName, this.storageOptions)
725
- break
726
- case "client":
727
- // Dynamic client registrations share the same credential-store entry as
728
- // tokens. Keep SDK invalidation local so a stale process cannot rewrite
729
- // that entry over credentials another process just authorized.
730
- this.invalidatedClientId = this.lastObservedClientId
731
- this.lastObservedClientId = undefined
732
- this.flowClientInfo = undefined
733
- invalidateAuthEntryCache(this.serverName)
734
- break
735
- case "tokens":
736
- // Invalidation is provider-local. Persistently deleting a shared token
737
- // here lets a process refreshing stale cached credentials erase a token
738
- // that another process just authorized. A later tokens() call bypasses
739
- // the local cache and adopts a replacement token when one exists.
740
- this.invalidatedAccessToken = this.pendingAuthAccessToken ?? this.lastSavedAccessToken
741
- this.lastSavedAccessToken = undefined
742
- this.pendingAuthAccessToken = undefined
743
- if (this.staleRedirectClientId !== undefined) {
744
- this.invalidatedClientId = this.staleRedirectClientId
745
- }
746
- invalidateAuthEntryCache(this.serverName)
747
- break
748
- case "verifier":
749
- clearCodeVerifier(this.serverName, this.storageOptions)
750
- break
751
- case "discovery":
752
- this.flowDiscoveryState = undefined
753
- break
754
- }
755
- }
756
-
757
- /**
758
- * Adds configured authorization-code scope without replacing the SDK's
759
- * default token endpoint authentication behavior.
760
- */
761
- addClientAuthentication: AddClientAuthentication = async (headers, params, _url, metadata) => {
762
- this.throwIfInactive()
763
- if (params.get("grant_type") === "authorization_code" && !params.has("scope") && this.config.scope) {
764
- params.set("scope", this.config.scope)
765
- }
766
-
767
- const clientInfo = await this.clientInformation()
768
- this.throwIfInactive()
769
- if (!clientInfo) {
770
- return
771
- }
772
-
773
- const supportedMethods = metadata?.token_endpoint_auth_methods_supported ?? []
774
- const hasClientSecret = clientInfo.client_secret !== undefined
775
- let authMethod: "client_secret_basic" | "client_secret_post" | "none"
776
-
777
- if (supportedMethods.length === 0) {
778
- authMethod = hasClientSecret ? "client_secret_post" : "none"
779
- } else if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
780
- authMethod = "client_secret_basic"
781
- } else if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
782
- authMethod = "client_secret_post"
783
- } else if (supportedMethods.includes("none")) {
784
- authMethod = "none"
785
- } else {
786
- authMethod = hasClientSecret ? "client_secret_post" : "none"
787
- }
788
-
789
- if (authMethod === "client_secret_basic") {
790
- if (!clientInfo.client_secret) {
791
- throw new Error("client_secret_basic authentication requires a client_secret")
792
- }
793
- headers.set("Authorization", `Basic ${Buffer.from(`${clientInfo.client_id}:${clientInfo.client_secret}`).toString("base64")}`)
794
- return
795
- }
796
-
797
- if (!params.has("client_id")) {
798
- params.set("client_id", clientInfo.client_id)
799
- }
800
- if (authMethod === "client_secret_post" && clientInfo.client_secret && !params.has("client_secret")) {
801
- params.set("client_secret", clientInfo.client_secret)
802
- }
803
- }
804
-
805
- prepareTokenRequest(scope?: string): URLSearchParams | undefined {
806
- if (!this.usesClientCredentials) {
807
- return undefined
808
- }
809
-
810
- const params = new URLSearchParams({ grant_type: "client_credentials" })
811
- const requestedScope = scope ?? this.config.scope
812
- if (requestedScope) {
813
- params.set("scope", requestedScope)
814
- }
815
- return params
816
- }
817
- }
818
-
819
- export { DEFAULT_OAUTH_CALLBACK_PORT, DEFAULT_OAUTH_CALLBACK_PATH }