toolcraft 0.0.306 → 0.0.307

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.
@@ -4102,47 +4102,137 @@ function getOwnEntry4(record2, key2) {
4102
4102
 
4103
4103
  // ../mcp-oauth/dist/client/loopback-authorization.js
4104
4104
  async function createLoopbackAuthorizationSession(options = {}) {
4105
- const callbackPath = options.callbackPath ?? "/callback";
4105
+ options.signal?.throwIfAborted();
4106
+ const timeoutMs = options.timeoutMs ?? 12e4;
4107
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647)
4108
+ throw new Error("OAuth authorization timeoutMs must be a positive supported timer interval");
4109
+ const target = loopbackTarget(options);
4106
4110
  const server = options.createServer ? options.createServer() : http.createServer();
4107
- const port = await startServer(server);
4108
- const redirectUri = `http://127.0.0.1:${port}${callbackPath}`;
4111
+ const controller = new AbortController();
4112
+ let closed = false;
4113
+ let used = false;
4114
+ const callerAbort = () => controller.abort(options.signal?.reason);
4115
+ const teardown = () => {
4116
+ if (closed)
4117
+ return;
4118
+ closed = true;
4119
+ clearTimeout(timer);
4120
+ options.signal?.removeEventListener("abort", callerAbort);
4121
+ server.closeAllConnections?.();
4122
+ server.close();
4123
+ };
4124
+ const timer = setTimeout(() => controller.abort(new Error("OAuth authorization timed out")), timeoutMs);
4125
+ timer.unref?.();
4126
+ controller.signal.addEventListener("abort", teardown, { once: true });
4127
+ options.signal?.addEventListener("abort", callerAbort, { once: true });
4128
+ if (options.signal?.aborted)
4129
+ callerAbort();
4130
+ let port;
4131
+ try {
4132
+ port = await startServer(server, target.port, target.host, controller.signal);
4133
+ } catch (error) {
4134
+ controller.abort(error);
4135
+ throw error;
4136
+ }
4137
+ const redirectUri = options.redirectUri ?? `http://127.0.0.1:${port}${target.callbackPath}`;
4109
4138
  return {
4110
4139
  redirectUri,
4111
4140
  async waitForCode(authorizationUrl) {
4112
- return waitForAuthorizationCode(server, authorizationUrl, options, callbackPath);
4141
+ controller.signal.throwIfAborted();
4142
+ if (used)
4143
+ throw new Error("OAuth authorization session has already been used");
4144
+ used = true;
4145
+ try {
4146
+ return await waitForAuthorizationCode(server, authorizationUrl, options, target.callbackPath, controller.signal);
4147
+ } finally {
4148
+ clearTimeout(timer);
4149
+ }
4113
4150
  },
4114
4151
  close() {
4115
- server.closeAllConnections?.();
4116
- server.close();
4152
+ controller.abort(new Error("OAuth authorization session closed"));
4117
4153
  }
4118
4154
  };
4119
4155
  }
