@lovable.dev/mcp-js 0.27.1 → 0.28.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 (46) hide show
  1. package/README.md +6 -6
  2. package/dist/{authorize-FOlzhxrM.js → authorize--rUeMOGU.js} +83 -32
  3. package/dist/{authorize-CB35c3Wg.cjs → authorize-ChY44o_1.cjs} +82 -31
  4. package/dist/{base-CReh7d3E.d.cts → base-CUkmyaXJ.d.cts} +6 -3
  5. package/dist/{base-CReh7d3E.d.ts → base-CUkmyaXJ.d.ts} +6 -3
  6. package/dist/cli/extract-manifest.cjs +2 -2
  7. package/dist/cli/extract-manifest.js +2 -2
  8. package/dist/{gate-BeHmyGxk.js → gate-BiM6EBeA.js} +1 -1
  9. package/dist/{gate-B9RSzvoI.cjs → gate-CGZl0gjJ.cjs} +1 -1
  10. package/dist/index.cjs +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/{io--MeYrWG7.d.ts → io-SMlD5WeX.d.ts} +1 -1
  13. package/dist/{io-BzTGjG_c.d.cts → io-VBHO8YH_.d.cts} +1 -1
  14. package/dist/{list-tools-Bku6XkVc.d.ts → list-tools-BAqQVIHk.d.ts} +1 -1
  15. package/dist/{list-tools-Dt-mhh52.js → list-tools-BLGr7mot.js} +2 -2
  16. package/dist/{list-tools-Cn7tpE0V.d.cts → list-tools-BN97L2Yv.d.cts} +1 -1
  17. package/dist/{list-tools-DiMCRunS.cjs → list-tools-DCF6G4fn.cjs} +2 -2
  18. package/dist/{logger-BkMMCFTv.cjs → logger-CN1q-KNn.cjs} +6 -6
  19. package/dist/{logger-rGakBvJ1.js → logger-Ctv5xUSD.js} +6 -6
  20. package/dist/{mcp-ECo1Ixk8.cjs → mcp-CUGwXkxb.cjs} +3 -3
  21. package/dist/{mcp-DiVQhHIw.js → mcp-Czp-hHjN.js} +3 -3
  22. package/dist/{package-BdaLbzEh.cjs → package-CGLPZwz-.cjs} +1 -1
  23. package/dist/{package-dtiombMt.js → package-DgiA0xuY.js} +1 -1
  24. package/dist/protocols/mcp/index.cjs +1 -1
  25. package/dist/protocols/mcp/index.d.cts +1 -1
  26. package/dist/protocols/mcp/index.d.ts +1 -1
  27. package/dist/protocols/mcp/index.js +1 -1
  28. package/dist/protocols/oauth-metadata.cjs +2 -2
  29. package/dist/protocols/oauth-metadata.js +2 -2
  30. package/dist/protocols/rest/index.cjs +2 -2
  31. package/dist/protocols/rest/index.d.cts +2 -2
  32. package/dist/protocols/rest/index.d.ts +2 -2
  33. package/dist/protocols/rest/index.js +2 -2
  34. package/dist/{rest-1Pf9sYNU.cjs → rest-BE05MUNS.cjs} +3 -3
  35. package/dist/{rest-Cit2862S.js → rest-BS7bBOd9.js} +3 -3
  36. package/dist/stacks/supabase/index.cjs +5 -5
  37. package/dist/stacks/supabase/index.js +5 -5
  38. package/dist/stacks/supabase/vite.cjs +1 -1
  39. package/dist/stacks/supabase/vite.d.cts +1 -1
  40. package/dist/stacks/supabase/vite.d.ts +1 -1
  41. package/dist/stacks/supabase/vite.js +1 -1
  42. package/dist/stacks/tanstack/index.cjs +4 -4
  43. package/dist/stacks/tanstack/index.js +4 -4
  44. package/dist/stacks/tanstack/vite.d.cts +1 -1
  45. package/dist/stacks/tanstack/vite.d.ts +1 -1
  46. package/package.json +1 -1
package/README.md CHANGED
@@ -211,7 +211,7 @@ Use `auth.oauth.issuer(...)`, set `resource` or `acceptedAudiences` to anchor th
211
211
 
212
212
  ## Debug logging
213
213
 
