@lovable.dev/mcp-js 0.21.1-rc.1 → 0.22.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 (87) hide show
  1. package/dist/authorize-BMeXd_Sh.d.ts +25 -0
  2. package/dist/base-CM-KCpp6.d.ts +28 -0
  3. package/dist/chunk-4EHZUUS5.js +141 -0
  4. package/dist/chunk-6DXGZZA4.js +6 -0
  5. package/dist/chunk-6KNM7RGD.js +79 -0
  6. package/dist/chunk-6QFZYYUV.js +11 -0
  7. package/dist/chunk-EOFPMSND.js +6 -0
  8. package/dist/chunk-H37EB22A.js +125 -0
  9. package/dist/chunk-MA5H6PSF.js +46 -0
  10. package/dist/chunk-P43FIUMZ.js +114 -0
  11. package/dist/chunk-RK62EMPY.js +741 -0
  12. package/dist/chunk-RLE4UE63.js +58 -0
  13. package/dist/chunk-UQK5UO6C.js +26 -0
  14. package/dist/chunk-XQWJN6DC.js +14 -0
  15. package/dist/chunk-Y3ZFPEQH.js +8 -0
  16. package/dist/cli/extract-manifest.cjs +201 -116
  17. package/dist/cli/extract-manifest.d.cts +1 -1
  18. package/dist/cli/extract-manifest.d.ts +1 -1
  19. package/dist/cli/extract-manifest.js +156 -117
  20. package/dist/index.cjs +329 -129
  21. package/dist/index.d.cts +26 -26
  22. package/dist/index.d.ts +26 -26
  23. package/dist/index.js +177 -118
  24. package/dist/{io-CS4UL6_A.d.ts → io-D4srzRKc.d.ts} +4 -6
  25. package/dist/protocols/mcp/index.cjs +750 -3
  26. package/dist/protocols/mcp/index.d.cts +7 -6
  27. package/dist/protocols/mcp/index.d.ts +7 -6
  28. package/dist/protocols/mcp/index.js +12 -2
  29. package/dist/protocols/oauth-metadata.cjs +539 -48
  30. package/dist/protocols/oauth-metadata.d.cts +6 -5
  31. package/dist/protocols/oauth-metadata.d.ts +6 -5
  32. package/dist/protocols/oauth-metadata.js +10 -52
  33. package/dist/protocols/rest/index.cjs +843 -5
  34. package/dist/protocols/rest/index.d.cts +10 -7
  35. package/dist/protocols/rest/index.d.ts +10 -7
  36. package/dist/protocols/rest/index.js +16 -3
  37. package/dist/stacks/supabase/index.cjs +1318 -76
  38. package/dist/stacks/supabase/index.d.cts +30 -29
  39. package/dist/stacks/supabase/index.d.ts +30 -29
  40. package/dist/stacks/supabase/index.js +89 -73
  41. package/dist/stacks/supabase/vite.cjs +287 -258
  42. package/dist/stacks/supabase/vite.d.cts +24 -24
  43. package/dist/stacks/supabase/vite.d.ts +24 -24
  44. package/dist/stacks/supabase/vite.js +252 -252
  45. package/dist/stacks/tanstack/index.cjs +1272 -42
  46. package/dist/stacks/tanstack/index.d.cts +9 -8
  47. package/dist/stacks/tanstack/index.d.ts +9 -8
  48. package/dist/stacks/tanstack/index.js +41 -36
  49. package/dist/stacks/tanstack/vite.cjs +312 -223
  50. package/dist/stacks/tanstack/vite.d.cts +81 -80
  51. package/dist/stacks/tanstack/vite.d.ts +81 -80
  52. package/dist/stacks/tanstack/vite.js +282 -216
  53. package/dist/types-qqrmJ736.d.ts +321 -0
  54. package/package.json +28 -71
  55. package/dist/authorize-CumVyk7p.d.cts +0 -27
  56. package/dist/authorize-D6p4-9_D.d.ts +0 -27
  57. package/dist/base-CoIFvAmS.d.cts +0 -26
  58. package/dist/base-CoIFvAmS.d.ts +0 -26
  59. package/dist/content-D5LJAHyM.js +0 -12
  60. package/dist/content-NCYIGgOb.cjs +0 -17
  61. package/dist/context-BweeEcoA.cjs +0 -56
  62. package/dist/context-CIpPzN7P.js +0 -51
  63. package/dist/cors-B7CTXIHD.js +0 -829
  64. package/dist/cors-BebjKPrc.cjs +0 -912
  65. package/dist/forwarded--h4efJy-.js +0 -43
  66. package/dist/forwarded-Pi8Hs5Ps.cjs +0 -48
  67. package/dist/fs-errors-CWNzOV75.cjs +0 -11
  68. package/dist/fs-errors-PA2t1TIp.js +0 -6
  69. package/dist/io-CbbUbPY3.d.cts +0 -15
  70. package/dist/list-tools-CBCuS1Tv.cjs +0 -57
  71. package/dist/list-tools-CsWgiRy1.d.ts +0 -8
  72. package/dist/list-tools-CtZHOuPv.d.cts +0 -8
  73. package/dist/list-tools-D75RGtgs.js +0 -46
  74. package/dist/logger-2OXtfiIW.js +0 -141
  75. package/dist/logger-BqPOa_E1.cjs +0 -194
  76. package/dist/mcp-Cdj0AYst.cjs +0 -123
  77. package/dist/mcp-GngXbcqN.js +0 -118
  78. package/dist/metadata-path-CAkNcfyY.js +0 -12
  79. package/dist/metadata-path-zd7NSNoa.cjs +0 -17
  80. package/dist/package-7EUptuSJ.js +0 -4
  81. package/dist/package-BwCGVRcB.cjs +0 -9
  82. package/dist/paths-IS65L6TA.js +0 -7
  83. package/dist/paths-OP318a6c.cjs +0 -18
  84. package/dist/rest-CXH6-zv9.js +0 -113
  85. package/dist/rest-CyV8LHeB.cjs +0 -118
  86. package/dist/types-BYdYYTjk.d.cts +0 -321
  87. package/dist/types-BYdYYTjk.d.ts +0 -321
