@bastani/atomic 0.9.25-alpha.2 → 0.9.25-alpha.4

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 (274) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/builtin/intercom/package.json +2 -2
  3. package/dist/builtin/mcp/CHANGELOG.md +43 -0
  4. package/dist/builtin/mcp/OAUTH.md +59 -269
  5. package/dist/builtin/mcp/README.md +58 -345
  6. package/dist/builtin/mcp/index.bundle.mjs +4 -27792
  7. package/dist/builtin/mcp/native-client-licenses/LICENSES/modelcontextprotocol-typescript-sdk.txt +21 -0
  8. package/dist/builtin/mcp/native-client-licenses/NOTICE +30 -0
  9. package/dist/builtin/mcp/package.json +4 -25
  10. package/dist/builtin/subagents/package.json +3 -3
  11. package/dist/builtin/web-access/package.json +2 -2
  12. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  13. package/dist/builtin/workflows/builtin/{chunk-e1254zvd.js → chunk-kfsnh3w7.js} +40 -12
  14. package/dist/builtin/workflows/builtin/{chunk-cpw5gtzg.js → chunk-rqmasd3d.js} +1 -1
  15. package/dist/builtin/workflows/builtin/{chunk-qy6g0baf.js → chunk-wz783pvd.js} +1 -1
  16. package/dist/builtin/workflows/builtin/goal.js +2 -2
  17. package/dist/builtin/workflows/builtin/index.js +3 -3
  18. package/dist/builtin/workflows/builtin/ralph.js +2 -2
  19. package/dist/builtin/workflows/package.json +2 -2
  20. package/dist/builtin/workflows/src/extension/index.bundle.mjs +472 -88
  21. package/dist/builtin/workflows/src/index.js +65 -28
  22. package/dist/cli/args.d.ts.map +1 -1
  23. package/dist/cli/args.js +2 -1
  24. package/dist/cli/args.js.map +1 -1
  25. package/dist/core/agent-session-accessors.d.ts.map +1 -1
  26. package/dist/core/agent-session-accessors.js +7 -0
  27. package/dist/core/agent-session-accessors.js.map +1 -1
  28. package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
  29. package/dist/core/agent-session-extension-bindings.js +103 -7
  30. package/dist/core/agent-session-extension-bindings.js.map +1 -1
  31. package/dist/core/agent-session-methods.d.ts +7 -1
  32. package/dist/core/agent-session-methods.d.ts.map +1 -1
  33. package/dist/core/agent-session-methods.js.map +1 -1
  34. package/dist/core/agent-session-state.d.ts.map +1 -1
  35. package/dist/core/agent-session-state.js +3 -2
  36. package/dist/core/agent-session-state.js.map +1 -1
  37. package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
  38. package/dist/core/agent-session-tool-registry.js +6 -3
  39. package/dist/core/agent-session-tool-registry.js.map +1 -1
  40. package/dist/core/agent-session-types.d.ts +1 -0
  41. package/dist/core/agent-session-types.d.ts.map +1 -1
  42. package/dist/core/agent-session-types.js.map +1 -1
  43. package/dist/core/agent-session.d.ts +3 -0
  44. package/dist/core/agent-session.d.ts.map +1 -1
  45. package/dist/core/agent-session.js +6 -0
  46. package/dist/core/agent-session.js.map +1 -1
  47. package/dist/core/extensions/api-types.d.ts +3 -0
  48. package/dist/core/extensions/api-types.d.ts.map +1 -1
  49. package/dist/core/extensions/api-types.js.map +1 -1
  50. package/dist/core/extensions/context-types.d.ts +3 -1
  51. package/dist/core/extensions/context-types.d.ts.map +1 -1
  52. package/dist/core/extensions/context-types.js.map +1 -1
  53. package/dist/core/extensions/index.d.ts +2 -0
  54. package/dist/core/extensions/index.d.ts.map +1 -1
  55. package/dist/core/extensions/index.js +1 -0
  56. package/dist/core/extensions/index.js.map +1 -1
  57. package/dist/core/extensions/loader-api.d.ts.map +1 -1
  58. package/dist/core/extensions/loader-api.js +15 -0
  59. package/dist/core/extensions/loader-api.js.map +1 -1
  60. package/dist/core/extensions/loader-runtime.d.ts.map +1 -1
  61. package/dist/core/extensions/loader-runtime.js +3 -0
  62. package/dist/core/extensions/loader-runtime.js.map +1 -1
  63. package/dist/core/extensions/loader-virtual-modules.d.ts.map +1 -1
  64. package/dist/core/extensions/loader-virtual-modules.js +3 -0
  65. package/dist/core/extensions/loader-virtual-modules.js.map +1 -1
  66. package/dist/core/extensions/mcp-server-registry.d.ts.map +1 -1
  67. package/dist/core/extensions/mcp-server-registry.js +4 -0
  68. package/dist/core/extensions/mcp-server-registry.js.map +1 -1
  69. package/dist/core/extensions/runner.d.ts +3 -0
  70. package/dist/core/extensions/runner.d.ts.map +1 -1
  71. package/dist/core/extensions/runner.js +4 -0
  72. package/dist/core/extensions/runner.js.map +1 -1
  73. package/dist/core/extensions/runtime-types.d.ts +3 -0
  74. package/dist/core/extensions/runtime-types.d.ts.map +1 -1
  75. package/dist/core/extensions/runtime-types.js.map +1 -1
  76. package/dist/core/extensions/tool-types.d.ts +1 -0
  77. package/dist/core/extensions/tool-types.d.ts.map +1 -1
  78. package/dist/core/extensions/tool-types.js.map +1 -1
  79. package/dist/core/extensions/workflow-run-control-hub.d.ts +23 -0
  80. package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -0
  81. package/dist/core/extensions/workflow-run-control-hub.js +57 -0
  82. package/dist/core/extensions/workflow-run-control-hub.js.map +1 -0
  83. package/dist/core/extensions/workflow-run-control.d.ts +163 -0
  84. package/dist/core/extensions/workflow-run-control.d.ts.map +1 -0
  85. package/dist/core/extensions/workflow-run-control.js +73 -0
  86. package/dist/core/extensions/workflow-run-control.js.map +1 -0
  87. package/dist/core/mcp-child-policy.d.ts +11 -0
  88. package/dist/core/mcp-child-policy.d.ts.map +1 -0
  89. package/dist/core/mcp-child-policy.js +31 -0
  90. package/dist/core/mcp-child-policy.js.map +1 -0
  91. package/dist/core/mcp-servers.d.ts +34 -25
  92. package/dist/core/mcp-servers.d.ts.map +1 -1
  93. package/dist/core/mcp-servers.js +148 -1
  94. package/dist/core/mcp-servers.js.map +1 -1
  95. package/dist/core/package-manager-manifest.js.map +1 -1
  96. package/dist/core/package-manager-mcp-servers.js +1 -1
  97. package/dist/core/package-manager-mcp-servers.js.map +1 -1
  98. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  99. package/dist/core/remote-catalog-provider.js +4 -9
  100. package/dist/core/remote-catalog-provider.js.map +1 -1
  101. package/dist/core/sdk.js +11 -1
  102. package/dist/core/sdk.js.map +1 -1
  103. package/dist/core/tool-loadout.d.ts +1 -0
  104. package/dist/core/tool-loadout.d.ts.map +1 -1
  105. package/dist/core/tool-loadout.js +3 -0
  106. package/dist/core/tool-loadout.js.map +1 -1
  107. package/dist/core/tools/bash.d.ts.map +1 -1
  108. package/dist/core/tools/bash.js +11 -30
  109. package/dist/core/tools/bash.js.map +1 -1
  110. package/dist/core/tools/truncate.d.ts +8 -0
  111. package/dist/core/tools/truncate.d.ts.map +1 -1
  112. package/dist/core/tools/truncate.js +24 -0
  113. package/dist/core/tools/truncate.js.map +1 -1
  114. package/dist/extensions/codemode/execute.d.ts.map +1 -1
  115. package/dist/extensions/codemode/execute.js +26 -0
  116. package/dist/extensions/codemode/execute.js.map +1 -1
  117. package/dist/extensions/codemode/renderer.d.ts.map +1 -1
  118. package/dist/extensions/codemode/renderer.js +38 -23
  119. package/dist/extensions/codemode/renderer.js.map +1 -1
  120. package/dist/extensions/codemode/tool.d.ts.map +1 -1
  121. package/dist/extensions/codemode/tool.js +22 -10
  122. package/dist/extensions/codemode/tool.js.map +1 -1
  123. package/dist/extensions/mcp/cli.d.ts +21 -0
  124. package/dist/extensions/mcp/cli.d.ts.map +1 -0
  125. package/dist/extensions/mcp/cli.js +500 -0
  126. package/dist/extensions/mcp/cli.js.map +1 -0
  127. package/dist/extensions/mcp/cli.lazy.d.ts +3 -0
  128. package/dist/extensions/mcp/cli.lazy.d.ts.map +1 -0
  129. package/dist/extensions/mcp/cli.lazy.js +3 -0
  130. package/dist/extensions/mcp/cli.lazy.js.map +1 -0
  131. package/dist/extensions/mcp/client/auth-provider.d.ts +15 -0
  132. package/dist/extensions/mcp/client/auth-provider.d.ts.map +1 -0
  133. package/dist/extensions/mcp/client/auth-provider.js +2 -0
  134. package/dist/extensions/mcp/client/auth-provider.js.map +1 -0
  135. package/dist/extensions/mcp/client/client.d.ts +89 -0
  136. package/dist/extensions/mcp/client/client.d.ts.map +1 -0
  137. package/dist/extensions/mcp/client/client.js +457 -0
  138. package/dist/extensions/mcp/client/client.js.map +1 -0
  139. package/dist/extensions/mcp/client/index.d.ts +9 -0
  140. package/dist/extensions/mcp/client/index.d.ts.map +1 -0
  141. package/dist/extensions/mcp/client/index.js +7 -0
  142. package/dist/extensions/mcp/client/index.js.map +1 -0
  143. package/dist/extensions/mcp/client/oauth/callback.d.ts +42 -0
  144. package/dist/extensions/mcp/client/oauth/callback.d.ts.map +1 -0
  145. package/dist/extensions/mcp/client/oauth/callback.js +106 -0
  146. package/dist/extensions/mcp/client/oauth/callback.js.map +1 -0
  147. package/dist/extensions/mcp/client/oauth/discovery.d.ts +27 -0
  148. package/dist/extensions/mcp/client/oauth/discovery.d.ts.map +1 -0
  149. package/dist/extensions/mcp/client/oauth/discovery.js +153 -0
  150. package/dist/extensions/mcp/client/oauth/discovery.js.map +1 -0
  151. package/dist/extensions/mcp/client/oauth/errors.d.ts +24 -0
  152. package/dist/extensions/mcp/client/oauth/errors.d.ts.map +1 -0
  153. package/dist/extensions/mcp/client/oauth/errors.js +46 -0
  154. package/dist/extensions/mcp/client/oauth/errors.js.map +1 -0
  155. package/dist/extensions/mcp/client/oauth/flow.d.ts +82 -0
  156. package/dist/extensions/mcp/client/oauth/flow.d.ts.map +1 -0
  157. package/dist/extensions/mcp/client/oauth/flow.js +292 -0
  158. package/dist/extensions/mcp/client/oauth/flow.js.map +1 -0
  159. package/dist/extensions/mcp/client/oauth/index.d.ts +7 -0
  160. package/dist/extensions/mcp/client/oauth/index.d.ts.map +1 -0
  161. package/dist/extensions/mcp/client/oauth/index.js +6 -0
  162. package/dist/extensions/mcp/client/oauth/index.js.map +1 -0
  163. package/dist/extensions/mcp/client/oauth/provider.d.ts +59 -0
  164. package/dist/extensions/mcp/client/oauth/provider.d.ts.map +1 -0
  165. package/dist/extensions/mcp/client/oauth/provider.js +116 -0
  166. package/dist/extensions/mcp/client/oauth/provider.js.map +1 -0
  167. package/dist/extensions/mcp/client/oauth/types.d.ts +77 -0
  168. package/dist/extensions/mcp/client/oauth/types.d.ts.map +1 -0
  169. package/dist/extensions/mcp/client/oauth/types.js +109 -0
  170. package/dist/extensions/mcp/client/oauth/types.js.map +1 -0
  171. package/dist/extensions/mcp/client/protocol/content.d.ts +82 -0
  172. package/dist/extensions/mcp/client/protocol/content.d.ts.map +1 -0
  173. package/dist/extensions/mcp/client/protocol/content.js +41 -0
  174. package/dist/extensions/mcp/client/protocol/content.js.map +1 -0
  175. package/dist/extensions/mcp/client/protocol/jsonrpc.d.ts +59 -0
  176. package/dist/extensions/mcp/client/protocol/jsonrpc.d.ts.map +1 -0
  177. package/dist/extensions/mcp/client/protocol/jsonrpc.js +67 -0
  178. package/dist/extensions/mcp/client/protocol/jsonrpc.js.map +1 -0
  179. package/dist/extensions/mcp/client/protocol/types.d.ts +123 -0
  180. package/dist/extensions/mcp/client/protocol/types.d.ts.map +1 -0
  181. package/dist/extensions/mcp/client/protocol/types.js +7 -0
  182. package/dist/extensions/mcp/client/protocol/types.js.map +1 -0
  183. package/dist/extensions/mcp/client/testing/index.d.ts +2 -0
  184. package/dist/extensions/mcp/client/testing/index.d.ts.map +1 -0
  185. package/dist/extensions/mcp/client/testing/index.js +2 -0
  186. package/dist/extensions/mcp/client/testing/index.js.map +1 -0
  187. package/dist/extensions/mcp/client/transports/in-memory.d.ts +19 -0
  188. package/dist/extensions/mcp/client/transports/in-memory.d.ts.map +1 -0
  189. package/dist/extensions/mcp/client/transports/in-memory.js +50 -0
  190. package/dist/extensions/mcp/client/transports/in-memory.js.map +1 -0
  191. package/dist/extensions/mcp/client/transports/stdio.d.ts +32 -0
  192. package/dist/extensions/mcp/client/transports/stdio.d.ts.map +1 -0
  193. package/dist/extensions/mcp/client/transports/stdio.js +201 -0
  194. package/dist/extensions/mcp/client/transports/stdio.js.map +1 -0
  195. package/dist/extensions/mcp/client/transports/streamable-http.d.ts +96 -0
  196. package/dist/extensions/mcp/client/transports/streamable-http.d.ts.map +1 -0
  197. package/dist/extensions/mcp/client/transports/streamable-http.js +456 -0
  198. package/dist/extensions/mcp/client/transports/streamable-http.js.map +1 -0
  199. package/dist/extensions/mcp/client/transports/transport.d.ts +28 -0
  200. package/dist/extensions/mcp/client/transports/transport.d.ts.map +1 -0
  201. package/dist/extensions/mcp/client/transports/transport.js +38 -0
  202. package/dist/extensions/mcp/client/transports/transport.js.map +1 -0
  203. package/dist/extensions/mcp/config.d.ts +72 -0
  204. package/dist/extensions/mcp/config.d.ts.map +1 -0
  205. package/dist/extensions/mcp/config.js +158 -0
  206. package/dist/extensions/mcp/config.js.map +1 -0
  207. package/dist/extensions/mcp/index.d.ts +76 -0
  208. package/dist/extensions/mcp/index.d.ts.map +1 -0
  209. package/dist/extensions/mcp/index.js +1119 -0
  210. package/dist/extensions/mcp/index.js.map +1 -0
  211. package/dist/extensions/mcp/log.d.ts +16 -0
  212. package/dist/extensions/mcp/log.d.ts.map +1 -0
  213. package/dist/extensions/mcp/log.js +66 -0
  214. package/dist/extensions/mcp/log.js.map +1 -0
  215. package/dist/extensions/mcp/oauth.d.ts +103 -0
  216. package/dist/extensions/mcp/oauth.d.ts.map +1 -0
  217. package/dist/extensions/mcp/oauth.js +382 -0
  218. package/dist/extensions/mcp/oauth.js.map +1 -0
  219. package/dist/extensions/mcp/resources.d.ts +43 -0
  220. package/dist/extensions/mcp/resources.d.ts.map +1 -0
  221. package/dist/extensions/mcp/resources.js +262 -0
  222. package/dist/extensions/mcp/resources.js.map +1 -0
  223. package/dist/extensions/mcp/runtime.d.ts +104 -0
  224. package/dist/extensions/mcp/runtime.d.ts.map +1 -0
  225. package/dist/extensions/mcp/runtime.js +546 -0
  226. package/dist/extensions/mcp/runtime.js.map +1 -0
  227. package/dist/extensions/mcp/runtime.lazy.d.ts +3 -0
  228. package/dist/extensions/mcp/runtime.lazy.d.ts.map +1 -0
  229. package/dist/extensions/mcp/runtime.lazy.js +3 -0
  230. package/dist/extensions/mcp/runtime.lazy.js.map +1 -0
  231. package/dist/extensions/mcp/tools.d.ts +84 -0
  232. package/dist/extensions/mcp/tools.d.ts.map +1 -0
  233. package/dist/extensions/mcp/tools.js +251 -0
  234. package/dist/extensions/mcp/tools.js.map +1 -0
  235. package/dist/extensions/mcp/ui.d.ts +60 -0
  236. package/dist/extensions/mcp/ui.d.ts.map +1 -0
  237. package/dist/extensions/mcp/ui.js +175 -0
  238. package/dist/extensions/mcp/ui.js.map +1 -0
  239. package/dist/extensions/tool-search/tool.d.ts +1 -1
  240. package/dist/extensions/tool-search/tool.d.ts.map +1 -1
  241. package/dist/extensions/tool-search/tool.js +3 -13
  242. package/dist/extensions/tool-search/tool.js.map +1 -1
  243. package/dist/index-extensions.d.ts +2 -1
  244. package/dist/index-extensions.d.ts.map +1 -1
  245. package/dist/index-extensions.js +1 -1
  246. package/dist/index-extensions.js.map +1 -1
  247. package/dist/index.d.ts +5 -1
  248. package/dist/index.d.ts.map +1 -1
  249. package/dist/index.js +5 -0
  250. package/dist/index.js.map +1 -1
  251. package/dist/main.d.ts.map +1 -1
  252. package/dist/main.js +7 -0
  253. package/dist/main.js.map +1 -1
  254. package/dist/modes/interactive/components/visual-truncate.d.ts +27 -3
  255. package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
  256. package/dist/modes/interactive/components/visual-truncate.js +39 -6
  257. package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
  258. package/docs/extensions/api-reference.md +3 -3
  259. package/docs/extensions/events.md +2 -0
  260. package/docs/extensions.md +8 -8
  261. package/docs/mcp-servers.md +171 -50
  262. package/docs/packages/authoring.md +2 -2
  263. package/docs/providers.md +8 -0
  264. package/docs/sdk/reference.md +16 -0
  265. package/docs/sdk.md +67 -1
  266. package/docs/settings.md +2 -0
  267. package/docs/tools.md +6 -0
  268. package/docs/workflows/operations.md +3 -1
  269. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  270. package/examples/extensions/minimal-mode.ts +28 -108
  271. package/npm-shrinkwrap.json +69 -69
  272. package/package.json +8 -8
  273. package/dist/builtin/mcp/app-bridge.bundle.js +0 -67
  274. package/dist/builtin/mcp/xdg-open +0 -1267