214
- The runtime is silent by default. Raise the log level to trace OAuth discovery, JWKS resolution, and token verification when a deployed MCP server returns `401`/`500` and you need to see why. Logs go to `console` (so they land in your platform's function logs) and **never include the bearer token, full claims, or PII** — only non-secret fields such as the JWT header `alg`/`kid`, `issuer`, `jwks_uri`, the token `sub`/`client_id`/`scopes`, and `jose` error codes.
214
+ The runtime logs operational events (tool invocations, auth outcomes, warnings, errors) at `info` by default. Raise the level to `debug` to trace OAuth discovery, JWKS resolution, and token verification when a deployed MCP server returns `401`/`500` and you need to see why. Logs go to `console` (so they land in your platform's function logs) and **never include the bearer token, full claims, or PII** — only non-secret fields such as the JWT header `alg`/`kid`, `issuer`, `jwks_uri`, the token `scopes`, and `jose` error codes. End-user identifiers (the token `sub`/`client_id`) appear only at `debug`, as the `oauth.verify.principal` event — the default `info` level never collects them.
215
215
 
216
216
  Enable it either way:
217
217
 
@@ -222,17 +222,17 @@ setLogLevel("debug"); // "silent" | "error" | "warn" | "info" | "debug"
222
222
  ```
223
223
 
224
224
  ```bash
225
- # Or via env var, read once at startup. Node/Deno only: it reads `process.env`,
226
- # which is absent on a deployed Cloudflare Worker (env arrives via bindings), so
227
- # the var is silently ignored there use `setLogLevel()` on Workers.
225
+ # Or via env var. Node reads it at startup; on Deno and Cloudflare Workers the
226
+ # recorder applies it at the first request's telemetry emit, so logs before that
227
+ # point may not honor itprefer `setLogLevel()` there.
228
228
  LOVABLE_MCP_LOG_LEVEL=debug
229
229
  ```
230
230
 
231
- A `500` on an OAuth-protected route is always one of two causes, logged at `error`: an `OAuthConfigurationError` from issuer-metadata discovery or a JWKS *fetch* failure (`oauth.discovery.config_error` / `oauth.jwks.fetch_failed` → `auth.config_error`), or a transport-level fault in the MCP handler (`mcp.transport_error`). Auth outcomes are logged at `info`: a granted request as `oauth.verify.ok`, and a `401`/`403` as `auth.token_rejected` (with the `jose` reason) or `auth.no_bearer_token` — so a request rejected for insufficient scope shows both `oauth.verify.ok` and the `auth.token_rejected` that follows it.
231
+ A `500` on an OAuth-protected route is always one of two causes, logged at `error`: an `OAuthConfigurationError` from issuer-metadata discovery or a JWKS *fetch* failure (`oauth.discovery.config_error` / `oauth.jwks.fetch_failed` → `auth.config_error`), or a transport-level fault in the MCP handler (`mcp.transport_error`). Auth outcomes are logged at `info`: a granted request as `oauth.verify.ok`, a request with no parseable bearer as `auth.no_bearer_token`, and a rejected token as `auth.token_rejected` (a `jose` rejection such as an expired token carries the `jose` error name and code; the full reason appears at `debug` as `oauth.verify.rejected`) — so a request rejected for insufficient scope shows both `oauth.verify.ok` and the `auth.token_rejected` that follows it. A sustained flood of `auth.token_rejected` whose `code` is `ERR_JOSE_NOT_SUPPORTED` or `ERR_JOSE_ALG_NOT_ALLOWED` (rather than `ERR_JWT_EXPIRED`) points at server-side key or algorithm configuration, not client error.
232
232
 
233
233
  ## Usage metrics
234
234
 
235
- Each MCP server records per-invocation telemetry — tool name, JSON-RPC method, outcome (`ok` / `handler_error` / `transport_error`), and latency and POSTs it in fire-and-forget batches as **OTLP/HTTP JSON logs**. No tool arguments or response payloads are ever captured. Emission is **on by default**, self-disables at runtime when `LOVABLE_API_KEY` is absent (so a local `vite dev` stays silent), and degrades silentlya failed flush never blocks or fails a tool call.
235
+ Each MCP server records per-invocation telemetry — tool name, JSON-RPC method, outcome, and latency — as **OTLP/HTTP JSON logs**, one awaited POST per record, bounded by a 3-second timeout; a failed or slow POST is logged (`metrics.failed`) and swallowed, never failing the request. Outcomes cover tool results (`ok`, `tool_error`, `handler_error`, `transport_error`) and the authorization gate: `auth_challenge` for an unauthenticated request answered with the `401` challenge (so probe traffic produces records), and the `auth_*` discovery/JWKS failure outcomes. No tool arguments or response payloads are ever captured. Emission is **on by default** and self-disables at runtime when `LOVABLE_API_KEY` is absent: records are dropped and one `metrics.disabled_no_api_key` warning is logged per process, so a local `vite dev` stays quiet. With `metrics: false` the recorder never runs on Deno and Cloudflare Workers that also means `LOVABLE_MCP_LOG_LEVEL` is never applied (use `setLogLevel()` instead).
236
236
 
237
237
  Configure it on the MCP definition:
238
238
 
@@ -1,7 +1,7 @@
1
- import { i as log, n as applyLogLevelFromEnv, o as parseSafeUrl, r as describeError, s as trimTrailingSlash, t as LOG_LEVEL_ENV_VAR, u as resolveMetricsConfig } from "./logger-rGakBvJ1.js";
2
- import { t as version } from "./package-dtiombMt.js";
1
+ import { i as log, n as applyLogLevelFromEnv, o as parseSafeUrl, r as describeError, s as trimTrailingSlash, t as LOG_LEVEL_ENV_VAR, u as resolveMetricsConfig } from "./logger-Ctv5xUSD.js";
2
+ import { t as version } from "./package-DgiA0xuY.js";
3
3
  import "./metadata-path-CAkNcfyY.js";
4
- import { createLocalJWKSet, decodeProtectedHeader, jwtVerify } from "jose";
4
+ import { createLocalJWKSet, decodeProtectedHeader, errors, jwtVerify } from "jose";
5
5
  //#region src/core/cors.ts
6
6
  const EXPOSE_HEADERS = "WWW-Authenticate, Mcp-Session-Id, Mcp-Protocol-Version";
7
7
  const ALLOW_HEADERS = "Authorization, Content-Type, Mcp-Session-Id, Mcp-Protocol-Version, Last-Event-ID";
@@ -73,6 +73,7 @@ function toLogRecord(rec) {
73
73
  if (rec.tool !== null) attributes.push(strAttr("mcp.tool", rec.tool));
74
74
  if (rec.reqBytes !== void 0) attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
75
75
  if (rec.resBytes !== void 0) attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
76
+ if (rec.httpMethod !== void 0) attributes.push(strAttr("http.request.method", rec.httpMethod));
76
77
  attributes.push(strAttr("mcp.stack", rec.stack));
77
78
  if (rec.endUserId !== void 0) attributes.push(strAttr("mcp.end_user_id", rec.endUserId));
78
79
  return {
@@ -120,6 +121,8 @@ function nowUnixNano() {
120
121
  function nowMs() {
121
122
  return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
122
123
  }
124
+ const METRICS_POST_TIMEOUT_MS = 3e3;
125
+ let warnedNoApiKey = false;
123
126
  const NOOP_RECORDER = { async emit() {} };
124
127
  function createNoopRecorder() {
125
128
  return NOOP_RECORDER;
@@ -168,7 +171,7 @@ var BaseMetricRecorder = class {
168
171
  }
169
172
  async emit(ev) {
170
173
  await this.applyLazyLogLevel();
171
- log.info("tool.invoked", {
174
+ if (ev.outcome !== "auth_challenge") log.info("tool.invoked", {
172
175
  tool: ev.tool,
173
176
  method: ev.method,
174
177
  outcome: ev.outcome,
@@ -181,30 +184,34 @@ var BaseMetricRecorder = class {
181
184
  log.warn("metrics.disabled_no_fetch", { endpoint: this.config.endpoint });
182
185
  return;
183
186
  }
184
- const headers = { ...this.baseHeaders };
185
- if (this.usesLovableEndpoint) {
186
- const key = await this.resolveApiKey();
187
- if (!key) {
188
- log.warn("metrics.disabled_no_api_key", {
189
- envVar: this.config.apiKeyEnvVar,
190
- endpoint: this.config.endpoint
191
- });
192
- return;
193
- }
194
- headers.authorization = `Bearer ${key}`;
195
- }
196
- const { errorText: _localOnly, ...wireEvent } = ev;
197
- const body = buildLogsPayload([{
198
- ...wireEvent,
199
- timeUnixNano: nowUnixNano(),
200
- stack: this.stack
201
- }], this.server);
202
187
  try {
188
+ const headers = { ...this.baseHeaders };
189
+ if (this.usesLovableEndpoint) {
190
+ const key = await this.resolveApiKey();
191
+ if (!key) {
192
+ if (!warnedNoApiKey) {
193
+ warnedNoApiKey = true;
194
+ log.warn("metrics.disabled_no_api_key", {
195
+ envVar: this.config.apiKeyEnvVar,
196
+ endpoint: this.config.endpoint
197
+ });
198
+ }
199
+ return;
200
+ }
201
+ headers.authorization = `Bearer ${key}`;
202
+ }
203
+ const { errorText: _localOnly, ...wireEvent } = ev;
204
+ const body = buildLogsPayload([{
205
+ ...wireEvent,
206
+ timeUnixNano: nowUnixNano(),
207
+ stack: this.stack
208
+ }], this.server);
203
209
  const res = await this.doFetch(this.config.endpoint, {
204
210
  method: "POST",
205
211
  headers,
206
212
  body,
207
- keepalive: true
213
+ keepalive: true,
214
+ signal: AbortSignal.timeout(METRICS_POST_TIMEOUT_MS)
208
215
  });
209
216
  if (!res.ok) log.warn("metrics.rejected", {
210
217
  status: res.status,
@@ -295,8 +302,8 @@ var SupabaseMetricRecorder = class extends BaseMetricRecorder {
295
302
  //#endregion
296
303
  //#region src/metrics/recorder.ts
297
304
  /** Vend the recorder for a stack, in-flight per request. Returns a no-op when
298
- * metrics are disabled (`metrics: false`); otherwise the stack-specific class,
299
- * which still logs `tool.invoked` even if the key or endpoint is unavailable. */
305
+ * metrics are disabled (`metrics: false`); otherwise the stack-specific class, which
306
+ * logs `tool.invoked` for tool invocations even if the key or endpoint is unavailable. */
300
307
  function createRecorderForRuntime(mcp, opts) {
301
308
  const config = resolveMetricsConfig(mcp.metrics);
302
309
  const server = {
@@ -593,6 +600,16 @@ async function fetchVerificationKeySet(jwksUri) {
593
600
  throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
594
601
  }
595
602
  }
603
+ function assertCompactJwsShape(token) {
604
+ const parts = token.split(".");
605
+ if (parts.length !== 3 || parts.some((part) => part.length === 0)) {
606
+ log.debug("oauth.verify.bad_shape", {
607
+ tokenLength: token.length,
608
+ outcome: "401 invalid_token"
609
+ });
610
+ throw new OAuthTokenError(401, "invalid_token", "Access token is not a JWT");
611
+ }
612
+ }
596
613
  function assertAccessTokenTyp(token, allowed) {
597
614
  let header;
598
615
  try {
@@ -694,6 +711,8 @@ function buildMcpAuthContext(args) {
694
711
  function createOAuthTokenVerifier(auth, discovery) {
695
712
  const allowedTyps = auth.accessTokenTyp ?? DEFAULT_ACCESS_TOKEN_TYPS;
696
713
  return async (token, request, options) => {
714
+ assertCompactJwsShape(token);
715
+ assertAccessTokenTyp(token, allowedTyps);
697
716
  const resource = resolveProtectedResource(auth, request, options);
698
717
  const issuer = await discovery.resolveIssuer();
699
718
  const acceptedAudiences = resolveAcceptedAudiences(auth, resource);
@@ -705,9 +724,7 @@ function createOAuthTokenVerifier(auth, discovery) {
705
724
  });
706
725
  const jwksUri = await discovery.resolveJwksUri();
707
726
  log.debug("oauth.jwks.fetch", { jwksUri });
708
- const keySet = await fetchVerificationKeySet(jwksUri);
709
- assertAccessTokenTyp(token, allowedTyps);
710
- const claims = await verifyJwtClaims(token, keySet, issuer, auth);
727
+ const claims = await verifyJwtClaims(token, await fetchVerificationKeySet(jwksUri), issuer, auth);
711
728
  const audienceVia = checkAcceptedAudience(claims, acceptedAudiences, auth);
712
729
  assertNonEmptySubject(claims);
713
730
  const context = buildMcpAuthContext({
@@ -719,11 +736,13 @@ function createOAuthTokenVerifier(auth, discovery) {
719
736
  });
720
737
  assertOAuthClientClaim(auth, context.principal.clientId);
721
738
  log.info("oauth.verify.ok", {
722
- sub: context.principal.sub,
723
- clientId: context.principal.clientId,
724
739
  scopes: context.principal.scopes,
725
740
  audienceVia
726
741
  });
742
+ log.debug("oauth.verify.principal", {
743
+ sub: context.principal.sub,
744
+ clientId: context.principal.clientId
745
+ });
727
746
  return context;
728
747
  };
729
748
  }
@@ -776,6 +795,22 @@ function oauthUpstreamUnreachableResponse() {
776
795
  }
777
796
  });
778
797
  }
798
+ const KNOWN_HTTP_METHODS = /* @__PURE__ */ new Set([
799
+ "GET",
800
+ "HEAD",
801
+ "POST",
802
+ "PUT",
803
+ "DELETE",
804
+ "PATCH",
805
+ "OPTIONS",
806
+ "TRACE",
807
+ "CONNECT",
808
+ "QUERY"
809
+ ]);
810
+ function normalizeHttpMethod(method) {
811
+ const upper = method.toUpperCase();
812
+ return KNOWN_HTTP_METHODS.has(upper) ? upper : "_OTHER";
813
+ }
779
814
  function parseBearerToken(request) {
780
815
  const header = request.headers.get("Authorization");
781
816
  if (!header) return void 0;
@@ -838,7 +873,18 @@ function createRequestAuthorizer(mcp, options = {}) {
838
873
  const startedAt = nowMs();
839
874
  const token = parseBearerToken(request);
840
875
  if (!token) {
841
- log.info("auth.no_bearer_token", { outcome: "401" });
876
+ const httpMethod = normalizeHttpMethod(request.method);
877
+ log.info("auth.no_bearer_token", {
878
+ httpMethod,
879
+ outcome: "401"
880
+ });
881
+ await recorder?.emit({
882
+ tool: null,
883
+ method: "authorize",
884
+ outcome: "auth_challenge",
885
+ httpMethod,
886
+ durationMs: nowMs() - startedAt
887
+ });
842
888
  return {
843
889
  ok: false,
844
890
  response: challengeResponse(runtime.auth, request, runtime.options, 401)
@@ -896,7 +942,12 @@ function createRequestAuthorizer(mcp, options = {}) {
896
942
  response: challengeResponse(runtime.auth, request, runtime.options, err.status, err.oauthError, err.message)
897
943
  };
898
944
  }
899
- log.error("auth.unexpected_error", {
945
+ if (err instanceof errors.JOSEError) log.info("auth.token_rejected", {
946
+ ...describeError(err),
947
+ status: 401,
948
+ oauthError: "invalid_token"
949
+ });
950
+ else log.error("auth.unexpected_error", {
900
951
  ...describeError(err),
901
952
  outcome: "401"
902
953
  });
@@ -1,5 +1,5 @@
1
- const require_logger = require("./logger-BkMMCFTv.cjs");
2
- const require_package = require("./package-BdaLbzEh.cjs");
1
+ const require_logger = require("./logger-CN1q-KNn.cjs");
2
+ const require_package = require("./package-CGLPZwz-.cjs");
3
3
  require("./metadata-path-zd7NSNoa.cjs");
4
4
  let jose = require("jose");
5
5
  //#region src/core/cors.ts
@@ -73,6 +73,7 @@ function toLogRecord(rec) {
73
73
  if (rec.tool !== null) attributes.push(strAttr("mcp.tool", rec.tool));
74
74
  if (rec.reqBytes !== void 0) attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
75
75
  if (rec.resBytes !== void 0) attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
76
+ if (rec.httpMethod !== void 0) attributes.push(strAttr("http.request.method", rec.httpMethod));
76
77
  attributes.push(strAttr("mcp.stack", rec.stack));
77
78
  if (rec.endUserId !== void 0) attributes.push(strAttr("mcp.end_user_id", rec.endUserId));
78
79
  return {
@@ -120,6 +121,8 @@ function nowUnixNano() {
120
121
  function nowMs() {
121
122
  return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
122
123
  }
124
+ const METRICS_POST_TIMEOUT_MS = 3e3;
125
+ let warnedNoApiKey = false;
123
126
  const NOOP_RECORDER = { async emit() {} };
124
127
  function createNoopRecorder() {
125
128
  return NOOP_RECORDER;
@@ -168,7 +171,7 @@ var BaseMetricRecorder = class {
168
171
  }
169
172
  async emit(ev) {
170
173
  await this.applyLazyLogLevel();
171
- require_logger.log.info("tool.invoked", {
174
+ if (ev.outcome !== "auth_challenge") require_logger.log.info("tool.invoked", {
172
175
  tool: ev.tool,
173
176
  method: ev.method,
174
177
  outcome: ev.outcome,
@@ -181,30 +184,34 @@ var BaseMetricRecorder = class {
181
184
  require_logger.log.warn("metrics.disabled_no_fetch", { endpoint: this.config.endpoint });
182
185
  return;
183
186
  }
184
- const headers = { ...this.baseHeaders };
185
- if (this.usesLovableEndpoint) {
186
- const key = await this.resolveApiKey();
187
- if (!key) {
188
- require_logger.log.warn("metrics.disabled_no_api_key", {
189
- envVar: this.config.apiKeyEnvVar,
190
- endpoint: this.config.endpoint
191
- });
192
- return;
193
- }
194
- headers.authorization = `Bearer ${key}`;
195
- }
196
- const { errorText: _localOnly, ...wireEvent } = ev;
197
- const body = buildLogsPayload([{
198
- ...wireEvent,
199
- timeUnixNano: nowUnixNano(),
200
- stack: this.stack
201
- }], this.server);
202
187
  try {
188
+ const headers = { ...this.baseHeaders };
189
+ if (this.usesLovableEndpoint) {
190
+ const key = await this.resolveApiKey();
191
+ if (!key) {
192
+ if (!warnedNoApiKey) {
193
+ warnedNoApiKey = true;
194
+ require_logger.log.warn("metrics.disabled_no_api_key", {
195
+ envVar: this.config.apiKeyEnvVar,
196
+ endpoint: this.config.endpoint
197
+ });
198
+ }
199
+ return;
200
+ }
201
+ headers.authorization = `Bearer ${key}`;
202
+ }
203
+ const { errorText: _localOnly, ...wireEvent } = ev;
204
+ const body = buildLogsPayload([{
205
+ ...wireEvent,
206
+ timeUnixNano: nowUnixNano(),
207
+ stack: this.stack
208
+ }], this.server);
203
209
  const res = await this.doFetch(this.config.endpoint, {
204
210
  method: "POST",
205
211
  headers,
206
212
  body,
207
- keepalive: true
213
+ keepalive: true,
214
+ signal: AbortSignal.timeout(METRICS_POST_TIMEOUT_MS)
208
215
  });
209
216
  if (!res.ok) require_logger.log.warn("metrics.rejected", {
210
217
  status: res.status,
@@ -295,8 +302,8 @@ var SupabaseMetricRecorder = class extends BaseMetricRecorder {
295
302
  //#endregion
296
303
  //#region src/metrics/recorder.ts
297
304
  /** Vend the recorder for a stack, in-flight per request. Returns a no-op when
298
- * metrics are disabled (`metrics: false`); otherwise the stack-specific class,
299
- * which still logs `tool.invoked` even if the key or endpoint is unavailable. */
305
+ * metrics are disabled (`metrics: false`); otherwise the stack-specific class, which
306
+ * logs `tool.invoked` for tool invocations even if the key or endpoint is unavailable. */
300
307
  function createRecorderForRuntime(mcp, opts) {
301
308
  const config = require_logger.resolveMetricsConfig(mcp.metrics);
302
309
  const server = {
@@ -593,6 +600,16 @@ async function fetchVerificationKeySet(jwksUri) {
593
600
  throw new OAuthConfigurationError(`JWKS fetch failed: ${err instanceof Error ? err.message : String(err)}`, "jwks");
594
601
  }
595
602
  }
603
+ function assertCompactJwsShape(token) {
604
+ const parts = token.split(".");
605
+ if (parts.length !== 3 || parts.some((part) => part.length === 0)) {
606
+ require_logger.log.debug("oauth.verify.bad_shape", {
607
+ tokenLength: token.length,
608
+ outcome: "401 invalid_token"
609
+ });
610
+ throw new OAuthTokenError(401, "invalid_token", "Access token is not a JWT");
611
+ }
612
+ }
596
613
  function assertAccessTokenTyp(token, allowed) {
597
614
  let header;
598
615
  try {
@@ -694,6 +711,8 @@ function buildMcpAuthContext(args) {
694
711
  function createOAuthTokenVerifier(auth, discovery) {
695
712
  const allowedTyps = auth.accessTokenTyp ?? DEFAULT_ACCESS_TOKEN_TYPS;
696
713
  return async (token, request, options) => {
714
+ assertCompactJwsShape(token);
715
+ assertAccessTokenTyp(token, allowedTyps);
697
716
  const resource = resolveProtectedResource(auth, request, options);
698
717
  const issuer = await discovery.resolveIssuer();
699
718
  const acceptedAudiences = resolveAcceptedAudiences(auth, resource);
@@ -705,9 +724,7 @@ function createOAuthTokenVerifier(auth, discovery) {
705
724
  });
706
725
  const jwksUri = await discovery.resolveJwksUri();
707
726
  require_logger.log.debug("oauth.jwks.fetch", { jwksUri });
708
- const keySet = await fetchVerificationKeySet(jwksUri);
709
- assertAccessTokenTyp(token, allowedTyps);
710
- const claims = await verifyJwtClaims(token, keySet, issuer, auth);
727
+ const claims = await verifyJwtClaims(token, await fetchVerificationKeySet(jwksUri), issuer, auth);
711
728
  const audienceVia = checkAcceptedAudience(claims, acceptedAudiences, auth);
712
729
  assertNonEmptySubject(claims);
713
730
  const context = buildMcpAuthContext({
@@ -719,11 +736,13 @@ function createOAuthTokenVerifier(auth, discovery) {
719
736
  });
720
737
  assertOAuthClientClaim(auth, context.principal.clientId);
721
738
  require_logger.log.info("oauth.verify.ok", {
722
- sub: context.principal.sub,
723
- clientId: context.principal.clientId,
724
739
  scopes: context.principal.scopes,
725
740
  audienceVia
726
741
  });
742
+ require_logger.log.debug("oauth.verify.principal", {
743
+ sub: context.principal.sub,
744
+ clientId: context.principal.clientId
745
+ });
727
746
  return context;
728
747
  };
729
748
  }
@@ -776,6 +795,22 @@ function oauthUpstreamUnreachableResponse() {
776
795
  }
777
796
  });
778
797
  }
798
+ const KNOWN_HTTP_METHODS = /* @__PURE__ */ new Set([
799
+ "GET",
800
+ "HEAD",
801
+ "POST",
802
+ "PUT",
803
+ "DELETE",
804
+ "PATCH",
805
+ "OPTIONS",
806
+ "TRACE",
807
+ "CONNECT",
808
+ "QUERY"
809
+ ]);
810
+ function normalizeHttpMethod(method) {
811
+ const upper = method.toUpperCase();
812
+ return KNOWN_HTTP_METHODS.has(upper) ? upper : "_OTHER";
813
+ }
779
814
  function parseBearerToken(request) {
780
815
  const header = request.headers.get("Authorization");
781
816
  if (!header) return void 0;
@@ -838,7 +873,18 @@ function createRequestAuthorizer(mcp, options = {}) {
838
873
  const startedAt = nowMs();
839
874
  const token = parseBearerToken(request);
840
875
  if (!token) {
841
- require_logger.log.info("auth.no_bearer_token", { outcome: "401" });
876
+ const httpMethod = normalizeHttpMethod(request.method);
877
+ require_logger.log.info("auth.no_bearer_token", {
878
+ httpMethod,
879
+ outcome: "401"
880
+ });
881
+ await recorder?.emit({
882
+ tool: null,
883
+ method: "authorize",
884
+ outcome: "auth_challenge",
885
+ httpMethod,
886
+ durationMs: nowMs() - startedAt
887
+ });
842
888
  return {
843
889
  ok: false,
844
890
  response: challengeResponse(runtime.auth, request, runtime.options, 401)
@@ -896,7 +942,12 @@ function createRequestAuthorizer(mcp, options = {}) {
896
942
  response: challengeResponse(runtime.auth, request, runtime.options, err.status, err.oauthError, err.message)
897
943
  };
898
944
  }
899
- require_logger.log.error("auth.unexpected_error", {
945
+ if (err instanceof jose.errors.JOSEError) require_logger.log.info("auth.token_rejected", {
946
+ ...require_logger.describeError(err),
947
+ status: 401,
948
+ oauthError: "invalid_token"
949
+ });
950
+ else require_logger.log.error("auth.unexpected_error", {
900
951
  ...require_logger.describeError(err),
901
952
  outcome: "401"
902
953
  });
@@ -1,18 +1,21 @@
1
1
  //#region src/metrics/impl/base.d.ts
2
- type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_discovery_config_error" | "auth_discovery_unreachable" | "auth_jwks_config_error" | "auth_jwks_unreachable";
2
+ type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_challenge" | "auth_discovery_config_error" | "auth_discovery_unreachable" | "auth_jwks_config_error" | "auth_jwks_unreachable";
3
3
  /** One recorded MCP call. Carries no arguments or response payloads — only the
4
4
  * tool name, the JSON-RPC method, the result class, timing, and byte sizes.
5
5
  * `errorText` is the sole exception: it is logged locally for debugging and
6
6
  * deliberately never included in the OTLP payload (see `emit` / `buildLogsPayload`). */
7
7
  interface InvocationRecord {
8
- /** Tool name for `tools/call`; `null` for list/initialize, transport faults, and auth-config failures. */
8
+ /** Tool name for `tools/call`; `null` for list/initialize, transport faults, and `authorize` records. */
9
9
  tool: string | null;
10
- /** JSON-RPC method, e.g. `tools/call`; `authorize` for auth-config failures. */
10
+ /** JSON-RPC method, e.g. `tools/call`; `authorize` for records from the authorization gate. */
11
11
  method: string;
12
12
  outcome: InvocationOutcome;
13
13
  durationMs: number;
14
14
  reqBytes?: number;
15
15
  resBytes?: number;
16
+ /** HTTP request method. Set on `auth_challenge` so probe traffic (GET vs
17
+ * POST discovery) is distinguishable; absent on tool-call records. */
18
+ httpMethod?: string;
16
19
  /** The app end-user that made the call (the access token `sub`), or
17
20
  * `undefined` when the request is unauthenticated. Not a Lovable identity. */
18
21
  endUserId?: string;
@@ -1,18 +1,21 @@
1
1
  //#region src/metrics/impl/base.d.ts
2
- type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_discovery_config_error" | "auth_discovery_unreachable" | "auth_jwks_config_error" | "auth_jwks_unreachable";
2
+ type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_challenge" | "auth_discovery_config_error" | "auth_discovery_unreachable" | "auth_jwks_config_error" | "auth_jwks_unreachable";
3
3
  /** One recorded MCP call. Carries no arguments or response payloads — only the
4
4
  * tool name, the JSON-RPC method, the result class, timing, and byte sizes.
5
5
  * `errorText` is the sole exception: it is logged locally for debugging and
6
6
  * deliberately never included in the OTLP payload (see `emit` / `buildLogsPayload`). */
7
7
  interface InvocationRecord {
8
- /** Tool name for `tools/call`; `null` for list/initialize, transport faults, and auth-config failures. */
8
+ /** Tool name for `tools/call`; `null` for list/initialize, transport faults, and `authorize` records. */
9
9
  tool: string | null;
10
- /** JSON-RPC method, e.g. `tools/call`; `authorize` for auth-config failures. */
10
+ /** JSON-RPC method, e.g. `tools/call`; `authorize` for records from the authorization gate. */
11
11
  method: string;
12
12
  outcome: InvocationOutcome;
13
13
  durationMs: number;
14
14
  reqBytes?: number;
15
15
  resBytes?: number;
16
+ /** HTTP request method. Set on `auth_challenge` so probe traffic (GET vs
17
+ * POST discovery) is distinguishable; absent on tool-call records. */
18
+ httpMethod?: string;
16
19
  /** The app end-user that made the call (the access token `sub`), or
17
20
  * `undefined` when the request is unauthenticated. Not a Lovable identity. */
18
21
  endUserId?: string;
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- const require_package = require("../package-BdaLbzEh.cjs");
3
- const require_list_tools = require("../list-tools-DiMCRunS.cjs");
2
+ const require_package = require("../package-CGLPZwz-.cjs");
3
+ const require_list_tools = require("../list-tools-DCF6G4fn.cjs");
4
4
  const require_fs_errors = require("../fs-errors-CWNzOV75.cjs");
5
5
  let node_fs = require("node:fs");
6
6
  let node_path = require("node:path");
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { t as version } from "../package-dtiombMt.js";
3
- import { t as buildMcpListing } from "../list-tools-Dt-mhh52.js";
2
+ import { t as version } from "../package-DgiA0xuY.js";
3
+ import { t as buildMcpListing } from "../list-tools-BLGr7mot.js";
4
4
  import { t as isFileMissing } from "../fs-errors-PA2t1TIp.js";
5
5
  import { lstatSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
6
6
  import { dirname, resolve } from "node:path";
@@ -1,4 +1,4 @@
1
- import { c as createNoopRecorder, d as finalizeWireResponse, p as corsPreflightResponse } from "./authorize-FOlzhxrM.js";
1
+ import { c as createNoopRecorder, d as finalizeWireResponse, p as corsPreflightResponse } from "./authorize--rUeMOGU.js";
2
2
  //#region src/protocols/gate.ts
3
3
  function createGatedHandler(gate) {
4
4
  const allow = [...gate.methods, "OPTIONS"].join(", ");
@@ -1,4 +1,4 @@
1
- const require_authorize = require("./authorize-CB35c3Wg.cjs");
1
+ const require_authorize = require("./authorize-ChY44o_1.cjs");
2
2
  //#region src/protocols/gate.ts
3
3
  function createGatedHandler(gate) {
4
4
  const allow = [...gate.methods, "OPTIONS"].join(", ");
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_logger = require("./logger-BkMMCFTv.cjs");
2
+ const require_logger = require("./logger-CN1q-KNn.cjs");
3
3
  const require_errors = require("./errors-CN6Da8iz.cjs");
4
4
  //#region src/core/define.ts
5
5
  function assertUniqueNames(mcp) {
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as setLogLevel, o as parseSafeUrl, s as trimTrailingSlash, u as resolveMetricsConfig } from "./logger-rGakBvJ1.js";
1
+ import { a as setLogLevel, o as parseSafeUrl, s as trimTrailingSlash, u as resolveMetricsConfig } from "./logger-Ctv5xUSD.js";
2
2
  import { i as ToolContext, t as ToolError } from "./errors-DSe96Ffd.js";
3
3
  //#region src/core/define.ts
4
4
  function assertUniqueNames(mcp) {
@@ -1,4 +1,4 @@
1
- import "./list-tools-Bku6XkVc.js";
1
+ import "./list-tools-BAqQVIHk.js";
2
2
  //#region src/manifest/io.d.ts
3
3
  /**
4
4
  * Shape every MCP Vite plugin exposes on its `api` so `runExtract` can read
@@ -1,4 +1,4 @@
1
- import "./list-tools-Cn7tpE0V.cjs";
1
+ import "./list-tools-BN97L2Yv.cjs";
2
2
  //#region src/manifest/io.d.ts
3
3
  /**
4
4
  * Shape every MCP Vite plugin exposes on its `api` so `runExtract` can read
@@ -1,5 +1,5 @@
1
1
  import { c as McpDefinition } from "./types-C0Wgm9zp.js";
2
- import { t as MetricsRecorder } from "./base-CReh7d3E.js";
2
+ import { t as MetricsRecorder } from "./base-CUkmyaXJ.js";
3
3
  import { t as McpRuntimeOptions } from "./authorize-Cs1yyLrq.js";
4
4
  //#region src/protocols/rest/list-tools.d.ts
5
5
  type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,5 +1,5 @@
1
- import { f as methodNotAllowed, n as createRequestAuthorizer, t as assertRestResourceBinding } from "./authorize-FOlzhxrM.js";
2
- import { t as createGatedHandler } from "./gate-BeHmyGxk.js";
1
+ import { f as methodNotAllowed, n as createRequestAuthorizer, t as assertRestResourceBinding } from "./authorize--rUeMOGU.js";
2
+ import { t as createGatedHandler } from "./gate-BiM6EBeA.js";
3
3
  import { objectFromShape } from "@modelcontextprotocol/sdk/server/zod-compat.js";
4
4
  import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
5
5
  //#region src/protocols/rest/list-tools.ts
@@ -1,5 +1,5 @@
1
1
  import { c as McpDefinition } from "./types-C0Wgm9zp.cjs";
2
- import { t as MetricsRecorder } from "./base-CReh7d3E.cjs";
2
+ import { t as MetricsRecorder } from "./base-CUkmyaXJ.cjs";
3
3
  import { t as McpRuntimeOptions } from "./authorize-BcNuNPtP.cjs";
4
4
  //#region src/protocols/rest/list-tools.d.ts
5
5
  type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,5 +1,5 @@
1
- const require_authorize = require("./authorize-CB35c3Wg.cjs");
2
- const require_gate = require("./gate-B9RSzvoI.cjs");
1
+ const require_authorize = require("./authorize-ChY44o_1.cjs");
2
+ const require_gate = require("./gate-CGZl0gjJ.cjs");
3
3
  let _modelcontextprotocol_sdk_server_zod_compat_js = require("@modelcontextprotocol/sdk/server/zod-compat.js");
4
4
  let _modelcontextprotocol_sdk_server_zod_json_schema_compat_js = require("@modelcontextprotocol/sdk/server/zod-json-schema-compat.js");
5
5
  //#region src/protocols/rest/list-tools.ts
@@ -84,13 +84,12 @@ function isLogLevel(value) {
84
84
  const LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
85
85
  function readEnvLevel() {
86
86
  try {
87
- const normalized = (typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0)?.trim().toLowerCase();
88
- return isLogLevel(normalized) ? normalized : void 0;
87
+ return parseLogLevel(typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0);
89
88
  } catch {
90
89
  return;
91
90
  }
92
91
  }
93
- let currentLevel = readEnvLevel() ?? "debug";
92
+ let currentLevel = readEnvLevel() ?? "info";
94
93
  /**
95
94
  * Set the runtime log level programmatically. Use this when the deployment can't
96
95
  * surface `LOVABLE_MCP_LOG_LEVEL` to the package (e.g. a Cloudflare Worker that
@@ -108,11 +107,12 @@ function parseLogLevel(raw) {
108
107
  return isLogLevel(normalized) ? normalized : void 0;
109
108
  }
110
109
  /**
111
- * Apply the log level from an env value: use it when it names a valid level,
112
- * otherwise fall back to `debug` so the SDK's diagnostics are on by default.
110
+ * Apply the log level from an env value when it names a valid level; otherwise
111
+ * leave the current level alone so a programmatic `setLogLevel` sticks.
113
112
  */
114
113
  function applyLogLevelFromEnv(raw) {
115
- setLogLevel(parseLogLevel(raw) ?? "debug");
114
+ const level = parseLogLevel(raw);
115
+ if (level !== void 0) setLogLevel(level);
116
116
  }
117
117
  function enabled(level) {
118
118
  return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
@@ -84,13 +84,12 @@ function isLogLevel(value) {
84
84
  const LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
85
85
  function readEnvLevel() {
86
86
  try {
87
- const normalized = (typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0)?.trim().toLowerCase();
88
- return isLogLevel(normalized) ? normalized : void 0;
87
+ return parseLogLevel(typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0);
89
88
  } catch {
90
89
  return;
91
90
  }
92
91
  }
93
- let currentLevel = readEnvLevel() ?? "debug";
92
+ let currentLevel = readEnvLevel() ?? "info";
94
93
  /**
95
94
  * Set the runtime log level programmatically. Use this when the deployment can't
96
95
  * surface `LOVABLE_MCP_LOG_LEVEL` to the package (e.g. a Cloudflare Worker that
@@ -108,11 +107,12 @@ function parseLogLevel(raw) {
108
107
  return isLogLevel(normalized) ? normalized : void 0;
109
108
  }
110
109
  /**
111
- * Apply the log level from an env value: use it when it names a valid level,
112
- * otherwise fall back to `debug` so the SDK's diagnostics are on by default.
110
+ * Apply the log level from an env value when it names a valid level; otherwise
111
+ * leave the current level alone so a programmatic `setLogLevel` sticks.
113
112
  */
114
113
  function applyLogLevelFromEnv(raw) {
115
- setLogLevel(parseLogLevel(raw) ?? "debug");
114
+ const level = parseLogLevel(raw);
115
+ if (level !== void 0) setLogLevel(level);
116
116
  }
117
117
  function enabled(level) {
118
118
  return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
@@ -1,8 +1,8 @@
1
- const require_logger = require("./logger-BkMMCFTv.cjs");
1
+ const require_logger = require("./logger-CN1q-KNn.cjs");
2
2
  const require_errors = require("./errors-CN6Da8iz.cjs");
3
- const require_authorize = require("./authorize-CB35c3Wg.cjs");
3
+ const require_authorize = require("./authorize-ChY44o_1.cjs");
4
4
  const require_content = require("./content-NCYIGgOb.cjs");
5
- const require_gate = require("./gate-B9RSzvoI.cjs");
5
+ const require_gate = require("./gate-CGZl0gjJ.cjs");
6
6
  let _modelcontextprotocol_sdk_server_mcp_js = require("@modelcontextprotocol/sdk/server/mcp.js");
7
7
  let _modelcontextprotocol_sdk_server_webStandardStreamableHttp_js = require("@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js");
8
8
  //#region src/protocols/mcp/protocol.ts
@@ -1,8 +1,8 @@
1
- import { i as log, r as describeError } from "./logger-rGakBvJ1.js";
1
+ import { i as log, r as describeError } from "./logger-Ctv5xUSD.js";
2
2
  import { i as ToolContext, n as errorSummary, r as resolveToolErrorMessage } from "./errors-DSe96Ffd.js";
3
- import { l as nowMs, n as createRequestAuthorizer } from "./authorize-FOlzhxrM.js";
3
+ import { l as nowMs, n as createRequestAuthorizer } from "./authorize--rUeMOGU.js";
4
4
  import { t as extractTextContent } from "./content-D5LJAHyM.js";
5
- import { t as createGatedHandler } from "./gate-BeHmyGxk.js";
5
+ import { t as createGatedHandler } from "./gate-BiM6EBeA.js";
6
6
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
7
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
8
8
  //#region src/protocols/mcp/protocol.ts
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.27.1";
2
+ var version = "0.28.0";
3
3
  //#endregion
4
4
  Object.defineProperty(exports, "version", {
5
5
  enumerable: true,
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.27.1";
2
+ var version = "0.28.0";
3
3
  //#endregion
4
4
  export { version as t };
@@ -1,3 +1,3 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_mcp = require("../../mcp-ECo1Ixk8.cjs");
2
+ const require_mcp = require("../../mcp-CUGwXkxb.cjs");
3
3
  exports.createMcpProtocolHandler = require_mcp.createMcpProtocolHandler;
@@ -1,5 +1,5 @@
1
1
  import { c as McpDefinition } from "../../types-C0Wgm9zp.cjs";
2
- import { t as MetricsRecorder } from "../../base-CReh7d3E.cjs";
2
+ import { t as MetricsRecorder } from "../../base-CUkmyaXJ.cjs";
3
3
  import { t as McpRuntimeOptions } from "../../authorize-BcNuNPtP.cjs";
4
4
  //#region src/protocols/mcp/protocol.d.ts
5
5
  type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,5 +1,5 @@
1
1
  import { c as McpDefinition } from "../../types-C0Wgm9zp.js";
2
- import { t as MetricsRecorder } from "../../base-CReh7d3E.js";
2
+ import { t as MetricsRecorder } from "../../base-CUkmyaXJ.js";
3
3
  import { t as McpRuntimeOptions } from "../../authorize-Cs1yyLrq.js";
4
4
  //#region src/protocols/mcp/protocol.d.ts
5
5
  type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,2 +1,2 @@
1
- import { t as createMcpProtocolHandler } from "../../mcp-DiVQhHIw.js";
1
+ import { t as createMcpProtocolHandler } from "../../mcp-Czp-hHjN.js";
2
2
  export { createMcpProtocolHandler };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_logger = require("../logger-BkMMCFTv.cjs");
3
- const require_authorize = require("../authorize-CB35c3Wg.cjs");
2
+ const require_logger = require("../logger-CN1q-KNn.cjs");
3
+ const require_authorize = require("../authorize-ChY44o_1.cjs");
4
4
  //#region src/protocols/oauth-metadata.ts
5
5
  function notFound() {
6
6
  return new Response(JSON.stringify({ error: "not found" }), {
@@ -1,5 +1,5 @@
1
- import { i as log, r as describeError } from "../logger-rGakBvJ1.js";
2
- import { d as finalizeWireResponse, f as methodNotAllowed, i as oauthConfigurationErrorResponse, o as resolveProtectedResource, p as corsPreflightResponse, r as getOAuthRuntime, u as JSON_HEADERS } from "../authorize-FOlzhxrM.js";
1
+ import { i as log, r as describeError } from "../logger-Ctv5xUSD.js";
2
+ import { d as finalizeWireResponse, f as methodNotAllowed, i as oauthConfigurationErrorResponse, o as resolveProtectedResource, p as corsPreflightResponse, r as getOAuthRuntime, u as JSON_HEADERS } from "../authorize--rUeMOGU.js";
3
3
  //#region src/protocols/oauth-metadata.ts
4
4
  function notFound() {
5
5
  return new Response(JSON.stringify({ error: "not found" }), {
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_list_tools = require("../../list-tools-DiMCRunS.cjs");
3
- const require_rest = require("../../rest-1Pf9sYNU.cjs");
2
+ const require_list_tools = require("../../list-tools-DCF6G4fn.cjs");
3
+ const require_rest = require("../../rest-BE05MUNS.cjs");
4
4
  exports.createInvokeToolHandler = require_rest.createInvokeToolHandler;
5
5
  exports.createListToolsHandler = require_list_tools.createListToolsHandler;
@@ -1,7 +1,7 @@
1
1
  import { c as McpDefinition } from "../../types-C0Wgm9zp.cjs";
2
- import { t as MetricsRecorder } from "../../base-CReh7d3E.cjs";
2
+ import { t as MetricsRecorder } from "../../base-CUkmyaXJ.cjs";
3
3
  import { t as McpRuntimeOptions } from "../../authorize-BcNuNPtP.cjs";
4
- import { n as createListToolsHandler, t as RestListToolsHandler } from "../../list-tools-Cn7tpE0V.cjs";
4
+ import { n as createListToolsHandler, t as RestListToolsHandler } from "../../list-tools-BN97L2Yv.cjs";
5
5
  //#region src/protocols/rest/invoke-tool.d.ts
6
6
  type RestInvokeToolHandler = (request: Request, toolName: string, recorder?: MetricsRecorder) => Promise<Response>;
7
7
  declare function createInvokeToolHandler(mcp: McpDefinition, options?: McpRuntimeOptions): RestInvokeToolHandler;
@@ -1,7 +1,7 @@
1
1
  import { c as McpDefinition } from "../../types-C0Wgm9zp.js";
2
- import { t as MetricsRecorder } from "../../base-CReh7d3E.js";
2
+ import { t as MetricsRecorder } from "../../base-CUkmyaXJ.js";
3
3
  import { t as McpRuntimeOptions } from "../../authorize-Cs1yyLrq.js";
4
- import { n as createListToolsHandler, t as RestListToolsHandler } from "../../list-tools-Bku6XkVc.js";
4
+ import { n as createListToolsHandler, t as RestListToolsHandler } from "../../list-tools-BAqQVIHk.js";
5
5
  //#region src/protocols/rest/invoke-tool.d.ts
6
6
  type RestInvokeToolHandler = (request: Request, toolName: string, recorder?: MetricsRecorder) => Promise<Response>;
7
7
  declare function createInvokeToolHandler(mcp: McpDefinition, options?: McpRuntimeOptions): RestInvokeToolHandler;
@@ -1,3 +1,3 @@
1
- import { n as createListToolsHandler } from "../../list-tools-Dt-mhh52.js";
2
- import { t as createInvokeToolHandler } from "../../rest-Cit2862S.js";
1
+ import { n as createListToolsHandler } from "../../list-tools-BLGr7mot.js";
2
+ import { t as createInvokeToolHandler } from "../../rest-BS7bBOd9.js";
3
3
  export { createInvokeToolHandler, createListToolsHandler };
@@ -1,8 +1,8 @@
1
1
  const require_errors = require("./errors-CN6Da8iz.cjs");
2
- const require_authorize = require("./authorize-CB35c3Wg.cjs");
2
+ const require_authorize = require("./authorize-ChY44o_1.cjs");
3
3
  const require_content = require("./content-NCYIGgOb.cjs");
4
- const require_gate = require("./gate-B9RSzvoI.cjs");
5
- require("./list-tools-DiMCRunS.cjs");
4
+ const require_gate = require("./gate-CGZl0gjJ.cjs");
5
+ require("./list-tools-DCF6G4fn.cjs");
6
6
  let _modelcontextprotocol_sdk_server_zod_compat_js = require("@modelcontextprotocol/sdk/server/zod-compat.js");
7
7
  //#region src/protocols/rest/invoke-tool.ts
8
8
  const MAX_REFLECTED_TOOL_NAME = 256;
@@ -1,8 +1,8 @@
1
1
  import { i as ToolContext, n as errorSummary, r as resolveToolErrorMessage } from "./errors-DSe96Ffd.js";
2
- import { f as methodNotAllowed, l as nowMs, n as createRequestAuthorizer, t as assertRestResourceBinding, u as JSON_HEADERS } from "./authorize-FOlzhxrM.js";
2
+ import { f as methodNotAllowed, l as nowMs, n as createRequestAuthorizer, t as assertRestResourceBinding, u as JSON_HEADERS } from "./authorize--rUeMOGU.js";
3
3
  import { t as extractTextContent } from "./content-D5LJAHyM.js";
4
- import { t as createGatedHandler } from "./gate-BeHmyGxk.js";
5
- import "./list-tools-Dt-mhh52.js";
4
+ import { t as createGatedHandler } from "./gate-BiM6EBeA.js";
5
+ import "./list-tools-BLGr7mot.js";
6
6
  import { getParseErrorMessage, objectFromShape, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
7
7
  //#region src/protocols/rest/invoke-tool.ts
8
8
  const MAX_REFLECTED_TOOL_NAME = 256;
@@ -1,11 +1,11 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_logger = require("../../logger-BkMMCFTv.cjs");
3
- const require_authorize = require("../../authorize-CB35c3Wg.cjs");
2
+ const require_logger = require("../../logger-CN1q-KNn.cjs");
3
+ const require_authorize = require("../../authorize-ChY44o_1.cjs");
4
4
  const require_metadata_path = require("../../metadata-path-zd7NSNoa.cjs");
5
- const require_mcp = require("../../mcp-ECo1Ixk8.cjs");
5
+ const require_mcp = require("../../mcp-CUGwXkxb.cjs");
6
6
  const require_protocols_oauth_metadata = require("../../protocols/oauth-metadata.cjs");
7
- const require_list_tools = require("../../list-tools-DiMCRunS.cjs");
8
- const require_rest = require("../../rest-1Pf9sYNU.cjs");
7
+ const require_list_tools = require("../../list-tools-DCF6G4fn.cjs");
8
+ const require_rest = require("../../rest-BE05MUNS.cjs");
9
9
  const require_forwarded = require("../../forwarded-Bhwcj22u.cjs");
10
10
  const require_paths = require("../../paths-OP318a6c.cjs");
11
11
  //#region src/stacks/supabase/handler.ts
@@ -1,10 +1,10 @@
1
- import { s as trimTrailingSlash } from "../../logger-rGakBvJ1.js";
2
- import { a as assertResourcePathShape, s as createRecorderForRuntime } from "../../authorize-FOlzhxrM.js";
1
+ import { s as trimTrailingSlash } from "../../logger-Ctv5xUSD.js";
2
+ import { a as assertResourcePathShape, s as createRecorderForRuntime } from "../../authorize--rUeMOGU.js";
3
3
  import { t as OAUTH_PROTECTED_RESOURCE_METADATA_PATH } from "../../metadata-path-CAkNcfyY.js";
4
- import { t as createMcpProtocolHandler } from "../../mcp-DiVQhHIw.js";
4
+ import { t as createMcpProtocolHandler } from "../../mcp-Czp-hHjN.js";
5
5
  import { createOAuthProtectedResourceMetadataHandler } from "../../protocols/oauth-metadata.js";
6
- import { n as createListToolsHandler } from "../../list-tools-Dt-mhh52.js";
7
- import { t as createInvokeToolHandler } from "../../rest-Cit2862S.js";
6
+ import { n as createListToolsHandler } from "../../list-tools-BLGr7mot.js";
7
+ import { t as createInvokeToolHandler } from "../../rest-BS7bBOd9.js";
8
8
  import { t as applyForwardedOrigin } from "../../forwarded-BlLF3dfc.js";
9
9
  import { n as assertFunctionName, t as FUNCTIONS_MOUNT_PREFIX } from "../../paths-IS65L6TA.js";
10
10
  //#region src/stacks/supabase/handler.ts
@@ -2,7 +2,7 @@ Object.defineProperties(exports, {
2
2
  __esModule: { value: true },
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
- const require_package = require("../../package-BdaLbzEh.cjs");
5
+ const require_package = require("../../package-CGLPZwz-.cjs");
6
6
  const require_fs_errors = require("../../fs-errors-CWNzOV75.cjs");
7
7
  const require_supabase_config = require("../../supabase-config-Dz7dnUv0.cjs");
8
8
  const require_paths = require("../../paths-OP318a6c.cjs");
@@ -1,4 +1,4 @@
1
- import { t as McpPluginApi } from "../../io-BzTGjG_c.cjs";
1
+ import { t as McpPluginApi } from "../../io-VBHO8YH_.cjs";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/stacks/supabase/vite.d.ts
4
4
  interface McpPluginOptions {
@@ -1,4 +1,4 @@
1
- import { t as McpPluginApi } from "../../io--MeYrWG7.js";
1
+ import { t as McpPluginApi } from "../../io-SMlD5WeX.js";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/stacks/supabase/vite.d.ts
4
4
  interface McpPluginOptions {
@@ -1,4 +1,4 @@
1
- import { t as version } from "../../package-dtiombMt.js";
1
+ import { t as version } from "../../package-DgiA0xuY.js";
2
2
  import { t as isFileMissing } from "../../fs-errors-PA2t1TIp.js";
3
3
  import { t as readSupabaseProjectRef } from "../../supabase-config-CakTU8YF.js";
4
4
  import { n as assertFunctionName, t as FUNCTIONS_MOUNT_PREFIX } from "../../paths-IS65L6TA.js";
@@ -1,9 +1,9 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_authorize = require("../../authorize-CB35c3Wg.cjs");
3
- const require_mcp = require("../../mcp-ECo1Ixk8.cjs");
2
+ const require_authorize = require("../../authorize-ChY44o_1.cjs");
3
+ const require_mcp = require("../../mcp-CUGwXkxb.cjs");
4
4
  const require_protocols_oauth_metadata = require("../../protocols/oauth-metadata.cjs");
5
- const require_list_tools = require("../../list-tools-DiMCRunS.cjs");
6
- const require_rest = require("../../rest-1Pf9sYNU.cjs");
5
+ const require_list_tools = require("../../list-tools-DCF6G4fn.cjs");
6
+ const require_rest = require("../../rest-BE05MUNS.cjs");
7
7
  const require_forwarded = require("../../forwarded-Bhwcj22u.cjs");
8
8
  //#region src/stacks/tanstack/handlers.ts
9
9
  const STACK = "tanstack";
@@ -1,8 +1,8 @@
1
- import { s as createRecorderForRuntime } from "../../authorize-FOlzhxrM.js";
2
- import { t as createMcpProtocolHandler } from "../../mcp-DiVQhHIw.js";
1
+ import { s as createRecorderForRuntime } from "../../authorize--rUeMOGU.js";
2
+ import { t as createMcpProtocolHandler } from "../../mcp-Czp-hHjN.js";
3
3
  import { createOAuthProtectedResourceMetadataHandler } from "../../protocols/oauth-metadata.js";
4
- import { n as createListToolsHandler } from "../../list-tools-Dt-mhh52.js";
5
- import { t as createInvokeToolHandler } from "../../rest-Cit2862S.js";
4
+ import { n as createListToolsHandler } from "../../list-tools-BLGr7mot.js";
5
+ import { t as createInvokeToolHandler } from "../../rest-BS7bBOd9.js";
6
6
  import { t as applyForwardedOrigin } from "../../forwarded-BlLF3dfc.js";
7
7
  //#region src/stacks/tanstack/handlers.ts
8
8
  const STACK = "tanstack";
@@ -1,4 +1,4 @@
1
- import { t as McpPluginApi } from "../../io-BzTGjG_c.cjs";
1
+ import { t as McpPluginApi } from "../../io-VBHO8YH_.cjs";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/stacks/tanstack/vite.d.ts
4
4
  interface McpPluginOptions {
@@ -1,4 +1,4 @@
1
- import { t as McpPluginApi } from "../../io--MeYrWG7.js";
1
+ import { t as McpPluginApi } from "../../io-SMlD5WeX.js";
2
2
  import { Plugin } from "vite";
3
3
  //#region src/stacks/tanstack/vite.d.ts
4
4
  interface McpPluginOptions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/mcp-js",
3
- "version": "0.27.1",
3
+ "version": "0.28.0",
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": {