@@ -1,43 +0,0 @@
1
- //#region src/core/forwarded.ts
2
- /**
3
- * Rewrites a request's URL to the public origin a reverse proxy forwards via
4
- * `X-Forwarded-*`, so SDK-derived OAuth `resource`/metadata/`WWW-Authenticate`
5
- * URLs name the host the client actually connected to — not the internal
6
- * backend origin the proxy rewrites `Host` to. Without this, an app on a custom
7
- * domain advertises its internal `*.lovable.dev`/`*.supabase.co` host and every
8
- * MCP call 401s on an audience the client can't satisfy.
9
- *
10
- * Each header is trusted independently, because a forwarded value is only as
11
- * trustworthy as the proxy that sets it:
12
- * - `X-Forwarded-Host` can redirect the advertised resource to an attacker
13
- * origin (the threat `auth/resource.ts` guards against), so it is honored only
14
- * when `trustForwardedHost` is set — enabled on emit paths that sit behind a
15
- * proxy which *overwrites* the header (Lovable's web-proxy does), never by a
16
- * bare SDK consumer.
17
- * - `X-Forwarded-Proto` only selects http/https, so it is gated separately:
18
- * Supabase terminates TLS upstream and forwards over http with a
19
- * gateway-stamped proto, so that stack trusts it; the TanStack proxy does not
20
- * sanitize proto, so that stack leaves it alone.
21
- */
22
- function applyForwardedOrigin(request, options) {
23
- const proto = options.trustForwardedProto ? firstForwardedValue(request, "x-forwarded-proto") : void 0;
24
- const host = options.trustForwardedHost ? firstForwardedValue(request, "x-forwarded-host") : void 0;
25
- if (proto === void 0 && host === void 0) return request;
26
- const url = new URL(request.url);
27
- let changed = false;
28
- if (proto !== void 0 && `${proto}:` !== url.protocol) {
29
- url.protocol = `${proto}:`;
30
- changed = true;
31
- }
32
- if (host !== void 0 && host !== url.host) {
33
- url.host = host;
34
- changed = true;
35
- }
36
- return changed ? new Request(url.href, request) : request;
37
- }
38
- function firstForwardedValue(request, header) {
39
- const value = request.headers.get(header)?.split(",")[0]?.trim();
40
- return value ? value : void 0;
41
- }
42
- //#endregion
43
- export { applyForwardedOrigin as t };
@@ -1,48 +0,0 @@
1
- //#region src/core/forwarded.ts
2
- /**
3
- * Rewrites a request's URL to the public origin a reverse proxy forwards via
4
- * `X-Forwarded-*`, so SDK-derived OAuth `resource`/metadata/`WWW-Authenticate`
5
- * URLs name the host the client actually connected to — not the internal
6
- * backend origin the proxy rewrites `Host` to. Without this, an app on a custom
7
- * domain advertises its internal `*.lovable.dev`/`*.supabase.co` host and every
8
- * MCP call 401s on an audience the client can't satisfy.
9
- *
10
- * Each header is trusted independently, because a forwarded value is only as
11
- * trustworthy as the proxy that sets it:
12
- * - `X-Forwarded-Host` can redirect the advertised resource to an attacker
13
- * origin (the threat `auth/resource.ts` guards against), so it is honored only
14
- * when `trustForwardedHost` is set — enabled on emit paths that sit behind a
15
- * proxy which *overwrites* the header (Lovable's web-proxy does), never by a
16
- * bare SDK consumer.
17
- * - `X-Forwarded-Proto` only selects http/https, so it is gated separately:
18
- * Supabase terminates TLS upstream and forwards over http with a
19
- * gateway-stamped proto, so that stack trusts it; the TanStack proxy does not
20
- * sanitize proto, so that stack leaves it alone.
21
- */
22
- function applyForwardedOrigin(request, options) {
23
- const proto = options.trustForwardedProto ? firstForwardedValue(request, "x-forwarded-proto") : void 0;
24
- const host = options.trustForwardedHost ? firstForwardedValue(request, "x-forwarded-host") : void 0;
25
- if (proto === void 0 && host === void 0) return request;
26
- const url = new URL(request.url);
27
- let changed = false;
28
- if (proto !== void 0 && `${proto}:` !== url.protocol) {
29
- url.protocol = `${proto}:`;
30
- changed = true;
31
- }
32
- if (host !== void 0 && host !== url.host) {
33
- url.host = host;
34
- changed = true;
35
- }
36
- return changed ? new Request(url.href, request) : request;
37
- }
38
- function firstForwardedValue(request, header) {
39
- const value = request.headers.get(header)?.split(",")[0]?.trim();
40
- return value ? value : void 0;
41
- }
42
- //#endregion
43
- Object.defineProperty(exports, "applyForwardedOrigin", {
44
- enumerable: true,
45
- get: function() {
46
- return applyForwardedOrigin;
47
- }
48
- });
@@ -1,11 +0,0 @@
1
- //#region src/core/fs-errors.ts
2
- function isFileMissing(err) {
3
- return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
4
- }
5
- //#endregion
6
- Object.defineProperty(exports, "isFileMissing", {
7
- enumerable: true,
8
- get: function() {
9
- return isFileMissing;
10
- }
11
- });
@@ -1,6 +0,0 @@
1
- //#region src/core/fs-errors.ts
2
- function isFileMissing(err) {
3
- return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
4
- }
5
- //#endregion
6
- export { isFileMissing as t };
@@ -1,15 +0,0 @@
1
- import "./list-tools-CtZHOuPv.cjs";
2
- //#region src/manifest/io.d.ts
3
- /**
4
- * Shape every MCP Vite plugin exposes on its `api` so `runExtract` can read
5
- * back the resolved entry path and the URL the stack mounts the MCP server at.
6
- * TanStack sets `urlPath` to the configured route path (default `/mcp`);
7
- * Supabase sets it to `/functions/v1/<functionName>` (the public mount under
8
- * which the function and its companion routes live).
9
- */
10
- interface McpPluginApi {
11
- readonly mcpEntry: string;
12
- readonly urlPath: string;
13
- }
14
- //#endregion
15
- export { McpPluginApi as t };
@@ -1,57 +0,0 @@
1
- const require_cors = require("./cors-BebjKPrc.cjs");
2
- let _modelcontextprotocol_sdk_server_zod_compat_js = require("@modelcontextprotocol/sdk/server/zod-compat.js");
3
- let _modelcontextprotocol_sdk_server_zod_json_schema_compat_js = require("@modelcontextprotocol/sdk/server/zod-json-schema-compat.js");
4
- //#region src/protocols/rest/list-tools.ts
5
- function shapeToJsonSchema(shape) {
6
- if (!shape) return null;
7
- try {
8
- return (0, _modelcontextprotocol_sdk_server_zod_json_schema_compat_js.toJsonSchemaCompat)((0, _modelcontextprotocol_sdk_server_zod_compat_js.objectFromShape)(shape));
9
- } catch {
10
- return null;
11
- }
12
- }
13
- function buildMcpListing(mcp) {
14
- return {
15
- server: {
16
- name: mcp.name,
17
- version: mcp.version,
18
- title: mcp.title
19
- },
20
- tools: mcp.tools.map((tool) => ({
21
- name: tool.name,
22
- title: tool.title,
23
- description: tool.description,
24
- annotations: tool.annotations,
25
- inputSchema: shapeToJsonSchema(tool.inputSchema),
26
- outputSchema: shapeToJsonSchema(tool.outputSchema)
27
- }))
28
- };
29
- }
30
- function createListToolsHandler(mcp, options = {}) {
31
- require_cors.assertRestResourceBinding(mcp, options);
32
- const authorizer = require_cors.createRequestAuthorizer(mcp, options);
33
- const handle = async (request, recorder) => {
34
- const authResult = await authorizer.authorize(request, recorder);
35
- if (!authResult.ok) return authResult.response;
36
- if (request.method !== "GET" && request.method !== "HEAD") return require_cors.methodNotAllowed("GET, HEAD, OPTIONS");
37
- const response = Response.json(buildMcpListing(mcp));
38
- return request.method === "HEAD" ? require_cors.headResponse(response) : response;
39
- };
40
- return async (request, recorder = require_cors.createNoopRecorder()) => {
41
- if (request.method === "OPTIONS") return require_cors.corsPreflightResponse("GET, HEAD, OPTIONS");
42
- return require_cors.withCors(await handle(request, recorder));
43
- };
44
- }
45
- //#endregion
46
- Object.defineProperty(exports, "buildMcpListing", {
47
- enumerable: true,
48
- get: function() {
49
- return buildMcpListing;
50
- }
51
- });
52
- Object.defineProperty(exports, "createListToolsHandler", {
53
- enumerable: true,
54
- get: function() {
55
- return createListToolsHandler;
56
- }
57
- });
@@ -1,8 +0,0 @@
1
- import { c as McpDefinition } from "./types-BYdYYTjk.js";
2
- import { t as MetricsRecorder } from "./base-CoIFvAmS.js";
3
- import { t as McpRuntimeOptions } from "./authorize-D6p4-9_D.js";
4
- //#region src/protocols/rest/list-tools.d.ts
5
- type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
6
- declare function createListToolsHandler(mcp: McpDefinition, options?: McpRuntimeOptions): RestListToolsHandler;
7
- //#endregion
8
- export { createListToolsHandler as n, RestListToolsHandler as t };
@@ -1,8 +0,0 @@
1
- import { c as McpDefinition } from "./types-BYdYYTjk.cjs";
2
- import { t as MetricsRecorder } from "./base-CoIFvAmS.cjs";
3
- import { t as McpRuntimeOptions } from "./authorize-CumVyk7p.cjs";
4
- //#region src/protocols/rest/list-tools.d.ts
5
- type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
6
- declare function createListToolsHandler(mcp: McpDefinition, options?: McpRuntimeOptions): RestListToolsHandler;
7
- //#endregion
8
- export { createListToolsHandler as n, RestListToolsHandler as t };
@@ -1,46 +0,0 @@
1
- import { i as createRequestAuthorizer, m as methodNotAllowed, n as withCors, p as headResponse, r as assertRestResourceBinding, t as corsPreflightResponse, u as createNoopRecorder } from "./cors-B7CTXIHD.js";
2
- import { objectFromShape } from "@modelcontextprotocol/sdk/server/zod-compat.js";
3
- import { toJsonSchemaCompat } from "@modelcontextprotocol/sdk/server/zod-json-schema-compat.js";
4
- //#region src/protocols/rest/list-tools.ts
5
- function shapeToJsonSchema(shape) {
6
- if (!shape) return null;
7
- try {
8
- return toJsonSchemaCompat(objectFromShape(shape));
9
- } catch {
10
- return null;
11
- }
12
- }
13
- function buildMcpListing(mcp) {
14
- return {
15
- server: {
16
- name: mcp.name,
17
- version: mcp.version,
18
- title: mcp.title
19
- },
20
- tools: mcp.tools.map((tool) => ({
21
- name: tool.name,
22
- title: tool.title,
23
- description: tool.description,
24
- annotations: tool.annotations,
25
- inputSchema: shapeToJsonSchema(tool.inputSchema),
26
- outputSchema: shapeToJsonSchema(tool.outputSchema)
27
- }))
28
- };
29
- }
30
- function createListToolsHandler(mcp, options = {}) {
31
- assertRestResourceBinding(mcp, options);
32
- const authorizer = createRequestAuthorizer(mcp, options);
33
- const handle = async (request, recorder) => {
34
- const authResult = await authorizer.authorize(request, recorder);
35
- if (!authResult.ok) return authResult.response;
36
- if (request.method !== "GET" && request.method !== "HEAD") return methodNotAllowed("GET, HEAD, OPTIONS");
37
- const response = Response.json(buildMcpListing(mcp));
38
- return request.method === "HEAD" ? headResponse(response) : response;
39
- };
40
- return async (request, recorder = createNoopRecorder()) => {
41
- if (request.method === "OPTIONS") return corsPreflightResponse("GET, HEAD, OPTIONS");
42
- return withCors(await handle(request, recorder));
43
- };
44
- }
45
- //#endregion
46
- export { createListToolsHandler as n, buildMcpListing as t };
@@ -1,141 +0,0 @@
1
- //#region src/metrics/config.ts
2
- const DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
3
- const METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
4
- /**
5
- * Validate the ingest endpoint at plugin-construction time so a malformed URL
6
- * fails the build rather than silently dropping every batch at runtime.
7
- */
8
- function assertMetricsEndpoint(endpoint) {
9
- let url;
10
- try {
11
- url = new URL(endpoint);
12
- } catch {
13
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
14
- }
15
- if (url.protocol !== "https:" && url.protocol !== "http:") throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
16
- }
17
- /**
18
- * Resolve `boolean | MetricsOptions` into a frozen config. Telemetry is on by
19
- * default and self-disables at runtime when `LOVABLE_API_KEY` is absent (so a
20
- * local `vite dev` stays silent); pass `false` to opt out entirely.
21
- */
22
- function resolveMetricsConfig(config = true) {
23
- const options = typeof config === "boolean" ? { enabled: config } : config;
24
- const endpoint = options.endpoint ?? "https://api.lovable.dev/v1/app-mcp-usage";
25
- assertMetricsEndpoint(endpoint);
26
- return Object.freeze({
27
- enabled: options.enabled ?? true,
28
- endpoint,
29
- headers: options.headers ?? {},
30
- apiKeyEnvVar: METRICS_API_KEY_ENV_VAR
31
- });
32
- }
33
- //#endregion
34
- //#region src/core/url.ts
35
- function trimTrailingSlash(value) {
36
- return value.replace(/\/+$/, "");
37
- }
38
- function isLocalHTTPHost(hostname) {
39
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
40
- }
41
- /**
42
- * Shared scheme/credential/query checks for every absolute URL we accept or
43
- * discover. Returns the human-readable problem suffix so each call site can
44
- * prefix it with its own subject and throw its own error type.
45
- */
46
- function urlSafetyProblem(url) {
47
- const isAllowedHTTP = url.protocol === "http:" && isLocalHTTPHost(url.hostname);
48
- if (url.protocol !== "https:" && !isAllowedHTTP) return "must use https://, except localhost development URLs";
49
- if (url.username || url.password) return "must not include credentials";
50
- if (url.search || url.hash) return "must not include query or fragment";
51
- }
52
- //#endregion
53
- //#region src/core/validation.ts
54
- /**
55
- * Parse `raw` as an absolute URL and reject unsafe shapes (non-HTTPS except
56
- * localhost, embedded credentials, query/fragment). `subject` is the
57
- * fully-formed message prefix (e.g. `auth.issuer`, `managed OAuth issuer`) so
58
- * each call site keeps its own wording; `ErrorClass` selects the thrown type.
59
- */
60
- function parseSafeUrl(subject, raw, ErrorClass = Error) {
61
- let url;
62
- try {
63
- url = new URL(raw);
64
- } catch {
65
- throw new ErrorClass(`${subject} must be an absolute URL`);
66
- }
67
- const problem = urlSafetyProblem(url);
68
- if (problem) throw new ErrorClass(`${subject} ${problem}`);
69
- return url;
70
- }
71
- //#endregion
72
- //#region src/core/logger.ts
73
- const LEVEL_RANK = {
74
- silent: 0,
75
- error: 1,
76
- warn: 2,
77
- info: 3,
78
- debug: 4
79
- };
80
- function isLogLevel(value) {
81
- return typeof value === "string" && value in LEVEL_RANK;
82
- }
83
- const LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
84
- function readEnvLevel() {
85
- try {
86
- const normalized = (typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0)?.trim().toLowerCase();
87
- return isLogLevel(normalized) ? normalized : void 0;
88
- } catch {
89
- return;
90
- }
91
- }
92
- let currentLevel = readEnvLevel() ?? "debug";
93
- /**
94
- * Set the runtime log level programmatically. Use this when the deployment can't
95
- * surface `LOVABLE_MCP_LOG_LEVEL` to the package (e.g. a Cloudflare Worker that
96
- * passes vars via bindings): call `setLogLevel("debug")` once at server startup.
97
- */
98
- function setLogLevel(level) {
99
- currentLevel = level;
100
- }
101
- /** Parse an env value into a LogLevel, or undefined if it names no valid level. */
102
- function parseLogLevel(raw) {
103
- const normalized = raw?.trim().toLowerCase();
104
- return isLogLevel(normalized) ? normalized : void 0;
105
- }
106
- /**
107
- * Apply the log level from an env value: use it when it names a valid level,
108
- * otherwise fall back to `debug` so the SDK's diagnostics are on by default.
109
- */
110
- function applyLogLevelFromEnv(raw) {
111
- setLogLevel(parseLogLevel(raw) ?? "debug");
112
- }
113
- function enabled(level) {
114
- return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
115
- }
116
- function emit(level, method, event, fields) {
117
- if (!enabled(level)) return;
118
- const message = `[mcp-js] ${event}`;
119
- if (fields) console[method](message, fields);
120
- else console[method](message);
121
- }
122
- const log = {
123
- error: (event, fields) => emit("error", "error", event, fields),
124
- warn: (event, fields) => emit("warn", "warn", event, fields),
125
- info: (event, fields) => emit("info", "info", event, fields),
126
- debug: (event, fields) => emit("debug", "debug", event, fields)
127
- };
128
- /** Non-secret error shape for logs: name, message, and a string `code` (jose carries one) when present. */
129
- function describeError(err) {
130
- if (err instanceof Error) {
131
- const code = err.code;
132
- return {
133
- name: err.name,
134
- message: err.message,
135
- ...typeof code === "string" ? { code } : {}
136
- };
137
- }
138
- return { value: String(err) };
139
- }
140
- //#endregion
141
- export { setLogLevel as a, DEFAULT_METRICS_ENDPOINT as c, log as i, resolveMetricsConfig as l, applyLogLevelFromEnv as n, parseSafeUrl as o, describeError as r, trimTrailingSlash as s, LOG_LEVEL_ENV_VAR as t };
@@ -1,194 +0,0 @@
1
- //#region src/metrics/config.ts
2
- const DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
3
- const METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
4
- /**
5
- * Validate the ingest endpoint at plugin-construction time so a malformed URL
6
- * fails the build rather than silently dropping every batch at runtime.
7
- */
8
- function assertMetricsEndpoint(endpoint) {
9
- let url;
10
- try {
11
- url = new URL(endpoint);
12
- } catch {
13
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
14
- }
15
- if (url.protocol !== "https:" && url.protocol !== "http:") throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
16
- }
17
- /**
18
- * Resolve `boolean | MetricsOptions` into a frozen config. Telemetry is on by
19
- * default and self-disables at runtime when `LOVABLE_API_KEY` is absent (so a
20
- * local `vite dev` stays silent); pass `false` to opt out entirely.
21
- */
22
- function resolveMetricsConfig(config = true) {
23
- const options = typeof config === "boolean" ? { enabled: config } : config;
24
- const endpoint = options.endpoint ?? "https://api.lovable.dev/v1/app-mcp-usage";
25
- assertMetricsEndpoint(endpoint);
26
- return Object.freeze({
27
- enabled: options.enabled ?? true,
28
- endpoint,
29
- headers: options.headers ?? {},
30
- apiKeyEnvVar: METRICS_API_KEY_ENV_VAR
31
- });
32
- }
33
- //#endregion
34
- //#region src/core/url.ts
35
- function trimTrailingSlash(value) {
36
- return value.replace(/\/+$/, "");
37
- }
38
- function isLocalHTTPHost(hostname) {
39
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
40
- }
41
- /**
42
- * Shared scheme/credential/query checks for every absolute URL we accept or
43
- * discover. Returns the human-readable problem suffix so each call site can
44
- * prefix it with its own subject and throw its own error type.
45
- */
46
- function urlSafetyProblem(url) {
47
- const isAllowedHTTP = url.protocol === "http:" && isLocalHTTPHost(url.hostname);
48
- if (url.protocol !== "https:" && !isAllowedHTTP) return "must use https://, except localhost development URLs";
49
- if (url.username || url.password) return "must not include credentials";
50
- if (url.search || url.hash) return "must not include query or fragment";
51
- }
52
- //#endregion
53
- //#region src/core/validation.ts
54
- /**
55
- * Parse `raw` as an absolute URL and reject unsafe shapes (non-HTTPS except
56
- * localhost, embedded credentials, query/fragment). `subject` is the
57
- * fully-formed message prefix (e.g. `auth.issuer`, `managed OAuth issuer`) so
58
- * each call site keeps its own wording; `ErrorClass` selects the thrown type.
59
- */
60
- function parseSafeUrl(subject, raw, ErrorClass = Error) {
61
- let url;
62
- try {
63
- url = new URL(raw);
64
- } catch {
65
- throw new ErrorClass(`${subject} must be an absolute URL`);
66
- }
67
- const problem = urlSafetyProblem(url);
68
- if (problem) throw new ErrorClass(`${subject} ${problem}`);
69
- return url;
70
- }
71
- //#endregion
72
- //#region src/core/logger.ts
73
- const LEVEL_RANK = {
74
- silent: 0,
75
- error: 1,
76
- warn: 2,
77
- info: 3,
78
- debug: 4
79
- };
80
- function isLogLevel(value) {
81
- return typeof value === "string" && value in LEVEL_RANK;
82
- }
83
- const LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
84
- function readEnvLevel() {
85
- try {
86
- const normalized = (typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0)?.trim().toLowerCase();
87
- return isLogLevel(normalized) ? normalized : void 0;
88
- } catch {
89
- return;
90
- }
91
- }
92
- let currentLevel = readEnvLevel() ?? "debug";
93
- /**
94
- * Set the runtime log level programmatically. Use this when the deployment can't
95
- * surface `LOVABLE_MCP_LOG_LEVEL` to the package (e.g. a Cloudflare Worker that
96
- * passes vars via bindings): call `setLogLevel("debug")` once at server startup.
97
- */
98
- function setLogLevel(level) {
99
- currentLevel = level;
100
- }
101
- /** Parse an env value into a LogLevel, or undefined if it names no valid level. */
102
- function parseLogLevel(raw) {
103
- const normalized = raw?.trim().toLowerCase();
104
- return isLogLevel(normalized) ? normalized : void 0;
105
- }
106
- /**
107
- * Apply the log level from an env value: use it when it names a valid level,
108
- * otherwise fall back to `debug` so the SDK's diagnostics are on by default.
109
- */
110
- function applyLogLevelFromEnv(raw) {
111
- setLogLevel(parseLogLevel(raw) ?? "debug");
112
- }
113
- function enabled(level) {
114
- return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
115
- }
116
- function emit(level, method, event, fields) {
117
- if (!enabled(level)) return;
118
- const message = `[mcp-js] ${event}`;
119
- if (fields) console[method](message, fields);
120
- else console[method](message);
121
- }
122
- const log = {
123
- error: (event, fields) => emit("error", "error", event, fields),
124
- warn: (event, fields) => emit("warn", "warn", event, fields),
125
- info: (event, fields) => emit("info", "info", event, fields),
126
- debug: (event, fields) => emit("debug", "debug", event, fields)
127
- };
128
- /** Non-secret error shape for logs: name, message, and a string `code` (jose carries one) when present. */
129
- function describeError(err) {
130
- if (err instanceof Error) {
131
- const code = err.code;
132
- return {
133
- name: err.name,
134
- message: err.message,
135
- ...typeof code === "string" ? { code } : {}
136
- };
137
- }
138
- return { value: String(err) };
139
- }
140
- //#endregion
141
- Object.defineProperty(exports, "DEFAULT_METRICS_ENDPOINT", {
142
- enumerable: true,
143
- get: function() {
144
- return DEFAULT_METRICS_ENDPOINT;
145
- }
146
- });
147
- Object.defineProperty(exports, "LOG_LEVEL_ENV_VAR", {
148
- enumerable: true,
149
- get: function() {
150
- return LOG_LEVEL_ENV_VAR;
151
- }
152
- });
153
- Object.defineProperty(exports, "applyLogLevelFromEnv", {
154
- enumerable: true,
155
- get: function() {
156
- return applyLogLevelFromEnv;
157
- }
158
- });
159
- Object.defineProperty(exports, "describeError", {
160
- enumerable: true,
161
- get: function() {
162
- return describeError;
163
- }
164
- });
165
- Object.defineProperty(exports, "log", {
166
- enumerable: true,
167
- get: function() {
168
- return log;
169
- }
170
- });
171
- Object.defineProperty(exports, "parseSafeUrl", {
172
- enumerable: true,
173
- get: function() {
174
- return parseSafeUrl;
175
- }
176
- });
177
- Object.defineProperty(exports, "resolveMetricsConfig", {
178
- enumerable: true,
179
- get: function() {
180
- return resolveMetricsConfig;
181
- }
182
- });
183
- Object.defineProperty(exports, "setLogLevel", {
184
- enumerable: true,
185
- get: function() {
186
- return setLogLevel;
187
- }
188
- });
189
- Object.defineProperty(exports, "trimTrailingSlash", {
190
- enumerable: true,
191
- get: function() {
192
- return trimTrailingSlash;
193
- }
194
- });