@atxp/client 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/index.cjs +745 -142
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +745 -142
  4. package/dist/index.js.map +1 -1
  5. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js +369 -99
  6. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/client/auth.js.map +1 -1
  7. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js +18 -18
  8. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/client/streamableHttp.js.map +1 -1
  9. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js +162 -0
  10. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js.map +1 -0
  11. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js +86 -14
  12. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/auth.js.map +1 -1
  13. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js +47 -9
  14. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/protocol.js.map +1 -1
  15. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js +64 -5
  16. package/dist/node_modules/@modelcontextprotocol/sdk/dist/esm/types.js.map +1 -1
  17. package/dist/node_modules/eventsource-parser/dist/index.js +1 -1
  18. package/dist/node_modules/eventsource-parser/dist/index.js.map +1 -1
  19. package/dist/node_modules/zod/{dist/esm/v3 → v3}/ZodError.js +3 -2
  20. package/dist/node_modules/zod/v3/ZodError.js.map +1 -0
  21. package/dist/node_modules/zod/v3/errors.js.map +1 -0
  22. package/dist/node_modules/zod/v3/helpers/errorUtil.js.map +1 -0
  23. package/dist/node_modules/zod/v3/helpers/parseUtil.js.map +1 -0
  24. package/dist/node_modules/zod/v3/helpers/util.js.map +1 -0
  25. package/dist/node_modules/zod/{dist/esm/v3 → v3}/locales/en.js +2 -0
  26. package/dist/node_modules/zod/v3/locales/en.js.map +1 -0
  27. package/dist/node_modules/zod/{dist/esm/v3 → v3}/types.js +5 -2
  28. package/dist/node_modules/zod/v3/types.js.map +1 -0
  29. package/package.json +2 -2
  30. package/dist/node_modules/zod/dist/esm/v3/ZodError.js.map +0 -1
  31. package/dist/node_modules/zod/dist/esm/v3/errors.js.map +0 -1
  32. package/dist/node_modules/zod/dist/esm/v3/helpers/errorUtil.js.map +0 -1
  33. package/dist/node_modules/zod/dist/esm/v3/helpers/parseUtil.js.map +0 -1
  34. package/dist/node_modules/zod/dist/esm/v3/helpers/util.js.map +0 -1
  35. package/dist/node_modules/zod/dist/esm/v3/locales/en.js.map +0 -1
  36. package/dist/node_modules/zod/dist/esm/v3/types.js.map +0 -1
  37. /package/dist/node_modules/zod/{dist/esm/v3 → v3}/errors.js +0 -0
  38. /package/dist/node_modules/zod/{dist/esm/v3 → v3}/helpers/errorUtil.js +0 -0
  39. /package/dist/node_modules/zod/{dist/esm/v3 → v3}/helpers/parseUtil.js +0 -0
  40. /package/dist/node_modules/zod/{dist/esm/v3 → v3}/helpers/util.js +0 -0
