@lovable.dev/mcp-js 2.0.0 → 2.0.1

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.
package/README.md CHANGED
@@ -228,9 +228,19 @@ The request-derived `resource` default trusts the incoming `Host` to name this s
228
228
 
229
229
  Use `auth.oauth.issuer(...)`, set `resource` or `acceptedAudiences` to anchor the accepted audience, and optionally set `jwksUri` and `requiredScopes`. For Supabase project auth, set `acceptedAudiences: "authenticated"`, keep app/business checks in app code, and forward `ctx.getToken()` to Supabase for RLS-backed data access.
230
230
 
231
+ ## Security posture
232
+
233
+ For anyone evaluating an app that exposes an MCP server with this package:
234
+
235
+ - **Verification runs in the app runtime.** When `defineMcp({ auth })` configures OAuth, the emitted TanStack route or Supabase Edge Function verifies the bearer before dispatching a tool. Clients call the app's published endpoint; the SDK does not relay MCP calls through a shared Lovable MCP protocol gateway, although a Lovable-hosted TanStack app still receives ordinary web traffic through Lovable's hosting proxy. The SDK may fetch issuer metadata and JWKS. When default usage telemetry is emitted, it sends the operational fields described below, including the verified token `sub`; it never sends the bearer, full claims, tool arguments, or tool results.
236
+ - **No protocol sessions.** Every HTTP request gets a fresh MCP server, auth context, and tool callback closure. The endpoint never mints a session ID or retains MCP protocol or auth session state across requests. Durable application state belongs in the app's own storage.
237
+ - **Audience validation is explicit.** A populated token `aud` must exactly match `resource` or `acceptedAudiences`. For issuer compatibility, the default also accepts a matching `resource` claim when `aud` is absent or an empty array; set `acceptResourceClaim: false` to require a matching `aud` (strict RFC 9068).
238
+ - **The deployment controls the SDK version.** TanStack resolves the app's declared dependency through its package manager and lockfile. The generated Supabase function exact-pins the SDK release that emitted it. Updating or regenerating the dependency and redeploying is how an app adopts a newer SDK.
239
+ - **Controls are divided between layers.** When OAuth is configured, the SDK owns bearer verification; it also owns origin policy (`allowedOrigins`) and redacts unexpected errors. `ToolError` and returned `isError` results are intentionally caller-visible. Per-tool authorization, data access (including RLS), rate limiting, and WAF belong to the app and its host.
240
+
231
241
  ## Debug logging
232
242
 
233
- 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.
243
+ 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 or full claims**. Depending on the log level, operational fields include the JWT header `alg`/`kid`, `issuer`, `jwks_uri`, token scopes, and `jose` error codes. The default `info` level excludes end-user identifiers; the token `sub`/`client_id` appears only at `debug`, as the `oauth.verify.principal` event.
234
244
 
235
245
  Enable it either way:
236
246
 
