@lovable.dev/mcp-js 0.21.0 → 0.21.1-rc.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.
Files changed (86) hide show
  1. package/dist/authorize-CumVyk7p.d.cts +27 -0
  2. package/dist/authorize-D6p4-9_D.d.ts +27 -0
  3. package/dist/{base-CFy5vZ5Z.d.ts → base-CoIFvAmS.d.cts} +15 -14
  4. package/dist/base-CoIFvAmS.d.ts +26 -0
  5. package/dist/cli/extract-manifest.cjs +116 -201
  6. package/dist/cli/extract-manifest.d.cts +1 -1
  7. package/dist/cli/extract-manifest.d.ts +1 -1
  8. package/dist/cli/extract-manifest.js +117 -156
  9. package/dist/content-D5LJAHyM.js +12 -0
  10. package/dist/content-NCYIGgOb.cjs +17 -0
  11. package/dist/context-BweeEcoA.cjs +56 -0
  12. package/dist/context-CIpPzN7P.js +51 -0
  13. package/dist/cors-B7CTXIHD.js +829 -0
  14. package/dist/cors-BebjKPrc.cjs +912 -0
  15. package/dist/forwarded--h4efJy-.js +43 -0
  16. package/dist/forwarded-Pi8Hs5Ps.cjs +48 -0
  17. package/dist/fs-errors-CWNzOV75.cjs +11 -0
  18. package/dist/fs-errors-PA2t1TIp.js +6 -0
  19. package/dist/index.cjs +129 -329
  20. package/dist/index.d.cts +26 -26
  21. package/dist/index.d.ts +26 -26
  22. package/dist/index.js +118 -177
  23. package/dist/{io-D4srzRKc.d.ts → io-CS4UL6_A.d.ts} +6 -4
  24. package/dist/io-CbbUbPY3.d.cts +15 -0
  25. package/dist/list-tools-CBCuS1Tv.cjs +57 -0
  26. package/dist/list-tools-CsWgiRy1.d.ts +8 -0
  27. package/dist/list-tools-CtZHOuPv.d.cts +8 -0
  28. package/dist/list-tools-D75RGtgs.js +46 -0
  29. package/dist/logger-2OXtfiIW.js +141 -0
  30. package/dist/logger-BqPOa_E1.cjs +194 -0
  31. package/dist/mcp-Cdj0AYst.cjs +123 -0
  32. package/dist/mcp-GngXbcqN.js +118 -0
  33. package/dist/metadata-path-CAkNcfyY.js +12 -0
  34. package/dist/metadata-path-zd7NSNoa.cjs +17 -0
  35. package/dist/package-7EUptuSJ.js +4 -0
  36. package/dist/package-BwCGVRcB.cjs +9 -0
  37. package/dist/paths-IS65L6TA.js +7 -0
  38. package/dist/paths-OP318a6c.cjs +18 -0
  39. package/dist/protocols/mcp/index.cjs +3 -740
  40. package/dist/protocols/mcp/index.d.cts +6 -7
  41. package/dist/protocols/mcp/index.d.ts +6 -7
  42. package/dist/protocols/mcp/index.js +2 -12
  43. package/dist/protocols/oauth-metadata.cjs +48 -539
  44. package/dist/protocols/oauth-metadata.d.cts +5 -6
  45. package/dist/protocols/oauth-metadata.d.ts +5 -6
  46. package/dist/protocols/oauth-metadata.js +52 -10
  47. package/dist/protocols/rest/index.cjs +5 -839
  48. package/dist/protocols/rest/index.d.cts +7 -10
  49. package/dist/protocols/rest/index.d.ts +7 -10
  50. package/dist/protocols/rest/index.js +3 -16
  51. package/dist/rest-CXH6-zv9.js +113 -0
  52. package/dist/rest-CyV8LHeB.cjs +118 -0
  53. package/dist/stacks/supabase/index.cjs +76 -1302
  54. package/dist/stacks/supabase/index.d.cts +29 -30
  55. package/dist/stacks/supabase/index.d.ts +29 -30
  56. package/dist/stacks/supabase/index.js +73 -89
  57. package/dist/stacks/supabase/vite.cjs +258 -287
  58. package/dist/stacks/supabase/vite.d.cts +24 -24
  59. package/dist/stacks/supabase/vite.d.ts +24 -24
  60. package/dist/stacks/supabase/vite.js +252 -252
  61. package/dist/stacks/tanstack/index.cjs +42 -1256
  62. package/dist/stacks/tanstack/index.d.cts +8 -9
  63. package/dist/stacks/tanstack/index.d.ts +8 -9
  64. package/dist/stacks/tanstack/index.js +36 -41
  65. package/dist/stacks/tanstack/vite.cjs +223 -312
  66. package/dist/stacks/tanstack/vite.d.cts +80 -81
  67. package/dist/stacks/tanstack/vite.d.ts +80 -81
  68. package/dist/stacks/tanstack/vite.js +216 -282
  69. package/dist/types-BYdYYTjk.d.cts +321 -0
  70. package/dist/types-BYdYYTjk.d.ts +321 -0
  71. package/package.json +71 -28
  72. package/dist/authorize-BMeXd_Sh.d.ts +0 -25
  73. package/dist/chunk-6DXGZZA4.js +0 -6
  74. package/dist/chunk-6QFZYYUV.js +0 -11
  75. package/dist/chunk-CI7JYLV3.js +0 -104
  76. package/dist/chunk-E3Q3FRKQ.js +0 -6
  77. package/dist/chunk-ENJDNFEB.js +0 -79
  78. package/dist/chunk-H37EB22A.js +0 -125
  79. package/dist/chunk-LFXK3FNF.js +0 -58
  80. package/dist/chunk-MA5H6PSF.js +0 -46
  81. package/dist/chunk-QPKPYDPB.js +0 -137
  82. package/dist/chunk-UQK5UO6C.js +0 -26
  83. package/dist/chunk-XQWJN6DC.js +0 -14
  84. package/dist/chunk-Y3ZFPEQH.js +0 -8
  85. package/dist/chunk-YLU2JTHL.js +0 -739
  86. package/dist/types-qqrmJ736.d.ts +0 -321
