@lovable.dev/mcp-js 0.21.0-rc.0 → 0.21.0-rc.2

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.
@@ -1,4 +1,4 @@
1
- type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_config_error" | "auth_upstream_unreachable";
1
+ type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_discovery_config_error" | "auth_discovery_unreachable" | "auth_jwks_config_error" | "auth_jwks_unreachable";
2
2
  /** One recorded MCP call. Carries no arguments or response payloads — only the
3
3
  * tool name, the JSON-RPC method, the result class, timing, and byte sizes. */
4
4
  interface InvocationRecord {
@@ -7,7 +7,7 @@ import {
7
7
  createRequestAuthorizer,
8
8
  nowMs,
9
9
  withCors
10
- } from "./chunk-VTIP6LMI.js";
10
+ } from "./chunk-IRCVDFWG.js";
11
11
  import {
12
12
  describeError,
13
13
  log
@@ -7,7 +7,7 @@ import {
7
7
  oauthConfigurationErrorResponse,
8
8
  resolveProtectedResource,
9
9
  withCors
10
- } from "./chunk-VTIP6LMI.js";
10
+ } from "./chunk-IRCVDFWG.js";
11
11
  import {
12
12
  describeError,
13
13
  log
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-6DXGZZA4.js";
14
14
  import {
15
15
  version
16
- } from "./chunk-XOCASA3L.js";
16
+ } from "./chunk-OIRVEGPQ.js";
17
17
 
18
18
  // src/core/http.ts
19
19
  var JSON_HEADERS = { "Content-Type": "application/json" };
@@ -284,14 +284,16 @@ function cachedPromise(load, label) {
284
284
 
285
285
  // src/auth/discovery.ts
286
286
  var OAuthConfigurationError = class extends Error {
287
- constructor(message) {
287
+ constructor(message, stage) {
288
288
  super(message);
289
+ this.stage = stage;
289
290
  this.name = "OAuthConfigurationError";
290
291
  }
291
292
  };
292
293
  var OAuthUpstreamUnreachableError = class extends Error {
293
- constructor(message) {
294
+ constructor(message, stage) {
294
295
  super(message);
296
+ this.stage = stage;
295
297
  this.name = "OAuthUpstreamUnreachableError";
296
298
  }
297
299
  };
@@ -325,32 +327,28 @@ function oauthMetadataUrlsForIssuer(issuer) {
325
327
  return [...pathInsertedOAuthMetadataUrls(url, path), `${normalizedIssuer}/.well-known/openid-configuration`];
326
328
  }
327
329
  async function fetchFirstValidOAuthServerMetadata(metadataUrls, expectedIssuer) {
328
- const controller = new AbortController();
329
- const attempts = metadataUrls.map(
330
- (url) => fetchOAuthServerMetadata(url, expectedIssuer, controller.signal).catch((err) => {
331
- log.debug("oauth.discovery.attempt_failed", { url, ...describeError(err) });
332
- throw err instanceof Error ? err : new Error(String(err));
333
- })
334
- );
335
- try {
336
- const metadata = await Promise.any(attempts);
337
- controller.abort();
338
- return metadata;
339
- } catch (aggregate) {
340
- const causes = aggregate instanceof AggregateError ? aggregate.errors : [aggregate];
341
- const unreachable = causes.some((c) => c instanceof MetadataUnreachableError);
342
- const detail = causes.map((c) => c instanceof Error ? c.message : String(c)).join("; ");
343
- log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
344
- const message = `failed to discover OAuth server metadata (${detail})`;
345
- throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
346
- }
347
- }
348
- async function fetchOAuthServerMetadata(url, expectedIssuer, signal) {
330
+ const errors = [];
331
+ for (const url of metadataUrls) {
332
+ try {
333
+ return await fetchOAuthServerMetadata(url, expectedIssuer);
334
+ } catch (err) {
335
+ const error = err instanceof Error ? err : new Error(String(err));
336
+ log.debug("oauth.discovery.attempt_failed", { url, ...describeError(error) });
337
+ errors.push(error);
338
+ }
339
+ }
340
+ const unreachable = errors.some((e) => e instanceof MetadataUnreachableError);
341
+ const detail = errors.map((e) => e.message).join("; ");
342
+ log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
343
+ const message = `failed to discover OAuth server metadata (${detail})`;
344
+ throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
345
+ }
346
+ async function fetchOAuthServerMetadata(url, expectedIssuer) {
349
347
  log.debug("oauth.discovery.fetch", { url });
350
348
  let response;
351
349
  try {
352
350
  response = await fetch(url, {
353
- signal: AbortSignal.any([signal, AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS)]),
351
+ signal: AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS),
354
352
  redirect: "manual"
355
353
  });
356
354
  } catch (err) {
@@ -385,14 +383,14 @@ async function fetchIssuerOAuthServerMetadata(issuer) {
385
383
  ...describeError(err),
386
384
  outcome: "503 authorization server unreachable"
387
385
  });
388
- throw new OAuthUpstreamUnreachableError(message);
386
+ throw new OAuthUpstreamUnreachableError(message, "discovery");
389
387
  }
390
388
  log.error("oauth.discovery.config_error", {
391
389
  issuer,
392
390
  ...describeError(err),
393
391
  outcome: "500 oauth configuration error"
394
392
  });
395
- throw new OAuthConfigurationError(message);
393
+ throw new OAuthConfigurationError(message, "discovery");
396
394
  }
397
395
  }