@@ -0,0 +1,292 @@
1
+ /*
2
+ * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.
3
+ * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.
4
+ * Modified to remove SDK/Zod dependencies and use WebCrypto for PKCE.
5
+ */
6
+ import { isObject } from "../protocol/jsonrpc.js";
7
+ import { discoverAuthorizationServerMetadata, discoverOAuthServerInfo, parseWwwAuthenticate, selectResource, } from "./discovery.js";
8
+ import { McpOAuthAuthorizationRequiredError, OAuthError, OAuthInsecureEndpointError, OAuthIssuerMismatchError, OAuthRegistrationError, } from "./errors.js";
9
+ import { parseClientInformation, parseOAuthTokens, } from "./types.js";
10
+ function loopback(hostname) {
11
+ return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
12
+ }
13
+ function secureEndpoint(value) {
14
+ const url = new URL(value);
15
+ if (url.protocol !== "https:" && !loopback(url.hostname))
16
+ throw new OAuthInsecureEndpointError(url.href);
17
+ return url;
18
+ }
19
+ function selectClientAuthMethod(information, supported) {
20
+ const hinted = "token_endpoint_auth_method" in information ? information.token_endpoint_auth_method : undefined;
21
+ if (hinted &&
22
+ ["client_secret_basic", "client_secret_post", "none"].includes(hinted) &&
23
+ (supported.length === 0 || supported.includes(hinted))) {
24
+ return hinted;
25
+ }
26
+ if (supported.length === 0)
27
+ return information.client_secret ? "client_secret_basic" : "none";
28
+ if (information.client_secret && supported.includes("client_secret_basic"))
29
+ return "client_secret_basic";
30
+ if (information.client_secret && supported.includes("client_secret_post"))
31
+ return "client_secret_post";
32
+ if (supported.includes("none"))
33
+ return "none";
34
+ return information.client_secret ? "client_secret_post" : "none";
35
+ }
36
+ function applyClientAuthentication(method, information, headers, params) {
37
+ if (method === "client_secret_basic") {
38
+ if (!information.client_secret)
39
+ throw new Error("client_secret_basic requires a client secret");
40
+ headers.set("Authorization", `Basic ${Buffer.from(`${information.client_id}:${information.client_secret}`).toString("base64")}`);
41
+ }
42
+ else {
43
+ params.set("client_id", information.client_id);
44
+ if (method === "client_secret_post" && information.client_secret)
45
+ params.set("client_secret", information.client_secret);
46
+ }
47
+ }
48
+ async function pkce() {
49
+ const bytes = crypto.getRandomValues(new Uint8Array(32));
50
+ const verifier = Buffer.from(bytes).toString("base64url");
51
+ const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
52
+ return { verifier, challenge: Buffer.from(digest).toString("base64url") };
53
+ }
54
+ export async function startAuthorization(authorizationServerUrl, options) {
55
+ const metadata = options.metadata;
56
+ if (metadata && !metadata.response_types_supported.includes("code")) {
57
+ throw new Error("Authorization server does not support authorization codes");
58
+ }
59
+ if (metadata?.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes("S256")) {
60
+ throw new Error("Authorization server does not support PKCE S256");
61
+ }
62
+ const url = new URL(metadata?.authorization_endpoint ?? new URL("/authorize", authorizationServerUrl));
63
+ const { verifier, challenge } = await pkce();
64
+ url.searchParams.set("response_type", "code");
65
+ url.searchParams.set("client_id", options.clientInformation.client_id);
66
+ url.searchParams.set("code_challenge", challenge);
67
+ url.searchParams.set("code_challenge_method", "S256");
68
+ url.searchParams.set("redirect_uri", String(options.redirectUrl));
69
+ if (options.state)
70
+ url.searchParams.set("state", options.state);
71
+ if (options.scope)
72
+ url.searchParams.set("scope", options.scope);
73
+ if (options.scope?.split(/\s+/).includes("offline_access"))
74
+ url.searchParams.set("prompt", "consent");
75
+ if (options.resource)
76
+ url.searchParams.set("resource", options.resource);
77
+ return { authorizationUrl: url, codeVerifier: verifier };
78
+ }
79
+ async function tokenRequest(authorizationServerUrl, options, params) {
80
+ const url = secureEndpoint(options.metadata?.token_endpoint ?? new URL("/token", authorizationServerUrl));
81
+ const headers = new Headers({ Accept: "application/json", "content-type": "application/x-www-form-urlencoded" });
82
+ if (options.resource)
83
+ params.set("resource", options.resource);
84
+ if (options.addClientAuthentication) {
85
+ await options.addClientAuthentication(headers, params, url, options.metadata);
86
+ }
87
+ else {
88
+ applyClientAuthentication(selectClientAuthMethod(options.clientInformation, options.metadata?.token_endpoint_auth_methods_supported ?? []), options.clientInformation, headers, params);
89
+ }
90
+ const response = await (options.fetch ?? globalThis.fetch)(url, { method: "POST", headers, body: params });
91
+ const text = await response.text();
92
+ let value;
93
+ try {
94
+ value = JSON.parse(text);
95
+ }
96
+ catch { }
97
+ // Servers may report OAuth errors with any status, so check the body before the status.
98
+ if (isObject(value) && typeof value.error === "string") {
99
+ throw new OAuthError(value.error, typeof value.error_description === "string" ? value.error_description : value.error, typeof value.error_uri === "string" ? value.error_uri : undefined);
100
+ }
101
+ if (!response.ok)
102
+ throw new OAuthError("server_error", `HTTP ${response.status}: ${text}`);
103
+ return parseOAuthTokens(value);
104
+ }
105
+ export async function registerClient(authorizationServerUrl, options) {
106
+ const endpoint = options.metadata?.registration_endpoint;
107
+ if (options.metadata && !endpoint)
108
+ throw new Error("Authorization server does not support dynamic client registration");
109
+ const response = await (options.fetch ?? globalThis.fetch)(new URL(endpoint ?? new URL("/register", authorizationServerUrl)), {
110
+ method: "POST",
111
+ headers: { Accept: "application/json", "content-type": "application/json" },
112
+ body: JSON.stringify({ ...options.clientMetadata, ...(options.scope ? { scope: options.scope } : {}) }),
113
+ });
114
+ if (!response.ok)
115
+ throw new OAuthRegistrationError(response.status, await response.text());
116
+ return parseClientInformation(await response.json());
117
+ }
118
+ export async function exchangeAuthorizationCode(authorizationServerUrl, options) {
119
+ return tokenRequest(authorizationServerUrl, options, new URLSearchParams({
120
+ grant_type: "authorization_code",
121
+ code: options.code,
122
+ code_verifier: options.codeVerifier,
123
+ redirect_uri: String(options.redirectUrl),
124
+ }));
125
+ }
126
+ export async function refreshAuthorization(authorizationServerUrl, options) {
127
+ const tokens = await tokenRequest(authorizationServerUrl, options, new URLSearchParams({ grant_type: "refresh_token", refresh_token: options.refreshToken }));
128
+ return { refresh_token: options.refreshToken, ...tokens };
129
+ }
130
+ async function runFlow(provider, options) {
131
+ const metadataUrl = options.authorizationServerMetadataUrl && secureEndpoint(options.authorizationServerMetadataUrl);
132
+ // With a configured metadata URL, discovery is not cached, so changing the URL applies at once.
133
+ let cached = metadataUrl ? undefined : await provider.discoveryState?.();
134
+ if (options.resourceMetadataUrl && options.resourceMetadataUrl.href !== cached?.resourceMetadataUrl)
135
+ cached = undefined;
136
+ const discovered = cached?.authorizationServerUrl
137
+ ? {
138
+ authorizationServerUrl: cached.authorizationServerUrl,
139
+ authorizationServerMetadata: cached.authorizationServerMetadata ??
140
+ (await discoverAuthorizationServerMetadata(cached.authorizationServerUrl, {
141
+ fetch: options.fetch,
142
+ skipIssuerValidation: options.skipIssuerValidation,
143
+ })),
144
+ resourceMetadata: cached.resourceMetadata,
145
+ }
146
+ : await discoverOAuthServerInfo(options.serverUrl, {
147
+ resourceMetadataUrl: options.resourceMetadataUrl,
148
+ authorizationServerMetadataUrl: metadataUrl,
149
+ fetch: options.fetch,
150
+ skipIssuerValidation: options.skipIssuerValidation,
151
+ });
152
+ if (!metadataUrl) {
153
+ await provider.saveDiscoveryState?.({
154
+ ...discovered,
155
+ ...(options.resourceMetadataUrl || cached?.resourceMetadataUrl
156
+ ? { resourceMetadataUrl: options.resourceMetadataUrl?.href ?? cached?.resourceMetadataUrl }
157
+ : {}),
158
+ });
159
+ }
160
+ const metadata = discovered.authorizationServerMetadata;
161
+ const resource = selectResource(options.serverUrl, discovered.resourceMetadata);
162
+ // `||`, not `??`: an empty scope (for example from `scopes_supported: []`) falls through to the next source.
163
+ const scope = options.scope || discovered.resourceMetadata?.scopes_supported?.join(" ") || provider.clientMetadata.scope;
164
+ let client = await provider.clientInformation();
165
+ if (!client) {
166
+ if (options.authorizationCode)
167
+ throw new Error("OAuth client information is missing during code exchange");
168
+ if (metadata?.client_id_metadata_document_supported && provider.clientMetadataUrl) {
169
+ const url = new URL(provider.clientMetadataUrl);
170
+ if (url.protocol !== "https:" || url.pathname === "/")
171
+ throw new Error("Invalid OAuth client metadata URL");
172
+ client = { client_id: provider.clientMetadataUrl };
173
+ await provider.saveClientInformation?.(client);
174
+ }
175
+ else {
176
+ if (!provider.saveClientInformation)
177
+ throw new Error("OAuth client information cannot be persisted");
178
+ client = await registerClient(discovered.authorizationServerUrl, {
179
+ metadata,
180
+ clientMetadata: provider.clientMetadata,
181
+ scope,
182
+ fetch: options.fetch,
183
+ });
184
+ await provider.saveClientInformation(client);
185
+ }
186
+ }
187
+ const tokenOptions = {
188
+ metadata,
189
+ clientInformation: client,
190
+ resource,
191
+ addClientAuthentication: provider.addClientAuthentication,
192
+ fetch: options.fetch,
193
+ };
194
+ if (options.authorizationCode) {
195
+ // RFC 9207: never send a code from another authorization server to this one.
196
+ const iss = options.iss;
197
+ if (metadata && (iss !== undefined || metadata.authorization_response_iss_parameter_supported)) {
198
+ if (iss !== metadata.issuer)
199
+ throw new OAuthIssuerMismatchError(metadata.issuer, iss);
200
+ }
201
+ const tokens = await exchangeAuthorizationCode(discovered.authorizationServerUrl, {
202
+ ...tokenOptions,
203
+ code: options.authorizationCode,
204
+ codeVerifier: await provider.codeVerifier(),
205
+ redirectUrl: provider.redirectUrl,
206
+ });
207
+ await provider.saveTokens(tokens);
208
+ return "AUTHORIZED";
209
+ }
210
+ const existing = options.skipRefresh ? undefined : await provider.tokens();
211
+ if (existing?.refresh_token) {
212
+ try {
213
+ const tokens = await refreshAuthorization(discovered.authorizationServerUrl, {
214
+ ...tokenOptions,
215
+ refreshToken: existing.refresh_token,
216
+ });
217
+ await provider.saveTokens(tokens);
218
+ return "AUTHORIZED";
219
+ }
220
+ catch (error) {
221
+ if (error instanceof OAuthInsecureEndpointError)
222
+ throw error;
223
+ if (error instanceof OAuthError && error.code !== "server_error")
224
+ throw error;
225
+ }
226
+ }
227
+ const state = await provider.state?.();
228
+ const authorization = await startAuthorization(discovered.authorizationServerUrl, {
229
+ metadata,
230
+ clientInformation: client,
231
+ redirectUrl: provider.redirectUrl,
232
+ scope,
233
+ state,
234
+ resource,
235
+ });
236
+ await provider.saveCodeVerifier(authorization.codeVerifier);
237
+ await provider.redirectToAuthorization(authorization.authorizationUrl);
238
+ return "REDIRECT";
239
+ }
240
+ export async function authorizeMcp(provider, options) {
241
+ try {
242
+ return await runFlow(provider, options);
243
+ }
244
+ catch (error) {
245
+ if (error instanceof OAuthError && ["invalid_client", "unauthorized_client"].includes(error.code)) {
246
+ await provider.invalidateCredentials?.("all");
247
+ return runFlow(provider, options);
248
+ }
249
+ if (error instanceof OAuthError && error.code === "invalid_grant") {
250
+ await provider.invalidateCredentials?.("tokens");
251
+ return runFlow(provider, options);
252
+ }
253
+ throw error;
254
+ }
255
+ }
256
+ /**
257
+ * Auth provider for `StreamableHttpTransport`. After a 401 it refreshes the tokens, or throws
258
+ * `McpOAuthAuthorizationRequiredError` when the user has to authorize (again). Concurrent 401s share
259
+ * one refresh, and a request whose token was already replaced is just retried: with rotating refresh
260
+ * tokens, a second refresh with the old refresh token would fail and discard the new grant.
261
+ */
262
+ export function adaptOAuthProvider(provider) {
263
+ let inFlight;
264
+ return {
265
+ token: async () => (await provider.tokens())?.access_token,
266
+ onUnauthorized: async (context) => {
267
+ const challenge = parseWwwAuthenticate(context.response.headers.get("www-authenticate"));
268
+ const insufficientScope = challenge.error === "insufficient_scope";
269
+ if (!insufficientScope && !inFlight && context.token !== undefined) {
270
+ const current = (await provider.tokens())?.access_token;
271
+ if (current !== undefined && current !== context.token)
272
+ return;
273
+ }
274
+ inFlight ??= authorizeMcp(provider, {
275
+ serverUrl: context.serverUrl,
276
+ resourceMetadataUrl: challenge.resourceMetadataUrl,
277
+ scope: challenge.scope,
278
+ fetch: context.fetch,
279
+ skipRefresh: insufficientScope,
280
+ })
281
+ .then((result) => {
282
+ if (result === "REDIRECT")
283
+ throw new McpOAuthAuthorizationRequiredError();
284
+ })
285
+ .finally(() => {
286
+ inFlight = undefined;
287
+ });
288
+ await inFlight;
289
+ },
290
+ };
291
+ }
292
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../../../../src/extensions/mcp/client/oauth/flow.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove SDK/Zod dependencies and use WebCrypto for PKCE.\n */\n\nimport type { AuthProvider, McpFetch, UnauthorizedContext } from \"../auth-provider.js\";\nimport { isObject } from \"../protocol/jsonrpc.js\";\nimport {\n\tdiscoverAuthorizationServerMetadata,\n\tdiscoverOAuthServerInfo,\n\tparseWwwAuthenticate,\n\tselectResource,\n} from \"./discovery.js\";\nimport {\n\tMcpOAuthAuthorizationRequiredError,\n\tOAuthError,\n\tOAuthInsecureEndpointError,\n\tOAuthIssuerMismatchError,\n\tOAuthRegistrationError,\n} from \"./errors.js\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthClientInformation,\n\ttype OAuthClientInformationFull,\n\ttype OAuthClientInformationMixed,\n\ttype OAuthClientMetadata,\n\ttype OAuthDiscoveryState,\n\ttype OAuthTokens,\n\tparseClientInformation,\n\tparseOAuthTokens,\n} from \"./types.js\";\n\nexport type AddClientAuthentication = (\n\theaders: Headers,\n\tparams: URLSearchParams,\n\turl: string | URL,\n\tmetadata?: AuthorizationServerMetadata,\n) => void | Promise<void>;\n\nexport interface OAuthClientProvider {\n\treadonly redirectUrl: string | URL;\n\treadonly clientMetadata: OAuthClientMetadata;\n\treadonly clientMetadataUrl?: string;\n\tstate?(): string | Promise<string>;\n\tclientInformation(): OAuthClientInformationMixed | undefined | Promise<OAuthClientInformationMixed | undefined>;\n\tsaveClientInformation?(information: OAuthClientInformationMixed): void | Promise<void>;\n\ttokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;\n\tsaveTokens(tokens: OAuthTokens): void | Promise<void>;\n\tredirectToAuthorization(url: URL): void | Promise<void>;\n\tsaveCodeVerifier(verifier: string): void | Promise<void>;\n\tcodeVerifier(): string | Promise<string>;\n\taddClientAuthentication?: AddClientAuthentication;\n\tinvalidateCredentials?(kind: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): void | Promise<void>;\n\tsaveDiscoveryState?(state: OAuthDiscoveryState): void | Promise<void>;\n\tdiscoveryState?(): OAuthDiscoveryState | undefined | Promise<OAuthDiscoveryState | undefined>;\n}\n\nexport interface OAuthFlowOptions {\n\tserverUrl: string | URL;\n\tauthorizationCode?: string;\n\t/** `iss` parameter of the authorization response that delivered `authorizationCode` (RFC 9207). */\n\tiss?: string;\n\tscope?: string;\n\tresourceMetadataUrl?: URL;\n\t/**\n\t * Authorization server metadata document to use instead of discovery, for servers that advertise a\n\t * wrong authorization server or none. It is trusted as configured. Must use https, except on loopback.\n\t */\n\tauthorizationServerMetadataUrl?: URL;\n\tfetch?: McpFetch;\n\tskipIssuerValidation?: boolean;\n\t/**\n\t * Go straight to the authorization redirect instead of refreshing stored tokens, for example when the\n\t * server asks for scopes the current grant lacks (a refresh keeps the old scope).\n\t */\n\tskipRefresh?: boolean;\n}\n\nexport type OAuthFlowResult = \"AUTHORIZED\" | \"REDIRECT\";\ntype ClientAuthMethod = \"client_secret_basic\" | \"client_secret_post\" | \"none\";\n\nexport interface TokenRequestOptions {\n\tmetadata?: AuthorizationServerMetadata;\n\tclientInformation: OAuthClientInformationMixed;\n\tresource?: string;\n\taddClientAuthentication?: AddClientAuthentication;\n\tfetch?: McpFetch;\n}\n\nfunction loopback(hostname: string): boolean {\n\treturn hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\" || hostname === \"::1\";\n}\n\nfunction secureEndpoint(value: string | URL): URL {\n\tconst url = new URL(value);\n\tif (url.protocol !== \"https:\" && !loopback(url.hostname)) throw new OAuthInsecureEndpointError(url.href);\n\treturn url;\n}\n\nfunction selectClientAuthMethod(information: OAuthClientInformationMixed, supported: string[]): ClientAuthMethod {\n\tconst hinted = \"token_endpoint_auth_method\" in information ? information.token_endpoint_auth_method : undefined;\n\tif (\n\t\thinted &&\n\t\t[\"client_secret_basic\", \"client_secret_post\", \"none\"].includes(hinted) &&\n\t\t(supported.length === 0 || supported.includes(hinted))\n\t) {\n\t\treturn hinted as ClientAuthMethod;\n\t}\n\tif (supported.length === 0) return information.client_secret ? \"client_secret_basic\" : \"none\";\n\tif (information.client_secret && supported.includes(\"client_secret_basic\")) return \"client_secret_basic\";\n\tif (information.client_secret && supported.includes(\"client_secret_post\")) return \"client_secret_post\";\n\tif (supported.includes(\"none\")) return \"none\";\n\treturn information.client_secret ? \"client_secret_post\" : \"none\";\n}\n\nfunction applyClientAuthentication(\n\tmethod: ClientAuthMethod,\n\tinformation: OAuthClientInformation,\n\theaders: Headers,\n\tparams: URLSearchParams,\n): void {\n\tif (method === \"client_secret_basic\") {\n\t\tif (!information.client_secret) throw new Error(\"client_secret_basic requires a client secret\");\n\t\theaders.set(\n\t\t\t\"Authorization\",\n\t\t\t`Basic ${Buffer.from(`${information.client_id}:${information.client_secret}`).toString(\"base64\")}`,\n\t\t);\n\t} else {\n\t\tparams.set(\"client_id\", information.client_id);\n\t\tif (method === \"client_secret_post\" && information.client_secret)\n\t\t\tparams.set(\"client_secret\", information.client_secret);\n\t}\n}\n\nasync function pkce(): Promise<{ verifier: string; challenge: string }> {\n\tconst bytes = crypto.getRandomValues(new Uint8Array(32));\n\tconst verifier = Buffer.from(bytes).toString(\"base64url\");\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(verifier));\n\treturn { verifier, challenge: Buffer.from(digest).toString(\"base64url\") };\n}\n\nexport async function startAuthorization(\n\tauthorizationServerUrl: string | URL,\n\toptions: {\n\t\tmetadata?: AuthorizationServerMetadata;\n\t\tclientInformation: OAuthClientInformationMixed;\n\t\tredirectUrl: string | URL;\n\t\tscope?: string;\n\t\tstate?: string;\n\t\tresource?: string;\n\t},\n): Promise<{ authorizationUrl: URL; codeVerifier: string }> {\n\tconst metadata = options.metadata;\n\tif (metadata && !metadata.response_types_supported.includes(\"code\")) {\n\t\tthrow new Error(\"Authorization server does not support authorization codes\");\n\t}\n\tif (metadata?.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes(\"S256\")) {\n\t\tthrow new Error(\"Authorization server does not support PKCE S256\");\n\t}\n\tconst url = new URL(metadata?.authorization_endpoint ?? new URL(\"/authorize\", authorizationServerUrl));\n\tconst { verifier, challenge } = await pkce();\n\turl.searchParams.set(\"response_type\", \"code\");\n\turl.searchParams.set(\"client_id\", options.clientInformation.client_id);\n\turl.searchParams.set(\"code_challenge\", challenge);\n\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\turl.searchParams.set(\"redirect_uri\", String(options.redirectUrl));\n\tif (options.state) url.searchParams.set(\"state\", options.state);\n\tif (options.scope) url.searchParams.set(\"scope\", options.scope);\n\tif (options.scope?.split(/\\s+/).includes(\"offline_access\")) url.searchParams.set(\"prompt\", \"consent\");\n\tif (options.resource) url.searchParams.set(\"resource\", options.resource);\n\treturn { authorizationUrl: url, codeVerifier: verifier };\n}\n\nasync function tokenRequest(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions,\n\tparams: URLSearchParams,\n): Promise<OAuthTokens> {\n\tconst url = secureEndpoint(options.metadata?.token_endpoint ?? new URL(\"/token\", authorizationServerUrl));\n\tconst headers = new Headers({ Accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" });\n\tif (options.resource) params.set(\"resource\", options.resource);\n\tif (options.addClientAuthentication) {\n\t\tawait options.addClientAuthentication(headers, params, url, options.metadata);\n\t} else {\n\t\tapplyClientAuthentication(\n\t\t\tselectClientAuthMethod(\n\t\t\t\toptions.clientInformation,\n\t\t\t\toptions.metadata?.token_endpoint_auth_methods_supported ?? [],\n\t\t\t),\n\t\t\toptions.clientInformation,\n\t\t\theaders,\n\t\t\tparams,\n\t\t);\n\t}\n\tconst response = await (options.fetch ?? globalThis.fetch)(url, { method: \"POST\", headers, body: params });\n\tconst text = await response.text();\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(text);\n\t} catch {}\n\t// Servers may report OAuth errors with any status, so check the body before the status.\n\tif (isObject(value) && typeof value.error === \"string\") {\n\t\tthrow new OAuthError(\n\t\t\tvalue.error,\n\t\t\ttypeof value.error_description === \"string\" ? value.error_description : value.error,\n\t\t\ttypeof value.error_uri === \"string\" ? value.error_uri : undefined,\n\t\t);\n\t}\n\tif (!response.ok) throw new OAuthError(\"server_error\", `HTTP ${response.status}: ${text}`);\n\treturn parseOAuthTokens(value);\n}\n\nexport async function registerClient(\n\tauthorizationServerUrl: string | URL,\n\toptions: {\n\t\tmetadata?: AuthorizationServerMetadata;\n\t\tclientMetadata: OAuthClientMetadata;\n\t\tscope?: string;\n\t\tfetch?: McpFetch;\n\t},\n): Promise<OAuthClientInformationFull> {\n\tconst endpoint = options.metadata?.registration_endpoint;\n\tif (options.metadata && !endpoint)\n\t\tthrow new Error(\"Authorization server does not support dynamic client registration\");\n\tconst response = await (options.fetch ?? globalThis.fetch)(\n\t\tnew URL(endpoint ?? new URL(\"/register\", authorizationServerUrl)),\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Accept: \"application/json\", \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ ...options.clientMetadata, ...(options.scope ? { scope: options.scope } : {}) }),\n\t\t},\n\t);\n\tif (!response.ok) throw new OAuthRegistrationError(response.status, await response.text());\n\treturn parseClientInformation(await response.json());\n}\n\nexport async function exchangeAuthorizationCode(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions & { code: string; codeVerifier: string; redirectUrl: string | URL },\n): Promise<OAuthTokens> {\n\treturn tokenRequest(\n\t\tauthorizationServerUrl,\n\t\toptions,\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode: options.code,\n\t\t\tcode_verifier: options.codeVerifier,\n\t\t\tredirect_uri: String(options.redirectUrl),\n\t\t}),\n\t);\n}\n\nexport async function refreshAuthorization(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions & { refreshToken: string },\n): Promise<OAuthTokens> {\n\tconst tokens = await tokenRequest(\n\t\tauthorizationServerUrl,\n\t\toptions,\n\t\tnew URLSearchParams({ grant_type: \"refresh_token\", refresh_token: options.refreshToken }),\n\t);\n\treturn { refresh_token: options.refreshToken, ...tokens };\n}\n\nasync function runFlow(provider: OAuthClientProvider, options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n\tconst metadataUrl = options.authorizationServerMetadataUrl && secureEndpoint(options.authorizationServerMetadataUrl);\n\t// With a configured metadata URL, discovery is not cached, so changing the URL applies at once.\n\tlet cached = metadataUrl ? undefined : await provider.discoveryState?.();\n\tif (options.resourceMetadataUrl && options.resourceMetadataUrl.href !== cached?.resourceMetadataUrl)\n\t\tcached = undefined;\n\tconst discovered = cached?.authorizationServerUrl\n\t\t? {\n\t\t\t\tauthorizationServerUrl: cached.authorizationServerUrl,\n\t\t\t\tauthorizationServerMetadata:\n\t\t\t\t\tcached.authorizationServerMetadata ??\n\t\t\t\t\t(await discoverAuthorizationServerMetadata(cached.authorizationServerUrl, {\n\t\t\t\t\t\tfetch: options.fetch,\n\t\t\t\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\t\t\t})),\n\t\t\t\tresourceMetadata: cached.resourceMetadata,\n\t\t\t}\n\t\t: await discoverOAuthServerInfo(options.serverUrl, {\n\t\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\t\tauthorizationServerMetadataUrl: metadataUrl,\n\t\t\t\tfetch: options.fetch,\n\t\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\t});\n\tif (!metadataUrl) {\n\t\tawait provider.saveDiscoveryState?.({\n\t\t\t...discovered,\n\t\t\t...(options.resourceMetadataUrl || cached?.resourceMetadataUrl\n\t\t\t\t? { resourceMetadataUrl: options.resourceMetadataUrl?.href ?? cached?.resourceMetadataUrl }\n\t\t\t\t: {}),\n\t\t});\n\t}\n\tconst metadata = discovered.authorizationServerMetadata;\n\tconst resource = selectResource(options.serverUrl, discovered.resourceMetadata);\n\t// `||`, not `??`: an empty scope (for example from `scopes_supported: []`) falls through to the next source.\n\tconst scope =\n\t\toptions.scope || discovered.resourceMetadata?.scopes_supported?.join(\" \") || provider.clientMetadata.scope;\n\tlet client = await provider.clientInformation();\n\tif (!client) {\n\t\tif (options.authorizationCode) throw new Error(\"OAuth client information is missing during code exchange\");\n\t\tif (metadata?.client_id_metadata_document_supported && provider.clientMetadataUrl) {\n\t\t\tconst url = new URL(provider.clientMetadataUrl);\n\t\t\tif (url.protocol !== \"https:\" || url.pathname === \"/\") throw new Error(\"Invalid OAuth client metadata URL\");\n\t\t\tclient = { client_id: provider.clientMetadataUrl };\n\t\t\tawait provider.saveClientInformation?.(client);\n\t\t} else {\n\t\t\tif (!provider.saveClientInformation) throw new Error(\"OAuth client information cannot be persisted\");\n\t\t\tclient = await registerClient(discovered.authorizationServerUrl, {\n\t\t\t\tmetadata,\n\t\t\t\tclientMetadata: provider.clientMetadata,\n\t\t\t\tscope,\n\t\t\t\tfetch: options.fetch,\n\t\t\t});\n\t\t\tawait provider.saveClientInformation(client);\n\t\t}\n\t}\n\tconst tokenOptions: TokenRequestOptions = {\n\t\tmetadata,\n\t\tclientInformation: client,\n\t\tresource,\n\t\taddClientAuthentication: provider.addClientAuthentication,\n\t\tfetch: options.fetch,\n\t};\n\tif (options.authorizationCode) {\n\t\t// RFC 9207: never send a code from another authorization server to this one.\n\t\tconst iss = options.iss;\n\t\tif (metadata && (iss !== undefined || metadata.authorization_response_iss_parameter_supported)) {\n\t\t\tif (iss !== metadata.issuer) throw new OAuthIssuerMismatchError(metadata.issuer, iss);\n\t\t}\n\t\tconst tokens = await exchangeAuthorizationCode(discovered.authorizationServerUrl, {\n\t\t\t...tokenOptions,\n\t\t\tcode: options.authorizationCode,\n\t\t\tcodeVerifier: await provider.codeVerifier(),\n\t\t\tredirectUrl: provider.redirectUrl,\n\t\t});\n\t\tawait provider.saveTokens(tokens);\n\t\treturn \"AUTHORIZED\";\n\t}\n\tconst existing = options.skipRefresh ? undefined : await provider.tokens();\n\tif (existing?.refresh_token) {\n\t\ttry {\n\t\t\tconst tokens = await refreshAuthorization(discovered.authorizationServerUrl, {\n\t\t\t\t...tokenOptions,\n\t\t\t\trefreshToken: existing.refresh_token,\n\t\t\t});\n\t\t\tawait provider.saveTokens(tokens);\n\t\t\treturn \"AUTHORIZED\";\n\t\t} catch (error) {\n\t\t\tif (error instanceof OAuthInsecureEndpointError) throw error;\n\t\t\tif (error instanceof OAuthError && error.code !== \"server_error\") throw error;\n\t\t}\n\t}\n\tconst state = await provider.state?.();\n\tconst authorization = await startAuthorization(discovered.authorizationServerUrl, {\n\t\tmetadata,\n\t\tclientInformation: client,\n\t\tredirectUrl: provider.redirectUrl,\n\t\tscope,\n\t\tstate,\n\t\tresource,\n\t});\n\tawait provider.saveCodeVerifier(authorization.codeVerifier);\n\tawait provider.redirectToAuthorization(authorization.authorizationUrl);\n\treturn \"REDIRECT\";\n}\n\nexport async function authorizeMcp(provider: OAuthClientProvider, options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n\ttry {\n\t\treturn await runFlow(provider, options);\n\t} catch (error) {\n\t\tif (error instanceof OAuthError && [\"invalid_client\", \"unauthorized_client\"].includes(error.code)) {\n\t\t\tawait provider.invalidateCredentials?.(\"all\");\n\t\t\treturn runFlow(provider, options);\n\t\t}\n\t\tif (error instanceof OAuthError && error.code === \"invalid_grant\") {\n\t\t\tawait provider.invalidateCredentials?.(\"tokens\");\n\t\t\treturn runFlow(provider, options);\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Auth provider for `StreamableHttpTransport`. After a 401 it refreshes the tokens, or throws\n * `McpOAuthAuthorizationRequiredError` when the user has to authorize (again). Concurrent 401s share\n * one refresh, and a request whose token was already replaced is just retried: with rotating refresh\n * tokens, a second refresh with the old refresh token would fail and discard the new grant.\n */\nexport function adaptOAuthProvider(provider: OAuthClientProvider): AuthProvider {\n\tlet inFlight: Promise<void> | undefined;\n\treturn {\n\t\ttoken: async () => (await provider.tokens())?.access_token,\n\t\tonUnauthorized: async (context: UnauthorizedContext) => {\n\t\t\tconst challenge = parseWwwAuthenticate(context.response.headers.get(\"www-authenticate\"));\n\t\t\tconst insufficientScope = challenge.error === \"insufficient_scope\";\n\t\t\tif (!insufficientScope && !inFlight && context.token !== undefined) {\n\t\t\t\tconst current = (await provider.tokens())?.access_token;\n\t\t\t\tif (current !== undefined && current !== context.token) return;\n\t\t\t}\n\t\t\tinFlight ??= authorizeMcp(provider, {\n\t\t\t\tserverUrl: context.serverUrl,\n\t\t\t\tresourceMetadataUrl: challenge.resourceMetadataUrl,\n\t\t\t\tscope: challenge.scope,\n\t\t\t\tfetch: context.fetch,\n\t\t\t\tskipRefresh: insufficientScope,\n\t\t\t})\n\t\t\t\t.then((result) => {\n\t\t\t\t\tif (result === \"REDIRECT\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tinFlight = undefined;\n\t\t\t\t});\n\t\t\tawait inFlight;\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export { type OAuthCallback, type OAuthCallbackPage, OAuthCallbackServer, type OAuthCallbackServerOptions, } from "./callback.js";
2
+ export { buildAuthorizationServerDiscoveryUrls, discoverAuthorizationServerMetadata, discoverOAuthServerInfo, discoverProtectedResourceMetadata, parseWwwAuthenticate, resourceUrlFromServerUrl, selectResource, } from "./discovery.js";
3
+ export { McpOAuthAuthorizationRequiredError, OAuthError, OAuthInsecureEndpointError, OAuthIssuerMismatchError, OAuthRegistrationError, } from "./errors.js";
4
+ export { type AddClientAuthentication, adaptOAuthProvider, authorizeMcp, exchangeAuthorizationCode, type OAuthClientProvider, type OAuthFlowOptions, type OAuthFlowResult, refreshAuthorization, registerClient, startAuthorization, type TokenRequestOptions, } from "./flow.js";
5
+ export { McpOAuthProvider, type McpOAuthProviderOptions, type McpOAuthState, type McpOAuthStateStore, MemoryOAuthStateStore, } from "./provider.js";
6
+ export type { AuthorizationServerMetadata, OAuthChallenge, OAuthClientInformation, OAuthClientInformationFull, OAuthClientInformationMixed, OAuthClientMetadata, OAuthDiscoveryState, OAuthProtectedResourceMetadata, OAuthServerInfo, OAuthTokens, } from "./types.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/mcp/client/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,mBAAmB,EACnB,KAAK,0BAA0B,GAC/B,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,qCAAqC,EACrC,mCAAmC,EACnC,uBAAuB,EACvB,iCAAiC,EACjC,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,kCAAkC,EAClC,UAAU,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,KAAK,uBAAuB,EAC5B,kBAAkB,EAClB,YAAY,EACZ,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,KAAK,mBAAmB,GACxB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,qBAAqB,GACrB,MAAM,eAAe,CAAC;AACvB,YAAY,EACX,2BAA2B,EAC3B,cAAc,EACd,sBAAsB,EACtB,0BAA0B,EAC1B,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,8BAA8B,EAC9B,eAAe,EACf,WAAW,GACX,MAAM,YAAY,CAAC"}
@@ -0,0 +1,6 @@
1
+ export { OAuthCallbackServer, } from "./callback.js";
2
+ export { buildAuthorizationServerDiscoveryUrls, discoverAuthorizationServerMetadata, discoverOAuthServerInfo, discoverProtectedResourceMetadata, parseWwwAuthenticate, resourceUrlFromServerUrl, selectResource, } from "./discovery.js";
3
+ export { McpOAuthAuthorizationRequiredError, OAuthError, OAuthInsecureEndpointError, OAuthIssuerMismatchError, OAuthRegistrationError, } from "./errors.js";
4
+ export { adaptOAuthProvider, authorizeMcp, exchangeAuthorizationCode, refreshAuthorization, registerClient, startAuthorization, } from "./flow.js";
5
+ export { McpOAuthProvider, MemoryOAuthStateStore, } from "./provider.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/extensions/mcp/client/oauth/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,mBAAmB,GAEnB,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,qCAAqC,EACrC,mCAAmC,EACnC,uBAAuB,EACvB,iCAAiC,EACjC,oBAAoB,EACpB,wBAAwB,EACxB,cAAc,GACd,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACN,kCAAkC,EAClC,UAAU,EACV,0BAA0B,EAC1B,wBAAwB,EACxB,sBAAsB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EAEN,kBAAkB,EAClB,YAAY,EACZ,yBAAyB,EAIzB,oBAAoB,EACpB,cAAc,EACd,kBAAkB,GAElB,MAAM,WAAW,CAAC;AACnB,OAAO,EACN,gBAAgB,EAIhB,qBAAqB,GACrB,MAAM,eAAe,CAAC","sourcesContent":["export {\n\ttype OAuthCallback,\n\ttype OAuthCallbackPage,\n\tOAuthCallbackServer,\n\ttype OAuthCallbackServerOptions,\n} from \"./callback.js\";\nexport {\n\tbuildAuthorizationServerDiscoveryUrls,\n\tdiscoverAuthorizationServerMetadata,\n\tdiscoverOAuthServerInfo,\n\tdiscoverProtectedResourceMetadata,\n\tparseWwwAuthenticate,\n\tresourceUrlFromServerUrl,\n\tselectResource,\n} from \"./discovery.js\";\nexport {\n\tMcpOAuthAuthorizationRequiredError,\n\tOAuthError,\n\tOAuthInsecureEndpointError,\n\tOAuthIssuerMismatchError,\n\tOAuthRegistrationError,\n} from \"./errors.js\";\nexport {\n\ttype AddClientAuthentication,\n\tadaptOAuthProvider,\n\tauthorizeMcp,\n\texchangeAuthorizationCode,\n\ttype OAuthClientProvider,\n\ttype OAuthFlowOptions,\n\ttype OAuthFlowResult,\n\trefreshAuthorization,\n\tregisterClient,\n\tstartAuthorization,\n\ttype TokenRequestOptions,\n} from \"./flow.js\";\nexport {\n\tMcpOAuthProvider,\n\ttype McpOAuthProviderOptions,\n\ttype McpOAuthState,\n\ttype McpOAuthStateStore,\n\tMemoryOAuthStateStore,\n} from \"./provider.js\";\nexport type {\n\tAuthorizationServerMetadata,\n\tOAuthChallenge,\n\tOAuthClientInformation,\n\tOAuthClientInformationFull,\n\tOAuthClientInformationMixed,\n\tOAuthClientMetadata,\n\tOAuthDiscoveryState,\n\tOAuthProtectedResourceMetadata,\n\tOAuthServerInfo,\n\tOAuthTokens,\n} from \"./types.js\";\n"]}
@@ -0,0 +1,59 @@
1
+ import type { OAuthClientProvider } from "./flow.js";
2
+ import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthDiscoveryState, OAuthTokens } from "./types.js";
3
+ export interface McpOAuthState {
4
+ serverUrl: string;
5
+ clientInformation?: OAuthClientInformationMixed;
6
+ tokens?: OAuthTokens;
7
+ /** When the access token expires, in milliseconds since the epoch, from `expires_in` at the time it was saved. */
8
+ tokensExpireAt?: number;
9
+ codeVerifier?: string;
10
+ oauthState?: string;
11
+ discovery?: OAuthDiscoveryState;
12
+ }
13
+ export interface McpOAuthStateStore {
14
+ load(): McpOAuthState | undefined | Promise<McpOAuthState | undefined>;
15
+ save(state: McpOAuthState): void | Promise<void>;
16
+ }
17
+ export interface McpOAuthProviderOptions {
18
+ serverUrl: string | URL;
19
+ redirectUrl: string | URL;
20
+ clientMetadata: Omit<OAuthClientMetadata, "redirect_uris"> & {
21
+ redirect_uris?: string[];
22
+ };
23
+ clientId?: string;
24
+ clientSecret?: string;
25
+ store?: McpOAuthStateStore;
26
+ onRedirect(url: URL): void | Promise<void>;
27
+ }
28
+ export declare class MemoryOAuthStateStore implements McpOAuthStateStore {
29
+ private value;
30
+ load(): McpOAuthState | undefined;
31
+ save(state: McpOAuthState): void;
32
+ }
33
+ /** Default stateful provider for one exact MCP server URL. Applications inject durable storage if needed. */
34
+ export declare class McpOAuthProvider implements OAuthClientProvider {
35
+ readonly redirectUrl: string;
36
+ readonly clientMetadata: OAuthClientMetadata;
37
+ private serverUrl;
38
+ private configuredClient;
39
+ private store;
40
+ private onRedirect;
41
+ private writes;
42
+ constructor(options: McpOAuthProviderOptions);
43
+ state(): Promise<string>;
44
+ clientInformation(): Promise<OAuthClientInformationMixed | undefined>;
45
+ saveClientInformation(information: OAuthClientInformationMixed): Promise<void>;
46
+ tokens(): Promise<OAuthTokens | undefined>;
47
+ saveTokens(tokens: OAuthTokens): Promise<void>;
48
+ redirectToAuthorization(url: URL): Promise<void>;
49
+ saveCodeVerifier(verifier: string): Promise<void>;
50
+ codeVerifier(): Promise<string>;
51
+ invalidateCredentials(kind: "all" | "client" | "tokens" | "verifier" | "discovery"): Promise<void>;
52
+ saveDiscoveryState(discovery: OAuthDiscoveryState): Promise<void>;
53
+ discoveryState(): Promise<OAuthDiscoveryState | undefined>;
54
+ private load;
55
+ private update;
56
+ /** Stored state for another server URL is ignored so credentials never leak across servers. */
57
+ private own;
58
+ }
59
+ //# sourceMappingURL=provider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../../../src/extensions/mcp/client/oauth/provider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,116 @@
1
+ export class MemoryOAuthStateStore {
2
+ value;
3
+ load() {
4
+ return this.value === undefined ? undefined : structuredClone(this.value);
5
+ }
6
+ save(state) {
7
+ this.value = structuredClone(state);
8
+ }
9
+ }
10
+ /** Default stateful provider for one exact MCP server URL. Applications inject durable storage if needed. */
11
+ export class McpOAuthProvider {
12
+ redirectUrl;
13
+ clientMetadata;
14
+ serverUrl;
15
+ configuredClient;
16
+ store;
17
+ onRedirect;
18
+ writes = Promise.resolve();
19
+ constructor(options) {
20
+ this.serverUrl = String(new URL(options.serverUrl));
21
+ this.redirectUrl = String(options.redirectUrl);
22
+ this.clientMetadata = {
23
+ ...options.clientMetadata,
24
+ redirect_uris: options.clientMetadata.redirect_uris ?? [this.redirectUrl],
25
+ grant_types: options.clientMetadata.grant_types ?? ["authorization_code", "refresh_token"],
26
+ response_types: options.clientMetadata.response_types ?? ["code"],
27
+ token_endpoint_auth_method: options.clientMetadata.token_endpoint_auth_method ?? (options.clientSecret ? "client_secret_post" : "none"),
28
+ };
29
+ this.configuredClient = options.clientId
30
+ ? { client_id: options.clientId, ...(options.clientSecret ? { client_secret: options.clientSecret } : {}) }
31
+ : undefined;
32
+ this.store = options.store ?? new MemoryOAuthStateStore();
33
+ this.onRedirect = options.onRedirect;
34
+ }
35
+ async state() {
36
+ const existing = (await this.load()).oauthState;
37
+ if (existing)
38
+ return existing;
39
+ const state = Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString("hex");
40
+ await this.update((value) => ({ ...value, oauthState: state }));
41
+ return state;
42
+ }
43
+ async clientInformation() {
44
+ return this.configuredClient ?? (await this.load()).clientInformation;
45
+ }
46
+ async saveClientInformation(information) {
47
+ if (this.configuredClient)
48
+ return;
49
+ await this.update((value) => ({ ...value, clientInformation: information }));
50
+ }
51
+ async tokens() {
52
+ return (await this.load()).tokens;
53
+ }
54
+ async saveTokens(tokens) {
55
+ const expiresAt = tokens.expires_in === undefined ? undefined : Date.now() + tokens.expires_in * 1000;
56
+ await this.update((value) => {
57
+ const next = { ...value, tokens };
58
+ if (expiresAt === undefined)
59
+ delete next.tokensExpireAt;
60
+ else
61
+ next.tokensExpireAt = expiresAt;
62
+ return next;
63
+ });
64
+ }
65
+ async redirectToAuthorization(url) {
66
+ await this.onRedirect(url);
67
+ }
68
+ async saveCodeVerifier(verifier) {
69
+ await this.update((value) => ({ ...value, codeVerifier: verifier }));
70
+ }
71
+ async codeVerifier() {
72
+ const verifier = (await this.load()).codeVerifier;
73
+ if (!verifier)
74
+ throw new Error("No OAuth PKCE code verifier is stored");
75
+ return verifier;
76
+ }
77
+ async invalidateCredentials(kind) {
78
+ await this.update((value) => {
79
+ const next = { ...value };
80
+ if (kind === "all" || kind === "client")
81
+ delete next.clientInformation;
82
+ if (kind === "all" || kind === "tokens") {
83
+ delete next.tokens;
84
+ delete next.tokensExpireAt;
85
+ }
86
+ if (kind === "all" || kind === "verifier")
87
+ delete next.codeVerifier;
88
+ if (kind === "all" || kind === "discovery")
89
+ delete next.discovery;
90
+ if (kind === "all")
91
+ delete next.oauthState;
92
+ return next;
93
+ });
94
+ }
95
+ async saveDiscoveryState(discovery) {
96
+ await this.update((value) => ({ ...value, discovery }));
97
+ }
98
+ async discoveryState() {
99
+ return (await this.load()).discovery;
100
+ }
101
+ async load() {
102
+ await this.writes;
103
+ return this.own(await this.store.load());
104
+ }
105
+ async update(update) {
106
+ this.writes = this.writes.then(async () => {
107
+ await this.store.save(update(this.own(await this.store.load())));
108
+ });
109
+ await this.writes;
110
+ }
111
+ /** Stored state for another server URL is ignored so credentials never leak across servers. */
112
+ own(state) {
113
+ return state?.serverUrl === this.serverUrl ? state : { serverUrl: this.serverUrl };
114
+ }
115
+ }
116
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../../../src/extensions/mcp/client/oauth/provider.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OAuthClientProvider } from \"./flow.js\";\nimport type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthDiscoveryState, OAuthTokens } from \"./types.js\";\n\nexport interface McpOAuthState {\n\tserverUrl: string;\n\tclientInformation?: OAuthClientInformationMixed;\n\ttokens?: OAuthTokens;\n\t/** When the access token expires, in milliseconds since the epoch, from `expires_in` at the time it was saved. */\n\ttokensExpireAt?: number;\n\tcodeVerifier?: string;\n\toauthState?: string;\n\tdiscovery?: OAuthDiscoveryState;\n}\n\nexport interface McpOAuthStateStore {\n\tload(): McpOAuthState | undefined | Promise<McpOAuthState | undefined>;\n\tsave(state: McpOAuthState): void | Promise<void>;\n}\n\nexport interface McpOAuthProviderOptions {\n\tserverUrl: string | URL;\n\tredirectUrl: string | URL;\n\tclientMetadata: Omit<OAuthClientMetadata, \"redirect_uris\"> & { redirect_uris?: string[] };\n\tclientId?: string;\n\tclientSecret?: string;\n\tstore?: McpOAuthStateStore;\n\tonRedirect(url: URL): void | Promise<void>;\n}\n\nexport class MemoryOAuthStateStore implements McpOAuthStateStore {\n\tprivate value: McpOAuthState | undefined;\n\n\tload(): McpOAuthState | undefined {\n\t\treturn this.value === undefined ? undefined : structuredClone(this.value);\n\t}\n\n\tsave(state: McpOAuthState): void {\n\t\tthis.value = structuredClone(state);\n\t}\n}\n\n/** Default stateful provider for one exact MCP server URL. Applications inject durable storage if needed. */\nexport class McpOAuthProvider implements OAuthClientProvider {\n\treadonly redirectUrl: string;\n\treadonly clientMetadata: OAuthClientMetadata;\n\tprivate serverUrl: string;\n\tprivate configuredClient: OAuthClientInformationMixed | undefined;\n\tprivate store: McpOAuthStateStore;\n\tprivate onRedirect: (url: URL) => void | Promise<void>;\n\tprivate writes: Promise<void> = Promise.resolve();\n\n\tconstructor(options: McpOAuthProviderOptions) {\n\t\tthis.serverUrl = String(new URL(options.serverUrl));\n\t\tthis.redirectUrl = String(options.redirectUrl);\n\t\tthis.clientMetadata = {\n\t\t\t...options.clientMetadata,\n\t\t\tredirect_uris: options.clientMetadata.redirect_uris ?? [this.redirectUrl],\n\t\t\tgrant_types: options.clientMetadata.grant_types ?? [\"authorization_code\", \"refresh_token\"],\n\t\t\tresponse_types: options.clientMetadata.response_types ?? [\"code\"],\n\t\t\ttoken_endpoint_auth_method:\n\t\t\t\toptions.clientMetadata.token_endpoint_auth_method ?? (options.clientSecret ? \"client_secret_post\" : \"none\"),\n\t\t};\n\t\tthis.configuredClient = options.clientId\n\t\t\t? { client_id: options.clientId, ...(options.clientSecret ? { client_secret: options.clientSecret } : {}) }\n\t\t\t: undefined;\n\t\tthis.store = options.store ?? new MemoryOAuthStateStore();\n\t\tthis.onRedirect = options.onRedirect;\n\t}\n\n\tasync state(): Promise<string> {\n\t\tconst existing = (await this.load()).oauthState;\n\t\tif (existing) return existing;\n\t\tconst state = Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString(\"hex\");\n\t\tawait this.update((value) => ({ ...value, oauthState: state }));\n\t\treturn state;\n\t}\n\n\tasync clientInformation(): Promise<OAuthClientInformationMixed | undefined> {\n\t\treturn this.configuredClient ?? (await this.load()).clientInformation;\n\t}\n\n\tasync saveClientInformation(information: OAuthClientInformationMixed): Promise<void> {\n\t\tif (this.configuredClient) return;\n\t\tawait this.update((value) => ({ ...value, clientInformation: information }));\n\t}\n\n\tasync tokens(): Promise<OAuthTokens | undefined> {\n\t\treturn (await this.load()).tokens;\n\t}\n\n\tasync saveTokens(tokens: OAuthTokens): Promise<void> {\n\t\tconst expiresAt = tokens.expires_in === undefined ? undefined : Date.now() + tokens.expires_in * 1000;\n\t\tawait this.update((value) => {\n\t\t\tconst next: McpOAuthState = { ...value, tokens };\n\t\t\tif (expiresAt === undefined) delete next.tokensExpireAt;\n\t\t\telse next.tokensExpireAt = expiresAt;\n\t\t\treturn next;\n\t\t});\n\t}\n\n\tasync redirectToAuthorization(url: URL): Promise<void> {\n\t\tawait this.onRedirect(url);\n\t}\n\n\tasync saveCodeVerifier(verifier: string): Promise<void> {\n\t\tawait this.update((value) => ({ ...value, codeVerifier: verifier }));\n\t}\n\n\tasync codeVerifier(): Promise<string> {\n\t\tconst verifier = (await this.load()).codeVerifier;\n\t\tif (!verifier) throw new Error(\"No OAuth PKCE code verifier is stored\");\n\t\treturn verifier;\n\t}\n\n\tasync invalidateCredentials(kind: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): Promise<void> {\n\t\tawait this.update((value) => {\n\t\t\tconst next = { ...value };\n\t\t\tif (kind === \"all\" || kind === \"client\") delete next.clientInformation;\n\t\t\tif (kind === \"all\" || kind === \"tokens\") {\n\t\t\t\tdelete next.tokens;\n\t\t\t\tdelete next.tokensExpireAt;\n\t\t\t}\n\t\t\tif (kind === \"all\" || kind === \"verifier\") delete next.codeVerifier;\n\t\t\tif (kind === \"all\" || kind === \"discovery\") delete next.discovery;\n\t\t\tif (kind === \"all\") delete next.oauthState;\n\t\t\treturn next;\n\t\t});\n\t}\n\n\tasync saveDiscoveryState(discovery: OAuthDiscoveryState): Promise<void> {\n\t\tawait this.update((value) => ({ ...value, discovery }));\n\t}\n\n\tasync discoveryState(): Promise<OAuthDiscoveryState | undefined> {\n\t\treturn (await this.load()).discovery;\n\t}\n\n\tprivate async load(): Promise<McpOAuthState> {\n\t\tawait this.writes;\n\t\treturn this.own(await this.store.load());\n\t}\n\n\tprivate async update(update: (state: McpOAuthState) => McpOAuthState): Promise<void> {\n\t\tthis.writes = this.writes.then(async () => {\n\t\t\tawait this.store.save(update(this.own(await this.store.load())));\n\t\t});\n\t\tawait this.writes;\n\t}\n\n\t/** Stored state for another server URL is ignored so credentials never leak across servers. */\n\tprivate own(state: McpOAuthState | undefined): McpOAuthState {\n\t\treturn state?.serverUrl === this.serverUrl ? state : { serverUrl: this.serverUrl };\n\t}\n}\n"]}