@lovable.dev/mcp-js 0.15.0 → 0.16.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.
@@ -107,6 +107,223 @@ function describeError(err) {
107
107
  return { value: String(err) };
108
108
  }
109
109
 
110
+ // src/metrics/config.ts
111
+ var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
112
+ var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
113
+ var METRICS_SAMPLE_RATE = 1;
114
+ var METRICS_FLUSH_INTERVAL_MS = 5e3;
115
+ var METRICS_MAX_BATCH_SIZE = 50;
116
+ function assertMetricsEndpoint(endpoint) {
117
+ let url;
118
+ try {
119
+ url = new URL(endpoint);
120
+ } catch {
121
+ throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
122
+ }
123
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
124
+ throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
125
+ }
126
+ }
127
+ function resolveMetricsConfig(config = true) {
128
+ const options = typeof config === "boolean" ? { enabled: config } : config;
129
+ const endpoint = options.endpoint ?? DEFAULT_METRICS_ENDPOINT;
130
+ assertMetricsEndpoint(endpoint);
131
+ return Object.freeze({
132
+ enabled: options.enabled ?? true,
133
+ endpoint,
134
+ headers: options.headers ?? {},
135
+ apiKeyEnvVar: METRICS_API_KEY_ENV_VAR,
136
+ sampleRate: METRICS_SAMPLE_RATE,
137
+ flushIntervalMs: METRICS_FLUSH_INTERVAL_MS,
138
+ maxBatchSize: METRICS_MAX_BATCH_SIZE
139
+ });
140
+ }
141
+
142
+ // package.json
143
+ var version = "0.16.0";
144
+
145
+ // src/metrics/otlp.ts
146
+ var SCOPE_NAME = "@lovable.dev/mcp-js";
147
+ var EVENT_NAME = "mcp.tool.invocation";
148
+ var SEVERITY_INFO = 9;
149
+ function strAttr(key, value) {
150
+ return { key, value: { stringValue: value } };
151
+ }
152
+ function intAttr(key, value) {
153
+ return { key, value: { intValue: String(Math.round(value)) } };
154
+ }
155
+ function toLogRecord(rec) {
156
+ const attributes = [
157
+ strAttr("event.name", EVENT_NAME),
158
+ strAttr("mcp.method", rec.method),
159
+ strAttr("mcp.outcome", rec.outcome),
160
+ intAttr("mcp.duration_ms", rec.durationMs)
161
+ ];
162
+ if (rec.tool !== null)
163
+ attributes.push(strAttr("mcp.tool", rec.tool));
164
+ if (rec.reqBytes !== void 0)
165
+ attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
166
+ if (rec.resBytes !== void 0)
167
+ attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
168
+ return {
169
+ timeUnixNano: rec.timeUnixNano,
170
+ observedTimeUnixNano: rec.timeUnixNano,
171
+ severityNumber: SEVERITY_INFO,
172
+ severityText: "INFO",
173
+ body: { stringValue: EVENT_NAME },
174
+ attributes
175
+ };
176
+ }
177
+ function buildLogsPayload(records, server) {
178
+ return JSON.stringify({
179
+ resourceLogs: [
180
+ {
181
+ resource: {
182
+ attributes: [
183
+ strAttr("service.name", server.name),
184
+ strAttr("service.version", server.version),
185
+ strAttr("telemetry.sdk.name", SCOPE_NAME),
186
+ strAttr("telemetry.sdk.version", version),
187
+ strAttr("telemetry.sdk.language", "webjs")
188
+ ]
189
+ },
190
+ scopeLogs: [
191
+ {
192
+ scope: { name: SCOPE_NAME, version },
193
+ logRecords: records.map(toLogRecord)
194
+ }
195
+ ]
196
+ }
197
+ ]
198
+ });
199
+ }
200
+ function nowUnixNano() {
201
+ return `${Date.now()}000000`;
202
+ }
203
+
204
+ // src/metrics/recorder.ts
205
+ function nowMs() {
206
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
207
+ }
208
+ function reportInvocation(recorder, ev) {
209
+ log.info("tool.invoked", { tool: ev.tool, method: ev.method, outcome: ev.outcome, durationMs: ev.durationMs });
210
+ recorder.record(ev);
211
+ }
212
+ var NOOP_RECORDER = {
213
+ record() {
214
+ },
215
+ async flush() {
216
+ }
217
+ };
218
+ function createNoopRecorder() {
219
+ return NOOP_RECORDER;
220
+ }
221
+ function readRuntimeEnv(name) {
222
+ try {
223
+ const denoEnv = globalThis.Deno?.env;
224
+ const value = denoEnv?.get?.(name);
225
+ if (value)
226
+ return value;
227
+ } catch {
228
+ }
229
+ try {
230
+ if (typeof process !== "undefined") {
231
+ const value = process.env?.[name];
232
+ if (value)
233
+ return value;
234
+ }
235
+ } catch {
236
+ }
237
+ return void 0;
238
+ }
239
+ function probeWaitUntil() {
240
+ const fn = globalThis.EdgeRuntime?.waitUntil;
241
+ return typeof fn === "function" ? fn.bind(globalThis.EdgeRuntime) : void 0;
242
+ }
243
+ function createMetricsRecorder(ctx, deps = {}) {
244
+ const { config, server } = ctx;
245
+ if (!config.enabled)
246
+ return NOOP_RECORDER;
247
+ const doFetch = deps.fetch ?? globalThis.fetch;
248
+ if (!doFetch) {
249
+ log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
250
+ return NOOP_RECORDER;
251
+ }
252
+ const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
253
+ const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
254
+ if (usesLovableEndpoint && !apiKey) {
255
+ log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
256
+ return NOOP_RECORDER;
257
+ }
258
+ const waitUntil = deps.waitUntil ?? probeWaitUntil();
259
+ const buffer = [];
260
+ let timer;
261
+ const schedule = (p) => {
262
+ if (waitUntil) {
263
+ try {
264
+ waitUntil(p);
265
+ return;
266
+ } catch (err) {
267
+ log.warn("metrics.wait_until_failed", describeError(err));
268
+ }
269
+ }
270
+ void p.catch(() => {
271
+ });
272
+ };
273
+ const headers = {};
274
+ if (!usesLovableEndpoint) {
275
+ for (const [key, value] of Object.entries(config.headers)) {
276
+ if (key.toLowerCase() !== "content-type")
277
+ headers[key] = value;
278
+ }
279
+ }
280
+ headers["content-type"] = "application/json";
281
+ if (apiKey)
282
+ headers.authorization = `Bearer ${apiKey}`;
283
+ const flush = async () => {
284
+ if (buffer.length === 0)
285
+ return;
286
+ const records = buffer.splice(0, buffer.length);
287
+ const dropped = records.length;
288
+ try {
289
+ const res = await doFetch(config.endpoint, {
290
+ method: "POST",
291
+ headers,
292
+ body: buildLogsPayload(records, server),
293
+ keepalive: true
294
+ });
295
+ if (!res.ok) {
296
+ log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
297
+ }
298
+ } catch (err) {
299
+ log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
300
+ }
301
+ };
302
+ const ensureTimer = () => {
303
+ if (timer !== void 0)
304
+ return;
305
+ timer = setInterval(() => schedule(flush()), config.flushIntervalMs);
306
+ timer.unref?.();
307
+ };
308
+ return {
309
+ record(ev) {
310
+ if (config.sampleRate < 1 && Math.random() >= config.sampleRate)
311
+ return;
312
+ buffer.push({ ...ev, timeUnixNano: nowUnixNano() });
313
+ ensureTimer();
314
+ if (buffer.length >= config.maxBatchSize)
315
+ schedule(flush());
316
+ },
317
+ flush
318
+ };
319
+ }
320
+ function createRecorderForRuntime(mcp) {
321
+ const config = resolveMetricsConfig(mcp.metrics);
322
+ if (!config.enabled)
323
+ return createNoopRecorder();
324
+ return createMetricsRecorder({ config, server: { name: mcp.name, version: mcp.version } });
325
+ }
326
+
110
327
  // src/core/promise.ts