@@ -0,0 +1,141 @@
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 };
@@ -0,0 +1,194 @@
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
+ });
@@ -0,0 +1,123 @@
1
+ const require_logger = require("./logger-BqPOa_E1.cjs");
2
+ const require_context = require("./context-BweeEcoA.cjs");
3
+ const require_cors = require("./cors-BebjKPrc.cjs");
4
+ const require_content = require("./content-NCYIGgOb.cjs");
5
+ let _modelcontextprotocol_sdk_server_mcp_js = require("@modelcontextprotocol/sdk/server/mcp.js");
6
+ let _modelcontextprotocol_sdk_server_webStandardStreamableHttp_js = require("@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js");
7
+ //#region src/protocols/mcp/protocol.ts
8
+ /**
9
+ * Adapt a Lovable tool to the SDK's tool callback. The boundary cast bridges
10
+ * our SDK-decoupled content-block types to the SDK's; they match structurally.
11
+ */
12
+ function adaptToolToSdkCallback(tool, auth, recorder) {
13
+ return (async (first) => {
14
+ const args = tool.inputSchema ? first ?? {} : {};
15
+ const start = require_cors.nowMs();
16
+ let result;
17
+ try {
18
+ result = await tool.handler(args, new require_context.ToolContext(auth));
19
+ } catch {
20
+ await recorder.emit({
21
+ tool: tool.name,
22
+ method: "tools/call",
23
+ outcome: "handler_error",
24
+ durationMs: require_cors.nowMs() - start
25
+ });
26
+ return {
27
+ content: [{
28
+ type: "text",
29
+ text: "tool execution failed"
30
+ }],
31
+ isError: true
32
+ };
33
+ }
34
+ if (result == null) {
35
+ await recorder.emit({
36
+ tool: tool.name,
37
+ method: "tools/call",
38
+ outcome: "handler_error",
39
+ durationMs: require_cors.nowMs() - start
40
+ });
41
+ return {
42
+ content: [{
43
+ type: "text",
44
+ text: `tool "${tool.name}" returned no result`
45
+ }],
46
+ isError: true
47
+ };
48
+ }
49
+ await recorder.emit({
50
+ tool: tool.name,
51
+ method: "tools/call",
52
+ outcome: result.isError ? "tool_error" : "ok",
53
+ durationMs: require_cors.nowMs() - start,
54
+ errorText: result.isError ? require_content.extractTextContent(result.content) : void 0
55
+ });
56
+ return {
57
+ content: result.content ?? [],
58
+ structuredContent: result.structuredContent,
59
+ isError: result.isError
60
+ };
61
+ });
62
+ }
63
+ /**
64
+ * Build a Web-Standard request handler that serves the MCP protocol over
65
+ * streamable HTTP. A fresh `McpServer` + transport is constructed per
66
+ * request — the transport is stateless, so this is cheap and there is no
67
+ * cross-request state to leak. The per-request `recorder` is supplied by the
68
+ * caller (the stack handler) so telemetry reads the runtime env in-flight.
69
+ */
70
+ function createMcpProtocolHandler(mcp, options = {}) {
71
+ const authorizer = require_cors.createRequestAuthorizer(mcp, options);
72
+ const handle = async (request, recorder) => {
73
+ const authResult = await authorizer.authorize(request, recorder);
74
+ if (!authResult.ok) return authResult.response;
75
+ try {
76
+ const server = new _modelcontextprotocol_sdk_server_mcp_js.McpServer({
77
+ name: mcp.name,
78
+ version: mcp.version,
79
+ title: mcp.title
80
+ }, { instructions: mcp.instructions });
81
+ for (const tool of mcp.tools) server.registerTool(tool.name, {
82
+ title: tool.title,
83
+ description: tool.description,
84
+ inputSchema: tool.inputSchema,
85
+ outputSchema: tool.outputSchema,
86
+ annotations: tool.annotations
87
+ }, adaptToolToSdkCallback(tool, authResult.auth, recorder));
88
+ const transport = new _modelcontextprotocol_sdk_server_webStandardStreamableHttp_js.WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
89
+ await server.connect(transport);
90
+ return await transport.handleRequest(request);
91
+ } catch (err) {
92
+ await recorder.emit({
93
+ tool: null,
94
+ method: "transport",
95
+ outcome: "transport_error",
96
+ durationMs: 0
97
+ });
98
+ require_logger.log.error("mcp.transport_error", {
99
+ ...require_logger.describeError(err),
100
+ outcome: "500 internal error"
101
+ });
102
+ return Response.json({
103
+ jsonrpc: "2.0",
104
+ id: null,
105
+ error: {
106
+ code: -32603,
107
+ message: "internal error"
108
+ }
109
+ }, { status: 500 });
110
+ }
111
+ };
112
+ return async (request, recorder = require_cors.createNoopRecorder()) => {
113
+ if (request.method === "OPTIONS") return require_cors.corsPreflightResponse("GET, POST, DELETE, OPTIONS");
114
+ return require_cors.withCors(await handle(request, recorder));
115
+ };
116
+ }
117
+ //#endregion
118
+ Object.defineProperty(exports, "createMcpProtocolHandler", {
119
+ enumerable: true,
120
+ get: function() {
121
+ return createMcpProtocolHandler;
122
+ }
123
+ });
@@ -0,0 +1,118 @@
1
+ import { i as log, r as describeError } from "./logger-2OXtfiIW.js";
2
+ import { t as ToolContext } from "./context-CIpPzN7P.js";
3
+ import { d as nowMs, i as createRequestAuthorizer, n as withCors, t as corsPreflightResponse, u as createNoopRecorder } from "./cors-B7CTXIHD.js";
4
+ import { t as extractTextContent } from "./content-D5LJAHyM.js";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
7
+ //#region src/protocols/mcp/protocol.ts
8
+ /**
9
+ * Adapt a Lovable tool to the SDK's tool callback. The boundary cast bridges
10
+ * our SDK-decoupled content-block types to the SDK's; they match structurally.
11
+ */
12
+ function adaptToolToSdkCallback(tool, auth, recorder) {
13
+ return (async (first) => {
14
+ const args = tool.inputSchema ? first ?? {} : {};
15
+ const start = nowMs();
16
+ let result;
17
+ try {
18
+ result = await tool.handler(args, new ToolContext(auth));
19
+ } catch {
20
+ await recorder.emit({
21
+ tool: tool.name,
22
+ method: "tools/call",
23
+ outcome: "handler_error",
24
+ durationMs: nowMs() - start
25
+ });
26
+ return {
27
+ content: [{
28
+ type: "text",
29
+ text: "tool execution failed"
30
+ }],
31
+ isError: true
32
+ };
33
+ }
34
+ if (result == null) {
35
+ await recorder.emit({
36
+ tool: tool.name,
37
+ method: "tools/call",
38
+ outcome: "handler_error",
39
+ durationMs: nowMs() - start
40
+ });
41
+ return {
42
+ content: [{
43
+ type: "text",
44
+ text: `tool "${tool.name}" returned no result`
45
+ }],
46
+ isError: true
47
+ };
48
+ }
49
+ await recorder.emit({
50
+ tool: tool.name,
51
+ method: "tools/call",
52
+ outcome: result.isError ? "tool_error" : "ok",
53
+ durationMs: nowMs() - start,
54
+ errorText: result.isError ? extractTextContent(result.content) : void 0
55
+ });
56
+ return {
57
+ content: result.content ?? [],
58
+ structuredContent: result.structuredContent,
59
+ isError: result.isError
60
+ };
61
+ });
62
+ }
63
+ /**
64
+ * Build a Web-Standard request handler that serves the MCP protocol over
65
+ * streamable HTTP. A fresh `McpServer` + transport is constructed per
66
+ * request — the transport is stateless, so this is cheap and there is no
67
+ * cross-request state to leak. The per-request `recorder` is supplied by the
68
+ * caller (the stack handler) so telemetry reads the runtime env in-flight.
69
+ */
70
+ function createMcpProtocolHandler(mcp, options = {}) {
71
+ const authorizer = createRequestAuthorizer(mcp, options);
72
+ const handle = async (request, recorder) => {
73
+ const authResult = await authorizer.authorize(request, recorder);
74
+ if (!authResult.ok) return authResult.response;
75
+ try {
76
+ const server = new McpServer({
77
+ name: mcp.name,
78
+ version: mcp.version,
79
+ title: mcp.title
80
+ }, { instructions: mcp.instructions });
81
+ for (const tool of mcp.tools) server.registerTool(tool.name, {
82
+ title: tool.title,
83
+ description: tool.description,
84
+ inputSchema: tool.inputSchema,
85
+ outputSchema: tool.outputSchema,
86
+ annotations: tool.annotations
87
+ }, adaptToolToSdkCallback(tool, authResult.auth, recorder));
88
+ const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: void 0 });
89
+ await server.connect(transport);
90
+ return await transport.handleRequest(request);
91
+ } catch (err) {
92
+ await recorder.emit({
93
+ tool: null,
94
+ method: "transport",
95
+ outcome: "transport_error",
96
+ durationMs: 0
97
+ });
98
+ log.error("mcp.transport_error", {
99
+ ...describeError(err),
100
+ outcome: "500 internal error"
101
+ });
102
+ return Response.json({
103
+ jsonrpc: "2.0",
104
+ id: null,
105
+ error: {
106
+ code: -32603,
107
+ message: "internal error"
108
+ }
109
+ }, { status: 500 });
110
+ }
111
+ };
112
+ return async (request, recorder = createNoopRecorder()) => {
113
+ if (request.method === "OPTIONS") return corsPreflightResponse("GET, POST, DELETE, OPTIONS");
114
+ return withCors(await handle(request, recorder));
115
+ };
116
+ }
117
+ //#endregion
118
+ export { createMcpProtocolHandler as t };
@@ -0,0 +1,12 @@
1
+ //#region src/auth/metadata-path.ts
2
+ /**
3
+ * Default RFC 9728 protected-resource metadata path. Used by the runtime 401
4
+ * challenge (`authorize.ts`, which advertises this URL via the
5
+ * `WWW-Authenticate: resource_metadata` param) and the Vite plugin (which emits
6
+ * the route that serves it) when no `metadataPath` is configured. A configured
7
+ * `metadataPath` overrides it; the plugin injects that same path into every
8
+ * emitted handler, so the advertised URL and the served route still can't drift.
9
+ */
10
+ const OAUTH_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
11
+ //#endregion
12
+ export { OAUTH_PROTECTED_RESOURCE_METADATA_PATH as t };
@@ -0,0 +1,17 @@
1
+ //#region src/auth/metadata-path.ts
2
+ /**
3
+ * Default RFC 9728 protected-resource metadata path. Used by the runtime 401
4
+ * challenge (`authorize.ts`, which advertises this URL via the
5
+ * `WWW-Authenticate: resource_metadata` param) and the Vite plugin (which emits
6
+ * the route that serves it) when no `metadataPath` is configured. A configured
7
+ * `metadataPath` overrides it; the plugin injects that same path into every
8
+ * emitted handler, so the advertised URL and the served route still can't drift.
9
+ */
10
+ const OAUTH_PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
11
+ //#endregion
12
+ Object.defineProperty(exports, "OAUTH_PROTECTED_RESOURCE_METADATA_PATH", {
13
+ enumerable: true,
14
+ get: function() {
15
+ return OAUTH_PROTECTED_RESOURCE_METADATA_PATH;
16
+ }
17
+ });
@@ -0,0 +1,4 @@
1
+ //#region package.json
2
+ var version = "0.21.1-rc.1";
3
+ //#endregion
4
+ export { version as t };
@@ -0,0 +1,9 @@
1
+ //#region package.json
2
+ var version = "0.21.1-rc.1";
3
+ //#endregion
4
+ Object.defineProperty(exports, "version", {
5
+ enumerable: true,
6
+ get: function() {
7
+ return version;
8
+ }
9
+ });
@@ -0,0 +1,7 @@
1
+ //#region src/stacks/supabase/paths.ts
2
+ const FUNCTIONS_MOUNT_PREFIX = "/functions/v1/";
3
+ function assertFunctionName(value, label = "functionName") {
4
+ if (!/^[a-zA-Z0-9_-]+$/.test(value)) throw new Error(`@lovable.dev/mcp-js: ${label} must be a single path segment matching [A-Za-z0-9_-], got ${JSON.stringify(value)}`);
5
+ }
6
+ //#endregion
7
+ export { assertFunctionName as n, FUNCTIONS_MOUNT_PREFIX as t };
@@ -0,0 +1,18 @@
1
+ //#region src/stacks/supabase/paths.ts
2
+ const FUNCTIONS_MOUNT_PREFIX = "/functions/v1/";
3
+ function assertFunctionName(value, label = "functionName") {
4
+ if (!/^[a-zA-Z0-9_-]+$/.test(value)) throw new Error(`@lovable.dev/mcp-js: ${label} must be a single path segment matching [A-Za-z0-9_-], got ${JSON.stringify(value)}`);
5
+ }
6
+ //#endregion
7
+ Object.defineProperty(exports, "FUNCTIONS_MOUNT_PREFIX", {
8
+ enumerable: true,
9
+ get: function() {
10
+ return FUNCTIONS_MOUNT_PREFIX;
11
+ }
12
+ });
13
+ Object.defineProperty(exports, "assertFunctionName", {
14
+ enumerable: true,
15
+ get: function() {
16
+ return assertFunctionName;
17
+ }
18
+ });