package/dist/index.js CHANGED
@@ -915,8 +915,9 @@ class ZodError extends Error {
915
915
  const formErrors = [];
916
916
  for (const sub of this.issues) {
917
917
  if (sub.path.length > 0) {
918
- fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
919
- fieldErrors[sub.path[0]].push(mapper(sub));
918
+ const firstEl = sub.path[0];
919
+ fieldErrors[firstEl] = fieldErrors[firstEl] || [];
920
+ fieldErrors[firstEl].push(mapper(sub));
920
921
  }
921
922
  else {
922
923
  formErrors.push(mapper(sub));
@@ -1000,6 +1001,8 @@ const errorMap = (issue, _ctx) => {
1000
1001
  message = `String must contain ${issue.exact ? "exactly" : issue.inclusive ? `at least` : `over`} ${issue.minimum} character(s)`;
1001
1002
  else if (issue.type === "number")
1002
1003
  message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
1004
+ else if (issue.type === "bigint")
1005
+ message = `Number must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${issue.minimum}`;
1003
1006
  else if (issue.type === "date")
1004
1007
  message = `Date must be ${issue.exact ? `exactly equal to ` : issue.inclusive ? `greater than or equal to ` : `greater than `}${new Date(Number(issue.minimum))}`;
1005
1008
  else
@@ -1597,6 +1600,8 @@ function isValidJWT(jwt, alg) {
1597
1600
  return false;
1598
1601
  try {
1599
1602
  const [header] = jwt.split(".");
1603
+ if (!header)
1604
+ return false;
1600
1605
  // Convert base64url to base64
1601
1606
  const base64 = header
1602
1607
  .replace(/-/g, "+")
@@ -4637,6 +4642,7 @@ const enumType = ZodEnum.create;
4637
4642
  ZodPromise.create;
4638
4643
  const optionalType = ZodOptional.create;
4639
4644
  ZodNullable.create;
4645
+ const NEVER = INVALID;
4640
4646
 
4641
4647
  const LATEST_PROTOCOL_VERSION = "2025-06-18";
4642
4648
  const SUPPORTED_PROTOCOL_VERSIONS = [
@@ -4798,6 +4804,24 @@ const CancelledNotificationSchema = NotificationSchema.extend({
4798
4804
  }),
4799
4805
  });
4800
4806
  /* Base Metadata */
4807
+ /**
4808
+ * Icon schema for use in tools, prompts, resources, and implementations.
4809
+ */
4810
+ const IconSchema = objectType({
4811
+ /**
4812
+ * URL or data URI for the icon.
4813
+ */
4814
+ src: stringType(),
4815
+ /**
4816
+ * Optional MIME type for the icon.
4817
+ */
4818
+ mimeType: optionalType(stringType()),
4819
+ /**
4820
+ * Optional string specifying icon dimensions (e.g., "48x48 96x96").
4821
+ */
4822
+ sizes: optionalType(stringType()),
4823
+ })
4824
+ .passthrough();
4801
4825
  /**
4802
4826
  * Base metadata interface for common properties across resources, tools, prompts, and implementations.
4803
4827
  */
@@ -4821,6 +4845,19 @@ const BaseMetadataSchema = objectType({
4821
4845
  */
4822
4846
  const ImplementationSchema = BaseMetadataSchema.extend({
4823
4847
  version: stringType(),
4848
+ /**
4849
+ * An optional URL of the website for this implementation.
4850
+ */
4851
+ websiteUrl: optionalType(stringType()),
4852
+ /**
4853
+ * An optional list of icons for this implementation.
4854
+ * This can be used by clients to display the implementation in a user interface.
4855
+ * Each icon should have a `kind` property that specifies whether it is a data representation or a URL source, a `src` property that points to the icon file or data representation, and may also include a `mimeType` and `sizes` property.
4856
+ * The `mimeType` property should be a valid MIME type for the icon file, such as "image/png" or "image/svg+xml".
4857
+ * The `sizes` property should be a string that specifies one or more sizes at which the icon file can be used, such as "48x48" or "any" for scalable formats like SVG.
4858
+ * The `sizes` property is optional, and if not provided, the client should assume that the icon can be used at any size.
4859
+ */
4860
+ icons: optionalType(arrayType(IconSchema)),
4824
4861
  });
4825
4862
  /**
4826
4863
  * Capabilities a client may support. Known capabilities are defined here, in this schema, but this is not a closed set: any client can define its own, additional capabilities.
@@ -5018,11 +5055,27 @@ const TextResourceContentsSchema = ResourceContentsSchema.extend({
5018
5055
  */
5019
5056
  text: stringType(),
5020
5057
  });
5058
+ /**
5059
+ * A Zod schema for validating Base64 strings that is more performant and
5060
+ * robust for very large inputs than the default regex-based check. It avoids
5061
+ * stack overflows by using the native `atob` function for validation.
5062
+ */
5063
+ const Base64Schema = stringType().refine((val) => {
5064
+ try {
5065
+ // atob throws a DOMException if the string contains characters
5066
+ // that are not part of the Base64 character set.
5067
+ atob(val);
5068
+ return true;
5069
+ }
5070
+ catch (_a) {
5071
+ return false;
5072
+ }
5073
+ }, { message: "Invalid Base64 string" });
5021
5074
  const BlobResourceContentsSchema = ResourceContentsSchema.extend({
5022
5075
  /**
5023
5076
  * A base64-encoded string representing the binary data of the item.
5024
5077
  */
5025
- blob: stringType().base64(),
5078
+ blob: Base64Schema,
5026
5079
  });
5027
5080
  /**
5028
5081
  * A known resource that the server is capable of reading.
@@ -5042,6 +5095,10 @@ const ResourceSchema = BaseMetadataSchema.extend({
5042
5095
  * The MIME type of this resource, if known.
5043
5096
  */
5044
5097
  mimeType: optionalType(stringType()),
5098
+ /**
5099
+ * An optional list of icons for this resource.
5100
+ */
5101
+ icons: optionalType(arrayType(IconSchema)),
5045
5102
  /**
5046
5103
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
5047
5104
  * for notes on _meta usage.
@@ -5187,6 +5244,10 @@ const PromptSchema = BaseMetadataSchema.extend({
5187
5244
  * A list of arguments to use for templating the prompt.
5188
5245
  */
5189
5246
  arguments: optionalType(arrayType(PromptArgumentSchema)),
5247
+ /**
5248
+ * An optional list of icons for this prompt.
5249
+ */
5250
+ icons: optionalType(arrayType(IconSchema)),
5190
5251
  /**
5191
5252
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
5192
5253
  * for notes on _meta usage.
@@ -5245,7 +5306,7 @@ const ImageContentSchema = objectType({
5245
5306
  /**
5246
5307
  * The base64-encoded image data.
5247
5308
  */
5248
- data: stringType().base64(),
5309
+ data: Base64Schema,
5249
5310
  /**
5250
5311
  * The MIME type of the image. Different providers may support different image types.
5251
5312
  */
@@ -5265,7 +5326,7 @@ const AudioContentSchema = objectType({
5265
5326
  /**
5266
5327
  * The base64-encoded audio data.
5267
5328
  */
5268
- data: stringType().base64(),
5329
+ data: Base64Schema,
5269
5330
  /**
5270
5331
  * The MIME type of the audio. Different providers may support different audio types.
5271
5332
  */
@@ -5414,6 +5475,10 @@ const ToolSchema = BaseMetadataSchema.extend({
5414
5475
  * Optional additional tool information.
5415
5476
  */
5416
5477
  annotations: optionalType(ToolAnnotationsSchema),
5478
+ /**
5479
+ * An optional list of icons for this tool.
5480
+ */
5481
+ icons: optionalType(arrayType(IconSchema)),
5417
5482
  /**
5418
5483
  * See [MCP specification](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/47339c03c143bb4ec01a26e721a1b8fe66634ebe/docs/specification/draft/basic/index.mdx#general-fields)
5419
5484
  * for notes on _meta usage.
@@ -5906,6 +5971,7 @@ class Protocol {
5906
5971
  this._responseHandlers = new Map();
5907
5972
  this._progressHandlers = new Map();
5908
5973
  this._timeoutInfo = new Map();
5974
+ this._pendingDebouncedNotifications = new Set();
5909
5975
  this.setNotificationHandler(CancelledNotificationSchema, (notification) => {
5910
5976
  const controller = this._requestHandlerAbortControllers.get(notification.params.requestId);
5911
5977
  controller === null || controller === void 0 ? void 0 : controller.abort(notification.params.reason);
@@ -5988,6 +6054,7 @@ class Protocol {
5988
6054
  const responseHandlers = this._responseHandlers;
5989
6055
  this._responseHandlers = new Map();
5990
6056
  this._progressHandlers.clear();
6057
+ this._pendingDebouncedNotifications.clear();
5991
6058
  this._transport = undefined;
5992
6059
  (_a = this.onclose) === null || _a === void 0 ? void 0 : _a.call(this);
5993
6060
  const error = new McpError(ErrorCode.ConnectionClosed, "Connection closed");
@@ -6012,10 +6079,12 @@ class Protocol {
6012
6079
  .catch((error) => this._onerror(new Error(`Uncaught error in notification handler: ${error}`)));
6013
6080
  }
6014
6081
  _onrequest(request, extra) {
6015
- var _a, _b, _c, _d;
6082
+ var _a, _b;
6016
6083
  const handler = (_a = this._requestHandlers.get(request.method)) !== null && _a !== void 0 ? _a : this.fallbackRequestHandler;
6084
+ // Capture the current transport at request time to ensure responses go to the correct client
6085
+ const capturedTransport = this._transport;
6017
6086
  if (handler === undefined) {
6018
- (_b = this._transport) === null || _b === void 0 ? void 0 : _b.send({
6087
+ capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.send({
6019
6088
  jsonrpc: "2.0",
6020
6089
  id: request.id,
6021
6090
  error: {
@@ -6029,8 +6098,8 @@ class Protocol {
6029
6098
  this._requestHandlerAbortControllers.set(request.id, abortController);
6030
6099
  const fullExtra = {
6031
6100
  signal: abortController.signal,
6032
- sessionId: (_c = this._transport) === null || _c === void 0 ? void 0 : _c.sessionId,
6033
- _meta: (_d = request.params) === null || _d === void 0 ? void 0 : _d._meta,
6101
+ sessionId: capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.sessionId,
6102
+ _meta: (_b = request.params) === null || _b === void 0 ? void 0 : _b._meta,
6034
6103
  sendNotification: (notification) => this.notification(notification, { relatedRequestId: request.id }),
6035
6104
  sendRequest: (r, resultSchema, options) => this.request(r, resultSchema, { ...options, relatedRequestId: request.id }),
6036
6105
  authInfo: extra === null || extra === void 0 ? void 0 : extra.authInfo,
@@ -6041,28 +6110,27 @@ class Protocol {
6041
6110
  Promise.resolve()
6042
6111
  .then(() => handler(request, fullExtra))
6043
6112
  .then((result) => {
6044
- var _a;
6045
6113
  if (abortController.signal.aborted) {
6046
6114
  return;
6047
6115
  }
6048
- return (_a = this._transport) === null || _a === void 0 ? void 0 : _a.send({
6116
+ return capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.send({
6049
6117
  result,
6050
6118
  jsonrpc: "2.0",
6051
6119
  id: request.id,
6052
6120
  });
6053
6121
  }, (error) => {
6054
- var _a, _b;
6122
+ var _a;
6055
6123
  if (abortController.signal.aborted) {
6056
6124
  return;
6057
6125
  }
6058
- return (_a = this._transport) === null || _a === void 0 ? void 0 : _a.send({
6126
+ return capturedTransport === null || capturedTransport === void 0 ? void 0 : capturedTransport.send({
6059
6127
  jsonrpc: "2.0",
6060
6128
  id: request.id,
6061
6129
  error: {
6062
6130
  code: Number.isSafeInteger(error["code"])
6063
6131
  ? error["code"]
6064
6132
  : ErrorCode.InternalError,
6065
- message: (_b = error.message) !== null && _b !== void 0 ? _b : "Internal error",
6133
+ message: (_a = error.message) !== null && _a !== void 0 ? _a : "Internal error",
6066
6134
  },
6067
6135
  });
6068
6136
  })
@@ -6201,10 +6269,45 @@ class Protocol {
6201
6269
  * Emits a notification, which is a one-way message that does not expect a response.
6202
6270
  */
6203
6271
  async notification(notification, options) {
6272
+ var _a, _b;
6204
6273
  if (!this._transport) {
6205
6274
  throw new Error("Not connected");
6206
6275
  }
6207
6276
  this.assertNotificationCapability(notification.method);
6277
+ const debouncedMethods = (_b = (_a = this._options) === null || _a === void 0 ? void 0 : _a.debouncedNotificationMethods) !== null && _b !== void 0 ? _b : [];
6278
+ // A notification can only be debounced if it's in the list AND it's "simple"
6279
+ // (i.e., has no parameters and no related request ID that could be lost).
6280
+ const canDebounce = debouncedMethods.includes(notification.method)
6281
+ && !notification.params
6282
+ && !(options === null || options === void 0 ? void 0 : options.relatedRequestId);
6283
+ if (canDebounce) {
6284
+ // If a notification of this type is already scheduled, do nothing.
6285
+ if (this._pendingDebouncedNotifications.has(notification.method)) {
6286
+ return;
6287
+ }
6288
+ // Mark this notification type as pending.
6289
+ this._pendingDebouncedNotifications.add(notification.method);
6290
+ // Schedule the actual send to happen in the next microtask.
6291
+ // This allows all synchronous calls in the current event loop tick to be coalesced.
6292
+ Promise.resolve().then(() => {
6293
+ var _a;
6294
+ // Un-mark the notification so the next one can be scheduled.
6295
+ this._pendingDebouncedNotifications.delete(notification.method);
6296
+ // SAFETY CHECK: If the connection was closed while this was pending, abort.
6297
+ if (!this._transport) {
6298
+ return;
6299
+ }
6300
+ const jsonrpcNotification = {
6301
+ ...notification,
6302
+ jsonrpc: "2.0",
6303
+ };
6304
+ // Send the notification, but don't await it here to avoid blocking.
6305
+ // Handle potential errors with a .catch().
6306
+ (_a = this._transport) === null || _a === void 0 ? void 0 : _a.send(jsonrpcNotification, options).catch(error => this._onerror(error));
6307
+ });
6308
+ // Return immediately.
6309
+ return;
6310
+ }
6208
6311
  const jsonrpcNotification = {
6209
6312
  ...notification,
6210
6313
  jsonrpc: "2.0",
@@ -14102,12 +14205,29 @@ async function pkceChallenge(length) {
14102
14205
  };
14103
14206
  }
14104
14207
 
14208
+ /**
14209
+ * Reusable URL validation that disallows javascript: scheme
14210
+ */
14211
+ const SafeUrlSchema = stringType().url()
14212
+ .superRefine((val, ctx) => {
14213
+ if (!URL.canParse(val)) {
14214
+ ctx.addIssue({
14215
+ code: ZodIssueCode.custom,
14216
+ message: "URL must be parseable",
14217
+ fatal: true,
14218
+ });
14219
+ return NEVER;
14220
+ }
14221
+ }).refine((url) => {
14222
+ const u = new URL(url);
14223
+ return u.protocol !== 'javascript:' && u.protocol !== 'data:' && u.protocol !== 'vbscript:';
14224
+ }, { message: "URL cannot use javascript:, data:, or vbscript: scheme" });
14105
14225
  /**
14106
14226
  * RFC 9728 OAuth Protected Resource Metadata
14107
14227
  */
14108
14228
  const OAuthProtectedResourceMetadataSchema = objectType({
14109
14229
  resource: stringType().url(),
14110
- authorization_servers: arrayType(stringType().url()).optional(),
14230
+ authorization_servers: arrayType(SafeUrlSchema).optional(),
14111
14231
  jwks_uri: stringType().url().optional(),
14112
14232
  scopes_supported: arrayType(stringType()).optional(),
14113
14233
  bearer_methods_supported: arrayType(stringType()).optional(),
@@ -14127,9 +14247,9 @@ const OAuthProtectedResourceMetadataSchema = objectType({
14127
14247
  */
14128
14248
  const OAuthMetadataSchema = objectType({
14129
14249
  issuer: stringType(),
14130
- authorization_endpoint: stringType(),
14131
- token_endpoint: stringType(),
14132
- registration_endpoint: stringType().optional(),
14250
+ authorization_endpoint: SafeUrlSchema,
14251
+ token_endpoint: SafeUrlSchema,
14252
+ registration_endpoint: SafeUrlSchema.optional(),
14133
14253
  scopes_supported: arrayType(stringType()).optional(),
14134
14254
  response_types_supported: arrayType(stringType()),
14135
14255
  response_modes_supported: arrayType(stringType()).optional(),
@@ -14137,8 +14257,8 @@ const OAuthMetadataSchema = objectType({
14137
14257
  token_endpoint_auth_methods_supported: arrayType(stringType()).optional(),
14138
14258
  token_endpoint_auth_signing_alg_values_supported: arrayType(stringType())
14139
14259
  .optional(),
14140
- service_documentation: stringType().optional(),
14141
- revocation_endpoint: stringType().optional(),
14260
+ service_documentation: SafeUrlSchema.optional(),
14261
+ revocation_endpoint: SafeUrlSchema.optional(),
14142
14262
  revocation_endpoint_auth_methods_supported: arrayType(stringType()).optional(),
14143
14263
  revocation_endpoint_auth_signing_alg_values_supported: arrayType(stringType())
14144
14264
  .optional(),
@@ -14150,11 +14270,65 @@ const OAuthMetadataSchema = objectType({
14150
14270
  code_challenge_methods_supported: arrayType(stringType()).optional(),
14151
14271
  })
14152
14272
  .passthrough();
14273
+ /**
14274
+ * OpenID Connect Discovery 1.0 Provider Metadata
14275
+ * see: https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
14276
+ */
14277
+ const OpenIdProviderMetadataSchema = objectType({
14278
+ issuer: stringType(),
14279
+ authorization_endpoint: SafeUrlSchema,
14280
+ token_endpoint: SafeUrlSchema,
14281
+ userinfo_endpoint: SafeUrlSchema.optional(),
14282
+ jwks_uri: SafeUrlSchema,
14283
+ registration_endpoint: SafeUrlSchema.optional(),
14284
+ scopes_supported: arrayType(stringType()).optional(),
14285
+ response_types_supported: arrayType(stringType()),
14286
+ response_modes_supported: arrayType(stringType()).optional(),
14287
+ grant_types_supported: arrayType(stringType()).optional(),
14288
+ acr_values_supported: arrayType(stringType()).optional(),
14289
+ subject_types_supported: arrayType(stringType()),
14290
+ id_token_signing_alg_values_supported: arrayType(stringType()),
14291
+ id_token_encryption_alg_values_supported: arrayType(stringType()).optional(),
14292
+ id_token_encryption_enc_values_supported: arrayType(stringType()).optional(),
14293
+ userinfo_signing_alg_values_supported: arrayType(stringType()).optional(),
14294
+ userinfo_encryption_alg_values_supported: arrayType(stringType()).optional(),
14295
+ userinfo_encryption_enc_values_supported: arrayType(stringType()).optional(),
14296
+ request_object_signing_alg_values_supported: arrayType(stringType()).optional(),
14297
+ request_object_encryption_alg_values_supported: arrayType(stringType())
14298
+ .optional(),
14299
+ request_object_encryption_enc_values_supported: arrayType(stringType())
14300
+ .optional(),
14301
+ token_endpoint_auth_methods_supported: arrayType(stringType()).optional(),
14302
+ token_endpoint_auth_signing_alg_values_supported: arrayType(stringType())
14303
+ .optional(),
14304
+ display_values_supported: arrayType(stringType()).optional(),
14305
+ claim_types_supported: arrayType(stringType()).optional(),
14306
+ claims_supported: arrayType(stringType()).optional(),
14307
+ service_documentation: stringType().optional(),
14308
+ claims_locales_supported: arrayType(stringType()).optional(),
14309
+ ui_locales_supported: arrayType(stringType()).optional(),
14310
+ claims_parameter_supported: booleanType().optional(),
14311
+ request_parameter_supported: booleanType().optional(),
14312
+ request_uri_parameter_supported: booleanType().optional(),
14313
+ require_request_uri_registration: booleanType().optional(),
14314
+ op_policy_uri: SafeUrlSchema.optional(),
14315
+ op_tos_uri: SafeUrlSchema.optional(),
14316
+ })
14317
+ .passthrough();
14318
+ /**
14319
+ * OpenID Connect Discovery metadata that may include OAuth 2.0 fields
14320
+ * This schema represents the real-world scenario where OIDC providers
14321
+ * return a mix of OpenID Connect and OAuth 2.0 metadata fields
14322
+ */
14323
+ const OpenIdProviderDiscoveryMetadataSchema = OpenIdProviderMetadataSchema.merge(OAuthMetadataSchema.pick({
14324
+ code_challenge_methods_supported: true,
14325
+ }));
14153
14326
  /**
14154
14327
  * OAuth 2.1 token response
14155
14328
  */
14156
14329
  const OAuthTokensSchema = objectType({
14157
14330
  access_token: stringType(),
14331
+ id_token: stringType().optional(), // Optional for OAuth 2.1, but necessary in OpenID Connect
14158
14332
  token_type: stringType(),
14159
14333
  expires_in: numberType().optional(),
14160
14334
  scope: stringType().optional(),
@@ -14164,7 +14338,7 @@ const OAuthTokensSchema = objectType({
14164
14338
  /**
14165
14339
  * OAuth 2.1 error response
14166
14340
  */
14167
- objectType({
14341
+ const OAuthErrorResponseSchema = objectType({
14168
14342
  error: stringType(),
14169
14343
  error_description: stringType().optional(),
14170
14344
  error_uri: stringType().optional(),
@@ -14173,18 +14347,18 @@ objectType({
14173
14347
  * RFC 7591 OAuth 2.0 Dynamic Client Registration metadata
14174
14348
  */
14175
14349
  const OAuthClientMetadataSchema = objectType({
14176
- redirect_uris: arrayType(stringType()).refine((uris) => uris.every((uri) => URL.canParse(uri)), { message: "redirect_uris must contain valid URLs" }),
14350
+ redirect_uris: arrayType(SafeUrlSchema),
14177
14351
  token_endpoint_auth_method: stringType().optional(),
14178
14352
  grant_types: arrayType(stringType()).optional(),
14179
14353
  response_types: arrayType(stringType()).optional(),
14180
14354
  client_name: stringType().optional(),
14181
- client_uri: stringType().optional(),
14182
- logo_uri: stringType().optional(),
14355
+ client_uri: SafeUrlSchema.optional(),
14356
+ logo_uri: SafeUrlSchema.optional(),
14183
14357
  scope: stringType().optional(),
14184
14358
  contacts: arrayType(stringType()).optional(),
14185
- tos_uri: stringType().optional(),
14359
+ tos_uri: SafeUrlSchema.optional(),
14186
14360
  policy_uri: stringType().optional(),
14187
- jwks_uri: stringType().optional(),
14361
+ jwks_uri: SafeUrlSchema.optional(),
14188
14362
  jwks: anyType().optional(),
14189
14363
  software_id: stringType().optional(),
14190
14364
  software_version: stringType().optional(),
@@ -14262,22 +14436,313 @@ function checkResourceAllowed({ requestedResource, configuredResource }) {
14262
14436
  return requestedPath.startsWith(configuredPath);
14263
14437
  }
14264
14438
 
14439
+ /**
14440
+ * Base class for all OAuth errors
14441
+ */
14442
+ class OAuthError extends Error {
14443
+ constructor(message, errorUri) {
14444
+ super(message);
14445
+ this.errorUri = errorUri;
14446
+ this.name = this.constructor.name;
14447
+ }
14448
+ /**
14449
+ * Converts the error to a standard OAuth error response object
14450
+ */
14451
+ toResponseObject() {
14452
+ const response = {
14453
+ error: this.errorCode,
14454
+ error_description: this.message
14455
+ };
14456
+ if (this.errorUri) {
14457
+ response.error_uri = this.errorUri;
14458
+ }
14459
+ return response;
14460
+ }
14461
+ get errorCode() {
14462
+ return this.constructor.errorCode;
14463
+ }
14464
+ }
14465
+ /**
14466
+ * Invalid request error - The request is missing a required parameter,
14467
+ * includes an invalid parameter value, includes a parameter more than once,
14468
+ * or is otherwise malformed.
14469
+ */
14470
+ class InvalidRequestError extends OAuthError {
14471
+ }
14472
+ InvalidRequestError.errorCode = "invalid_request";
14473
+ /**
14474
+ * Invalid client error - Client authentication failed (e.g., unknown client, no client
14475
+ * authentication included, or unsupported authentication method).
14476
+ */
14477
+ class InvalidClientError extends OAuthError {
14478
+ }
14479
+ InvalidClientError.errorCode = "invalid_client";
14480
+ /**
14481
+ * Invalid grant error - The provided authorization grant or refresh token is
14482
+ * invalid, expired, revoked, does not match the redirection URI used in the
14483
+ * authorization request, or was issued to another client.
14484
+ */
14485
+ class InvalidGrantError extends OAuthError {
14486
+ }
14487
+ InvalidGrantError.errorCode = "invalid_grant";
14488
+ /**
14489
+ * Unauthorized client error - The authenticated client is not authorized to use
14490
+ * this authorization grant type.
14491
+ */
14492
+ class UnauthorizedClientError extends OAuthError {
14493
+ }
14494
+ UnauthorizedClientError.errorCode = "unauthorized_client";
14495
+ /**
14496
+ * Unsupported grant type error - The authorization grant type is not supported
14497
+ * by the authorization server.
14498
+ */
14499
+ class UnsupportedGrantTypeError extends OAuthError {
14500
+ }
14501
+ UnsupportedGrantTypeError.errorCode = "unsupported_grant_type";
14502
+ /**
14503
+ * Invalid scope error - The requested scope is invalid, unknown, malformed, or
14504
+ * exceeds the scope granted by the resource owner.
14505
+ */
14506
+ class InvalidScopeError extends OAuthError {
14507
+ }
14508
+ InvalidScopeError.errorCode = "invalid_scope";
14509
+ /**
14510
+ * Access denied error - The resource owner or authorization server denied the request.
14511
+ */
14512
+ class AccessDeniedError extends OAuthError {
14513
+ }
14514
+ AccessDeniedError.errorCode = "access_denied";
14515
+ /**
14516
+ * Server error - The authorization server encountered an unexpected condition
14517
+ * that prevented it from fulfilling the request.
14518
+ */
14519
+ class ServerError extends OAuthError {
14520
+ }
14521
+ ServerError.errorCode = "server_error";
14522
+ /**
14523
+ * Temporarily unavailable error - The authorization server is currently unable to
14524
+ * handle the request due to a temporary overloading or maintenance of the server.
14525
+ */
14526
+ class TemporarilyUnavailableError extends OAuthError {
14527
+ }
14528
+ TemporarilyUnavailableError.errorCode = "temporarily_unavailable";
14529
+ /**
14530
+ * Unsupported response type error - The authorization server does not support
14531
+ * obtaining an authorization code using this method.
14532
+ */
14533
+ class UnsupportedResponseTypeError extends OAuthError {
14534
+ }
14535
+ UnsupportedResponseTypeError.errorCode = "unsupported_response_type";
14536
+ /**
14537
+ * Unsupported token type error - The authorization server does not support
14538
+ * the requested token type.
14539
+ */
14540
+ class UnsupportedTokenTypeError extends OAuthError {
14541
+ }
14542
+ UnsupportedTokenTypeError.errorCode = "unsupported_token_type";
14543
+ /**
14544
+ * Invalid token error - The access token provided is expired, revoked, malformed,
14545
+ * or invalid for other reasons.
14546
+ */
14547
+ class InvalidTokenError extends OAuthError {
14548
+ }
14549
+ InvalidTokenError.errorCode = "invalid_token";
14550
+ /**
14551
+ * Method not allowed error - The HTTP method used is not allowed for this endpoint.
14552
+ * (Custom, non-standard error)
14553
+ */
14554
+ class MethodNotAllowedError extends OAuthError {
14555
+ }
14556
+ MethodNotAllowedError.errorCode = "method_not_allowed";
14557
+ /**
14558
+ * Too many requests error - Rate limit exceeded.
14559
+ * (Custom, non-standard error based on RFC 6585)
14560
+ */
14561
+ class TooManyRequestsError extends OAuthError {
14562
+ }
14563
+ TooManyRequestsError.errorCode = "too_many_requests";
14564
+ /**
14565
+ * Invalid client metadata error - The client metadata is invalid.
14566
+ * (Custom error for dynamic client registration - RFC 7591)
14567
+ */
14568
+ class InvalidClientMetadataError extends OAuthError {
14569
+ }
14570
+ InvalidClientMetadataError.errorCode = "invalid_client_metadata";
14571
+ /**
14572
+ * Insufficient scope error - The request requires higher privileges than provided by the access token.
14573
+ */
14574
+ class InsufficientScopeError extends OAuthError {
14575
+ }
14576
+ InsufficientScopeError.errorCode = "insufficient_scope";
14577
+ /**
14578
+ * A full list of all OAuthErrors, enabling parsing from error responses
14579
+ */
14580
+ const OAUTH_ERRORS = {
14581
+ [InvalidRequestError.errorCode]: InvalidRequestError,
14582
+ [InvalidClientError.errorCode]: InvalidClientError,
14583
+ [InvalidGrantError.errorCode]: InvalidGrantError,
14584
+ [UnauthorizedClientError.errorCode]: UnauthorizedClientError,
14585
+ [UnsupportedGrantTypeError.errorCode]: UnsupportedGrantTypeError,
14586
+ [InvalidScopeError.errorCode]: InvalidScopeError,
14587
+ [AccessDeniedError.errorCode]: AccessDeniedError,
14588
+ [ServerError.errorCode]: ServerError,
14589
+ [TemporarilyUnavailableError.errorCode]: TemporarilyUnavailableError,
14590
+ [UnsupportedResponseTypeError.errorCode]: UnsupportedResponseTypeError,
14591
+ [UnsupportedTokenTypeError.errorCode]: UnsupportedTokenTypeError,
14592
+ [InvalidTokenError.errorCode]: InvalidTokenError,
14593
+ [MethodNotAllowedError.errorCode]: MethodNotAllowedError,
14594
+ [TooManyRequestsError.errorCode]: TooManyRequestsError,
14595
+ [InvalidClientMetadataError.errorCode]: InvalidClientMetadataError,
14596
+ [InsufficientScopeError.errorCode]: InsufficientScopeError,
14597
+ };
14598
+
14265
14599
  class UnauthorizedError extends Error {
14266
14600
  constructor(message) {
14267
14601
  super(message !== null && message !== void 0 ? message : "Unauthorized");
14268
14602
  }
14269
14603
  }
14604
+ /**
14605
+ * Determines the best client authentication method to use based on server support and client configuration.
14606
+ *
14607
+ * Priority order (highest to lowest):
14608
+ * 1. client_secret_basic (if client secret is available)
14609
+ * 2. client_secret_post (if client secret is available)
14610
+ * 3. none (for public clients)
14611
+ *
14612
+ * @param clientInformation - OAuth client information containing credentials
14613
+ * @param supportedMethods - Authentication methods supported by the authorization server
14614
+ * @returns The selected authentication method
14615
+ */
14616
+ function selectClientAuthMethod(clientInformation, supportedMethods) {
14617
+ const hasClientSecret = clientInformation.client_secret !== undefined;
14618
+ // If server doesn't specify supported methods, use RFC 6749 defaults
14619
+ if (supportedMethods.length === 0) {
14620
+ return hasClientSecret ? "client_secret_post" : "none";
14621
+ }
14622
+ // Try methods in priority order (most secure first)
14623
+ if (hasClientSecret && supportedMethods.includes("client_secret_basic")) {
14624
+ return "client_secret_basic";
14625
+ }
14626
+ if (hasClientSecret && supportedMethods.includes("client_secret_post")) {
14627
+ return "client_secret_post";
14628
+ }
14629
+ if (supportedMethods.includes("none")) {
14630
+ return "none";
14631
+ }
14632
+ // Fallback: use what we have
14633
+ return hasClientSecret ? "client_secret_post" : "none";
14634
+ }
14635
+ /**
14636
+ * Applies client authentication to the request based on the specified method.
14637
+ *
14638
+ * Implements OAuth 2.1 client authentication methods:
14639
+ * - client_secret_basic: HTTP Basic authentication (RFC 6749 Section 2.3.1)
14640
+ * - client_secret_post: Credentials in request body (RFC 6749 Section 2.3.1)
14641
+ * - none: Public client authentication (RFC 6749 Section 2.1)
14642
+ *
14643
+ * @param method - The authentication method to use
14644
+ * @param clientInformation - OAuth client information containing credentials
14645
+ * @param headers - HTTP headers object to modify
14646
+ * @param params - URL search parameters to modify
14647
+ * @throws {Error} When required credentials are missing
14648
+ */
14649
+ function applyClientAuthentication(method, clientInformation, headers, params) {
14650
+ const { client_id, client_secret } = clientInformation;
14651
+ switch (method) {
14652
+ case "client_secret_basic":
14653
+ applyBasicAuth(client_id, client_secret, headers);
14654
+ return;
14655
+ case "client_secret_post":
14656
+ applyPostAuth(client_id, client_secret, params);
14657
+ return;
14658
+ case "none":
14659
+ applyPublicAuth(client_id, params);
14660
+ return;
14661
+ default:
14662
+ throw new Error(`Unsupported client authentication method: ${method}`);
14663
+ }
14664
+ }
14665
+ /**
14666
+ * Applies HTTP Basic authentication (RFC 6749 Section 2.3.1)
14667
+ */
14668
+ function applyBasicAuth(clientId, clientSecret, headers) {
14669
+ if (!clientSecret) {
14670
+ throw new Error("client_secret_basic authentication requires a client_secret");
14671
+ }
14672
+ const credentials = btoa(`${clientId}:${clientSecret}`);
14673
+ headers.set("Authorization", `Basic ${credentials}`);
14674
+ }
14675
+ /**
14676
+ * Applies POST body authentication (RFC 6749 Section 2.3.1)
14677
+ */
14678
+ function applyPostAuth(clientId, clientSecret, params) {
14679
+ params.set("client_id", clientId);
14680
+ if (clientSecret) {
14681
+ params.set("client_secret", clientSecret);
14682
+ }
14683
+ }
14684
+ /**
14685
+ * Applies public client authentication (RFC 6749 Section 2.1)
14686
+ */
14687
+ function applyPublicAuth(clientId, params) {
14688
+ params.set("client_id", clientId);
14689
+ }
14690
+ /**
14691
+ * Parses an OAuth error response from a string or Response object.
14692
+ *
14693
+ * If the input is a standard OAuth2.0 error response, it will be parsed according to the spec
14694
+ * and an instance of the appropriate OAuthError subclass will be returned.
14695
+ * If parsing fails, it falls back to a generic ServerError that includes
14696
+ * the response status (if available) and original content.
14697
+ *
14698
+ * @param input - A Response object or string containing the error response
14699
+ * @returns A Promise that resolves to an OAuthError instance
14700
+ */
14701
+ async function parseErrorResponse(input) {
14702
+ const statusCode = input instanceof Response ? input.status : undefined;
14703
+ const body = input instanceof Response ? await input.text() : input;
14704
+ try {
14705
+ const result = OAuthErrorResponseSchema.parse(JSON.parse(body));
14706
+ const { error, error_description, error_uri } = result;
14707
+ const errorClass = OAUTH_ERRORS[error] || ServerError;
14708
+ return new errorClass(error_description || '', error_uri);
14709
+ }
14710
+ catch (error) {
14711
+ // Not a valid OAuth error response, but try to inform the user of the raw data anyway
14712
+ const errorMessage = `${statusCode ? `HTTP ${statusCode}: ` : ''}Invalid OAuth error response: ${error}. Raw body: ${body}`;
14713
+ return new ServerError(errorMessage);
14714
+ }
14715
+ }
14270
14716
  /**
14271
14717
  * Orchestrates the full auth flow with a server.
14272
14718
  *
14273
14719
  * This can be used as a single entry point for all authorization functionality,
14274
14720
  * instead of linking together the other lower-level functions in this module.
14275
14721
  */
14276
- async function auth(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl }) {
14722
+ async function auth(provider, options) {
14723
+ var _a, _b;
14724
+ try {
14725
+ return await authInternal(provider, options);
14726
+ }
14727
+ catch (error) {
14728
+ // Handle recoverable error types by invalidating credentials and retrying
14729
+ if (error instanceof InvalidClientError || error instanceof UnauthorizedClientError) {
14730
+ await ((_a = provider.invalidateCredentials) === null || _a === void 0 ? void 0 : _a.call(provider, 'all'));
14731
+ return await authInternal(provider, options);
14732
+ }
14733
+ else if (error instanceof InvalidGrantError) {
14734
+ await ((_b = provider.invalidateCredentials) === null || _b === void 0 ? void 0 : _b.call(provider, 'tokens'));
14735
+ return await authInternal(provider, options);
14736
+ }
14737
+ // Throw otherwise
14738
+ throw error;
14739
+ }
14740
+ }
14741
+ async function authInternal(provider, { serverUrl, authorizationCode, scope, resourceMetadataUrl, fetchFn, }) {
14277
14742
  let resourceMetadata;
14278
- let authorizationServerUrl = serverUrl;
14743
+ let authorizationServerUrl;
14279
14744
  try {
14280
- resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl });
14745
+ resourceMetadata = await discoverOAuthProtectedResourceMetadata(serverUrl, { resourceMetadataUrl }, fetchFn);
14281
14746
  if (resourceMetadata.authorization_servers && resourceMetadata.authorization_servers.length > 0) {
14282
14747
  authorizationServerUrl = resourceMetadata.authorization_servers[0];
14283
14748
  }
@@ -14285,8 +14750,17 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
14285
14750
  catch (_a) {
14286
14751
  // Ignore errors and fall back to /.well-known/oauth-authorization-server
14287
14752
  }
14753
+ /**
14754
+ * If we don't get a valid authorization server metadata from protected resource metadata,
14755
+ * fallback to the legacy MCP spec's implementation (version 2025-03-26): MCP server acts as the Authorization server.
14756
+ */
14757
+ if (!authorizationServerUrl) {
14758
+ authorizationServerUrl = serverUrl;
14759
+ }
14288
14760
  const resource = await selectResourceURL(serverUrl, provider, resourceMetadata);
14289
- const metadata = await discoverOAuthMetadata(authorizationServerUrl);
14761
+ const metadata = await discoverAuthorizationServerMetadata(authorizationServerUrl, {
14762
+ fetchFn,
14763
+ });
14290
14764
  // Handle client registration if needed
14291
14765
  let clientInformation = await Promise.resolve(provider.clientInformation());
14292
14766
  if (!clientInformation) {
@@ -14299,6 +14773,7 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
14299
14773
  const fullInformation = await registerClient(authorizationServerUrl, {
14300
14774
  metadata,
14301
14775
  clientMetadata: provider.clientMetadata,
14776
+ fetchFn,
14302
14777
  });
14303
14778
  await provider.saveClientInformation(fullInformation);
14304
14779
  clientInformation = fullInformation;
@@ -14313,6 +14788,8 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
14313
14788
  codeVerifier,
14314
14789
  redirectUri: provider.redirectUrl,
14315
14790
  resource,
14791
+ addClientAuthentication: provider.addClientAuthentication,
14792
+ fetchFn: fetchFn,
14316
14793
  });
14317
14794
  await provider.saveTokens(tokens);
14318
14795
  return "AUTHORIZED";
@@ -14327,12 +14804,19 @@ async function auth(provider, { serverUrl, authorizationCode, scope, resourceMet
14327
14804
  clientInformation,
14328
14805
  refreshToken: tokens.refresh_token,
14329
14806
  resource,
14807
+ addClientAuthentication: provider.addClientAuthentication,
14808
+ fetchFn,
14330
14809
  });
14331
14810
  await provider.saveTokens(newTokens);
14332
14811
  return "AUTHORIZED";
14333
14812
  }
14334
- catch (_b) {
14335
- // Could not refresh OAuth tokens
14813
+ catch (error) {
14814
+ // If this is a ServerError, or an unknown type, log it out and try to continue. Otherwise, escalate so we can fix things and retry.
14815
+ if (!(error instanceof OAuthError) || error instanceof ServerError) ;
14816
+ else {
14817
+ // Refresh failed for another reason, re-throw
14818
+ throw error;
14819
+ }
14336
14820
  }
14337
14821
  }
14338
14822
  const state = provider.state ? await provider.state() : undefined;
@@ -14396,33 +14880,12 @@ function extractResourceMetadataUrl(res) {
14396
14880
  * If the server returns a 404 for the well-known endpoint, this function will
14397
14881
  * return `undefined`. Any other errors will be thrown as exceptions.
14398
14882
  */
14399
- async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
14400
- var _a;
14401
- let url;
14402
- if (opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl) {
14403
- url = new URL(opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl);
14404
- }
14405
- else {
14406
- url = new URL("/.well-known/oauth-protected-resource", serverUrl);
14407
- }
14408
- let response;
14409
- try {
14410
- response = await fetch(url, {
14411
- headers: {
14412
- "MCP-Protocol-Version": (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION
14413
- }
14414
- });
14415
- }
14416
- catch (error) {
14417
- // CORS errors come back as TypeError
14418
- if (error instanceof TypeError) {
14419
- response = await fetch(url);
14420
- }
14421
- else {
14422
- throw error;
14423
- }
14424
- }
14425
- if (response.status === 404) {
14883
+ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts, fetchFn = fetch) {
14884
+ const response = await discoverMetadataWithFallback(serverUrl, 'oauth-protected-resource', fetchFn, {
14885
+ protocolVersion: opts === null || opts === void 0 ? void 0 : opts.protocolVersion,
14886
+ metadataUrl: opts === null || opts === void 0 ? void 0 : opts.resourceMetadataUrl,
14887
+ });
14888
+ if (!response || response.status === 404) {
14426
14889
  throw new Error(`Resource server does not implement OAuth 2.0 Protected Resource Metadata.`);
14427
14890
  }
14428
14891
  if (!response.ok) {
@@ -14433,15 +14896,15 @@ async function discoverOAuthProtectedResourceMetadata(serverUrl, opts) {
14433
14896
  /**
14434
14897
  * Helper function to handle fetch with CORS retry logic
14435
14898
  */
14436
- async function fetchWithCorsRetry(url, headers) {
14899
+ async function fetchWithCorsRetry(url, headers, fetchFn = fetch) {
14437
14900
  try {
14438
- return await fetch(url, { headers });
14901
+ return await fetchFn(url, { headers });
14439
14902
  }
14440
14903
  catch (error) {
14441
14904
  if (error instanceof TypeError) {
14442
14905
  if (headers) {
14443
14906
  // CORS errors come back as TypeError, retry without headers
14444
- return fetchWithCorsRetry(url);
14907
+ return fetchWithCorsRetry(url, undefined, fetchFn);
14445
14908
  }
14446
14909
  else {
14447
14910
  // We're getting CORS errors on retry too, return undefined
@@ -14452,57 +14915,162 @@ async function fetchWithCorsRetry(url, headers) {
14452
14915
  }
14453
14916
  }
14454
14917
  /**
14455
- * Constructs the well-known path for OAuth metadata discovery
14918
+ * Constructs the well-known path for auth-related metadata discovery
14456
14919
  */
14457
- function buildWellKnownPath(pathname) {
14458
- let wellKnownPath = `/.well-known/oauth-authorization-server${pathname}`;
14920
+ function buildWellKnownPath(wellKnownPrefix, pathname = '', options = {}) {
14921
+ // Strip trailing slash from pathname to avoid double slashes
14459
14922
  if (pathname.endsWith('/')) {
14460
- // Strip trailing slash from pathname to avoid double slashes
14461
- wellKnownPath = wellKnownPath.slice(0, -1);
14923
+ pathname = pathname.slice(0, -1);
14462
14924
  }
14463
- return wellKnownPath;
14925
+ return options.prependPathname
14926
+ ? `${pathname}/.well-known/${wellKnownPrefix}`
14927
+ : `/.well-known/${wellKnownPrefix}${pathname}`;
14464
14928
  }
14465
14929
  /**
14466
14930
  * Tries to discover OAuth metadata at a specific URL
14467
14931
  */
14468
- async function tryMetadataDiscovery(url, protocolVersion) {
14932
+ async function tryMetadataDiscovery(url, protocolVersion, fetchFn = fetch) {
14469
14933
  const headers = {
14470
14934
  "MCP-Protocol-Version": protocolVersion
14471
14935
  };
14472
- return await fetchWithCorsRetry(url, headers);
14936
+ return await fetchWithCorsRetry(url, headers, fetchFn);
14473
14937
  }
14474
14938
  /**
14475
14939
  * Determines if fallback to root discovery should be attempted
14476
14940
  */
14477
14941
  function shouldAttemptFallback(response, pathname) {
14478
- return !response || response.status === 404 && pathname !== '/';
14942
+ return !response || (response.status >= 400 && response.status < 500) && pathname !== '/';
14479
14943
  }
14480
14944
  /**
14481
- * Looks up RFC 8414 OAuth 2.0 Authorization Server Metadata.
14482
- *
14483
- * If the server returns a 404 for the well-known endpoint, this function will
14484
- * return `undefined`. Any other errors will be thrown as exceptions.
14945
+ * Generic function for discovering OAuth metadata with fallback support
14485
14946
  */
14486
- async function discoverOAuthMetadata(authorizationServerUrl, opts) {
14487
- var _a;
14488
- const issuer = new URL(authorizationServerUrl);
14489
- const protocolVersion = (_a = void 0 ) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION;
14490
- // Try path-aware discovery first (RFC 8414 compliant)
14491
- const wellKnownPath = buildWellKnownPath(issuer.pathname);
14492
- const pathAwareUrl = new URL(wellKnownPath, issuer);
14493
- let response = await tryMetadataDiscovery(pathAwareUrl, protocolVersion);
14494
- // If path-aware discovery fails with 404, try fallback to root discovery
14495
- if (shouldAttemptFallback(response, issuer.pathname)) {
14496
- const rootUrl = new URL("/.well-known/oauth-authorization-server", issuer);
14497
- response = await tryMetadataDiscovery(rootUrl, protocolVersion);
14947
+ async function discoverMetadataWithFallback(serverUrl, wellKnownType, fetchFn, opts) {
14948
+ var _a, _b;
14949
+ const issuer = new URL(serverUrl);
14950
+ const protocolVersion = (_a = opts === null || opts === void 0 ? void 0 : opts.protocolVersion) !== null && _a !== void 0 ? _a : LATEST_PROTOCOL_VERSION;
14951
+ let url;
14952
+ if (opts === null || opts === void 0 ? void 0 : opts.metadataUrl) {
14953
+ url = new URL(opts.metadataUrl);
14498
14954
  }
14499
- if (!response || response.status === 404) {
14500
- return undefined;
14955
+ else {
14956
+ // Try path-aware discovery first
14957
+ const wellKnownPath = buildWellKnownPath(wellKnownType, issuer.pathname);
14958
+ url = new URL(wellKnownPath, (_b = opts === null || opts === void 0 ? void 0 : opts.metadataServerUrl) !== null && _b !== void 0 ? _b : issuer);
14959
+ url.search = issuer.search;
14501
14960
  }
14502
- if (!response.ok) {
14503
- throw new Error(`HTTP ${response.status} trying to load well-known OAuth metadata`);
14961
+ let response = await tryMetadataDiscovery(url, protocolVersion, fetchFn);
14962
+ // If path-aware discovery fails with 404 and we're not already at root, try fallback to root discovery
14963
+ if (!(opts === null || opts === void 0 ? void 0 : opts.metadataUrl) && shouldAttemptFallback(response, issuer.pathname)) {
14964
+ const rootUrl = new URL(`/.well-known/${wellKnownType}`, issuer);
14965
+ response = await tryMetadataDiscovery(rootUrl, protocolVersion, fetchFn);
14504
14966
  }
14505
- return OAuthMetadataSchema.parse(await response.json());
14967
+ return response;
14968
+ }
14969
+ /**
14970
+ * Builds a list of discovery URLs to try for authorization server metadata.
14971
+ * URLs are returned in priority order:
14972
+ * 1. OAuth metadata at the given URL
14973
+ * 2. OAuth metadata at root (if URL has path)
14974
+ * 3. OIDC metadata endpoints
14975
+ */
14976
+ function buildDiscoveryUrls(authorizationServerUrl) {
14977
+ const url = typeof authorizationServerUrl === 'string' ? new URL(authorizationServerUrl) : authorizationServerUrl;
14978
+ const hasPath = url.pathname !== '/';
14979
+ const urlsToTry = [];
14980
+ if (!hasPath) {
14981
+ // Root path: https://example.com/.well-known/oauth-authorization-server
14982
+ urlsToTry.push({
14983
+ url: new URL('/.well-known/oauth-authorization-server', url.origin),
14984
+ type: 'oauth'
14985
+ });
14986
+ // OIDC: https://example.com/.well-known/openid-configuration
14987
+ urlsToTry.push({
14988
+ url: new URL(`/.well-known/openid-configuration`, url.origin),
14989
+ type: 'oidc'
14990
+ });
14991
+ return urlsToTry;
14992
+ }
14993
+ // Strip trailing slash from pathname to avoid double slashes
14994
+ let pathname = url.pathname;
14995
+ if (pathname.endsWith('/')) {
14996
+ pathname = pathname.slice(0, -1);
14997
+ }
14998
+ // 1. OAuth metadata at the given URL
14999
+ // Insert well-known before the path: https://example.com/.well-known/oauth-authorization-server/tenant1
15000
+ urlsToTry.push({
15001
+ url: new URL(`/.well-known/oauth-authorization-server${pathname}`, url.origin),
15002
+ type: 'oauth'
15003
+ });
15004
+ // Root path: https://example.com/.well-known/oauth-authorization-server
15005
+ urlsToTry.push({
15006
+ url: new URL('/.well-known/oauth-authorization-server', url.origin),
15007
+ type: 'oauth'
15008
+ });
15009
+ // 3. OIDC metadata endpoints
15010
+ // RFC 8414 style: Insert /.well-known/openid-configuration before the path
15011
+ urlsToTry.push({
15012
+ url: new URL(`/.well-known/openid-configuration${pathname}`, url.origin),
15013
+ type: 'oidc'
15014
+ });
15015
+ // OIDC Discovery 1.0 style: Append /.well-known/openid-configuration after the path
15016
+ urlsToTry.push({
15017
+ url: new URL(`${pathname}/.well-known/openid-configuration`, url.origin),
15018
+ type: 'oidc'
15019
+ });
15020
+ return urlsToTry;
15021
+ }
15022
+ /**
15023
+ * Discovers authorization server metadata with support for RFC 8414 OAuth 2.0 Authorization Server Metadata
15024
+ * and OpenID Connect Discovery 1.0 specifications.
15025
+ *
15026
+ * This function implements a fallback strategy for authorization server discovery:
15027
+ * 1. Attempts RFC 8414 OAuth metadata discovery first
15028
+ * 2. If OAuth discovery fails, falls back to OpenID Connect Discovery
15029
+ *
15030
+ * @param authorizationServerUrl - The authorization server URL obtained from the MCP Server's
15031
+ * protected resource metadata, or the MCP server's URL if the
15032
+ * metadata was not found.
15033
+ * @param options - Configuration options
15034
+ * @param options.fetchFn - Optional fetch function for making HTTP requests, defaults to global fetch
15035
+ * @param options.protocolVersion - MCP protocol version to use, defaults to LATEST_PROTOCOL_VERSION
15036
+ * @returns Promise resolving to authorization server metadata, or undefined if discovery fails
15037
+ */
15038
+ async function discoverAuthorizationServerMetadata(authorizationServerUrl, { fetchFn = fetch, protocolVersion = LATEST_PROTOCOL_VERSION, } = {}) {
15039
+ var _a;
15040
+ const headers = { 'MCP-Protocol-Version': protocolVersion };
15041
+ // Get the list of URLs to try
15042
+ const urlsToTry = buildDiscoveryUrls(authorizationServerUrl);
15043
+ // Try each URL in order
15044
+ for (const { url: endpointUrl, type } of urlsToTry) {
15045
+ const response = await fetchWithCorsRetry(endpointUrl, headers, fetchFn);
15046
+ if (!response) {
15047
+ /**
15048
+ * CORS error occurred - don't throw as the endpoint may not allow CORS,
15049
+ * continue trying other possible endpoints
15050
+ */
15051
+ continue;
15052
+ }
15053
+ if (!response.ok) {
15054
+ // Continue looking for any 4xx response code.
15055
+ if (response.status >= 400 && response.status < 500) {
15056
+ continue; // Try next URL
15057
+ }
15058
+ throw new Error(`HTTP ${response.status} trying to load ${type === 'oauth' ? 'OAuth' : 'OpenID provider'} metadata from ${endpointUrl}`);
15059
+ }
15060
+ // Parse and validate based on type
15061
+ if (type === 'oauth') {
15062
+ return OAuthMetadataSchema.parse(await response.json());
15063
+ }
15064
+ else {
15065
+ const metadata = OpenIdProviderDiscoveryMetadataSchema.parse(await response.json());
15066
+ // MCP spec requires OIDC providers to support S256 PKCE
15067
+ if (!((_a = metadata.code_challenge_methods_supported) === null || _a === void 0 ? void 0 : _a.includes('S256'))) {
15068
+ throw new Error(`Incompatible OIDC provider at ${endpointUrl}: does not support S256 code challenge method required by MCP specification`);
15069
+ }
15070
+ return metadata;
15071
+ }
15072
+ }
15073
+ return undefined;
14506
15074
  }
14507
15075
  /**
14508
15076
  * Begins the authorization flow with the given server, by generating a PKCE challenge and constructing the authorization URL.
@@ -14539,6 +15107,12 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
14539
15107
  if (scope) {
14540
15108
  authorizationUrl.searchParams.set("scope", scope);
14541
15109
  }
15110
+ if (scope === null || scope === void 0 ? void 0 : scope.includes("offline_access")) {
15111
+ // if the request includes the OIDC-only "offline_access" scope,
15112
+ // we need to set the prompt to "consent" to ensure the user is prompted to grant offline access
15113
+ // https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
15114
+ authorizationUrl.searchParams.append("prompt", "consent");
15115
+ }
14542
15116
  if (resource) {
14543
15117
  authorizationUrl.searchParams.set("resource", resource.href);
14544
15118
  }
@@ -14546,50 +15120,73 @@ async function startAuthorization(authorizationServerUrl, { metadata, clientInfo
14546
15120
  }
14547
15121
  /**
14548
15122
  * Exchanges an authorization code for an access token with the given server.
15123
+ *
15124
+ * Supports multiple client authentication methods as specified in OAuth 2.1:
15125
+ * - Automatically selects the best authentication method based on server support
15126
+ * - Falls back to appropriate defaults when server metadata is unavailable
15127
+ *
15128
+ * @param authorizationServerUrl - The authorization server's base URL
15129
+ * @param options - Configuration object containing client info, auth code, etc.
15130
+ * @returns Promise resolving to OAuth tokens
15131
+ * @throws {Error} When token exchange fails or authentication is invalid
14549
15132
  */
14550
- async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, }) {
15133
+ async function exchangeAuthorization(authorizationServerUrl, { metadata, clientInformation, authorizationCode, codeVerifier, redirectUri, resource, addClientAuthentication, fetchFn, }) {
15134
+ var _a;
14551
15135
  const grantType = "authorization_code";
14552
- let tokenUrl;
14553
- if (metadata) {
14554
- tokenUrl = new URL(metadata.token_endpoint);
14555
- if (metadata.grant_types_supported &&
14556
- !metadata.grant_types_supported.includes(grantType)) {
14557
- throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
14558
- }
14559
- }
14560
- else {
14561
- tokenUrl = new URL("/token", authorizationServerUrl);
15136
+ const tokenUrl = (metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint)
15137
+ ? new URL(metadata.token_endpoint)
15138
+ : new URL("/token", authorizationServerUrl);
15139
+ if ((metadata === null || metadata === void 0 ? void 0 : metadata.grant_types_supported) &&
15140
+ !metadata.grant_types_supported.includes(grantType)) {
15141
+ throw new Error(`Incompatible auth server: does not support grant type ${grantType}`);
14562
15142
  }
14563
15143
  // Exchange code for tokens
15144
+ const headers = new Headers({
15145
+ "Content-Type": "application/x-www-form-urlencoded",
15146
+ "Accept": "application/json",
15147
+ });
14564
15148
  const params = new URLSearchParams({
14565
15149
  grant_type: grantType,
14566
- client_id: clientInformation.client_id,
14567
15150
  code: authorizationCode,
14568
15151
  code_verifier: codeVerifier,
14569
15152
  redirect_uri: String(redirectUri),
14570
15153
  });
14571
- if (clientInformation.client_secret) {
14572
- params.set("client_secret", clientInformation.client_secret);
15154
+ if (addClientAuthentication) {
15155
+ addClientAuthentication(headers, params, authorizationServerUrl, metadata);
15156
+ }
15157
+ else {
15158
+ // Determine and apply client authentication method
15159
+ const supportedMethods = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint_auth_methods_supported) !== null && _a !== void 0 ? _a : [];
15160
+ const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
15161
+ applyClientAuthentication(authMethod, clientInformation, headers, params);
14573
15162
  }
14574
15163
  if (resource) {
14575
15164
  params.set("resource", resource.href);
14576
15165
  }
14577
- const response = await fetch(tokenUrl, {
15166
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(tokenUrl, {
14578
15167
  method: "POST",
14579
- headers: {
14580
- "Content-Type": "application/x-www-form-urlencoded",
14581
- },
15168
+ headers,
14582
15169
  body: params,
14583
15170
  });
14584
15171
  if (!response.ok) {
14585
- throw new Error(`Token exchange failed: HTTP ${response.status}`);
15172
+ throw await parseErrorResponse(response);
14586
15173
  }
14587
15174
  return OAuthTokensSchema.parse(await response.json());
14588
15175
  }
14589
15176
  /**
14590
15177
  * Exchange a refresh token for an updated access token.
15178
+ *
15179
+ * Supports multiple client authentication methods as specified in OAuth 2.1:
15180
+ * - Automatically selects the best authentication method based on server support
15181
+ * - Preserves the original refresh token if a new one is not returned
15182
+ *
15183
+ * @param authorizationServerUrl - The authorization server's base URL
15184
+ * @param options - Configuration object containing client info, refresh token, etc.
15185
+ * @returns Promise resolving to OAuth tokens (preserves original refresh_token if not replaced)
15186
+ * @throws {Error} When token refresh fails or authentication is invalid
14591
15187
  */
14592
- async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, }) {
15188
+ async function refreshAuthorization(authorizationServerUrl, { metadata, clientInformation, refreshToken, resource, addClientAuthentication, fetchFn, }) {
15189
+ var _a;
14593
15190
  const grantType = "refresh_token";
14594
15191
  let tokenUrl;
14595
15192
  if (metadata) {
@@ -14603,33 +15200,39 @@ async function refreshAuthorization(authorizationServerUrl, { metadata, clientIn
14603
15200
  tokenUrl = new URL("/token", authorizationServerUrl);
14604
15201
  }
14605
15202
  // Exchange refresh token
15203
+ const headers = new Headers({
15204
+ "Content-Type": "application/x-www-form-urlencoded",
15205
+ });
14606
15206
  const params = new URLSearchParams({
14607
15207
  grant_type: grantType,
14608
- client_id: clientInformation.client_id,
14609
15208
  refresh_token: refreshToken,
14610
15209
  });
14611
- if (clientInformation.client_secret) {
14612
- params.set("client_secret", clientInformation.client_secret);
15210
+ if (addClientAuthentication) {
15211
+ addClientAuthentication(headers, params, authorizationServerUrl, metadata);
15212
+ }
15213
+ else {
15214
+ // Determine and apply client authentication method
15215
+ const supportedMethods = (_a = metadata === null || metadata === void 0 ? void 0 : metadata.token_endpoint_auth_methods_supported) !== null && _a !== void 0 ? _a : [];
15216
+ const authMethod = selectClientAuthMethod(clientInformation, supportedMethods);
15217
+ applyClientAuthentication(authMethod, clientInformation, headers, params);
14613
15218
  }
14614
15219
  if (resource) {
14615
15220
  params.set("resource", resource.href);
14616
15221
  }
14617
- const response = await fetch(tokenUrl, {
15222
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(tokenUrl, {
14618
15223
  method: "POST",
14619
- headers: {
14620
- "Content-Type": "application/x-www-form-urlencoded",
14621
- },
15224
+ headers,
14622
15225
  body: params,
14623
15226
  });
14624
15227
  if (!response.ok) {
14625
- throw new Error(`Token refresh failed: HTTP ${response.status}`);
15228
+ throw await parseErrorResponse(response);
14626
15229
  }
14627
15230
  return OAuthTokensSchema.parse({ refresh_token: refreshToken, ...(await response.json()) });
14628
15231
  }
14629
15232
  /**
14630
15233
  * Performs OAuth 2.0 Dynamic Client Registration according to RFC 7591.
14631
15234
  */
14632
- async function registerClient(authorizationServerUrl, { metadata, clientMetadata, }) {
15235
+ async function registerClient(authorizationServerUrl, { metadata, clientMetadata, fetchFn, }) {
14633
15236
  let registrationUrl;
14634
15237
  if (metadata) {
14635
15238
  if (!metadata.registration_endpoint) {
@@ -14640,7 +15243,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
14640
15243
  else {
14641
15244
  registrationUrl = new URL("/register", authorizationServerUrl);
14642
15245
  }
14643
- const response = await fetch(registrationUrl, {
15246
+ const response = await (fetchFn !== null && fetchFn !== void 0 ? fetchFn : fetch)(registrationUrl, {
14644
15247
  method: "POST",
14645
15248
  headers: {
14646
15249
  "Content-Type": "application/json",
@@ -14648,7 +15251,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
14648
15251
  body: JSON.stringify(clientMetadata),
14649
15252
  });
14650
15253
  if (!response.ok) {
14651
- throw new Error(`Dynamic client registration failed: HTTP ${response.status}`);
15254
+ throw await parseErrorResponse(response);
14652
15255
  }
14653
15256
  return OAuthClientInformationFullSchema.parse(await response.json());
14654
15257
  }
@@ -14743,7 +15346,7 @@ function splitLines(chunk) {
14743
15346
  const crIndex = chunk.indexOf("\r", searchIndex), lfIndex = chunk.indexOf(`
14744
15347
  `, searchIndex);
14745
15348
  let lineEnd = -1;
14746
- if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
15349
+ if (crIndex !== -1 && lfIndex !== -1 ? lineEnd = Math.min(crIndex, lfIndex) : crIndex !== -1 ? crIndex === chunk.length - 1 ? lineEnd = -1 : lineEnd = crIndex : lfIndex !== -1 && (lineEnd = lfIndex), lineEnd === -1) {
14747
15350
  incompleteLine = chunk.slice(searchIndex);
14748
15351
  break;
14749
15352
  } else {
@@ -14814,7 +15417,7 @@ class StreamableHTTPClientTransport {
14814
15417
  }
14815
15418
  let result;
14816
15419
  try {
14817
- result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
15420
+ result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
14818
15421
  }
14819
15422
  catch (error) {
14820
15423
  (_a = this.onerror) === null || _a === void 0 ? void 0 : _a.call(this, error);
@@ -14875,7 +15478,7 @@ class StreamableHTTPClientTransport {
14875
15478
  }
14876
15479
  throw new StreamableHTTPError(response.status, `Failed to open SSE stream: ${response.statusText}`);
14877
15480
  }
14878
- this._handleSseStream(response.body, options);
15481
+ this._handleSseStream(response.body, options, true);
14879
15482
  }
14880
15483
  catch (error) {
14881
15484
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, error);
@@ -14935,7 +15538,7 @@ class StreamableHTTPClientTransport {
14935
15538
  });
14936
15539
  }, delay);
14937
15540
  }
14938
- _handleSseStream(stream, options) {
15541
+ _handleSseStream(stream, options, isReconnectable) {
14939
15542
  if (!stream) {
14940
15543
  return;
14941
15544
  }
@@ -14979,19 +15582,19 @@ class StreamableHTTPClientTransport {
14979
15582
  // Handle stream errors - likely a network disconnect
14980
15583
  (_c = this.onerror) === null || _c === void 0 ? void 0 : _c.call(this, new Error(`SSE stream disconnected: ${error}`));
14981
15584
  // Attempt to reconnect if the stream disconnects unexpectedly and we aren't closing
14982
- if (this._abortController && !this._abortController.signal.aborted) {
15585
+ if (isReconnectable &&
15586
+ this._abortController &&
15587
+ !this._abortController.signal.aborted) {
14983
15588
  // Use the exponential backoff reconnection strategy
14984
- if (lastEventId !== undefined) {
14985
- try {
14986
- this._scheduleReconnection({
14987
- resumptionToken: lastEventId,
14988
- onresumptiontoken,
14989
- replayMessageId
14990
- }, 0);
14991
- }
14992
- catch (error) {
14993
- (_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, new Error(`Failed to reconnect: ${error instanceof Error ? error.message : String(error)}`));
14994
- }
15589
+ try {
15590
+ this._scheduleReconnection({
15591
+ resumptionToken: lastEventId,
15592
+ onresumptiontoken,
15593
+ replayMessageId
15594
+ }, 0);
15595
+ }
15596
+ catch (error) {
15597
+ (_d = this.onerror) === null || _d === void 0 ? void 0 : _d.call(this, new Error(`Failed to reconnect: ${error instanceof Error ? error.message : String(error)}`));
14995
15598
  }
14996
15599
  }
14997
15600
  }
@@ -15011,7 +15614,7 @@ class StreamableHTTPClientTransport {
15011
15614
  if (!this._authProvider) {
15012
15615
  throw new UnauthorizedError("No auth provider");
15013
15616
  }
15014
- const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl });
15617
+ const result = await auth(this._authProvider, { serverUrl: this._url, authorizationCode, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
15015
15618
  if (result !== "AUTHORIZED") {
15016
15619
  throw new UnauthorizedError("Failed to authorize");
15017
15620
  }
@@ -15050,7 +15653,7 @@ class StreamableHTTPClientTransport {
15050
15653
  if (!response.ok) {
15051
15654
  if (response.status === 401 && this._authProvider) {
15052
15655
  this._resourceMetadataUrl = extractResourceMetadataUrl(response);
15053
- const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl });
15656
+ const result = await auth(this._authProvider, { serverUrl: this._url, resourceMetadataUrl: this._resourceMetadataUrl, fetchFn: this._fetch });
15054
15657
  if (result !== "AUTHORIZED") {
15055
15658
  throw new UnauthorizedError();
15056
15659
  }
@@ -15080,7 +15683,7 @@ class StreamableHTTPClientTransport {
15080
15683
  // Handle SSE stream responses for requests
15081
15684
  // We use the same handler as standalone streams, which now supports
15082
15685
  // reconnection with the last event ID
15083
- this._handleSseStream(response.body, { onresumptiontoken });
15686
+ this._handleSseStream(response.body, { onresumptiontoken }, false);
15084
15687
  }
15085
15688
  else if (contentType === null || contentType === void 0 ? void 0 : contentType.includes("application/json")) {
15086
15689
  // For non-streaming servers, we might get direct JSON responses