4120
- async function startServer(server) {
4156
+ function loopbackTarget(options) {
4157
+ if (options.redirectUri !== void 0) {
4158
+ let url;
4159
+ try {
4160
+ url = new URL(options.redirectUri);
4161
+ } catch (cause) {
4162
+ throw new Error("Invalid OAuth loopback redirect URI", { cause });
4163
+ }
4164
+ const forbiddenQuery = ["code", "state", "error", "error_description", "iss"];
4165
+ if (url.protocol !== "http:" || !["localhost", "127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password || url.hash || url.port === "0" || forbiddenQuery.some((name) => url.searchParams.has(name)) || [...options.redirectUri].some((char) => char.codePointAt(0) <= 32) || options.callbackPath !== void 0 && options.callbackPath !== url.pathname)
4166
+ throw new Error("Invalid OAuth loopback redirect URI");
4167
+ return { port: url.port ? Number(url.port) : 80, host: url.hostname === "[::1]" ? "::1" : url.hostname, callbackPath: url.pathname };
4168
+ }
4169
+ const callbackPath = options.callbackPath ?? "/callback";
4170
+ const parsed = new URL(callbackPath, "http://127.0.0.1");
4171
+ if (!callbackPath.startsWith("/") || parsed.origin !== "http://127.0.0.1" || parsed.pathname !== callbackPath || parsed.search || parsed.hash)
4172
+ throw new Error("Invalid OAuth loopback callback path");
4173
+ return { port: 0, host: "127.0.0.1", callbackPath };
4174
+ }
4175
+ async function startServer(server, port, host, signal) {
4176
+ signal.throwIfAborted();
4121
4177
  return new Promise((resolve, reject) => {
4122
- const handleError = (error) => {
4178
+ const cleanup = () => {
4123
4179
  server.off("error", handleError);
4180
+ signal.removeEventListener("abort", aborted);
4181
+ };
4182
+ const handleError = (error) => {
4183
+ cleanup();
4124
4184
  reject(error);
4125
4185
  };
4186
+ const aborted = () => {
4187
+ cleanup();
4188
+ reject(signal.reason);
4189
+ };
4126
4190
  server.once("error", handleError);
4127
- server.listen(0, "127.0.0.1", () => {
4128
- server.off("error", handleError);
4129
- const address = server.address();
4130
- resolve(address.port);
4131
- });
4191
+ signal.addEventListener("abort", aborted, { once: true });
4192
+ try {
4193
+ server.listen(port, host, () => {
4194
+ cleanup();
4195
+ if (signal.aborted) {
4196
+ server.close();
4197
+ reject(signal.reason);
4198
+ return;
4199
+ }
4200
+ const address = server.address();
4201
+ if (address === null || typeof address === "string") {
4202
+ reject(new Error("OAuth listener has no TCP address"));
4203
+ return;
4204
+ }
4205
+ resolve(address.port);
4206
+ });
4207
+ } catch (error) {
4208
+ cleanup();
4209
+ reject(error);
4210
+ }
4132
4211
  });
4133
4212
  }
4134
- function waitForAuthorizationCode(server, authorizationUrl, options, callbackPath) {
4213
+ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPath, signal) {
4214
+ signal.throwIfAborted();
4135
4215
  const expectedAuthorization = readExpectedAuthorizationCallback(authorizationUrl);
4136
4216
  return new Promise((resolve, reject) => {
4137
4217
  let settled = false;
4138
4218
  const settle = (fn) => {
4139
- if (!settled) {
4140
- settled = true;
4141
- fn();
4142
- }
4219
+ if (settled)
4220
+ return;
4221
+ settled = true;
4222
+ server.off("request", request);
4223
+ signal.removeEventListener("abort", aborted);
4224
+ fn();
4143
4225
  };
4144
- server.on("request", (req, res) => {
4145
- const url = new URL(req.url ?? "/", "http://127.0.0.1");
4226
+ const aborted = () => settle(() => reject(signal.reason));
4227
+ const request = (req, res) => {
4228
+ let url;
4229
+ try {
4230
+ url = new URL(req.url ?? "/", "http://127.0.0.1");
4231
+ } catch {
4232
+ res.writeHead(400);
4233
+ res.end("Invalid callback URL");
4234
+ return;
4235
+ }
4146
4236
  if (url.pathname !== callbackPath) {
4147
4237
  res.writeHead(404);
4148
4238
  res.end("Not found");
@@ -4157,21 +4247,8 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
4157
4247
  };
4158
4248
  try {
4159
4249
  validateAuthorizationCallbackBinding(callbackParameters, expectedAuthorization);
4160
- } catch (error) {
4161
- res.writeHead(400);
4162
- res.end(error instanceof Error ? error.message : "Invalid OAuth callback");
4163
- settle(() => reject(error instanceof Error ? error : new Error(String(error))));
4164
- return;
4165
- }
4166
- const authorizationError = callbackParameters.error;
4167
- if (authorizationError !== null) {
4168
- const description = callbackParameters.errorDescription ?? authorizationError;
4169
- res.writeHead(400);
4170
- res.end(`Authorization failed: ${description}`);
4171
- settle(() => reject(createAuthorizationError(authorizationError, description)));
4172
- return;
4173
- }
4174
- try {
4250
+ if (callbackParameters.error !== null)
4251
+ throw createAuthorizationError(callbackParameters.error, callbackParameters.errorDescription ?? callbackParameters.error);
4175
4252
  const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
4176
4253
  res.writeHead(200, { "Content-Type": "text/html" });
4177
4254
  res.end(buildSuccessPage(options.landingPage));
@@ -4179,35 +4256,27 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
4179
4256
  } catch (error) {
4180
4257
  res.writeHead(400);
4181
4258
  res.end(error instanceof Error ? error.message : "Invalid OAuth callback");
4182
- settle(() => reject(error instanceof Error ? error : new Error(String(error))));
4259
+ settle(() => reject(error));
4183
4260
  }
4184
- });
4261
+ };
4262
+ server.on("request", request);
4263
+ signal.addEventListener("abort", aborted, { once: true });
4185
4264
  if (options.readLine !== void 0) {
4186
- options.readLine().then((input) => {
4187
- const callbackParameters = extractCallbackParametersFromInput(input);
4188
- if (callbackParameters === null) {
4189
- settle(() => reject(new Error("OAuth callback missing authorization code")));
4265
+ void Promise.resolve().then(() => settled ? void 0 : options.readLine()).then((input) => {
4266
+ if (settled)
4190
4267
  return;
4191
- }
4192
- try {
4193
- validateAuthorizationCallbackBinding(callbackParameters, expectedAuthorization);
4194
- if (callbackParameters.error !== null) {
4195
- const description = callbackParameters.errorDescription ?? callbackParameters.error;
4196
- throw createAuthorizationError(callbackParameters.error, description);
4197
- }
4198
- const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
4199
- settle(() => resolve(code));
4200
- } catch (error) {
4201
- settle(() => reject(error instanceof Error ? error : new Error(String(error))));
4202
- }
4203
- }).catch((error) => {
4204
- settle(() => reject(error instanceof Error ? error : new Error(String(error))));
4205
- });
4268
+ const callbackParameters = extractCallbackParametersFromInput(input);
4269
+ if (callbackParameters === null)
4270
+ throw new Error("OAuth callback missing authorization code");
4271
+ validateAuthorizationCallbackBinding(callbackParameters, expectedAuthorization);
4272
+ if (callbackParameters.error !== null)
4273
+ throw createAuthorizationError(callbackParameters.error, callbackParameters.errorDescription ?? callbackParameters.error);
4274
+ const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
4275
+ settle(() => resolve(code));
4276
+ }).catch((error) => settle(() => reject(error)));
4206
4277
  }
4207
4278
  if (options.openBrowser !== void 0) {
4208
- options.openBrowser(authorizationUrl).catch((error) => {
4209
- settle(() => reject(error));
4210
- });
4279
+ void Promise.resolve().then(() => settled ? void 0 : options.openBrowser(authorizationUrl)).catch((error) => settle(() => reject(error)));
4211
4280
  }
4212
4281
  });
4213
4282
  }
@@ -4387,6 +4456,7 @@ async function exchangeAuthorizationCode(input) {
4387
4456
  resource
4388
4457
  },
4389
4458
  fetch: input.fetch,
4459
+ signal: input.signal,
4390
4460
  now: input.now
4391
4461
  });
4392
4462
  }
@@ -4402,6 +4472,7 @@ async function refreshAccessToken(input) {
4402
4472
  resource
4403
4473
  },
4404
4474
  fetch: input.fetch,
4475
+ signal: input.signal,
4405
4476
  now: input.now
4406
4477
  });
4407
4478
  }
@@ -4413,7 +4484,9 @@ async function requestTokens(input) {
4413
4484
  if (input.clientSecret !== void 0) {
4414
4485
  body.set("client_secret", input.clientSecret);
4415
4486
  }
4416
- const signal = AbortSignal.timeout(3e4);
4487
+ input.signal?.throwIfAborted();
4488
+ const deadline = AbortSignal.timeout(3e4);
4489
+ const signal = input.signal === void 0 ? deadline : AbortSignal.any([input.signal, deadline]);
4417
4490
  const response = await fetchMcpResponse(input.fetch, input.tokenEndpoint, {
4418
4491
  method: "POST",
4419
4492
  headers: {
@@ -4525,7 +4598,7 @@ function createDefaultOAuthClientProvider(options) {
4525
4598
  async authorizeRequest(input) {
4526
4599
  assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
4527
4600
  const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
4528
- const session = await ensureAuthorizedSession(requestUrl, void 0, input.fetch, false);
4601
+ const session = await ensureAuthorizedSession(requestUrl, void 0, input.fetch, false, false, input.signal);
4529
4602
  const accessToken = session?.tokens?.accessToken;
4530
4603
  if (session === null || accessToken === void 0 || session.tokens === void 0 || isExpired(session.tokens, now)) {
4531
4604
  return;
@@ -4543,12 +4616,13 @@ function createDefaultOAuthClientProvider(options) {
4543
4616
  const session = await ensureAuthorizedSession(resource, {
4544
4617
  ...input.discovery,
4545
4618
  resource
4546
- }, input.fetch, true, forceRefresh);
4619
+ }, input.fetch, true, forceRefresh, input.signal);
4547
4620
  if (session?.tokens?.accessToken === void 0) {
4548
4621
  return { action: "fail" };
4549
4622
  }
4550
4623
  return { action: "retry" };
4551
4624
  } catch (error) {
4625
+ input.signal?.throwIfAborted();
4552
4626
  return {
4553
4627
  action: "fail",
4554
4628
  error: error instanceof Error ? error : new Error(String(error))
@@ -4556,9 +4630,11 @@ function createDefaultOAuthClientProvider(options) {
4556
4630
  }
4557
4631
  }
4558
4632
  };
4559
- async function ensureAuthorizedSession(resource, discovery, fetch2, allowInteractive, forceRefresh = false) {
4633
+ async function ensureAuthorizedSession(resource, discovery, fetch2, allowInteractive, forceRefresh = false, signal) {
4634
+ signal?.throwIfAborted();
4560
4635
  const canonicalResource = canonicalizeResourceIndicator(resource);
4561
4636
  let session = await loadSession(canonicalResource);
4637
+ signal?.throwIfAborted();
4562
4638
  if (discovery !== void 0 && getOwnString2(discovery.authorizationServerMetadata, "issuer") !== discovery.authorizationServer) {
4563
4639
  throw new Error("OAuth discovery authorization-server issuer mismatch");
4564
4640
  }
@@ -4571,7 +4647,7 @@ function createDefaultOAuthClientProvider(options) {
4571
4647
  return session;
4572
4648
  }
4573
4649
  if (session?.tokens?.refreshToken !== void 0 && sessionDiscovery !== void 0 && (forceRefresh || isExpired(session.tokens, now))) {
4574
- session = await refreshSession(canonicalResource, session, sessionDiscovery, fetch2);
4650
+ session = await refreshSession(canonicalResource, session, sessionDiscovery, fetch2, signal);
4575
4651
  if (session?.tokens !== void 0 && !isExpired(session.tokens, now)) {
4576
4652
  return session;
4577
4653
  }
@@ -4583,9 +4659,12 @@ function createDefaultOAuthClientProvider(options) {
4583
4659
  if (!allowInteractive || sessionDiscovery === void 0) {
4584
4660
  return session;
4585
4661
  }
4586
- return authorizeSession(canonicalResource, session, sessionDiscovery, fetch2);
4662
+ if (options.allowInteractive === false)
4663
+ throw new Error("OAuth interactive authorization is disabled");
4664
+ return authorizeSession(canonicalResource, session, sessionDiscovery, fetch2, signal);
4587
4665
  }
4588
- async function refreshSession(resource, session, discovery, fetch2) {
4666
+ async function refreshSession(resource, session, discovery, fetch2, signal) {
4667
+ signal?.throwIfAborted();
4589
4668
  assertSecureOAuthFlowEndpoints(discovery.authorizationServerMetadata);
4590
4669
  const inFlight = refreshPromises.get(resource);
4591
4670
  if (inFlight !== void 0) {
@@ -4607,10 +4686,12 @@ function createDefaultOAuthClientProvider(options) {
4607
4686
  refreshToken: session.tokens.refreshToken,
4608
4687
  resource,
4609
4688
  fetch: fetch2,
4689
+ signal,
4610
4690
  now
4611
4691
  });
4612
4692
  break;
4613
4693
  } catch (error) {
4694
+ signal?.throwIfAborted();
4614
4695
  if (error instanceof OAuthError && error.error === "invalid_grant") {
4615
4696
  const clearedSession = clearSessionTokens(session);
4616
4697
  await saveSession(resource, clearedSession);
@@ -4645,7 +4726,8 @@ function createDefaultOAuthClientProvider(options) {
4645
4726
  refreshPromises.set(resource, promise);
4646
4727
  return promise;
4647
4728
  }
4648
- async function authorizeSession(resource, existingSession, discovery, fetch2) {
4729
+ async function authorizeSession(resource, existingSession, discovery, fetch2, signal) {
4730
+ signal?.throwIfAborted();
4649
4731
  const inFlight = authorizationPromises.get(resource);
4650
4732
  if (inFlight !== void 0) {
4651
4733
  return inFlight;
@@ -4661,11 +4743,14 @@ function createDefaultOAuthClientProvider(options) {
4661
4743
  openBrowser: options.browser.openBrowser,
4662
4744
  readLine: options.browser.readLine,
4663
4745
  createServer: options.browser.createServer,
4664
- landingPage: options.browser.landingPage
4746
+ landingPage: options.browser.landingPage,
4747
+ redirectUri: options.browser.redirectUri,
4748
+ signal: options.browser.signal === void 0 ? signal : signal === void 0 ? options.browser.signal : AbortSignal.any([signal, options.browser.signal]),
4749
+ timeoutMs: options.browser.timeoutMs
4665
4750
  });
4666
4751
  let resolvedClient = null;
4667
4752
  try {
4668
- resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2);
4753
+ resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2, signal);
4669
4754
  const sessionWithoutTokens = {
4670
4755
  resource,
4671
4756
  authorizationServer: discovery.authorizationServer,
@@ -4693,6 +4778,7 @@ function createDefaultOAuthClientProvider(options) {
4693
4778
  redirectUri: loopback.redirectUri,
4694
4779
  resource,
4695
4780
  fetch: fetch2,
4781
+ signal,
4696
4782
  now
4697
4783
  });
4698
4784
  const session = {
@@ -4702,6 +4788,7 @@ function createDefaultOAuthClientProvider(options) {
4702
4788
  await saveSession(resource, session);
4703
4789
  return session;
4704
4790
  } catch (error) {
4791
+ signal?.throwIfAborted();
4705
4792
  if (shouldReRegisterStoredDynamicClient(error, resolvedClient, reRegistrationAttempted)) {
4706
4793
  reRegistrationAttempted = true;
4707
4794
  await clearRegisteredClient(discovery.authorizationServer);
@@ -4727,7 +4814,8 @@ function createDefaultOAuthClientProvider(options) {
4727
4814
  authorizationPromises.set(resource, finalPromise);
4728
4815
  return finalPromise;
4729
4816
  }
4730
- async function resolveClient(existingSession, discovery, redirectUri, fetch2) {
4817
+ async function resolveClient(existingSession, discovery, redirectUri, fetch2, parentSignal) {
4818
+ parentSignal?.throwIfAborted();
4731
4819
  const configuredClient = normalizeConfiguredClient(options.client);
4732
4820
  if (options.client.mode === "static") {
4733
4821
  if (configuredClient === null) {
@@ -4777,7 +4865,8 @@ function createDefaultOAuthClientProvider(options) {
4777
4865
  }
4778
4866
  }
4779
4867
  const registrationBody = buildClientRegistrationBody(getClientMetadata(options.client), redirectUri);
4780
- const signal = AbortSignal.timeout(3e4);
4868
+ const deadline = AbortSignal.timeout(3e4);
4869
+ const signal = parentSignal === void 0 ? deadline : AbortSignal.any([parentSignal, deadline]);
4781
4870
  const response = await fetchMcpResponse(fetch2, registrationEndpoint, {
4782
4871
  method: "POST",
4783
4872
  headers: {
@@ -5340,8 +5429,10 @@ async function readJsonResponse(response, label, signal) {
5340
5429
  throw new Error(`${label} response must be valid JSON`);
5341
5430
  }
5342
5431
  }
5343
- async function fetchMetadata(fetch2, location, label) {
5344
- const signal = AbortSignal.timeout(1e4);
5432
+ async function fetchMetadata(fetch2, location, label, parentSignal) {
5433
+ parentSignal?.throwIfAborted();
5434
+ const deadline = AbortSignal.timeout(1e4);
5435
+ const signal = parentSignal === void 0 ? deadline : AbortSignal.any([deadline, parentSignal]);
5345
5436
  const response = await fetchMcpResponse(fetch2, location, {
5346
5437
  method: "GET",
5347
5438
  headers: { Accept: "application/json" },
@@ -5443,7 +5534,7 @@ var OAuthMetadataDiscovery = class {
5443
5534
  this.fetchImpl = fetch2;
5444
5535
  this.cache = cache;
5445
5536
  }
5446
- async discoverProtectedResource(resource, resourceMetadataUrl) {
5537
+ async discoverProtectedResource(resource, resourceMetadataUrl, signal) {
5447
5538
  const locations = /* @__PURE__ */ new Set([resolveProtectedResourceMetadataUrl(resource, resourceMetadataUrl)]);
5448
5539
  if (resourceMetadataUrl === void 0) {
5449
5540
  locations.add(new URL("/.well-known/oauth-protected-resource", resource).toString());
@@ -5452,17 +5543,19 @@ var OAuthMetadataDiscovery = class {
5452
5543
  for (const location of locations) {
5453
5544
  try {
5454
5545
  const metadata = validateProtectedResourceMetadata(
5455
- await fetchMetadata(this.fetchImpl, location, "Protected resource metadata"),
5546
+ await fetchMetadata(this.fetchImpl, location, "Protected resource metadata", signal),
5456
5547
  resource
5457
5548
  );
5458
5549
  return { location, metadata };
5459
5550
  } catch (error) {
5551
+ signal?.throwIfAborted();
5460
5552
  lastError = error;
5461
5553
  }
5462
5554
  }
5463
5555
  throw lastError;
5464
5556
  }
5465
- async discover(resourceUrl, { resourceMetadataUrl } = {}) {
5557
+ async discover(resourceUrl, { resourceMetadataUrl, signal } = {}) {
5558
+ signal?.throwIfAborted();
5466
5559
  const cacheKey = canonicalizeResourceIndicator(resourceUrl);
5467
5560
  resolveProtectedResourceMetadataUrl(cacheKey, resourceMetadataUrl);
5468
5561
  const memoryCachedResult = this.memoryCache.get(cacheKey);
@@ -5470,6 +5563,7 @@ var OAuthMetadataDiscovery = class {
5470
5563
  return structuredClone(memoryCachedResult);
5471
5564
  }
5472
5565
  const sharedCachedResult = await this.cache?.get(cacheKey);
5566
+ signal?.throwIfAborted();
5473
5567
  if (sharedCachedResult !== null && sharedCachedResult !== void 0 && resourceMetadataUrl === void 0) {
5474
5568
  try {
5475
5569
  const result = validateCachedDiscovery(sharedCachedResult, cacheKey);
@@ -5479,7 +5573,7 @@ var OAuthMetadataDiscovery = class {
5479
5573
  await this.cache?.delete?.(cacheKey);
5480
5574
  }
5481
5575
  }
5482
- const { location: resourceMetadataLocation, metadata: resourceMetadata } = await this.discoverProtectedResource(cacheKey, resourceMetadataUrl);
5576
+ const { location: resourceMetadataLocation, metadata: resourceMetadata } = await this.discoverProtectedResource(cacheKey, resourceMetadataUrl, signal);
5483
5577
  const authorizationServerErrors = [];
5484
5578
  for (const authorizationServer of resourceMetadata.authorization_servers) {
5485
5579
  const normalizedAuthorizationServer = validateAuthorizationServerIssuer(authorizationServer);
@@ -5487,7 +5581,7 @@ var OAuthMetadataDiscovery = class {
5487
5581
  for (const authorizationServerMetadataUrl of metadataLocations) {
5488
5582
  try {
5489
5583
  const authorizationServerMetadata = validateAuthorizationServerMetadata(
5490
- await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "Authorization server metadata"),
5584
+ await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "Authorization server metadata", signal),
5491
5585
  normalizedAuthorizationServer
5492
5586
  );
5493
5587
  const result = {
@@ -5502,6 +5596,7 @@ var OAuthMetadataDiscovery = class {
5502
5596
  await this.cache?.set(cacheKey, structuredClone(result));
5503
5597
  return result;
5504
5598
  } catch (error) {
5599
+ signal?.throwIfAborted();
5505
5600
  authorizationServerErrors.push(
5506
5601
  `${authorizationServerMetadataUrl}: ${error instanceof Error ? error.message : String(error)}`
5507
5602
  );
@@ -6642,6 +6737,7 @@ var HttpTransport = class {
6642
6737
  oauthProvider;
6643
6738
  oauthMetadataDiscovery;
6644
6739
  inFlightFetchAbortControllers = /* @__PURE__ */ new Set();
6740
+ inFlightOAuthAbortControllers = /* @__PURE__ */ new Set();
6645
6741
  openResponseReaders = /* @__PURE__ */ new Set();
6646
6742
  modernRequests = /* @__PURE__ */ new Map();
6647
6743
  modernMode = false;
@@ -6711,7 +6807,7 @@ var HttpTransport = class {
6711
6807
  this.rejectLegacyEndpoint = void 0;
6712
6808
  this.resolveLegacyEndpoint = void 0;
6713
6809
  this.toolParameterHeaders.clear();
6714
- this.abortInFlightFetches();
6810
+ this.abortInFlightFetches(reason);
6715
6811
  this.cancelOpenResponseReaders();
6716
6812
  if (!this.writeStream.destroyed && !this.writeStream.writableEnded) {
6717
6813
  this.writeStream.end();
@@ -6747,12 +6843,14 @@ var HttpTransport = class {
6747
6843
  this.resolveClosed = void 0;
6748
6844
  resolveClosed?.({ reason: closeReason });
6749
6845
  }
6750
- abortInFlightFetches() {
6751
- for (const controller of this.modernRequests.values()) controller.abort();
6846
+ abortInFlightFetches(reason) {
6847
+ for (const controller of this.modernRequests.values()) controller.abort(reason);
6752
6848
  this.modernRequests.clear();
6753
6849
  for (const abortController of this.inFlightFetchAbortControllers) {
6754
- abortController.abort();
6850
+ abortController.abort(reason);
6755
6851
  }
6852
+ for (const controller of this.inFlightOAuthAbortControllers) controller.abort(reason);
6853
+ this.inFlightOAuthAbortControllers.clear();
6756
6854
  this.inFlightFetchAbortControllers.clear();
6757
6855
  }
6758
6856
  cancelOpenResponseReaders() {
@@ -6818,7 +6916,7 @@ var HttpTransport = class {
6818
6916
  const response = await this.fetchWithOAuthRetry({
6819
6917
  url: postUrl,
6820
6918
  method: "POST",
6821
- createHeaders: () => this.createPostHeaders(message, modern),
6919
+ createHeaders: (signal) => this.createPostHeaders(message, modern, signal),
6822
6920
  body: line,
6823
6921
  controller
6824
6922
  });
@@ -6858,7 +6956,7 @@ var HttpTransport = class {
6858
6956
  this.modernRequests.delete(id);
6859
6957
  }
6860
6958
  }
6861
- async createPostHeaders(message, modern = false) {
6959
+ async createPostHeaders(message, modern = false, signal) {
6862
6960
  const headers = new Headers(this.headers);
6863
6961
  headers.set("Accept", "application/json, text/event-stream");
6864
6962
  headers.set("Content-Type", "application/json");
@@ -6888,9 +6986,9 @@ var HttpTransport = class {
6888
6986
  headers.set("Mcp-Session-Id", this.sessionId);
6889
6987
  headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
6890
6988
  }
6891
- return this.authorizeRequestHeaders(headers);
6989
+ return this.authorizeRequestHeaders(headers, signal);
6892
6990
  }
6893
- async createGetHeaders() {
6991
+ async createGetHeaders(signal) {
6894
6992
  const headers = new Headers(this.headers);
6895
6993
  headers.set("Accept", "text/event-stream");
6896
6994
  if (this.sessionId !== void 0) {
@@ -6900,20 +6998,26 @@ var HttpTransport = class {
6900
6998
  if (this.lastEventId !== void 0) {
6901
6999
  headers.set("Last-Event-ID", this.lastEventId);
6902
7000
  }
6903
- return this.authorizeRequestHeaders(headers);
7001
+ return this.authorizeRequestHeaders(headers, signal);
6904
7002
  }
6905
- async createDeleteHeaders(sessionId) {
7003
+ async createDeleteHeaders(sessionId, signal) {
6906
7004
  const headers = new Headers(this.headers);
6907
7005
  headers.set("Mcp-Session-Id", sessionId);
6908
7006
  headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
6909
- return this.authorizeRequestHeaders(headers);
7007
+ return this.authorizeRequestHeaders(headers, signal);
6910
7008
  }
6911
- async authorizeRequestHeaders(headers) {
7009
+ async authorizeRequestHeaders(headers, signal) {
7010
+ signal?.throwIfAborted();
6912
7011
  await this.oauthProvider?.authorizeRequest?.({
6913
7012
  requestUrl: new URL(this.url),
6914
7013
  headers,
6915
- fetch: this.fetchImpl
7014
+ signal,
7015
+ fetch: (url, init) => fetchMcpResponse(this.fetchImpl, url, {
7016
+ ...init,
7017
+ signal: signal === void 0 ? init?.signal : init?.signal == null ? signal : AbortSignal.any([signal, init.signal])
7018
+ })
6916
7019
  });
7020
+ signal?.throwIfAborted();
6917
7021
  return headers;
6918
7022
  }
6919
7023
  captureSessionId(response) {
@@ -6950,7 +7054,7 @@ var HttpTransport = class {
6950
7054
  return this.legacyEndpointReady;
6951
7055
  }
6952
7056
  async sendSessionTerminationRequest(sessionId, signal) {
6953
- const headers = await this.createDeleteHeaders(sessionId);
7057
+ const headers = await this.createDeleteHeaders(sessionId, signal);
6954
7058
  signal.throwIfAborted();
6955
7059
  const response = await fetchMcpResponse(this.fetchImpl, this.url, {
6956
7060
  method: "DELETE",
@@ -6973,7 +7077,7 @@ var HttpTransport = class {
6973
7077
  async consumeGetSseStream() {
6974
7078
  const response = await this.fetchWithOAuthRetry({
6975
7079
  method: "GET",
6976
- createHeaders: () => this.createGetHeaders()
7080
+ createHeaders: (signal) => this.createGetHeaders(signal)
6977
7081
  });
6978
7082
  if (this.disposed) {
6979
7083
  void response.body?.cancel().catch(() => void 0);
@@ -7056,7 +7160,7 @@ var HttpTransport = class {
7056
7160
  const message = responseBody.length === 0 ? `HTTP transport POST failed (${statusDescriptor})` : `HTTP transport POST failed (${statusDescriptor}): ${responseBody}`;
7057
7161
  throw new HttpTransportError(message, response.status, "POST");
7058
7162
  }
7059
- async maybeHandleUnauthorizedResponse(response) {
7163
+ async maybeHandleUnauthorizedResponse(response, signal) {
7060
7164
  if (response.status !== 401 || this.oauthProvider === void 0) {
7061
7165
  return false;
7062
7166
  }
@@ -7067,7 +7171,7 @@ var HttpTransport = class {
7067
7171
  const challenge = parseBearerWwwAuthenticateHeader(response.headers.get("WWW-Authenticate"));
7068
7172
  const resourceMetadataUrl = challenge?.params.resource_metadata;
7069
7173
  try {
7070
- const discovery = await discoveryClient.discover(this.url, { resourceMetadataUrl });
7174
+ const discovery = await discoveryClient.discover(this.url, { resourceMetadataUrl, signal });
7071
7175
  const providerResponse = response.clone();
7072
7176
  let result;
7073
7177
  try {
@@ -7076,8 +7180,13 @@ var HttpTransport = class {
7076
7180
  response: providerResponse,
7077
7181
  challenge,
7078
7182
  discovery,
7079
- fetch: this.fetchImpl
7183
+ signal,
7184
+ fetch: (url, init) => fetchMcpResponse(this.fetchImpl, url, {
7185
+ ...init,
7186
+ signal: init?.signal == null ? signal : AbortSignal.any([signal, init.signal])
7187
+ })
7080
7188
  });
7189
+ signal.throwIfAborted();
7081
7190
  } finally {
7082
7191
  void providerResponse.body?.cancel().catch(() => void 0);
7083
7192
  }
@@ -7207,25 +7316,30 @@ var HttpTransport = class {
7207
7316
  `);
7208
7317
  }
7209
7318
  async fetchWithOAuthRetry(input) {
7210
- const request = async () => this.fetchWithAbort(
7211
- input.url ?? this.url,
7212
- {
7319
+ const controller = input.controller ?? new AbortController();
7320
+ this.inFlightOAuthAbortControllers.add(controller);
7321
+ const request = async () => {
7322
+ controller.signal.throwIfAborted();
7323
+ const headers = await input.createHeaders(controller.signal);
7324
+ controller.signal.throwIfAborted();
7325
+ return this.fetchWithAbort(input.url ?? this.url, {
7213
7326
  method: input.method,
7214
- headers: await input.createHeaders(),
7327
+ headers,
7215
7328
  body: input.body
7216
- },
7217
- input.controller
7218
- );
7219
- let response = await request();
7220
- if (await this.maybeHandleUnauthorizedResponse(response)) {
7221
- response = await request();
7222
- }
7223
- const oauthError = this.oauthProvider === void 0 ? null : this.readOAuthChallengeError(response);
7224
- if (oauthError !== null) {
7225
- void response.body?.cancel().catch(() => void 0);
7226
- throw oauthError;
7329
+ }, controller);
7330
+ };
7331
+ try {
7332
+ let response = await request();
7333
+ if (await this.maybeHandleUnauthorizedResponse(response, controller.signal)) response = await request();
7334
+ const oauthError = this.oauthProvider === void 0 ? null : this.readOAuthChallengeError(response);
7335
+ if (oauthError !== null) {
7336
+ void response.body?.cancel().catch(() => void 0);
7337
+ throw oauthError;
7338
+ }
7339
+ return response;
7340
+ } finally {
7341
+ this.inFlightOAuthAbortControllers.delete(controller);
7227
7342
  }
7228
- return response;
7229
7343
  }
7230
7344
  readOAuthChallengeError(response) {
7231
7345
  if (response.status !== 401 && response.status !== 403) {
@@ -8,7 +8,7 @@
8
8
  },
9
9
  {
10
10
  "name": "toolcraft-schema",
11
- "version": "0.0.306",
11
+ "version": "0.0.307",
12
12
  "license": "MIT"
13
13
  }
14
14
  ]