398
396
  function createOAuthDiscoveryResolver(auth) {
@@ -463,7 +461,10 @@ async function fetchVerificationKeySet(jwksUri) {
463
461
  response = await fetch(jwksUri, { signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS), redirect: "manual" });
464
462
  } catch (err) {
465
463
  log.error("oauth.jwks.unreachable", { ...describeError(err), outcome: "503 authorization server unreachable" });
466
- throw new OAuthUpstreamUnreachableError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
464
+ throw new OAuthUpstreamUnreachableError(
465
+ `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
466
+ "jwks"
467
+ );
467
468
  }
468
469
  try {
469
470
  if (!response.ok)
@@ -472,7 +473,7 @@ async function fetchVerificationKeySet(jwksUri) {
472
473
  return createLocalJWKSet(json);
473
474
  } catch (err) {
474
475
  log.error("oauth.jwks.fetch_failed", { ...describeError(err), outcome: "500 oauth configuration error" });
475
- throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
476
+ throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
476
477
  }
477
478
  }
478
479
  function assertAccessTokenTyp(token, allowed) {
@@ -685,21 +686,21 @@ function createRequestAuthorizer(mcp, options = {}) {
685
686
  return { ok: true, auth };
686
687
  } catch (err) {
687
688
  if (err instanceof OAuthUpstreamUnreachableError) {
688
- log.error("auth.upstream_unreachable", { ...describeError(err), outcome: "503" });
689
+ log.error("auth.upstream_unreachable", { ...describeError(err), stage: err.stage, outcome: "503" });
689
690
  await recorder?.emit({
690
691
  tool: null,
691
692
  method: "authorize",
692
- outcome: "auth_upstream_unreachable",
693
+ outcome: err.stage === "jwks" ? "auth_jwks_unreachable" : "auth_discovery_unreachable",
693
694
  durationMs: nowMs() - startedAt
694
695
  });
695
696
  return { ok: false, response: oauthUpstreamUnreachableResponse() };
696
697
  }
697
698
  if (err instanceof OAuthConfigurationError) {
698
- log.error("auth.config_error", { ...describeError(err), outcome: "500" });
699
+ log.error("auth.config_error", { ...describeError(err), stage: err.stage, outcome: "500" });
699
700
  await recorder?.emit({
700
701
  tool: null,
701
702
  method: "authorize",
702
- outcome: "auth_config_error",
703
+ outcome: err.stage === "jwks" ? "auth_jwks_config_error" : "auth_discovery_config_error",
703
704
  durationMs: nowMs() - startedAt
704
705
  });
705
706
  return { ok: false, response: oauthConfigurationErrorResponse() };
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.21.0-rc.0";
2
+ var version = "0.21.0-rc.2";
3
3
 
4
4
  export {
5
5
  version
@@ -10,7 +10,7 @@ import {
10
10
  methodNotAllowed,
11
11
  nowMs,
12
12
  withCors
13
- } from "./chunk-VTIP6LMI.js";
13
+ } from "./chunk-IRCVDFWG.js";
14
14
 
15
15
  // src/protocols/rest/invoke-tool.ts
16
16
  import { getParseErrorMessage, objectFromShape, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
@@ -6,7 +6,7 @@ import {
6
6
  headResponse,
7
7
  methodNotAllowed,
8
8
  withCors
9
- } from "./chunk-VTIP6LMI.js";
9
+ } from "./chunk-IRCVDFWG.js";
10
10
 
11
11
  // src/protocols/rest/list-tools.ts
12
12
  import { objectFromShape } from "@modelcontextprotocol/sdk/server/zod-compat.js";
@@ -13,7 +13,7 @@ function isFileMissing(err) {
13
13
  }
14
14
 
15
15
  // package.json
16
- var version = "0.21.0-rc.0";
16
+ var version = "0.21.0-rc.2";
17
17
 
18
18
  // src/protocols/rest/list-tools.ts
19
19
  var import_zod_compat = require("@modelcontextprotocol/sdk/server/zod-compat.js");
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  buildMcpListing
4
- } from "../chunk-KYKL5ECH.js";
5
- import "../chunk-VTIP6LMI.js";
4
+ } from "../chunk-YE6N7XLA.js";
5
+ import "../chunk-IRCVDFWG.js";
6
6
  import "../chunk-H37EB22A.js";
7
7
  import "../chunk-6DXGZZA4.js";
8
8
  import {
@@ -10,7 +10,7 @@ import {
10
10
  } from "../chunk-Y3ZFPEQH.js";
11
11
  import {
12
12
  version
13
- } from "../chunk-XOCASA3L.js";
13
+ } from "../chunk-OIRVEGPQ.js";
14
14
 
15
15
  // src/manifest/io.ts
16
16
  import { randomUUID } from "crypto";
@@ -148,14 +148,16 @@ function parseSafeUrl(subject, raw, ErrorClass = Error) {
148
148
 
149
149
  // src/auth/discovery.ts
150
150
  var OAuthConfigurationError = class extends Error {
151
- constructor(message) {
151
+ constructor(message, stage) {
152
152
  super(message);
153
+ this.stage = stage;
153
154
  this.name = "OAuthConfigurationError";
154
155
  }
155
156
  };
156
157
  var OAuthUpstreamUnreachableError = class extends Error {
157
- constructor(message) {
158
+ constructor(message, stage) {
158
159
  super(message);
160
+ this.stage = stage;
159
161
  this.name = "OAuthUpstreamUnreachableError";
160
162
  }
161
163
  };
@@ -189,32 +191,28 @@ function oauthMetadataUrlsForIssuer(issuer) {
189
191
  return [...pathInsertedOAuthMetadataUrls(url, path), `${normalizedIssuer}/.well-known/openid-configuration`];
190
192
  }
191
193
  async function fetchFirstValidOAuthServerMetadata(metadataUrls, expectedIssuer) {
192
- const controller = new AbortController();
193
- const attempts = metadataUrls.map(
194
- (url) => fetchOAuthServerMetadata(url, expectedIssuer, controller.signal).catch((err) => {
195
- log.debug("oauth.discovery.attempt_failed", { url, ...describeError(err) });
196
- throw err instanceof Error ? err : new Error(String(err));
197
- })
198
- );
199
- try {
200
- const metadata = await Promise.any(attempts);
201
- controller.abort();
202
- return metadata;
203
- } catch (aggregate) {
204
- const causes = aggregate instanceof AggregateError ? aggregate.errors : [aggregate];
205
- const unreachable = causes.some((c) => c instanceof MetadataUnreachableError);
206
- const detail = causes.map((c) => c instanceof Error ? c.message : String(c)).join("; ");
207
- log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
208
- const message = `failed to discover OAuth server metadata (${detail})`;
209
- throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
210
- }
211
- }
212
- async function fetchOAuthServerMetadata(url, expectedIssuer, signal) {
194
+ const errors = [];
195
+ for (const url of metadataUrls) {
196
+ try {
197
+ return await fetchOAuthServerMetadata(url, expectedIssuer);
198
+ } catch (err) {
199
+ const error = err instanceof Error ? err : new Error(String(err));
200
+ log.debug("oauth.discovery.attempt_failed", { url, ...describeError(error) });
201
+ errors.push(error);
202
+ }
203
+ }
204
+ const unreachable = errors.some((e) => e instanceof MetadataUnreachableError);
205
+ const detail = errors.map((e) => e.message).join("; ");
206
+ log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
207
+ const message = `failed to discover OAuth server metadata (${detail})`;
208
+ throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
209
+ }
210
+ async function fetchOAuthServerMetadata(url, expectedIssuer) {
213
211
  log.debug("oauth.discovery.fetch", { url });
214
212
  let response;
215
213
  try {
216
214
  response = await fetch(url, {
217
- signal: AbortSignal.any([signal, AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS)]),
215
+ signal: AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS),
218
216
  redirect: "manual"
219
217
  });
220
218
  } catch (err) {
@@ -249,14 +247,14 @@ async function fetchIssuerOAuthServerMetadata(issuer) {
249
247
  ...describeError(err),
250
248
  outcome: "503 authorization server unreachable"
251
249
  });
252
- throw new OAuthUpstreamUnreachableError(message);
250
+ throw new OAuthUpstreamUnreachableError(message, "discovery");
253
251
  }
254
252
  log.error("oauth.discovery.config_error", {
255
253
  issuer,
256
254
  ...describeError(err),
257
255
  outcome: "500 oauth configuration error"
258
256
  });
259
- throw new OAuthConfigurationError(message);
257
+ throw new OAuthConfigurationError(message, "discovery");
260
258
  }
261
259
  }
262
260
  function createOAuthDiscoveryResolver(auth) {
@@ -354,7 +352,10 @@ async function fetchVerificationKeySet(jwksUri) {
354
352
  response = await fetch(jwksUri, { signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS), redirect: "manual" });
355
353
  } catch (err) {
356
354
  log.error("oauth.jwks.unreachable", { ...describeError(err), outcome: "503 authorization server unreachable" });
357
- throw new OAuthUpstreamUnreachableError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
355
+ throw new OAuthUpstreamUnreachableError(
356
+ `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
357
+ "jwks"
358
+ );
358
359
  }
359
360
  try {
360
361
  if (!response.ok)
@@ -363,7 +364,7 @@ async function fetchVerificationKeySet(jwksUri) {
363
364
  return (0, import_jose.createLocalJWKSet)(json);
364
365
  } catch (err) {
365
366
  log.error("oauth.jwks.fetch_failed", { ...describeError(err), outcome: "500 oauth configuration error" });
366
- throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
367
+ throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
367
368
  }
368
369
  }
369
370
  function assertAccessTokenTyp(token, allowed) {
@@ -568,21 +569,21 @@ function createRequestAuthorizer(mcp, options = {}) {
568
569
  return { ok: true, auth };
569
570
  } catch (err) {
570
571
  if (err instanceof OAuthUpstreamUnreachableError) {
571
- log.error("auth.upstream_unreachable", { ...describeError(err), outcome: "503" });
572
+ log.error("auth.upstream_unreachable", { ...describeError(err), stage: err.stage, outcome: "503" });
572
573
  await recorder?.emit({
573
574
  tool: null,
574
575
  method: "authorize",
575
- outcome: "auth_upstream_unreachable",
576
+ outcome: err.stage === "jwks" ? "auth_jwks_unreachable" : "auth_discovery_unreachable",
576
577
  durationMs: nowMs() - startedAt
577
578
  });
578
579
  return { ok: false, response: oauthUpstreamUnreachableResponse() };
579
580
  }
580
581
  if (err instanceof OAuthConfigurationError) {
581
- log.error("auth.config_error", { ...describeError(err), outcome: "500" });
582
+ log.error("auth.config_error", { ...describeError(err), stage: err.stage, outcome: "500" });
582
583
  await recorder?.emit({
583
584
  tool: null,
584
585
  method: "authorize",
585
- outcome: "auth_config_error",
586
+ outcome: err.stage === "jwks" ? "auth_jwks_config_error" : "auth_discovery_config_error",
586
587
  durationMs: nowMs() - startedAt
587
588
  });
588
589
  return { ok: false, response: oauthConfigurationErrorResponse() };
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-CPkhCRxc.js';
3
- import { M as MetricsRecorder } from '../../base-RSqYamjy.js';
3
+ import { M as MetricsRecorder } from '../../base-DTtaX5Rf.js';
4
4
  import 'zod';
5
5
 
6
6
  type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-CPkhCRxc.js';
3
- import { M as MetricsRecorder } from '../../base-RSqYamjy.js';
3
+ import { M as MetricsRecorder } from '../../base-DTtaX5Rf.js';
4
4
  import 'zod';
5
5
 
6
6
  type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  createMcpProtocolHandler
3
- } from "../../chunk-2LLCWLQL.js";
3
+ } from "../../chunk-4H3Y2KYT.js";
4
4
  import "../../chunk-MA5H6PSF.js";
5
- import "../../chunk-VTIP6LMI.js";
5
+ import "../../chunk-IRCVDFWG.js";
6
6
  import "../../chunk-H37EB22A.js";
7
7
  import "../../chunk-6DXGZZA4.js";
8
- import "../../chunk-XOCASA3L.js";
8
+ import "../../chunk-OIRVEGPQ.js";
9
9
  export {
10
10
  createMcpProtocolHandler
11
11
  };
@@ -143,14 +143,16 @@ function parseSafeUrl(subject, raw, ErrorClass = Error) {
143
143
 
144
144
  // src/auth/discovery.ts
145
145
  var OAuthConfigurationError = class extends Error {
146
- constructor(message) {
146
+ constructor(message, stage) {
147
147
  super(message);
148
+ this.stage = stage;
148
149
  this.name = "OAuthConfigurationError";
149
150
  }
150
151
  };
151
152
  var OAuthUpstreamUnreachableError = class extends Error {
152
- constructor(message) {
153
+ constructor(message, stage) {
153
154
  super(message);
155
+ this.stage = stage;
154
156
  this.name = "OAuthUpstreamUnreachableError";
155
157
  }
156
158
  };
@@ -184,32 +186,28 @@ function oauthMetadataUrlsForIssuer(issuer) {
184
186
  return [...pathInsertedOAuthMetadataUrls(url, path), `${normalizedIssuer}/.well-known/openid-configuration`];
185
187
  }
186
188
  async function fetchFirstValidOAuthServerMetadata(metadataUrls, expectedIssuer) {
187
- const controller = new AbortController();
188
- const attempts = metadataUrls.map(
189
- (url) => fetchOAuthServerMetadata(url, expectedIssuer, controller.signal).catch((err) => {
190
- log.debug("oauth.discovery.attempt_failed", { url, ...describeError(err) });
191
- throw err instanceof Error ? err : new Error(String(err));
192
- })
193
- );
194
- try {
195
- const metadata = await Promise.any(attempts);
196
- controller.abort();
197
- return metadata;
198
- } catch (aggregate) {
199
- const causes = aggregate instanceof AggregateError ? aggregate.errors : [aggregate];
200
- const unreachable = causes.some((c) => c instanceof MetadataUnreachableError);
201
- const detail = causes.map((c) => c instanceof Error ? c.message : String(c)).join("; ");
202
- log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
203
- const message = `failed to discover OAuth server metadata (${detail})`;
204
- throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
189
+ const errors = [];
190
+ for (const url of metadataUrls) {
191
+ try {
192
+ return await fetchOAuthServerMetadata(url, expectedIssuer);
193
+ } catch (err) {
194
+ const error = err instanceof Error ? err : new Error(String(err));
195
+ log.debug("oauth.discovery.attempt_failed", { url, ...describeError(error) });
196
+ errors.push(error);
197
+ }
205
198
  }
199
+ const unreachable = errors.some((e) => e instanceof MetadataUnreachableError);
200
+ const detail = errors.map((e) => e.message).join("; ");
201
+ log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
202
+ const message = `failed to discover OAuth server metadata (${detail})`;
203
+ throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
206
204
  }
207
- async function fetchOAuthServerMetadata(url, expectedIssuer, signal) {
205
+ async function fetchOAuthServerMetadata(url, expectedIssuer) {
208
206
  log.debug("oauth.discovery.fetch", { url });
209
207
  let response;
210
208
  try {
211
209
  response = await fetch(url, {
212
- signal: AbortSignal.any([signal, AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS)]),
210
+ signal: AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS),
213
211
  redirect: "manual"
214
212
  });
215
213
  } catch (err) {
@@ -244,14 +242,14 @@ async function fetchIssuerOAuthServerMetadata(issuer) {
244
242
  ...describeError(err),
245
243
  outcome: "503 authorization server unreachable"
246
244
  });
247
- throw new OAuthUpstreamUnreachableError(message);
245
+ throw new OAuthUpstreamUnreachableError(message, "discovery");
248
246
  }
249
247
  log.error("oauth.discovery.config_error", {
250
248
  issuer,
251
249
  ...describeError(err),
252
250
  outcome: "500 oauth configuration error"
253
251
  });
254
- throw new OAuthConfigurationError(message);
252
+ throw new OAuthConfigurationError(message, "discovery");
255
253
  }
256
254
  }
257
255
  function createOAuthDiscoveryResolver(auth) {
@@ -346,7 +344,10 @@ async function fetchVerificationKeySet(jwksUri) {
346
344
  response = await fetch(jwksUri, { signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS), redirect: "manual" });
347
345
  } catch (err) {
348
346
  log.error("oauth.jwks.unreachable", { ...describeError(err), outcome: "503 authorization server unreachable" });
349
- throw new OAuthUpstreamUnreachableError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
347
+ throw new OAuthUpstreamUnreachableError(
348
+ `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
349
+ "jwks"
350
+ );
350
351
  }
351
352
  try {
352
353
  if (!response.ok)
@@ -355,7 +356,7 @@ async function fetchVerificationKeySet(jwksUri) {
355
356
  return (0, import_jose.createLocalJWKSet)(json);
356
357
  } catch (err) {
357
358
  log.error("oauth.jwks.fetch_failed", { ...describeError(err), outcome: "500 oauth configuration error" });
358
- throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
359
+ throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
359
360
  }
360
361
  }
361
362
  function assertAccessTokenTyp(token, allowed) {
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createOAuthProtectedResourceMetadataHandler
3
- } from "../chunk-NQZGVZ24.js";
4
- import "../chunk-VTIP6LMI.js";
3
+ } from "../chunk-7TVARTF4.js";
4
+ import "../chunk-IRCVDFWG.js";
5
5
  import "../chunk-H37EB22A.js";
6
6
  import "../chunk-6DXGZZA4.js";
7
- import "../chunk-XOCASA3L.js";
7
+ import "../chunk-OIRVEGPQ.js";
8
8
  export {
9
9
  createOAuthProtectedResourceMetadataHandler
10
10
  };
@@ -158,14 +158,16 @@ function parseSafeUrl(subject, raw, ErrorClass = Error) {
158
158
 
159
159
  // src/auth/discovery.ts
160
160
  var OAuthConfigurationError = class extends Error {
161
- constructor(message) {
161
+ constructor(message, stage) {
162
162
  super(message);
163
+ this.stage = stage;
163
164
  this.name = "OAuthConfigurationError";
164
165
  }
165
166
  };
166
167
  var OAuthUpstreamUnreachableError = class extends Error {
167
- constructor(message) {
168
+ constructor(message, stage) {
168
169
  super(message);
170
+ this.stage = stage;
169
171
  this.name = "OAuthUpstreamUnreachableError";
170
172
  }
171
173
  };
@@ -199,32 +201,28 @@ function oauthMetadataUrlsForIssuer(issuer) {
199
201
  return [...pathInsertedOAuthMetadataUrls(url, path), `${normalizedIssuer}/.well-known/openid-configuration`];
200
202
  }
201
203
  async function fetchFirstValidOAuthServerMetadata(metadataUrls, expectedIssuer) {
202
- const controller = new AbortController();
203
- const attempts = metadataUrls.map(
204
- (url) => fetchOAuthServerMetadata(url, expectedIssuer, controller.signal).catch((err) => {
205
- log.debug("oauth.discovery.attempt_failed", { url, ...describeError(err) });
206
- throw err instanceof Error ? err : new Error(String(err));
207
- })
208
- );
209
- try {
210
- const metadata = await Promise.any(attempts);
211
- controller.abort();
212
- return metadata;
213
- } catch (aggregate) {
214
- const causes = aggregate instanceof AggregateError ? aggregate.errors : [aggregate];
215
- const unreachable = causes.some((c) => c instanceof MetadataUnreachableError);
216
- const detail = causes.map((c) => c instanceof Error ? c.message : String(c)).join("; ");
217
- log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
218
- const message = `failed to discover OAuth server metadata (${detail})`;
219
- throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
220
- }
221
- }
222
- async function fetchOAuthServerMetadata(url, expectedIssuer, signal) {
204
+ const errors = [];
205
+ for (const url of metadataUrls) {
206
+ try {
207
+ return await fetchOAuthServerMetadata(url, expectedIssuer);
208
+ } catch (err) {
209
+ const error = err instanceof Error ? err : new Error(String(err));
210
+ log.debug("oauth.discovery.attempt_failed", { url, ...describeError(error) });
211
+ errors.push(error);
212
+ }
213
+ }
214
+ const unreachable = errors.some((e) => e instanceof MetadataUnreachableError);
215
+ const detail = errors.map((e) => e.message).join("; ");
216
+ log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
217
+ const message = `failed to discover OAuth server metadata (${detail})`;
218
+ throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
219
+ }
220
+ async function fetchOAuthServerMetadata(url, expectedIssuer) {
223
221
  log.debug("oauth.discovery.fetch", { url });
224
222
  let response;
225
223
  try {
226
224
  response = await fetch(url, {
227
- signal: AbortSignal.any([signal, AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS)]),
225
+ signal: AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS),
228
226
  redirect: "manual"
229
227
  });
230
228
  } catch (err) {
@@ -259,14 +257,14 @@ async function fetchIssuerOAuthServerMetadata(issuer) {
259
257
  ...describeError(err),
260
258
  outcome: "503 authorization server unreachable"
261
259
  });
262
- throw new OAuthUpstreamUnreachableError(message);
260
+ throw new OAuthUpstreamUnreachableError(message, "discovery");
263
261
  }
264
262
  log.error("oauth.discovery.config_error", {
265
263
  issuer,
266
264
  ...describeError(err),
267
265
  outcome: "500 oauth configuration error"
268
266
  });
269
- throw new OAuthConfigurationError(message);
267
+ throw new OAuthConfigurationError(message, "discovery");
270
268
  }
271
269
  }
272
270
  function createOAuthDiscoveryResolver(auth) {
@@ -364,7 +362,10 @@ async function fetchVerificationKeySet(jwksUri) {
364
362
  response = await fetch(jwksUri, { signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS), redirect: "manual" });
365
363
  } catch (err) {
366
364
  log.error("oauth.jwks.unreachable", { ...describeError(err), outcome: "503 authorization server unreachable" });
367
- throw new OAuthUpstreamUnreachableError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
365
+ throw new OAuthUpstreamUnreachableError(
366
+ `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
367
+ "jwks"
368
+ );
368
369
  }
369
370
  try {
370
371
  if (!response.ok)
@@ -373,7 +374,7 @@ async function fetchVerificationKeySet(jwksUri) {
373
374
  return (0, import_jose.createLocalJWKSet)(json);
374
375
  } catch (err) {
375
376
  log.error("oauth.jwks.fetch_failed", { ...describeError(err), outcome: "500 oauth configuration error" });
376
- throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
377
+ throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
377
378
  }
378
379
  }
379
380
  function assertAccessTokenTyp(token, allowed) {
@@ -586,21 +587,21 @@ function createRequestAuthorizer(mcp, options = {}) {
586
587
  return { ok: true, auth };
587
588
  } catch (err) {
588
589
  if (err instanceof OAuthUpstreamUnreachableError) {
589
- log.error("auth.upstream_unreachable", { ...describeError(err), outcome: "503" });
590
+ log.error("auth.upstream_unreachable", { ...describeError(err), stage: err.stage, outcome: "503" });
590
591
  await recorder?.emit({
591
592
  tool: null,
592
593
  method: "authorize",
593
- outcome: "auth_upstream_unreachable",
594
+ outcome: err.stage === "jwks" ? "auth_jwks_unreachable" : "auth_discovery_unreachable",
594
595
  durationMs: nowMs() - startedAt
595
596
  });
596
597
  return { ok: false, response: oauthUpstreamUnreachableResponse() };
597
598
  }
598
599
  if (err instanceof OAuthConfigurationError) {
599
- log.error("auth.config_error", { ...describeError(err), outcome: "500" });
600
+ log.error("auth.config_error", { ...describeError(err), stage: err.stage, outcome: "500" });
600
601
  await recorder?.emit({
601
602
  tool: null,
602
603
  method: "authorize",
603
- outcome: "auth_config_error",
604
+ outcome: err.stage === "jwks" ? "auth_jwks_config_error" : "auth_discovery_config_error",
604
605
  durationMs: nowMs() - startedAt
605
606
  });
606
607
  return { ok: false, response: oauthConfigurationErrorResponse() };
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-CPkhCRxc.js';
3
- import { M as MetricsRecorder } from '../../base-RSqYamjy.js';
3
+ import { M as MetricsRecorder } from '../../base-DTtaX5Rf.js';
4
4
  import 'zod';
5
5
 
6
6
  type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-CPkhCRxc.js';
3
- import { M as MetricsRecorder } from '../../base-RSqYamjy.js';
3
+ import { M as MetricsRecorder } from '../../base-DTtaX5Rf.js';
4
4
  import 'zod';
5
5
 
6
6
  type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  createInvokeToolHandler
3
- } from "../../chunk-M2TRF6OJ.js";
3
+ } from "../../chunk-WOKM6B6H.js";
4
4
  import {
5
5
  createListToolsHandler
6
- } from "../../chunk-KYKL5ECH.js";
6
+ } from "../../chunk-YE6N7XLA.js";
7
7
  import "../../chunk-MA5H6PSF.js";
8
- import "../../chunk-VTIP6LMI.js";
8
+ import "../../chunk-IRCVDFWG.js";
9
9
  import "../../chunk-H37EB22A.js";
10
10
  import "../../chunk-6DXGZZA4.js";
11
- import "../../chunk-XOCASA3L.js";
11
+ import "../../chunk-OIRVEGPQ.js";
12
12
  export {
13
13
  createInvokeToolHandler,
14
14
  createListToolsHandler
@@ -174,7 +174,7 @@ function describeError(err) {
174
174
  }
175
175
 
176
176
  // package.json
177
- var version = "0.21.0-rc.0";
177
+ var version = "0.21.0-rc.2";
178
178
 
179
179
  // src/metrics/otlp.ts
180
180
  var SCOPE_NAME = "@lovable.dev/mcp-js";
@@ -440,14 +440,16 @@ function parseSafeUrl(subject, raw, ErrorClass = Error) {
440
440
 
441
441
  // src/auth/discovery.ts
442
442
  var OAuthConfigurationError = class extends Error {
443
- constructor(message) {
443
+ constructor(message, stage) {
444
444
  super(message);
445
+ this.stage = stage;
445
446
  this.name = "OAuthConfigurationError";
446
447
  }
447
448
  };
448
449
  var OAuthUpstreamUnreachableError = class extends Error {
449
- constructor(message) {
450
+ constructor(message, stage) {
450
451
  super(message);
452
+ this.stage = stage;
451
453
  this.name = "OAuthUpstreamUnreachableError";
452
454
  }
453
455
  };
@@ -481,32 +483,28 @@ function oauthMetadataUrlsForIssuer(issuer) {
481
483
  return [...pathInsertedOAuthMetadataUrls(url, path), `${normalizedIssuer}/.well-known/openid-configuration`];
482
484
  }
483
485
  async function fetchFirstValidOAuthServerMetadata(metadataUrls, expectedIssuer) {
484
- const controller = new AbortController();
485
- const attempts = metadataUrls.map(
486
- (url) => fetchOAuthServerMetadata(url, expectedIssuer, controller.signal).catch((err) => {
487
- log.debug("oauth.discovery.attempt_failed", { url, ...describeError(err) });
488
- throw err instanceof Error ? err : new Error(String(err));
489
- })
490
- );
491
- try {
492
- const metadata = await Promise.any(attempts);
493
- controller.abort();
494
- return metadata;
495
- } catch (aggregate) {
496
- const causes = aggregate instanceof AggregateError ? aggregate.errors : [aggregate];
497
- const unreachable = causes.some((c) => c instanceof MetadataUnreachableError);
498
- const detail = causes.map((c) => c instanceof Error ? c.message : String(c)).join("; ");
499
- log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
500
- const message = `failed to discover OAuth server metadata (${detail})`;
501
- throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
486
+ const errors = [];
487
+ for (const url of metadataUrls) {
488
+ try {
489
+ return await fetchOAuthServerMetadata(url, expectedIssuer);
490
+ } catch (err) {
491
+ const error = err instanceof Error ? err : new Error(String(err));
492
+ log.debug("oauth.discovery.attempt_failed", { url, ...describeError(error) });
493
+ errors.push(error);
494
+ }
502
495
  }
496
+ const unreachable = errors.some((e) => e instanceof MetadataUnreachableError);
497
+ const detail = errors.map((e) => e.message).join("; ");
498
+ log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
499
+ const message = `failed to discover OAuth server metadata (${detail})`;
500
+ throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
503
501
  }
504
- async function fetchOAuthServerMetadata(url, expectedIssuer, signal) {
502
+ async function fetchOAuthServerMetadata(url, expectedIssuer) {
505
503
  log.debug("oauth.discovery.fetch", { url });
506
504
  let response;
507
505
  try {
508
506
  response = await fetch(url, {
509
- signal: AbortSignal.any([signal, AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS)]),
507
+ signal: AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS),
510
508
  redirect: "manual"
511
509
  });
512
510
  } catch (err) {
@@ -541,14 +539,14 @@ async function fetchIssuerOAuthServerMetadata(issuer) {
541
539
  ...describeError(err),
542
540
  outcome: "503 authorization server unreachable"
543
541
  });
544
- throw new OAuthUpstreamUnreachableError(message);
542
+ throw new OAuthUpstreamUnreachableError(message, "discovery");
545
543
  }
546
544
  log.error("oauth.discovery.config_error", {
547
545
  issuer,
548
546
  ...describeError(err),
549
547
  outcome: "500 oauth configuration error"
550
548
  });
551
- throw new OAuthConfigurationError(message);
549
+ throw new OAuthConfigurationError(message, "discovery");
552
550
  }
553
551
  }
554
552
  function createOAuthDiscoveryResolver(auth) {
@@ -619,7 +617,10 @@ async function fetchVerificationKeySet(jwksUri) {
619
617
  response = await fetch(jwksUri, { signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS), redirect: "manual" });
620
618
  } catch (err) {
621
619
  log.error("oauth.jwks.unreachable", { ...describeError(err), outcome: "503 authorization server unreachable" });
622
- throw new OAuthUpstreamUnreachableError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
620
+ throw new OAuthUpstreamUnreachableError(
621
+ `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
622
+ "jwks"
623
+ );
623
624
  }
624
625
  try {
625
626
  if (!response.ok)
@@ -628,7 +629,7 @@ async function fetchVerificationKeySet(jwksUri) {
628
629
  return (0, import_jose.createLocalJWKSet)(json);
629
630
  } catch (err) {
630
631
  log.error("oauth.jwks.fetch_failed", { ...describeError(err), outcome: "500 oauth configuration error" });
631
- throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
632
+ throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
632
633
  }
633
634
  }
634
635
  function assertAccessTokenTyp(token, allowed) {
@@ -841,21 +842,21 @@ function createRequestAuthorizer(mcp, options = {}) {
841
842
  return { ok: true, auth };
842
843
  } catch (err) {
843
844
  if (err instanceof OAuthUpstreamUnreachableError) {
844
- log.error("auth.upstream_unreachable", { ...describeError(err), outcome: "503" });
845
+ log.error("auth.upstream_unreachable", { ...describeError(err), stage: err.stage, outcome: "503" });
845
846
  await recorder?.emit({
846
847
  tool: null,
847
848
  method: "authorize",
848
- outcome: "auth_upstream_unreachable",
849
+ outcome: err.stage === "jwks" ? "auth_jwks_unreachable" : "auth_discovery_unreachable",
849
850
  durationMs: nowMs() - startedAt
850
851
  });
851
852
  return { ok: false, response: oauthUpstreamUnreachableResponse() };
852
853
  }
853
854
  if (err instanceof OAuthConfigurationError) {
854
- log.error("auth.config_error", { ...describeError(err), outcome: "500" });
855
+ log.error("auth.config_error", { ...describeError(err), stage: err.stage, outcome: "500" });
855
856
  await recorder?.emit({
856
857
  tool: null,
857
858
  method: "authorize",
858
- outcome: "auth_config_error",
859
+ outcome: err.stage === "jwks" ? "auth_jwks_config_error" : "auth_discovery_config_error",
859
860
  durationMs: nowMs() - startedAt
860
861
  });
861
862
  return { ok: false, response: oauthConfigurationErrorResponse() };
@@ -3,21 +3,21 @@ import {
3
3
  } from "../../chunk-UQK5UO6C.js";
4
4
  import {
5
5
  createMcpProtocolHandler
6
- } from "../../chunk-2LLCWLQL.js";
6
+ } from "../../chunk-4H3Y2KYT.js";
7
7
  import {
8
8
  createOAuthProtectedResourceMetadataHandler
9
- } from "../../chunk-NQZGVZ24.js";
9
+ } from "../../chunk-7TVARTF4.js";
10
10
  import {
11
11
  createInvokeToolHandler
12
- } from "../../chunk-M2TRF6OJ.js";
12
+ } from "../../chunk-WOKM6B6H.js";
13
13
  import {
14
14
  createListToolsHandler
15
- } from "../../chunk-KYKL5ECH.js";
15
+ } from "../../chunk-YE6N7XLA.js";
16
16
  import "../../chunk-MA5H6PSF.js";
17
17
  import {
18
18
  assertResourcePathShape,
19
19
  createRecorderForRuntime
20
- } from "../../chunk-VTIP6LMI.js";
20
+ } from "../../chunk-IRCVDFWG.js";
21
21
  import {
22
22
  trimTrailingSlash
23
23
  } from "../../chunk-H37EB22A.js";
@@ -28,7 +28,7 @@ import {
28
28
  FUNCTIONS_MOUNT_PREFIX,
29
29
  assertFunctionName
30
30
  } from "../../chunk-XQWJN6DC.js";
31
- import "../../chunk-XOCASA3L.js";
31
+ import "../../chunk-OIRVEGPQ.js";
32
32
 
33
33
  // src/stacks/supabase/handler.ts
34
34
  function deriveResourcePath(options) {
@@ -33,7 +33,7 @@ var import_node_fs = require("fs");
33
33
  var import_node_path = require("path");
34
34
 
35
35
  // package.json
36
- var version = "0.21.0-rc.0";
36
+ var version = "0.21.0-rc.2";
37
37
 
38
38
  // src/core/fs-errors.ts
39
39
  function isFileMissing(err) {
@@ -7,7 +7,7 @@ import {
7
7
  } from "../../chunk-XQWJN6DC.js";
8
8
  import {
9
9
  version
10
- } from "../../chunk-XOCASA3L.js";
10
+ } from "../../chunk-OIRVEGPQ.js";
11
11
 
12
12
  // src/stacks/supabase/vite.ts
13
13
  import { resolve as resolve2, sep as sep2 } from "path";
@@ -129,7 +129,7 @@ function describeError(err) {
129
129
  }
130
130
 
131
131
  // package.json
132
- var version = "0.21.0-rc.0";
132
+ var version = "0.21.0-rc.2";
133
133
 
134
134
  // src/metrics/otlp.ts
135
135
  var SCOPE_NAME = "@lovable.dev/mcp-js";
@@ -416,14 +416,16 @@ function parseSafeUrl(subject, raw, ErrorClass = Error) {
416
416
 
417
417
  // src/auth/discovery.ts
418
418
  var OAuthConfigurationError = class extends Error {
419
- constructor(message) {
419
+ constructor(message, stage) {
420
420
  super(message);
421
+ this.stage = stage;
421
422
  this.name = "OAuthConfigurationError";
422
423
  }
423
424
  };
424
425
  var OAuthUpstreamUnreachableError = class extends Error {
425
- constructor(message) {
426
+ constructor(message, stage) {
426
427
  super(message);
428
+ this.stage = stage;
427
429
  this.name = "OAuthUpstreamUnreachableError";
428
430
  }
429
431
  };
@@ -457,32 +459,28 @@ function oauthMetadataUrlsForIssuer(issuer) {
457
459
  return [...pathInsertedOAuthMetadataUrls(url, path), `${normalizedIssuer}/.well-known/openid-configuration`];
458
460
  }
459
461
  async function fetchFirstValidOAuthServerMetadata(metadataUrls, expectedIssuer) {
460
- const controller = new AbortController();
461
- const attempts = metadataUrls.map(
462
- (url) => fetchOAuthServerMetadata(url, expectedIssuer, controller.signal).catch((err) => {
463
- log.debug("oauth.discovery.attempt_failed", { url, ...describeError(err) });
464
- throw err instanceof Error ? err : new Error(String(err));
465
- })
466
- );
467
- try {
468
- const metadata = await Promise.any(attempts);
469
- controller.abort();
470
- return metadata;
471
- } catch (aggregate) {
472
- const causes = aggregate instanceof AggregateError ? aggregate.errors : [aggregate];
473
- const unreachable = causes.some((c) => c instanceof MetadataUnreachableError);
474
- const detail = causes.map((c) => c instanceof Error ? c.message : String(c)).join("; ");
475
- log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
476
- const message = `failed to discover OAuth server metadata (${detail})`;
477
- throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
462
+ const errors = [];
463
+ for (const url of metadataUrls) {
464
+ try {
465
+ return await fetchOAuthServerMetadata(url, expectedIssuer);
466
+ } catch (err) {
467
+ const error = err instanceof Error ? err : new Error(String(err));
468
+ log.debug("oauth.discovery.attempt_failed", { url, ...describeError(error) });
469
+ errors.push(error);
470
+ }
478
471
  }
472
+ const unreachable = errors.some((e) => e instanceof MetadataUnreachableError);
473
+ const detail = errors.map((e) => e.message).join("; ");
474
+ log.error("oauth.discovery.exhausted", { expectedIssuer, urlsTried: metadataUrls, errors: detail, unreachable });
475
+ const message = `failed to discover OAuth server metadata (${detail})`;
476
+ throw unreachable ? new MetadataUnreachableError(message) : new Error(message);
479
477
  }
480
- async function fetchOAuthServerMetadata(url, expectedIssuer, signal) {
478
+ async function fetchOAuthServerMetadata(url, expectedIssuer) {
481
479
  log.debug("oauth.discovery.fetch", { url });
482
480
  let response;
483
481
  try {
484
482
  response = await fetch(url, {
485
- signal: AbortSignal.any([signal, AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS)]),
483
+ signal: AbortSignal.timeout(METADATA_FETCH_TIMEOUT_MS),
486
484
  redirect: "manual"
487
485
  });
488
486
  } catch (err) {
@@ -517,14 +515,14 @@ async function fetchIssuerOAuthServerMetadata(issuer) {
517
515
  ...describeError(err),
518
516
  outcome: "503 authorization server unreachable"
519
517
  });
520
- throw new OAuthUpstreamUnreachableError(message);
518
+ throw new OAuthUpstreamUnreachableError(message, "discovery");
521
519
  }
522
520
  log.error("oauth.discovery.config_error", {
523
521
  issuer,
524
522
  ...describeError(err),
525
523
  outcome: "500 oauth configuration error"
526
524
  });
527
- throw new OAuthConfigurationError(message);
525
+ throw new OAuthConfigurationError(message, "discovery");
528
526
  }
529
527
  }
530
528
  function createOAuthDiscoveryResolver(auth) {
@@ -622,7 +620,10 @@ async function fetchVerificationKeySet(jwksUri) {
622
620
  response = await fetch(jwksUri, { signal: AbortSignal.timeout(JWKS_FETCH_TIMEOUT_MS), redirect: "manual" });
623
621
  } catch (err) {
624
622
  log.error("oauth.jwks.unreachable", { ...describeError(err), outcome: "503 authorization server unreachable" });
625
- throw new OAuthUpstreamUnreachableError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
623
+ throw new OAuthUpstreamUnreachableError(
624
+ `JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`,
625
+ "jwks"
626
+ );
626
627
  }
627
628
  try {
628
629
  if (!response.ok)
@@ -631,7 +632,7 @@ async function fetchVerificationKeySet(jwksUri) {
631
632
  return (0, import_jose.createLocalJWKSet)(json);
632
633
  } catch (err) {
633
634
  log.error("oauth.jwks.fetch_failed", { ...describeError(err), outcome: "500 oauth configuration error" });
634
- throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`);
635
+ throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
635
636
  }
636
637
  }
637
638
  function assertAccessTokenTyp(token, allowed) {
@@ -844,21 +845,21 @@ function createRequestAuthorizer(mcp, options = {}) {
844
845
  return { ok: true, auth };
845
846
  } catch (err) {
846
847
  if (err instanceof OAuthUpstreamUnreachableError) {
847
- log.error("auth.upstream_unreachable", { ...describeError(err), outcome: "503" });
848
+ log.error("auth.upstream_unreachable", { ...describeError(err), stage: err.stage, outcome: "503" });
848
849
  await recorder?.emit({
849
850
  tool: null,
850
851
  method: "authorize",
851
- outcome: "auth_upstream_unreachable",
852
+ outcome: err.stage === "jwks" ? "auth_jwks_unreachable" : "auth_discovery_unreachable",
852
853
  durationMs: nowMs() - startedAt
853
854
  });
854
855
  return { ok: false, response: oauthUpstreamUnreachableResponse() };
855
856
  }
856
857
  if (err instanceof OAuthConfigurationError) {
857
- log.error("auth.config_error", { ...describeError(err), outcome: "500" });
858
+ log.error("auth.config_error", { ...describeError(err), stage: err.stage, outcome: "500" });
858
859
  await recorder?.emit({
859
860
  tool: null,
860
861
  method: "authorize",
861
- outcome: "auth_config_error",
862
+ outcome: err.stage === "jwks" ? "auth_jwks_config_error" : "auth_discovery_config_error",
862
863
  durationMs: nowMs() - startedAt
863
864
  });
864
865
  return { ok: false, response: oauthConfigurationErrorResponse() };
@@ -3,23 +3,23 @@ import {
3
3
  } from "../../chunk-UQK5UO6C.js";
4
4
  import {
5
5
  createMcpProtocolHandler
6
- } from "../../chunk-2LLCWLQL.js";
6
+ } from "../../chunk-4H3Y2KYT.js";
7
7
  import {
8
8
  createOAuthProtectedResourceMetadataHandler
9
- } from "../../chunk-NQZGVZ24.js";
9
+ } from "../../chunk-7TVARTF4.js";
10
10
  import {
11
11
  createInvokeToolHandler
12
- } from "../../chunk-M2TRF6OJ.js";
12
+ } from "../../chunk-WOKM6B6H.js";
13
13
  import {
14
14
  createListToolsHandler
15
- } from "../../chunk-KYKL5ECH.js";
15
+ } from "../../chunk-YE6N7XLA.js";
16
16
  import "../../chunk-MA5H6PSF.js";
17
17
  import {
18
18
  createRecorderForRuntime
19
- } from "../../chunk-VTIP6LMI.js";
19
+ } from "../../chunk-IRCVDFWG.js";
20
20
  import "../../chunk-H37EB22A.js";
21
21
  import "../../chunk-6DXGZZA4.js";
22
- import "../../chunk-XOCASA3L.js";
22
+ import "../../chunk-OIRVEGPQ.js";
23
23
 
24
24
  // src/stacks/tanstack/handlers.ts
25
25
  var STACK = "tanstack";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/mcp-js",
3
- "version": "0.21.0-rc.0",
3
+ "version": "0.21.0-rc.2",
4
4
  "description": "Author MCP servers for Lovable apps. Declare tools with defineTool, register them in defineMcp, and a framework adapter (TanStack or Supabase Edge Functions) emits the route(s) at build time.",
5
5
  "type": "module",
6
6
  "repository": {