111
328
  function cachedPromise(load, label) {
112
329
  let settled = false;
@@ -535,12 +752,13 @@ function assertRequiredScopes(auth, context) {
535
752
  throw new OAuthTokenError(403, "insufficient_scope", "Additional OAuth scope is required");
536
753
  }
537
754
  }
538
- function createRequestAuthorizer(mcp, options = {}) {
755
+ function createRequestAuthorizer(mcp, options = {}, recorder) {
539
756
  const runtime = getOAuthRuntime(mcp, options);
540
757
  return {
541
758
  async authorize(request) {
542
759
  if (runtime.kind === "unconfigured")
543
760
  return { ok: true };
761
+ const startedAt = nowMs();
544
762
  const token = parseBearerToken(request);
545
763
  if (!token) {
546
764
  log.info("auth.no_bearer_token", { outcome: "401" });
@@ -553,6 +771,12 @@ function createRequestAuthorizer(mcp, options = {}) {
553
771
  } catch (err) {
554
772
  if (err instanceof OAuthConfigurationError) {
555
773
  log.error("auth.config_error", { ...describeError(err), outcome: "500" });
774
+ recorder?.record({
775
+ tool: null,
776
+ method: "authorize",
777
+ outcome: "auth_config_error",
778
+ durationMs: nowMs() - startedAt
779
+ });
556
780
  return { ok: false, response: oauthConfigurationErrorResponse() };
557
781
  }
558
782
  if (err instanceof OAuthTokenError) {
@@ -649,214 +873,6 @@ function corsPreflightResponse(allowMethods) {
649
873
  });
650
874
  }
651
875
 
652
- // src/metrics/config.ts
653
- var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
654
- var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
655
- var METRICS_SAMPLE_RATE = 1;
656
- var METRICS_FLUSH_INTERVAL_MS = 5e3;
657
- var METRICS_MAX_BATCH_SIZE = 50;
658
- function assertMetricsEndpoint(endpoint) {
659
- let url;
660
- try {
661
- url = new URL(endpoint);
662
- } catch {
663
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
664
- }
665
- if (url.protocol !== "https:" && url.protocol !== "http:") {
666
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
667
- }
668
- }
669
- function resolveMetricsConfig(config = true) {
670
- const options = typeof config === "boolean" ? { enabled: config } : config;
671
- const endpoint = options.endpoint ?? DEFAULT_METRICS_ENDPOINT;
672
- assertMetricsEndpoint(endpoint);
673
- return Object.freeze({
674
- enabled: options.enabled ?? true,
675
- endpoint,
676
- headers: options.headers ?? {},
677
- apiKeyEnvVar: METRICS_API_KEY_ENV_VAR,
678
- sampleRate: METRICS_SAMPLE_RATE,
679
- flushIntervalMs: METRICS_FLUSH_INTERVAL_MS,
680
- maxBatchSize: METRICS_MAX_BATCH_SIZE
681
- });
682
- }
683
-
684
- // package.json
685
- var version = "0.15.0";
686
-
687
- // src/metrics/otlp.ts
688
- var SCOPE_NAME = "@lovable.dev/mcp-js";
689
- var EVENT_NAME = "mcp.tool.invocation";
690
- var SEVERITY_INFO = 9;
691
- function strAttr(key, value) {
692
- return { key, value: { stringValue: value } };
693
- }
694
- function intAttr(key, value) {
695
- return { key, value: { intValue: String(Math.round(value)) } };
696
- }
697
- function toLogRecord(rec) {
698
- const attributes = [
699
- strAttr("event.name", EVENT_NAME),
700
- strAttr("mcp.method", rec.method),
701
- strAttr("mcp.outcome", rec.outcome),
702
- intAttr("mcp.duration_ms", rec.durationMs)
703
- ];
704
- if (rec.tool !== null)
705
- attributes.push(strAttr("mcp.tool", rec.tool));
706
- if (rec.reqBytes !== void 0)
707
- attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
708
- if (rec.resBytes !== void 0)
709
- attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
710
- return {
711
- timeUnixNano: rec.timeUnixNano,
712
- observedTimeUnixNano: rec.timeUnixNano,
713
- severityNumber: SEVERITY_INFO,
714
- severityText: "INFO",
715
- body: { stringValue: EVENT_NAME },
716
- attributes
717
- };
718
- }
719
- function buildLogsPayload(records, server) {
720
- return JSON.stringify({
721
- resourceLogs: [
722
- {
723
- resource: {
724
- attributes: [
725
- strAttr("service.name", server.name),
726
- strAttr("service.version", server.version),
727
- strAttr("telemetry.sdk.name", SCOPE_NAME),
728
- strAttr("telemetry.sdk.version", version),
729
- strAttr("telemetry.sdk.language", "webjs")
730
- ]
731
- },
732
- scopeLogs: [
733
- {
734
- scope: { name: SCOPE_NAME, version },
735
- logRecords: records.map(toLogRecord)
736
- }
737
- ]
738
- }
739
- ]
740
- });
741
- }
742
- function nowUnixNano() {
743
- return `${Date.now()}000000`;
744
- }
745
-
746
- // src/metrics/recorder.ts
747
- function nowMs() {
748
- return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
749
- }
750
- var NOOP_RECORDER = {
751
- record() {
752
- },
753
- async flush() {
754
- }
755
- };
756
- function createNoopRecorder() {
757
- return NOOP_RECORDER;
758
- }
759
- function readRuntimeEnv(name) {
760
- try {
761
- const denoEnv = globalThis.Deno?.env;
762
- const value = denoEnv?.get?.(name);
763
- if (value)
764
- return value;
765
- } catch {
766
- }
767
- try {
768
- if (typeof process !== "undefined") {
769
- const value = process.env?.[name];
770
- if (value)
771
- return value;
772
- }
773
- } catch {
774
- }
775
- return void 0;
776
- }
777
- function probeWaitUntil() {
778
- const fn = globalThis.EdgeRuntime?.waitUntil;
779
- return typeof fn === "function" ? fn.bind(globalThis.EdgeRuntime) : void 0;
780
- }
781
- function createMetricsRecorder(ctx, deps = {}) {
782
- const { config, server } = ctx;
783
- if (!config.enabled)
784
- return NOOP_RECORDER;
785
- const doFetch = deps.fetch ?? globalThis.fetch;
786
- if (!doFetch)
787
- return NOOP_RECORDER;
788
- const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
789
- const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
790
- if (usesLovableEndpoint && !apiKey) {
791
- log.debug("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar });
792
- return NOOP_RECORDER;
793
- }
794
- const waitUntil = deps.waitUntil ?? probeWaitUntil();
795
- const buffer = [];
796
- let timer;
797
- const schedule = (p) => {
798
- if (waitUntil) {
799
- try {
800
- waitUntil(p);
801
- return;
802
- } catch {
803
- }
804
- }
805
- void p.catch(() => {
806
- });
807
- };
808
- const headers = {};
809
- if (!usesLovableEndpoint) {
810
- for (const [key, value] of Object.entries(config.headers)) {
811
- if (key.toLowerCase() !== "content-type")
812
- headers[key] = value;
813
- }
814
- }
815
- headers["content-type"] = "application/json";
816
- if (apiKey)
817
- headers.authorization = `Bearer ${apiKey}`;
818
- const flush = async () => {
819
- if (buffer.length === 0)
820
- return;
821
- const records = buffer.splice(0, buffer.length);
822
- try {
823
- const res = await doFetch(config.endpoint, {
824
- method: "POST",
825
- headers,
826
- body: buildLogsPayload(records, server),
827
- keepalive: true
828
- });
829
- if (!res.ok)
830
- log.debug("metrics.flush_rejected", { status: res.status });
831
- } catch (err) {
832
- log.debug("metrics.flush_failed", describeError(err));
833
- }
834
- };
835
- const ensureTimer = () => {
836
- if (timer !== void 0)
837
- return;
838
- timer = setInterval(() => schedule(flush()), config.flushIntervalMs);
839
- timer.unref?.();
840
- };
841
- return {
842
- record(ev) {
843
- if (config.sampleRate < 1 && Math.random() >= config.sampleRate)
844
- return;
845
- buffer.push({ ...ev, timeUnixNano: nowUnixNano() });
846
- ensureTimer();
847
- if (buffer.length >= config.maxBatchSize)
848
- schedule(flush());
849
- },
850
- flush
851
- };
852
- }
853
- function createRecorderForRuntime(mcp) {
854
- const config = resolveMetricsConfig(mcp.metrics);
855
- if (!config.enabled)
856
- return createNoopRecorder();
857
- return createMetricsRecorder({ config, server: { name: mcp.name, version: mcp.version } });
858
- }
859
-
860
876
  // src/protocols/mcp/protocol.ts
861
877
  function adaptToolToSdkCallback(tool, auth, recorder) {
862
878
  return async (first) => {
@@ -866,14 +882,24 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
866
882
  try {
867
883
  result = await tool.handler(args, new ToolContext(auth));
868
884
  } catch {
869
- recorder.record({ tool: tool.name, method: "tools/call", outcome: "handler_error", durationMs: nowMs() - start });
885
+ reportInvocation(recorder, {
886
+ tool: tool.name,
887
+ method: "tools/call",
888
+ outcome: "handler_error",
889
+ durationMs: nowMs() - start
890
+ });
870
891
  return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
871
892
  }
872
893
  if (result == null) {
873
- recorder.record({ tool: tool.name, method: "tools/call", outcome: "handler_error", durationMs: nowMs() - start });
894
+ reportInvocation(recorder, {
895
+ tool: tool.name,
896
+ method: "tools/call",
897
+ outcome: "handler_error",
898
+ durationMs: nowMs() - start
899
+ });
874
900
  return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
875
901
  }
876
- recorder.record({
902
+ reportInvocation(recorder, {
877
903
  tool: tool.name,
878
904
  method: "tools/call",
879
905
  outcome: result.isError ? "tool_error" : "ok",
@@ -883,7 +909,7 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
883
909
  };
884
910
  }
885
911
  function createMcpProtocolHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
886
- const authorizer = createRequestAuthorizer(mcp, options);
912
+ const authorizer = createRequestAuthorizer(mcp, options, recorder);
887
913
  const handle = async (request) => {
888
914
  const authResult = await authorizer.authorize(request);
889
915
  if (!authResult.ok)
@@ -1013,9 +1039,9 @@ function buildMcpListing(mcp) {
1013
1039
  }))
1014
1040
  };
1015
1041
  }
1016
- function createListToolsHandler(mcp, options = {}) {
1042
+ function createListToolsHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
1017
1043
  assertRestResourceBinding(mcp, options);
1018
- const authorizer = createRequestAuthorizer(mcp, options);
1044
+ const authorizer = createRequestAuthorizer(mcp, options, recorder);
1019
1045
  const handle = async (request) => {
1020
1046
  const authResult = await authorizer.authorize(request);
1021
1047
  if (!authResult.ok)
@@ -1048,7 +1074,7 @@ function isEmptyArgs(value) {
1048
1074
  }
1049
1075
  function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
1050
1076
  assertRestResourceBinding(mcp, options);
1051
- const authorizer = createRequestAuthorizer(mcp, options);
1077
+ const authorizer = createRequestAuthorizer(mcp, options, recorder);
1052
1078
  const handle = async (request, toolName) => {
1053
1079
  const authResult = await authorizer.authorize(request);
1054
1080
  if (!authResult.ok)
@@ -1106,20 +1132,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
1106
1132
  try {
1107
1133
  result = await tool.handler(args, new ToolContext(authResult.auth));
1108
1134
  } catch {
1109
- recorder.record({ tool: tool.name, method: "tools/call", outcome: "handler_error", durationMs: nowMs() - start });
1135
+ reportInvocation(recorder, {
1136
+ tool: tool.name,
1137
+ method: "tools/call",
1138
+ outcome: "handler_error",
1139
+ durationMs: nowMs() - start
1140
+ });
1110
1141
  return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
1111
1142
  status: 500,
1112
1143
  headers: JSON_HEADERS
1113
1144
  });
1114
1145
  }
1115
1146
  if (result == null) {
1116
- recorder.record({ tool: tool.name, method: "tools/call", outcome: "handler_error", durationMs: nowMs() - start });
1147
+ reportInvocation(recorder, {
1148
+ tool: tool.name,
1149
+ method: "tools/call",
1150
+ outcome: "handler_error",
1151
+ durationMs: nowMs() - start
1152
+ });
1117
1153
  return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
1118
1154
  status: 500,
1119
1155
  headers: JSON_HEADERS
1120
1156
  });
1121
1157
  }
1122
- recorder.record({
1158
+ reportInvocation(recorder, {
1123
1159
  tool: tool.name,
1124
1160
  method: "tools/call",
1125
1161
  outcome: result.isError ? "tool_error" : "ok",
@@ -3,22 +3,21 @@ import {
3
3
  } from "../../chunk-UQK5UO6C.js";
4
4
  import {
5
5
  createMcpProtocolHandler
6
- } from "../../chunk-RHDEW56Y.js";
6
+ } from "../../chunk-EZQVUNXB.js";
7
7
  import {
8
8
  createOAuthProtectedResourceMetadataHandler
9
- } from "../../chunk-QDKOF4UF.js";
9
+ } from "../../chunk-T24Z753F.js";
10
10
  import {
11
11
  createInvokeToolHandler
12
- } from "../../chunk-T2RED2TG.js";
12
+ } from "../../chunk-W2EZWPJ5.js";
13
13
  import {
14
14
  createListToolsHandler
15
- } from "../../chunk-VNRQPA4K.js";
16
- import "../../chunk-XQSTN54Y.js";
17
- import "../../chunk-P3F324UC.js";
18
- import "../../chunk-G4XA7IJM.js";
19
- import "../../chunk-QC3DXQTH.js";
15
+ } from "../../chunk-I5CAQUQI.js";
16
+ import "../../chunk-MA5H6PSF.js";
17
+ import "../../chunk-H6BKTNJY.js";
18
+ import "../../chunk-DCWYK4CA.js";
20
19
  import "../../chunk-6DXGZZA4.js";
21
- import "../../chunk-LWHVXXKQ.js";
20
+ import "../../chunk-SKSKC747.js";
22
21
 
23
22
  // src/stacks/tanstack/handlers.ts
24
23
  function forwarded(request, options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/mcp-js",
3
- "version": "0.15.0",
3
+ "version": "0.16.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": {