@@ -251,7 +261,7 @@ A `500` on an OAuth-protected route is always one of two causes, logged at `erro
251
261
 
252
262
  ## Usage metrics
253
263
 
254
- 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`), 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 — and `origin_rejected` for a request refused `403` by the origin policy. Tool-call records also carry the protocol era (`mcp.protocol`: `2026-07-28` or `legacy`); records emitted before protocol classification (auth challenges, transport errors, origin rejections) have no protocol attribute. 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).
264
+ Each MCP server records per-invocation telemetry — tool name, JSON-RPC method, outcome, latency, request and response sizes when available, and the verified token `sub` for authenticated calls — 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`), 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 — and `origin_rejected` for a request refused `403` by the origin policy. Tool-call records also carry the protocol era (`mcp.protocol`: `2026-07-28` or `legacy`); records emitted before protocol classification (auth challenges, transport errors, origin rejections) have no protocol attribute. The bearer token, full claims, tool arguments, and response payloads are never 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).
255
265
 
256
266
  Configure it on the MCP definition:
257
267
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  const require_schema = require("../schema-D3vClxb7.cjs");
3
- const require_package = require("../package-RqZMyBY1.cjs");
3
+ const require_package = require("../package-D8nZVoHm.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
2
  import { t as jsonSchemaFromDefinition } from "../schema-CW1jKvio.js";
3
- import { t as version } from "../package-CZERyrAn.js";
3
+ import { t as version } from "../package-DSwNopNG.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,5 +1,5 @@
1
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-CZERyrAn.js";
2
+ import { t as version } from "./package-DSwNopNG.js";
3
3
  import "./metadata-path-CAkNcfyY.js";
4
4
  import { createLocalJWKSet, decodeProtectedHeader, errors, jwtVerify } from "jose";
5
5
  //#region src/core/http.ts
@@ -1,5 +1,5 @@
1
1
  const require_logger = require("./logger-CN1q-KNn.cjs");
2
- const require_package = require("./package-RqZMyBY1.cjs");
2
+ const require_package = require("./package-D8nZVoHm.cjs");
3
3
  require("./metadata-path-zd7NSNoa.cjs");
4
4
  let jose = require("jose");
5
5
  //#region src/core/http.ts
@@ -1,7 +1,7 @@
1
1
  const require_logger = require("./logger-CN1q-KNn.cjs");
2
2
  const require_schema = require("./schema-D3vClxb7.cjs");
3
3
  const require_errors = require("./errors-Cr95rSkB.cjs");
4
- const require_cors = require("./cors-aOILwe5U.cjs");
4
+ const require_cors = require("./cors-BvJ-XM16.cjs");
5
5
  let _modelcontextprotocol_sdk_server_zod_compat_js = require("@modelcontextprotocol/sdk/server/zod-compat.js");
6
6
  let _modelcontextprotocol_server = require("@modelcontextprotocol/server");
7
7
  //#region src/core/content.ts
@@ -1,7 +1,7 @@
1
1
  import { i as log, r as describeError } from "./logger-Ctv5xUSD.js";
2
2
  import { n as schemaFromDefinition, t as jsonSchemaFromDefinition } from "./schema-CW1jKvio.js";
3
3
  import { i as ToolContext, n as errorSummary, r as resolveToolErrorMessage } from "./errors-Bwd1L0Rf.js";
4
- import { f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, n as createRequestAuthorizer, t as evaluateCors, u as nowMs } from "./cors-Bb8_NLEB.js";
4
+ import { f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, n as createRequestAuthorizer, t as evaluateCors, u as nowMs } from "./cors-BLWQyVL5.js";
5
5
  import { getParseErrorMessage, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
6
6
  import { CLIENT_CAPABILITIES_META_KEY, CLIENT_INFO_META_KEY, McpServer, createMcpHandler } from "@modelcontextprotocol/server";
7
7
  //#region src/core/content.ts
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "2.0.0";
2
+ var version = "2.0.1";
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 = "2.0.0";
2
+ var version = "2.0.1";
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-Bbl8sdkl.cjs");
2
+ const require_mcp = require("../../mcp-BsvVuQvW.cjs");
3
3
  exports.createMcpProtocolHandler = require_mcp.createMcpProtocolHandler;
@@ -1,2 +1,2 @@
1
- import { t as createMcpProtocolHandler } from "../../mcp-B1hj8ZPg.js";
1
+ import { t as createMcpProtocolHandler } from "../../mcp-CMph8_rD.js";
2
2
  export { createMcpProtocolHandler };
@@ -1,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_logger = require("../logger-CN1q-KNn.cjs");
3
- const require_cors = require("../cors-aOILwe5U.cjs");
3
+ const require_cors = require("../cors-BvJ-XM16.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
1
  import { i as log, r as describeError } from "../logger-Ctv5xUSD.js";
2
- import { a as oauthConfigurationErrorResponse, d as JSON_HEADERS, f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, p as methodNotAllowed, r as getOAuthRuntime, s as resolveProtectedResource, t as evaluateCors } from "../cors-Bb8_NLEB.js";
2
+ import { a as oauthConfigurationErrorResponse, d as JSON_HEADERS, f as finalizeWireResponse, i as normalizeHttpMethod, l as createNoopRecorder, p as methodNotAllowed, r as getOAuthRuntime, s as resolveProtectedResource, t as evaluateCors } from "../cors-BLWQyVL5.js";
3
3
  //#region src/protocols/oauth-metadata.ts
4
4
  function notFound() {
5
5
  return new Response(JSON.stringify({ error: "not found" }), {
@@ -1,8 +1,8 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_logger = require("../../logger-CN1q-KNn.cjs");
3
- const require_cors = require("../../cors-aOILwe5U.cjs");
3
+ const require_cors = require("../../cors-BvJ-XM16.cjs");
4
4
  const require_metadata_path = require("../../metadata-path-zd7NSNoa.cjs");
5
- const require_mcp = require("../../mcp-Bbl8sdkl.cjs");
5
+ const require_mcp = require("../../mcp-BsvVuQvW.cjs");
6
6
  const require_protocols_oauth_metadata = require("../../protocols/oauth-metadata.cjs");
7
7
  const require_forwarded = require("../../forwarded-B37IdmMX.cjs");
8
8
  const require_paths = require("../../paths-OP318a6c.cjs");
@@ -1,7 +1,7 @@
1
1
  import { s as trimTrailingSlash } from "../../logger-Ctv5xUSD.js";
2
- import { c as createRecorderForRuntime, o as assertResourcePathShape } from "../../cors-Bb8_NLEB.js";
2
+ import { c as createRecorderForRuntime, o as assertResourcePathShape } from "../../cors-BLWQyVL5.js";
3
3
  import { t as OAUTH_PROTECTED_RESOURCE_METADATA_PATH } from "../../metadata-path-CAkNcfyY.js";
4
- import { t as createMcpProtocolHandler } from "../../mcp-B1hj8ZPg.js";
4
+ import { t as createMcpProtocolHandler } from "../../mcp-CMph8_rD.js";
5
5
  import { createOAuthProtectedResourceMetadataHandler } from "../../protocols/oauth-metadata.js";
6
6
  import { t as applyForwardedOrigin } from "../../forwarded-BBXvFeh6.js";
7
7
  import { n as assertFunctionName, t as FUNCTIONS_MOUNT_PREFIX } from "../../paths-IS65L6TA.js";
@@ -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-RqZMyBY1.cjs");
5
+ const require_package = require("../../package-D8nZVoHm.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 version } from "../../package-CZERyrAn.js";
1
+ import { t as version } from "../../package-DSwNopNG.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,6 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_cors = require("../../cors-aOILwe5U.cjs");
3
- const require_mcp = require("../../mcp-Bbl8sdkl.cjs");
2
+ const require_cors = require("../../cors-BvJ-XM16.cjs");
3
+ const require_mcp = require("../../mcp-BsvVuQvW.cjs");
4
4
  const require_protocols_oauth_metadata = require("../../protocols/oauth-metadata.cjs");
5
5
  const require_forwarded = require("../../forwarded-B37IdmMX.cjs");
6
6
  //#region src/stacks/tanstack/handlers.ts
@@ -1,5 +1,5 @@
1
- import { c as createRecorderForRuntime } from "../../cors-Bb8_NLEB.js";
2
- import { t as createMcpProtocolHandler } from "../../mcp-B1hj8ZPg.js";
1
+ import { c as createRecorderForRuntime } from "../../cors-BLWQyVL5.js";
2
+ import { t as createMcpProtocolHandler } from "../../mcp-CMph8_rD.js";
3
3
  import { createOAuthProtectedResourceMetadataHandler } from "../../protocols/oauth-metadata.js";
4
4
  import { t as applyForwardedOrigin } from "../../forwarded-BBXvFeh6.js";
5
5
  //#region src/stacks/tanstack/handlers.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/mcp-js",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },