@lovable.dev/mcp-js 0.15.1 → 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.
- package/dist/{chunk-UCPYLSNN.js → chunk-EZQVUNXB.js} +15 -4
- package/dist/{chunk-YTOMGJV5.js → chunk-H6BKTNJY.js} +17 -7
- package/dist/{chunk-QT5L4CS3.js → chunk-I5CAQUQI.js} +1 -1
- package/dist/{chunk-GIHCQT6L.js → chunk-SKSKC747.js} +1 -1
- package/dist/{chunk-ILYTJXDR.js → chunk-T24Z753F.js} +1 -1
- package/dist/{chunk-CEDD57G2.js → chunk-W2EZWPJ5.js} +15 -4
- package/dist/cli/extract-manifest.cjs +1 -1
- package/dist/cli/extract-manifest.js +3 -3
- package/dist/protocols/mcp/index.cjs +29 -10
- package/dist/protocols/mcp/index.js +3 -3
- package/dist/protocols/oauth-metadata.js +3 -3
- package/dist/protocols/rest/index.cjs +29 -10
- package/dist/protocols/rest/index.js +4 -4
- package/dist/stacks/supabase/index.cjs +42 -13
- package/dist/stacks/supabase/index.js +6 -6
- package/dist/stacks/supabase/vite.cjs +1 -1
- package/dist/stacks/supabase/vite.js +1 -1
- package/dist/stacks/tanstack/index.cjs +42 -13
- package/dist/stacks/tanstack/index.js +6 -6
- package/package.json +1 -1
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
createRecorderForRuntime,
|
|
7
7
|
createRequestAuthorizer,
|
|
8
8
|
nowMs,
|
|
9
|
+
reportInvocation,
|
|
9
10
|
withCors
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-H6BKTNJY.js";
|
|
11
12
|
import {
|
|
12
13
|
describeError,
|
|
13
14
|
log
|
|
@@ -24,14 +25,24 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
24
25
|
try {
|
|
25
26
|
result = await tool.handler(args, new ToolContext(auth));
|
|
26
27
|
} catch {
|
|
27
|
-
recorder
|
|
28
|
+
reportInvocation(recorder, {
|
|
29
|
+
tool: tool.name,
|
|
30
|
+
method: "tools/call",
|
|
31
|
+
outcome: "handler_error",
|
|
32
|
+
durationMs: nowMs() - start
|
|
33
|
+
});
|
|
28
34
|
return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
|
|
29
35
|
}
|
|
30
36
|
if (result == null) {
|
|
31
|
-
recorder
|
|
37
|
+
reportInvocation(recorder, {
|
|
38
|
+
tool: tool.name,
|
|
39
|
+
method: "tools/call",
|
|
40
|
+
outcome: "handler_error",
|
|
41
|
+
durationMs: nowMs() - start
|
|
42
|
+
});
|
|
32
43
|
return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
|
|
33
44
|
}
|
|
34
|
-
recorder
|
|
45
|
+
reportInvocation(recorder, {
|
|
35
46
|
tool: tool.name,
|
|
36
47
|
method: "tools/call",
|
|
37
48
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-6DXGZZA4.js";
|
|
12
12
|
import {
|
|
13
13
|
version
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-SKSKC747.js";
|
|
15
15
|
|
|
16
16
|
// src/core/http.ts
|
|
17
17
|
var JSON_HEADERS = { "Content-Type": "application/json" };
|
|
@@ -112,6 +112,10 @@ function nowUnixNano() {
|
|
|
112
112
|
function nowMs() {
|
|
113
113
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
114
114
|
}
|
|
115
|
+
function reportInvocation(recorder, ev) {
|
|
116
|
+
log.info("tool.invoked", { tool: ev.tool, method: ev.method, outcome: ev.outcome, durationMs: ev.durationMs });
|
|
117
|
+
recorder.record(ev);
|
|
118
|
+
}
|
|
115
119
|
var NOOP_RECORDER = {
|
|
116
120
|
record() {
|
|
117
121
|
},
|
|
@@ -148,12 +152,14 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
148
152
|
if (!config.enabled)
|
|
149
153
|
return NOOP_RECORDER;
|
|
150
154
|
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
151
|
-
if (!doFetch)
|
|
155
|
+
if (!doFetch) {
|
|
156
|
+
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
152
157
|
return NOOP_RECORDER;
|
|
158
|
+
}
|
|
153
159
|
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
154
160
|
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
155
161
|
if (usesLovableEndpoint && !apiKey) {
|
|
156
|
-
log.
|
|
162
|
+
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
157
163
|
return NOOP_RECORDER;
|
|
158
164
|
}
|
|
159
165
|
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
@@ -164,7 +170,8 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
164
170
|
try {
|
|
165
171
|
waitUntil(p);
|
|
166
172
|
return;
|
|
167
|
-
} catch {
|
|
173
|
+
} catch (err) {
|
|
174
|
+
log.warn("metrics.wait_until_failed", describeError(err));
|
|
168
175
|
}
|
|
169
176
|
}
|
|
170
177
|
void p.catch(() => {
|
|
@@ -184,6 +191,7 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
184
191
|
if (buffer.length === 0)
|
|
185
192
|
return;
|
|
186
193
|
const records = buffer.splice(0, buffer.length);
|
|
194
|
+
const dropped = records.length;
|
|
187
195
|
try {
|
|
188
196
|
const res = await doFetch(config.endpoint, {
|
|
189
197
|
method: "POST",
|
|
@@ -191,10 +199,11 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
191
199
|
body: buildLogsPayload(records, server),
|
|
192
200
|
keepalive: true
|
|
193
201
|
});
|
|
194
|
-
if (!res.ok)
|
|
195
|
-
log.
|
|
202
|
+
if (!res.ok) {
|
|
203
|
+
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
204
|
+
}
|
|
196
205
|
} catch (err) {
|
|
197
|
-
log.
|
|
206
|
+
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
198
207
|
}
|
|
199
208
|
};
|
|
200
209
|
const ensureTimer = () => {
|
|
@@ -670,6 +679,7 @@ export {
|
|
|
670
679
|
headResponse,
|
|
671
680
|
methodNotAllowed,
|
|
672
681
|
nowMs,
|
|
682
|
+
reportInvocation,
|
|
673
683
|
createRecorderForRuntime,
|
|
674
684
|
resolveProtectedResource,
|
|
675
685
|
assertResourcePathShape,
|
|
@@ -9,8 +9,9 @@ import {
|
|
|
9
9
|
createRequestAuthorizer,
|
|
10
10
|
methodNotAllowed,
|
|
11
11
|
nowMs,
|
|
12
|
+
reportInvocation,
|
|
12
13
|
withCors
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-H6BKTNJY.js";
|
|
14
15
|
|
|
15
16
|
// src/protocols/rest/invoke-tool.ts
|
|
16
17
|
import { getParseErrorMessage, objectFromShape, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
|
|
@@ -86,20 +87,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
|
|
|
86
87
|
try {
|
|
87
88
|
result = await tool.handler(args, new ToolContext(authResult.auth));
|
|
88
89
|
} catch {
|
|
89
|
-
recorder
|
|
90
|
+
reportInvocation(recorder, {
|
|
91
|
+
tool: tool.name,
|
|
92
|
+
method: "tools/call",
|
|
93
|
+
outcome: "handler_error",
|
|
94
|
+
durationMs: nowMs() - start
|
|
95
|
+
});
|
|
90
96
|
return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
|
|
91
97
|
status: 500,
|
|
92
98
|
headers: JSON_HEADERS
|
|
93
99
|
});
|
|
94
100
|
}
|
|
95
101
|
if (result == null) {
|
|
96
|
-
recorder
|
|
102
|
+
reportInvocation(recorder, {
|
|
103
|
+
tool: tool.name,
|
|
104
|
+
method: "tools/call",
|
|
105
|
+
outcome: "handler_error",
|
|
106
|
+
durationMs: nowMs() - start
|
|
107
|
+
});
|
|
97
108
|
return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
|
|
98
109
|
status: 500,
|
|
99
110
|
headers: JSON_HEADERS
|
|
100
111
|
});
|
|
101
112
|
}
|
|
102
|
-
recorder
|
|
113
|
+
reportInvocation(recorder, {
|
|
103
114
|
tool: tool.name,
|
|
104
115
|
method: "tools/call",
|
|
105
116
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
buildMcpListing
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-I5CAQUQI.js";
|
|
5
|
+
import "../chunk-H6BKTNJY.js";
|
|
6
6
|
import "../chunk-DCWYK4CA.js";
|
|
7
7
|
import "../chunk-6DXGZZA4.js";
|
|
8
8
|
import {
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "../chunk-Y3ZFPEQH.js";
|
|
11
11
|
import {
|
|
12
12
|
version
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-SKSKC747.js";
|
|
14
14
|
|
|
15
15
|
// src/manifest/io.ts
|
|
16
16
|
import { randomUUID } from "crypto";
|
|
@@ -105,7 +105,7 @@ function resolveMetricsConfig(config = true) {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
// package.json
|
|
108
|
-
var version = "0.
|
|
108
|
+
var version = "0.16.0";
|
|
109
109
|
|
|
110
110
|
// src/metrics/otlp.ts
|
|
111
111
|
var SCOPE_NAME = "@lovable.dev/mcp-js";
|
|
@@ -170,6 +170,10 @@ function nowUnixNano() {
|
|
|
170
170
|
function nowMs() {
|
|
171
171
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
172
172
|
}
|
|
173
|
+
function reportInvocation(recorder, ev) {
|
|
174
|
+
log.info("tool.invoked", { tool: ev.tool, method: ev.method, outcome: ev.outcome, durationMs: ev.durationMs });
|
|
175
|
+
recorder.record(ev);
|
|
176
|
+
}
|
|
173
177
|
var NOOP_RECORDER = {
|
|
174
178
|
record() {
|
|
175
179
|
},
|
|
@@ -206,12 +210,14 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
206
210
|
if (!config.enabled)
|
|
207
211
|
return NOOP_RECORDER;
|
|
208
212
|
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
209
|
-
if (!doFetch)
|
|
213
|
+
if (!doFetch) {
|
|
214
|
+
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
210
215
|
return NOOP_RECORDER;
|
|
216
|
+
}
|
|
211
217
|
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
212
218
|
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
213
219
|
if (usesLovableEndpoint && !apiKey) {
|
|
214
|
-
log.
|
|
220
|
+
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
215
221
|
return NOOP_RECORDER;
|
|
216
222
|
}
|
|
217
223
|
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
@@ -222,7 +228,8 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
222
228
|
try {
|
|
223
229
|
waitUntil(p);
|
|
224
230
|
return;
|
|
225
|
-
} catch {
|
|
231
|
+
} catch (err) {
|
|
232
|
+
log.warn("metrics.wait_until_failed", describeError(err));
|
|
226
233
|
}
|
|
227
234
|
}
|
|
228
235
|
void p.catch(() => {
|
|
@@ -242,6 +249,7 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
242
249
|
if (buffer.length === 0)
|
|
243
250
|
return;
|
|
244
251
|
const records = buffer.splice(0, buffer.length);
|
|
252
|
+
const dropped = records.length;
|
|
245
253
|
try {
|
|
246
254
|
const res = await doFetch(config.endpoint, {
|
|
247
255
|
method: "POST",
|
|
@@ -249,10 +257,11 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
249
257
|
body: buildLogsPayload(records, server),
|
|
250
258
|
keepalive: true
|
|
251
259
|
});
|
|
252
|
-
if (!res.ok)
|
|
253
|
-
log.
|
|
260
|
+
if (!res.ok) {
|
|
261
|
+
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
262
|
+
}
|
|
254
263
|
} catch (err) {
|
|
255
|
-
log.
|
|
264
|
+
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
256
265
|
}
|
|
257
266
|
};
|
|
258
267
|
const ensureTimer = () => {
|
|
@@ -830,14 +839,24 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
830
839
|
try {
|
|
831
840
|
result = await tool.handler(args, new ToolContext(auth));
|
|
832
841
|
} catch {
|
|
833
|
-
recorder
|
|
842
|
+
reportInvocation(recorder, {
|
|
843
|
+
tool: tool.name,
|
|
844
|
+
method: "tools/call",
|
|
845
|
+
outcome: "handler_error",
|
|
846
|
+
durationMs: nowMs() - start
|
|
847
|
+
});
|
|
834
848
|
return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
|
|
835
849
|
}
|
|
836
850
|
if (result == null) {
|
|
837
|
-
recorder
|
|
851
|
+
reportInvocation(recorder, {
|
|
852
|
+
tool: tool.name,
|
|
853
|
+
method: "tools/call",
|
|
854
|
+
outcome: "handler_error",
|
|
855
|
+
durationMs: nowMs() - start
|
|
856
|
+
});
|
|
838
857
|
return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
|
|
839
858
|
}
|
|
840
|
-
recorder
|
|
859
|
+
reportInvocation(recorder, {
|
|
841
860
|
tool: tool.name,
|
|
842
861
|
method: "tools/call",
|
|
843
862
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createMcpProtocolHandler
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-EZQVUNXB.js";
|
|
4
4
|
import "../../chunk-MA5H6PSF.js";
|
|
5
|
-
import "../../chunk-
|
|
5
|
+
import "../../chunk-H6BKTNJY.js";
|
|
6
6
|
import "../../chunk-DCWYK4CA.js";
|
|
7
7
|
import "../../chunk-6DXGZZA4.js";
|
|
8
|
-
import "../../chunk-
|
|
8
|
+
import "../../chunk-SKSKC747.js";
|
|
9
9
|
export {
|
|
10
10
|
createMcpProtocolHandler
|
|
11
11
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createOAuthProtectedResourceMetadataHandler
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-T24Z753F.js";
|
|
4
|
+
import "../chunk-H6BKTNJY.js";
|
|
5
5
|
import "../chunk-DCWYK4CA.js";
|
|
6
6
|
import "../chunk-6DXGZZA4.js";
|
|
7
|
-
import "../chunk-
|
|
7
|
+
import "../chunk-SKSKC747.js";
|
|
8
8
|
export {
|
|
9
9
|
createOAuthProtectedResourceMetadataHandler
|
|
10
10
|
};
|
|
@@ -115,7 +115,7 @@ function resolveMetricsConfig(config = true) {
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
// package.json
|
|
118
|
-
var version = "0.
|
|
118
|
+
var version = "0.16.0";
|
|
119
119
|
|
|
120
120
|
// src/metrics/otlp.ts
|
|
121
121
|
var SCOPE_NAME = "@lovable.dev/mcp-js";
|
|
@@ -180,6 +180,10 @@ function nowUnixNano() {
|
|
|
180
180
|
function nowMs() {
|
|
181
181
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
182
182
|
}
|
|
183
|
+
function reportInvocation(recorder, ev) {
|
|
184
|
+
log.info("tool.invoked", { tool: ev.tool, method: ev.method, outcome: ev.outcome, durationMs: ev.durationMs });
|
|
185
|
+
recorder.record(ev);
|
|
186
|
+
}
|
|
183
187
|
var NOOP_RECORDER = {
|
|
184
188
|
record() {
|
|
185
189
|
},
|
|
@@ -216,12 +220,14 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
216
220
|
if (!config.enabled)
|
|
217
221
|
return NOOP_RECORDER;
|
|
218
222
|
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
219
|
-
if (!doFetch)
|
|
223
|
+
if (!doFetch) {
|
|
224
|
+
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
220
225
|
return NOOP_RECORDER;
|
|
226
|
+
}
|
|
221
227
|
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
222
228
|
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
223
229
|
if (usesLovableEndpoint && !apiKey) {
|
|
224
|
-
log.
|
|
230
|
+
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
225
231
|
return NOOP_RECORDER;
|
|
226
232
|
}
|
|
227
233
|
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
@@ -232,7 +238,8 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
232
238
|
try {
|
|
233
239
|
waitUntil(p);
|
|
234
240
|
return;
|
|
235
|
-
} catch {
|
|
241
|
+
} catch (err) {
|
|
242
|
+
log.warn("metrics.wait_until_failed", describeError(err));
|
|
236
243
|
}
|
|
237
244
|
}
|
|
238
245
|
void p.catch(() => {
|
|
@@ -252,6 +259,7 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
252
259
|
if (buffer.length === 0)
|
|
253
260
|
return;
|
|
254
261
|
const records = buffer.splice(0, buffer.length);
|
|
262
|
+
const dropped = records.length;
|
|
255
263
|
try {
|
|
256
264
|
const res = await doFetch(config.endpoint, {
|
|
257
265
|
method: "POST",
|
|
@@ -259,10 +267,11 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
259
267
|
body: buildLogsPayload(records, server),
|
|
260
268
|
keepalive: true
|
|
261
269
|
});
|
|
262
|
-
if (!res.ok)
|
|
263
|
-
log.
|
|
270
|
+
if (!res.ok) {
|
|
271
|
+
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
272
|
+
}
|
|
264
273
|
} catch (err) {
|
|
265
|
-
log.
|
|
274
|
+
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
266
275
|
}
|
|
267
276
|
};
|
|
268
277
|
const ensureTimer = () => {
|
|
@@ -957,20 +966,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
|
|
|
957
966
|
try {
|
|
958
967
|
result = await tool.handler(args, new ToolContext(authResult.auth));
|
|
959
968
|
} catch {
|
|
960
|
-
recorder
|
|
969
|
+
reportInvocation(recorder, {
|
|
970
|
+
tool: tool.name,
|
|
971
|
+
method: "tools/call",
|
|
972
|
+
outcome: "handler_error",
|
|
973
|
+
durationMs: nowMs() - start
|
|
974
|
+
});
|
|
961
975
|
return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
|
|
962
976
|
status: 500,
|
|
963
977
|
headers: JSON_HEADERS
|
|
964
978
|
});
|
|
965
979
|
}
|
|
966
980
|
if (result == null) {
|
|
967
|
-
recorder
|
|
981
|
+
reportInvocation(recorder, {
|
|
982
|
+
tool: tool.name,
|
|
983
|
+
method: "tools/call",
|
|
984
|
+
outcome: "handler_error",
|
|
985
|
+
durationMs: nowMs() - start
|
|
986
|
+
});
|
|
968
987
|
return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
|
|
969
988
|
status: 500,
|
|
970
989
|
headers: JSON_HEADERS
|
|
971
990
|
});
|
|
972
991
|
}
|
|
973
|
-
recorder
|
|
992
|
+
reportInvocation(recorder, {
|
|
974
993
|
tool: tool.name,
|
|
975
994
|
method: "tools/call",
|
|
976
995
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createInvokeToolHandler
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-W2EZWPJ5.js";
|
|
4
4
|
import {
|
|
5
5
|
createListToolsHandler
|
|
6
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-I5CAQUQI.js";
|
|
7
7
|
import "../../chunk-MA5H6PSF.js";
|
|
8
|
-
import "../../chunk-
|
|
8
|
+
import "../../chunk-H6BKTNJY.js";
|
|
9
9
|
import "../../chunk-DCWYK4CA.js";
|
|
10
10
|
import "../../chunk-6DXGZZA4.js";
|
|
11
|
-
import "../../chunk-
|
|
11
|
+
import "../../chunk-SKSKC747.js";
|
|
12
12
|
export {
|
|
13
13
|
createInvokeToolHandler,
|
|
14
14
|
createListToolsHandler
|
|
@@ -169,7 +169,7 @@ function resolveMetricsConfig(config = true) {
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
// package.json
|
|
172
|
-
var version = "0.
|
|
172
|
+
var version = "0.16.0";
|
|
173
173
|
|
|
174
174
|
// src/metrics/otlp.ts
|
|
175
175
|
var SCOPE_NAME = "@lovable.dev/mcp-js";
|
|
@@ -234,6 +234,10 @@ function nowUnixNano() {
|
|
|
234
234
|
function nowMs() {
|
|
235
235
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
236
236
|
}
|
|
237
|
+
function reportInvocation(recorder, ev) {
|
|
238
|
+
log.info("tool.invoked", { tool: ev.tool, method: ev.method, outcome: ev.outcome, durationMs: ev.durationMs });
|
|
239
|
+
recorder.record(ev);
|
|
240
|
+
}
|
|
237
241
|
var NOOP_RECORDER = {
|
|
238
242
|
record() {
|
|
239
243
|
},
|
|
@@ -270,12 +274,14 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
270
274
|
if (!config.enabled)
|
|
271
275
|
return NOOP_RECORDER;
|
|
272
276
|
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
273
|
-
if (!doFetch)
|
|
277
|
+
if (!doFetch) {
|
|
278
|
+
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
274
279
|
return NOOP_RECORDER;
|
|
280
|
+
}
|
|
275
281
|
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
276
282
|
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
277
283
|
if (usesLovableEndpoint && !apiKey) {
|
|
278
|
-
log.
|
|
284
|
+
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
279
285
|
return NOOP_RECORDER;
|
|
280
286
|
}
|
|
281
287
|
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
@@ -286,7 +292,8 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
286
292
|
try {
|
|
287
293
|
waitUntil(p);
|
|
288
294
|
return;
|
|
289
|
-
} catch {
|
|
295
|
+
} catch (err) {
|
|
296
|
+
log.warn("metrics.wait_until_failed", describeError(err));
|
|
290
297
|
}
|
|
291
298
|
}
|
|
292
299
|
void p.catch(() => {
|
|
@@ -306,6 +313,7 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
306
313
|
if (buffer.length === 0)
|
|
307
314
|
return;
|
|
308
315
|
const records = buffer.splice(0, buffer.length);
|
|
316
|
+
const dropped = records.length;
|
|
309
317
|
try {
|
|
310
318
|
const res = await doFetch(config.endpoint, {
|
|
311
319
|
method: "POST",
|
|
@@ -313,10 +321,11 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
313
321
|
body: buildLogsPayload(records, server),
|
|
314
322
|
keepalive: true
|
|
315
323
|
});
|
|
316
|
-
if (!res.ok)
|
|
317
|
-
log.
|
|
324
|
+
if (!res.ok) {
|
|
325
|
+
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
326
|
+
}
|
|
318
327
|
} catch (err) {
|
|
319
|
-
log.
|
|
328
|
+
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
320
329
|
}
|
|
321
330
|
};
|
|
322
331
|
const ensureTimer = () => {
|
|
@@ -870,14 +879,24 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
870
879
|
try {
|
|
871
880
|
result = await tool.handler(args, new ToolContext(auth));
|
|
872
881
|
} catch {
|
|
873
|
-
recorder
|
|
882
|
+
reportInvocation(recorder, {
|
|
883
|
+
tool: tool.name,
|
|
884
|
+
method: "tools/call",
|
|
885
|
+
outcome: "handler_error",
|
|
886
|
+
durationMs: nowMs() - start
|
|
887
|
+
});
|
|
874
888
|
return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
|
|
875
889
|
}
|
|
876
890
|
if (result == null) {
|
|
877
|
-
recorder
|
|
891
|
+
reportInvocation(recorder, {
|
|
892
|
+
tool: tool.name,
|
|
893
|
+
method: "tools/call",
|
|
894
|
+
outcome: "handler_error",
|
|
895
|
+
durationMs: nowMs() - start
|
|
896
|
+
});
|
|
878
897
|
return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
|
|
879
898
|
}
|
|
880
|
-
recorder
|
|
899
|
+
reportInvocation(recorder, {
|
|
881
900
|
tool: tool.name,
|
|
882
901
|
method: "tools/call",
|
|
883
902
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -1110,20 +1129,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
|
|
|
1110
1129
|
try {
|
|
1111
1130
|
result = await tool.handler(args, new ToolContext(authResult.auth));
|
|
1112
1131
|
} catch {
|
|
1113
|
-
recorder
|
|
1132
|
+
reportInvocation(recorder, {
|
|
1133
|
+
tool: tool.name,
|
|
1134
|
+
method: "tools/call",
|
|
1135
|
+
outcome: "handler_error",
|
|
1136
|
+
durationMs: nowMs() - start
|
|
1137
|
+
});
|
|
1114
1138
|
return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
|
|
1115
1139
|
status: 500,
|
|
1116
1140
|
headers: JSON_HEADERS
|
|
1117
1141
|
});
|
|
1118
1142
|
}
|
|
1119
1143
|
if (result == null) {
|
|
1120
|
-
recorder
|
|
1144
|
+
reportInvocation(recorder, {
|
|
1145
|
+
tool: tool.name,
|
|
1146
|
+
method: "tools/call",
|
|
1147
|
+
outcome: "handler_error",
|
|
1148
|
+
durationMs: nowMs() - start
|
|
1149
|
+
});
|
|
1121
1150
|
return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
|
|
1122
1151
|
status: 500,
|
|
1123
1152
|
headers: JSON_HEADERS
|
|
1124
1153
|
});
|
|
1125
1154
|
}
|
|
1126
|
-
recorder
|
|
1155
|
+
reportInvocation(recorder, {
|
|
1127
1156
|
tool: tool.name,
|
|
1128
1157
|
method: "tools/call",
|
|
1129
1158
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -3,21 +3,21 @@ import {
|
|
|
3
3
|
} from "../../chunk-UQK5UO6C.js";
|
|
4
4
|
import {
|
|
5
5
|
createMcpProtocolHandler
|
|
6
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-EZQVUNXB.js";
|
|
7
7
|
import {
|
|
8
8
|
createOAuthProtectedResourceMetadataHandler
|
|
9
|
-
} from "../../chunk-
|
|
9
|
+
} from "../../chunk-T24Z753F.js";
|
|
10
10
|
import {
|
|
11
11
|
createInvokeToolHandler
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-W2EZWPJ5.js";
|
|
13
13
|
import {
|
|
14
14
|
createListToolsHandler
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-I5CAQUQI.js";
|
|
16
16
|
import "../../chunk-MA5H6PSF.js";
|
|
17
17
|
import {
|
|
18
18
|
assertResourcePathShape,
|
|
19
19
|
createRecorderForRuntime
|
|
20
|
-
} from "../../chunk-
|
|
20
|
+
} from "../../chunk-H6BKTNJY.js";
|
|
21
21
|
import {
|
|
22
22
|
trimTrailingSlash
|
|
23
23
|
} from "../../chunk-DCWYK4CA.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
FUNCTIONS_MOUNT_PREFIX,
|
|
29
29
|
assertFunctionName
|
|
30
30
|
} from "../../chunk-XQWJN6DC.js";
|
|
31
|
-
import "../../chunk-
|
|
31
|
+
import "../../chunk-SKSKC747.js";
|
|
32
32
|
|
|
33
33
|
// src/stacks/supabase/handler.ts
|
|
34
34
|
function deriveResourcePath(options) {
|
|
@@ -140,7 +140,7 @@ function resolveMetricsConfig(config = true) {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
// package.json
|
|
143
|
-
var version = "0.
|
|
143
|
+
var version = "0.16.0";
|
|
144
144
|
|
|
145
145
|
// src/metrics/otlp.ts
|
|
146
146
|
var SCOPE_NAME = "@lovable.dev/mcp-js";
|
|
@@ -205,6 +205,10 @@ function nowUnixNano() {
|
|
|
205
205
|
function nowMs() {
|
|
206
206
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
207
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
|
+
}
|
|
208
212
|
var NOOP_RECORDER = {
|
|
209
213
|
record() {
|
|
210
214
|
},
|
|
@@ -241,12 +245,14 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
241
245
|
if (!config.enabled)
|
|
242
246
|
return NOOP_RECORDER;
|
|
243
247
|
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
244
|
-
if (!doFetch)
|
|
248
|
+
if (!doFetch) {
|
|
249
|
+
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
245
250
|
return NOOP_RECORDER;
|
|
251
|
+
}
|
|
246
252
|
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
247
253
|
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
248
254
|
if (usesLovableEndpoint && !apiKey) {
|
|
249
|
-
log.
|
|
255
|
+
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
250
256
|
return NOOP_RECORDER;
|
|
251
257
|
}
|
|
252
258
|
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
@@ -257,7 +263,8 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
257
263
|
try {
|
|
258
264
|
waitUntil(p);
|
|
259
265
|
return;
|
|
260
|
-
} catch {
|
|
266
|
+
} catch (err) {
|
|
267
|
+
log.warn("metrics.wait_until_failed", describeError(err));
|
|
261
268
|
}
|
|
262
269
|
}
|
|
263
270
|
void p.catch(() => {
|
|
@@ -277,6 +284,7 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
277
284
|
if (buffer.length === 0)
|
|
278
285
|
return;
|
|
279
286
|
const records = buffer.splice(0, buffer.length);
|
|
287
|
+
const dropped = records.length;
|
|
280
288
|
try {
|
|
281
289
|
const res = await doFetch(config.endpoint, {
|
|
282
290
|
method: "POST",
|
|
@@ -284,10 +292,11 @@ function createMetricsRecorder(ctx, deps = {}) {
|
|
|
284
292
|
body: buildLogsPayload(records, server),
|
|
285
293
|
keepalive: true
|
|
286
294
|
});
|
|
287
|
-
if (!res.ok)
|
|
288
|
-
log.
|
|
295
|
+
if (!res.ok) {
|
|
296
|
+
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
297
|
+
}
|
|
289
298
|
} catch (err) {
|
|
290
|
-
log.
|
|
299
|
+
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
291
300
|
}
|
|
292
301
|
};
|
|
293
302
|
const ensureTimer = () => {
|
|
@@ -873,14 +882,24 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
873
882
|
try {
|
|
874
883
|
result = await tool.handler(args, new ToolContext(auth));
|
|
875
884
|
} catch {
|
|
876
|
-
recorder
|
|
885
|
+
reportInvocation(recorder, {
|
|
886
|
+
tool: tool.name,
|
|
887
|
+
method: "tools/call",
|
|
888
|
+
outcome: "handler_error",
|
|
889
|
+
durationMs: nowMs() - start
|
|
890
|
+
});
|
|
877
891
|
return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
|
|
878
892
|
}
|
|
879
893
|
if (result == null) {
|
|
880
|
-
recorder
|
|
894
|
+
reportInvocation(recorder, {
|
|
895
|
+
tool: tool.name,
|
|
896
|
+
method: "tools/call",
|
|
897
|
+
outcome: "handler_error",
|
|
898
|
+
durationMs: nowMs() - start
|
|
899
|
+
});
|
|
881
900
|
return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
|
|
882
901
|
}
|
|
883
|
-
recorder
|
|
902
|
+
reportInvocation(recorder, {
|
|
884
903
|
tool: tool.name,
|
|
885
904
|
method: "tools/call",
|
|
886
905
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -1113,20 +1132,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
|
|
|
1113
1132
|
try {
|
|
1114
1133
|
result = await tool.handler(args, new ToolContext(authResult.auth));
|
|
1115
1134
|
} catch {
|
|
1116
|
-
recorder
|
|
1135
|
+
reportInvocation(recorder, {
|
|
1136
|
+
tool: tool.name,
|
|
1137
|
+
method: "tools/call",
|
|
1138
|
+
outcome: "handler_error",
|
|
1139
|
+
durationMs: nowMs() - start
|
|
1140
|
+
});
|
|
1117
1141
|
return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
|
|
1118
1142
|
status: 500,
|
|
1119
1143
|
headers: JSON_HEADERS
|
|
1120
1144
|
});
|
|
1121
1145
|
}
|
|
1122
1146
|
if (result == null) {
|
|
1123
|
-
recorder
|
|
1147
|
+
reportInvocation(recorder, {
|
|
1148
|
+
tool: tool.name,
|
|
1149
|
+
method: "tools/call",
|
|
1150
|
+
outcome: "handler_error",
|
|
1151
|
+
durationMs: nowMs() - start
|
|
1152
|
+
});
|
|
1124
1153
|
return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
|
|
1125
1154
|
status: 500,
|
|
1126
1155
|
headers: JSON_HEADERS
|
|
1127
1156
|
});
|
|
1128
1157
|
}
|
|
1129
|
-
recorder
|
|
1158
|
+
reportInvocation(recorder, {
|
|
1130
1159
|
tool: tool.name,
|
|
1131
1160
|
method: "tools/call",
|
|
1132
1161
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -3,21 +3,21 @@ import {
|
|
|
3
3
|
} from "../../chunk-UQK5UO6C.js";
|
|
4
4
|
import {
|
|
5
5
|
createMcpProtocolHandler
|
|
6
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-EZQVUNXB.js";
|
|
7
7
|
import {
|
|
8
8
|
createOAuthProtectedResourceMetadataHandler
|
|
9
|
-
} from "../../chunk-
|
|
9
|
+
} from "../../chunk-T24Z753F.js";
|
|
10
10
|
import {
|
|
11
11
|
createInvokeToolHandler
|
|
12
|
-
} from "../../chunk-
|
|
12
|
+
} from "../../chunk-W2EZWPJ5.js";
|
|
13
13
|
import {
|
|
14
14
|
createListToolsHandler
|
|
15
|
-
} from "../../chunk-
|
|
15
|
+
} from "../../chunk-I5CAQUQI.js";
|
|
16
16
|
import "../../chunk-MA5H6PSF.js";
|
|
17
|
-
import "../../chunk-
|
|
17
|
+
import "../../chunk-H6BKTNJY.js";
|
|
18
18
|
import "../../chunk-DCWYK4CA.js";
|
|
19
19
|
import "../../chunk-6DXGZZA4.js";
|
|
20
|
-
import "../../chunk-
|
|
20
|
+
import "../../chunk-SKSKC747.js";
|
|
21
21
|
|
|
22
22
|
// src/stacks/tanstack/handlers.ts
|
|
23
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.
|
|
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": {
|