@lovable.dev/mcp-js 0.16.0 → 0.19.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/{recorder-qlzUKFxG.d.ts → base-C9rhAHZ0.d.ts} +3 -4
- package/dist/{chunk-W2EZWPJ5.js → chunk-57ZH2WW5.js} +11 -12
- package/dist/{chunk-H6BKTNJY.js → chunk-5FX6IIQ6.js} +129 -105
- package/dist/{chunk-SKSKC747.js → chunk-CDZ7MBXC.js} +1 -1
- package/dist/{chunk-EZQVUNXB.js → chunk-CLXKPZZE.js} +13 -14
- package/dist/{chunk-DCWYK4CA.js → chunk-H37EB22A.js} +13 -9
- package/dist/{chunk-I5CAQUQI.js → chunk-OMWXY6WY.js} +8 -8
- package/dist/{chunk-T24Z753F.js → chunk-UEOBGHXF.js} +2 -2
- package/dist/cli/extract-manifest.cjs +4 -3
- package/dist/cli/extract-manifest.js +4 -4
- package/dist/index.cjs +4 -9
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/protocols/mcp/index.cjs +19 -225
- package/dist/protocols/mcp/index.d.cts +6 -5
- package/dist/protocols/mcp/index.d.ts +6 -5
- package/dist/protocols/mcp/index.js +4 -4
- package/dist/protocols/oauth-metadata.cjs +3 -2
- package/dist/protocols/oauth-metadata.d.cts +1 -1
- package/dist/protocols/oauth-metadata.d.ts +1 -1
- package/dist/protocols/oauth-metadata.js +4 -4
- package/dist/protocols/rest/index.cjs +24 -230
- package/dist/protocols/rest/index.d.cts +6 -6
- package/dist/protocols/rest/index.d.ts +6 -6
- package/dist/protocols/rest/index.js +5 -5
- package/dist/stacks/supabase/index.cjs +196 -169
- package/dist/stacks/supabase/index.d.cts +1 -1
- package/dist/stacks/supabase/index.d.ts +1 -1
- package/dist/stacks/supabase/index.js +14 -14
- package/dist/stacks/supabase/vite.cjs +1 -1
- package/dist/stacks/supabase/vite.js +1 -1
- package/dist/stacks/tanstack/index.cjs +205 -177
- package/dist/stacks/tanstack/index.d.cts +1 -1
- package/dist/stacks/tanstack/index.d.ts +1 -1
- package/dist/stacks/tanstack/index.js +13 -10
- package/dist/{types-COY42xux.d.ts → types-CPkhCRxc.d.ts} +3 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -31,9 +31,6 @@ module.exports = __toCommonJS(src_exports);
|
|
|
31
31
|
// src/metrics/config.ts
|
|
32
32
|
var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
|
|
33
33
|
var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
|
|
34
|
-
var METRICS_SAMPLE_RATE = 1;
|
|
35
|
-
var METRICS_FLUSH_INTERVAL_MS = 5e3;
|
|
36
|
-
var METRICS_MAX_BATCH_SIZE = 50;
|
|
37
34
|
function assertMetricsEndpoint(endpoint) {
|
|
38
35
|
let url;
|
|
39
36
|
try {
|
|
@@ -53,10 +50,7 @@ function resolveMetricsConfig(config = true) {
|
|
|
53
50
|
enabled: options.enabled ?? true,
|
|
54
51
|
endpoint,
|
|
55
52
|
headers: options.headers ?? {},
|
|
56
|
-
apiKeyEnvVar: METRICS_API_KEY_ENV_VAR
|
|
57
|
-
sampleRate: METRICS_SAMPLE_RATE,
|
|
58
|
-
flushIntervalMs: METRICS_FLUSH_INTERVAL_MS,
|
|
59
|
-
maxBatchSize: METRICS_MAX_BATCH_SIZE
|
|
53
|
+
apiKeyEnvVar: METRICS_API_KEY_ENV_VAR
|
|
60
54
|
});
|
|
61
55
|
}
|
|
62
56
|
|
|
@@ -319,16 +313,17 @@ var LEVEL_RANK = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
|
|
|
319
313
|
function isLogLevel(value) {
|
|
320
314
|
return typeof value === "string" && value in LEVEL_RANK;
|
|
321
315
|
}
|
|
316
|
+
var LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
|
|
322
317
|
function readEnvLevel() {
|
|
323
318
|
try {
|
|
324
|
-
const raw = typeof process !== "undefined" ? process.env?.[
|
|
319
|
+
const raw = typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0;
|
|
325
320
|
const normalized = raw?.trim().toLowerCase();
|
|
326
321
|
return isLogLevel(normalized) ? normalized : void 0;
|
|
327
322
|
} catch {
|
|
328
323
|
return void 0;
|
|
329
324
|
}
|
|
330
325
|
}
|
|
331
|
-
var currentLevel = readEnvLevel() ?? "
|
|
326
|
+
var currentLevel = readEnvLevel() ?? "debug";
|
|
332
327
|
function setLogLevel(level) {
|
|
333
328
|
currentLevel = level;
|
|
334
329
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { e as McpDefinitionInput, d as McpDefinition, Z as ZodRawShape, l as ToolDefinition, M as McpAuthConfig } from './types-
|
|
2
|
-
export { A as AudioContent, C as ContentAnnotations, a as ContentBlock, E as EmbeddedBlobResource, b as EmbeddedResource, c as EmbeddedTextResource, I as ImageContent, J as JwtClaims, f as MetricsConfig, g as MetricsOptions, R as ResourceLink, h as ResourceLinkIcon, T as TextContent, i as ToolAnnotations, j as ToolContent, k as ToolContext, m as ToolHandlerResult, n as ZodSchema } from './types-
|
|
1
|
+
import { e as McpDefinitionInput, d as McpDefinition, Z as ZodRawShape, l as ToolDefinition, M as McpAuthConfig } from './types-CPkhCRxc.js';
|
|
2
|
+
export { A as AudioContent, C as ContentAnnotations, a as ContentBlock, E as EmbeddedBlobResource, b as EmbeddedResource, c as EmbeddedTextResource, I as ImageContent, J as JwtClaims, f as MetricsConfig, g as MetricsOptions, R as ResourceLink, h as ResourceLinkIcon, T as TextContent, i as ToolAnnotations, j as ToolContent, k as ToolContext, m as ToolHandlerResult, n as ZodSchema } from './types-CPkhCRxc.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { e as McpDefinitionInput, d as McpDefinition, Z as ZodRawShape, l as ToolDefinition, M as McpAuthConfig } from './types-
|
|
2
|
-
export { A as AudioContent, C as ContentAnnotations, a as ContentBlock, E as EmbeddedBlobResource, b as EmbeddedResource, c as EmbeddedTextResource, I as ImageContent, J as JwtClaims, f as MetricsConfig, g as MetricsOptions, R as ResourceLink, h as ResourceLinkIcon, T as TextContent, i as ToolAnnotations, j as ToolContent, k as ToolContext, m as ToolHandlerResult, n as ZodSchema } from './types-
|
|
1
|
+
import { e as McpDefinitionInput, d as McpDefinition, Z as ZodRawShape, l as ToolDefinition, M as McpAuthConfig } from './types-CPkhCRxc.js';
|
|
2
|
+
export { A as AudioContent, C as ContentAnnotations, a as ContentBlock, E as EmbeddedBlobResource, b as EmbeddedResource, c as EmbeddedTextResource, I as ImageContent, J as JwtClaims, f as MetricsConfig, g as MetricsOptions, R as ResourceLink, h as ResourceLinkIcon, T as TextContent, i as ToolAnnotations, j as ToolContent, k as ToolContext, m as ToolHandlerResult, n as ZodSchema } from './types-CPkhCRxc.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
/**
|
package/dist/index.js
CHANGED
|
@@ -36,16 +36,17 @@ var LEVEL_RANK = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
|
|
|
36
36
|
function isLogLevel(value) {
|
|
37
37
|
return typeof value === "string" && value in LEVEL_RANK;
|
|
38
38
|
}
|
|
39
|
+
var LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
|
|
39
40
|
function readEnvLevel() {
|
|
40
41
|
try {
|
|
41
|
-
const raw = typeof process !== "undefined" ? process.env?.[
|
|
42
|
+
const raw = typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0;
|
|
42
43
|
const normalized = raw?.trim().toLowerCase();
|
|
43
44
|
return isLogLevel(normalized) ? normalized : void 0;
|
|
44
45
|
} catch {
|
|
45
46
|
return void 0;
|
|
46
47
|
}
|
|
47
48
|
}
|
|
48
|
-
var currentLevel = readEnvLevel() ?? "
|
|
49
|
+
var currentLevel = readEnvLevel() ?? "debug";
|
|
49
50
|
function enabled(level) {
|
|
50
51
|
return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
|
|
51
52
|
}
|
|
@@ -72,222 +73,15 @@ function describeError(err) {
|
|
|
72
73
|
return { value: String(err) };
|
|
73
74
|
}
|
|
74
75
|
|
|
75
|
-
// src/metrics/
|
|
76
|
-
var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
|
|
77
|
-
var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
|
|
78
|
-
var METRICS_SAMPLE_RATE = 1;
|
|
79
|
-
var METRICS_FLUSH_INTERVAL_MS = 5e3;
|
|
80
|
-
var METRICS_MAX_BATCH_SIZE = 50;
|
|
81
|
-
function assertMetricsEndpoint(endpoint) {
|
|
82
|
-
let url;
|
|
83
|
-
try {
|
|
84
|
-
url = new URL(endpoint);
|
|
85
|
-
} catch {
|
|
86
|
-
throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
|
|
87
|
-
}
|
|
88
|
-
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
89
|
-
throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
function resolveMetricsConfig(config = true) {
|
|
93
|
-
const options = typeof config === "boolean" ? { enabled: config } : config;
|
|
94
|
-
const endpoint = options.endpoint ?? DEFAULT_METRICS_ENDPOINT;
|
|
95
|
-
assertMetricsEndpoint(endpoint);
|
|
96
|
-
return Object.freeze({
|
|
97
|
-
enabled: options.enabled ?? true,
|
|
98
|
-
endpoint,
|
|
99
|
-
headers: options.headers ?? {},
|
|
100
|
-
apiKeyEnvVar: METRICS_API_KEY_ENV_VAR,
|
|
101
|
-
sampleRate: METRICS_SAMPLE_RATE,
|
|
102
|
-
flushIntervalMs: METRICS_FLUSH_INTERVAL_MS,
|
|
103
|
-
maxBatchSize: METRICS_MAX_BATCH_SIZE
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// package.json
|
|
108
|
-
var version = "0.16.0";
|
|
109
|
-
|
|
110
|
-
// src/metrics/otlp.ts
|
|
111
|
-
var SCOPE_NAME = "@lovable.dev/mcp-js";
|
|
112
|
-
var EVENT_NAME = "mcp.tool.invocation";
|
|
113
|
-
var SEVERITY_INFO = 9;
|
|
114
|
-
function strAttr(key, value) {
|
|
115
|
-
return { key, value: { stringValue: value } };
|
|
116
|
-
}
|
|
117
|
-
function intAttr(key, value) {
|
|
118
|
-
return { key, value: { intValue: String(Math.round(value)) } };
|
|
119
|
-
}
|
|
120
|
-
function toLogRecord(rec) {
|
|
121
|
-
const attributes = [
|
|
122
|
-
strAttr("event.name", EVENT_NAME),
|
|
123
|
-
strAttr("mcp.method", rec.method),
|
|
124
|
-
strAttr("mcp.outcome", rec.outcome),
|
|
125
|
-
intAttr("mcp.duration_ms", rec.durationMs)
|
|
126
|
-
];
|
|
127
|
-
if (rec.tool !== null)
|
|
128
|
-
attributes.push(strAttr("mcp.tool", rec.tool));
|
|
129
|
-
if (rec.reqBytes !== void 0)
|
|
130
|
-
attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
|
|
131
|
-
if (rec.resBytes !== void 0)
|
|
132
|
-
attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
|
|
133
|
-
return {
|
|
134
|
-
timeUnixNano: rec.timeUnixNano,
|
|
135
|
-
observedTimeUnixNano: rec.timeUnixNano,
|
|
136
|
-
severityNumber: SEVERITY_INFO,
|
|
137
|
-
severityText: "INFO",
|
|
138
|
-
body: { stringValue: EVENT_NAME },
|
|
139
|
-
attributes
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
function buildLogsPayload(records, server) {
|
|
143
|
-
return JSON.stringify({
|
|
144
|
-
resourceLogs: [
|
|
145
|
-
{
|
|
146
|
-
resource: {
|
|
147
|
-
attributes: [
|
|
148
|
-
strAttr("service.name", server.name),
|
|
149
|
-
strAttr("service.version", server.version),
|
|
150
|
-
strAttr("telemetry.sdk.name", SCOPE_NAME),
|
|
151
|
-
strAttr("telemetry.sdk.version", version),
|
|
152
|
-
strAttr("telemetry.sdk.language", "webjs")
|
|
153
|
-
]
|
|
154
|
-
},
|
|
155
|
-
scopeLogs: [
|
|
156
|
-
{
|
|
157
|
-
scope: { name: SCOPE_NAME, version },
|
|
158
|
-
logRecords: records.map(toLogRecord)
|
|
159
|
-
}
|
|
160
|
-
]
|
|
161
|
-
}
|
|
162
|
-
]
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
function nowUnixNano() {
|
|
166
|
-
return `${Date.now()}000000`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// src/metrics/recorder.ts
|
|
76
|
+
// src/metrics/impl/base.ts
|
|
170
77
|
function nowMs() {
|
|
171
78
|
return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
|
|
172
79
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
recorder.record(ev);
|
|
176
|
-
}
|
|
177
|
-
var NOOP_RECORDER = {
|
|
178
|
-
record() {
|
|
179
|
-
},
|
|
180
|
-
async flush() {
|
|
181
|
-
}
|
|
182
|
-
};
|
|
80
|
+
var NOOP_RECORDER = { async emit() {
|
|
81
|
+
} };
|
|
183
82
|
function createNoopRecorder() {
|
|
184
83
|
return NOOP_RECORDER;
|
|
185
84
|
}
|
|
186
|
-
function readRuntimeEnv(name) {
|
|
187
|
-
try {
|
|
188
|
-
const denoEnv = globalThis.Deno?.env;
|
|
189
|
-
const value = denoEnv?.get?.(name);
|
|
190
|
-
if (value)
|
|
191
|
-
return value;
|
|
192
|
-
} catch {
|
|
193
|
-
}
|
|
194
|
-
try {
|
|
195
|
-
if (typeof process !== "undefined") {
|
|
196
|
-
const value = process.env?.[name];
|
|
197
|
-
if (value)
|
|
198
|
-
return value;
|
|
199
|
-
}
|
|
200
|
-
} catch {
|
|
201
|
-
}
|
|
202
|
-
return void 0;
|
|
203
|
-
}
|
|
204
|
-
function probeWaitUntil() {
|
|
205
|
-
const fn = globalThis.EdgeRuntime?.waitUntil;
|
|
206
|
-
return typeof fn === "function" ? fn.bind(globalThis.EdgeRuntime) : void 0;
|
|
207
|
-
}
|
|
208
|
-
function createMetricsRecorder(ctx, deps = {}) {
|
|
209
|
-
const { config, server } = ctx;
|
|
210
|
-
if (!config.enabled)
|
|
211
|
-
return NOOP_RECORDER;
|
|
212
|
-
const doFetch = deps.fetch ?? globalThis.fetch;
|
|
213
|
-
if (!doFetch) {
|
|
214
|
-
log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
|
|
215
|
-
return NOOP_RECORDER;
|
|
216
|
-
}
|
|
217
|
-
const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
|
|
218
|
-
const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
|
|
219
|
-
if (usesLovableEndpoint && !apiKey) {
|
|
220
|
-
log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
|
|
221
|
-
return NOOP_RECORDER;
|
|
222
|
-
}
|
|
223
|
-
const waitUntil = deps.waitUntil ?? probeWaitUntil();
|
|
224
|
-
const buffer = [];
|
|
225
|
-
let timer;
|
|
226
|
-
const schedule = (p) => {
|
|
227
|
-
if (waitUntil) {
|
|
228
|
-
try {
|
|
229
|
-
waitUntil(p);
|
|
230
|
-
return;
|
|
231
|
-
} catch (err) {
|
|
232
|
-
log.warn("metrics.wait_until_failed", describeError(err));
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
void p.catch(() => {
|
|
236
|
-
});
|
|
237
|
-
};
|
|
238
|
-
const headers = {};
|
|
239
|
-
if (!usesLovableEndpoint) {
|
|
240
|
-
for (const [key, value] of Object.entries(config.headers)) {
|
|
241
|
-
if (key.toLowerCase() !== "content-type")
|
|
242
|
-
headers[key] = value;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
headers["content-type"] = "application/json";
|
|
246
|
-
if (apiKey)
|
|
247
|
-
headers.authorization = `Bearer ${apiKey}`;
|
|
248
|
-
const flush = async () => {
|
|
249
|
-
if (buffer.length === 0)
|
|
250
|
-
return;
|
|
251
|
-
const records = buffer.splice(0, buffer.length);
|
|
252
|
-
const dropped = records.length;
|
|
253
|
-
try {
|
|
254
|
-
const res = await doFetch(config.endpoint, {
|
|
255
|
-
method: "POST",
|
|
256
|
-
headers,
|
|
257
|
-
body: buildLogsPayload(records, server),
|
|
258
|
-
keepalive: true
|
|
259
|
-
});
|
|
260
|
-
if (!res.ok) {
|
|
261
|
-
log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
|
|
262
|
-
}
|
|
263
|
-
} catch (err) {
|
|
264
|
-
log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
|
|
265
|
-
}
|
|
266
|
-
};
|
|
267
|
-
const ensureTimer = () => {
|
|
268
|
-
if (timer !== void 0)
|
|
269
|
-
return;
|
|
270
|
-
timer = setInterval(() => schedule(flush()), config.flushIntervalMs);
|
|
271
|
-
timer.unref?.();
|
|
272
|
-
};
|
|
273
|
-
return {
|
|
274
|
-
record(ev) {
|
|
275
|
-
if (config.sampleRate < 1 && Math.random() >= config.sampleRate)
|
|
276
|
-
return;
|
|
277
|
-
buffer.push({ ...ev, timeUnixNano: nowUnixNano() });
|
|
278
|
-
ensureTimer();
|
|
279
|
-
if (buffer.length >= config.maxBatchSize)
|
|
280
|
-
schedule(flush());
|
|
281
|
-
},
|
|
282
|
-
flush
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
function createRecorderForRuntime(mcp) {
|
|
286
|
-
const config = resolveMetricsConfig(mcp.metrics);
|
|
287
|
-
if (!config.enabled)
|
|
288
|
-
return createNoopRecorder();
|
|
289
|
-
return createMetricsRecorder({ config, server: { name: mcp.name, version: mcp.version } });
|
|
290
|
-
}
|
|
291
85
|
|
|
292
86
|
// src/core/promise.ts
|
|
293
87
|
function cachedPromise(load, label) {
|
|
@@ -709,10 +503,10 @@ function assertRequiredScopes(auth, context) {
|
|
|
709
503
|
throw new OAuthTokenError(403, "insufficient_scope", "Additional OAuth scope is required");
|
|
710
504
|
}
|
|
711
505
|
}
|
|
712
|
-
function createRequestAuthorizer(mcp, options = {}
|
|
506
|
+
function createRequestAuthorizer(mcp, options = {}) {
|
|
713
507
|
const runtime = getOAuthRuntime(mcp, options);
|
|
714
508
|
return {
|
|
715
|
-
async authorize(request) {
|
|
509
|
+
async authorize(request, recorder) {
|
|
716
510
|
if (runtime.kind === "unconfigured")
|
|
717
511
|
return { ok: true };
|
|
718
512
|
const startedAt = nowMs();
|
|
@@ -728,7 +522,7 @@ function createRequestAuthorizer(mcp, options = {}, recorder) {
|
|
|
728
522
|
} catch (err) {
|
|
729
523
|
if (err instanceof OAuthConfigurationError) {
|
|
730
524
|
log.error("auth.config_error", { ...describeError(err), outcome: "500" });
|
|
731
|
-
recorder?.
|
|
525
|
+
await recorder?.emit({
|
|
732
526
|
tool: null,
|
|
733
527
|
method: "authorize",
|
|
734
528
|
outcome: "auth_config_error",
|
|
@@ -839,7 +633,7 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
839
633
|
try {
|
|
840
634
|
result = await tool.handler(args, new ToolContext(auth));
|
|
841
635
|
} catch {
|
|
842
|
-
|
|
636
|
+
await recorder.emit({
|
|
843
637
|
tool: tool.name,
|
|
844
638
|
method: "tools/call",
|
|
845
639
|
outcome: "handler_error",
|
|
@@ -848,7 +642,7 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
848
642
|
return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
|
|
849
643
|
}
|
|
850
644
|
if (result == null) {
|
|
851
|
-
|
|
645
|
+
await recorder.emit({
|
|
852
646
|
tool: tool.name,
|
|
853
647
|
method: "tools/call",
|
|
854
648
|
outcome: "handler_error",
|
|
@@ -856,7 +650,7 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
856
650
|
});
|
|
857
651
|
return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
|
|
858
652
|
}
|
|
859
|
-
|
|
653
|
+
await recorder.emit({
|
|
860
654
|
tool: tool.name,
|
|
861
655
|
method: "tools/call",
|
|
862
656
|
outcome: result.isError ? "tool_error" : "ok",
|
|
@@ -865,10 +659,10 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
|
|
|
865
659
|
return { content: result.content ?? [], structuredContent: result.structuredContent, isError: result.isError };
|
|
866
660
|
};
|
|
867
661
|
}
|
|
868
|
-
function createMcpProtocolHandler(mcp, options = {}
|
|
869
|
-
const authorizer = createRequestAuthorizer(mcp, options
|
|
870
|
-
const handle = async (request) => {
|
|
871
|
-
const authResult = await authorizer.authorize(request);
|
|
662
|
+
function createMcpProtocolHandler(mcp, options = {}) {
|
|
663
|
+
const authorizer = createRequestAuthorizer(mcp, options);
|
|
664
|
+
const handle = async (request, recorder) => {
|
|
665
|
+
const authResult = await authorizer.authorize(request, recorder);
|
|
872
666
|
if (!authResult.ok)
|
|
873
667
|
return authResult.response;
|
|
874
668
|
try {
|
|
@@ -895,7 +689,7 @@ function createMcpProtocolHandler(mcp, options = {}, recorder = createRecorderFo
|
|
|
895
689
|
await server.connect(transport);
|
|
896
690
|
return await transport.handleRequest(request);
|
|
897
691
|
} catch (err) {
|
|
898
|
-
recorder.
|
|
692
|
+
await recorder.emit({ tool: null, method: "transport", outcome: "transport_error", durationMs: 0 });
|
|
899
693
|
log.error("mcp.transport_error", { ...describeError(err), outcome: "500 internal error" });
|
|
900
694
|
return Response.json(
|
|
901
695
|
{ jsonrpc: "2.0", id: null, error: { code: -32603, message: "internal error" } },
|
|
@@ -903,10 +697,10 @@ function createMcpProtocolHandler(mcp, options = {}, recorder = createRecorderFo
|
|
|
903
697
|
);
|
|
904
698
|
}
|
|
905
699
|
};
|
|
906
|
-
return async (request) => {
|
|
700
|
+
return async (request, recorder = createNoopRecorder()) => {
|
|
907
701
|
if (request.method === "OPTIONS")
|
|
908
702
|
return corsPreflightResponse("GET, POST, DELETE, OPTIONS");
|
|
909
|
-
return withCors(await handle(request));
|
|
703
|
+
return withCors(await handle(request, recorder));
|
|
910
704
|
};
|
|
911
705
|
}
|
|
912
706
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
|
|
2
|
-
import { d as McpDefinition } from '../../types-
|
|
3
|
-
import { M as MetricsRecorder } from '../../
|
|
2
|
+
import { d as McpDefinition } from '../../types-CPkhCRxc.js';
|
|
3
|
+
import { M as MetricsRecorder } from '../../base-C9rhAHZ0.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
6
|
-
type McpProtocolHandler = (request: Request) => Promise<Response>;
|
|
6
|
+
type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
|
|
7
7
|
/**
|
|
8
8
|
* Build a Web-Standard request handler that serves the MCP protocol over
|
|
9
9
|
* streamable HTTP. A fresh `McpServer` + transport is constructed per
|
|
10
10
|
* request — the transport is stateless, so this is cheap and there is no
|
|
11
|
-
* cross-request state to leak.
|
|
11
|
+
* cross-request state to leak. The per-request `recorder` is supplied by the
|
|
12
|
+
* caller (the stack handler) so telemetry reads the runtime env in-flight.
|
|
12
13
|
*/
|
|
13
|
-
declare function createMcpProtocolHandler(mcp: McpDefinition, options?: McpRuntimeOptions
|
|
14
|
+
declare function createMcpProtocolHandler(mcp: McpDefinition, options?: McpRuntimeOptions): McpProtocolHandler;
|
|
14
15
|
|
|
15
16
|
export { type McpProtocolHandler, createMcpProtocolHandler };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
|
|
2
|
-
import { d as McpDefinition } from '../../types-
|
|
3
|
-
import { M as MetricsRecorder } from '../../
|
|
2
|
+
import { d as McpDefinition } from '../../types-CPkhCRxc.js';
|
|
3
|
+
import { M as MetricsRecorder } from '../../base-C9rhAHZ0.js';
|
|
4
4
|
import 'zod';
|
|
5
5
|
|
|
6
|
-
type McpProtocolHandler = (request: Request) => Promise<Response>;
|
|
6
|
+
type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
|
|
7
7
|
/**
|
|
8
8
|
* Build a Web-Standard request handler that serves the MCP protocol over
|
|
9
9
|
* streamable HTTP. A fresh `McpServer` + transport is constructed per
|
|
10
10
|
* request — the transport is stateless, so this is cheap and there is no
|
|
11
|
-
* cross-request state to leak.
|
|
11
|
+
* cross-request state to leak. The per-request `recorder` is supplied by the
|
|
12
|
+
* caller (the stack handler) so telemetry reads the runtime env in-flight.
|
|
12
13
|
*/
|
|
13
|
-
declare function createMcpProtocolHandler(mcp: McpDefinition, options?: McpRuntimeOptions
|
|
14
|
+
declare function createMcpProtocolHandler(mcp: McpDefinition, options?: McpRuntimeOptions): McpProtocolHandler;
|
|
14
15
|
|
|
15
16
|
export { type McpProtocolHandler, createMcpProtocolHandler };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createMcpProtocolHandler
|
|
3
|
-
} from "../../chunk-
|
|
3
|
+
} from "../../chunk-CLXKPZZE.js";
|
|
4
4
|
import "../../chunk-MA5H6PSF.js";
|
|
5
|
-
import "../../chunk-
|
|
6
|
-
import "../../chunk-
|
|
5
|
+
import "../../chunk-5FX6IIQ6.js";
|
|
6
|
+
import "../../chunk-H37EB22A.js";
|
|
7
7
|
import "../../chunk-6DXGZZA4.js";
|
|
8
|
-
import "../../chunk-
|
|
8
|
+
import "../../chunk-CDZ7MBXC.js";
|
|
9
9
|
export {
|
|
10
10
|
createMcpProtocolHandler
|
|
11
11
|
};
|
|
@@ -41,16 +41,17 @@ var LEVEL_RANK = { silent: 0, error: 1, warn: 2, info: 3, debug: 4 };
|
|
|
41
41
|
function isLogLevel(value) {
|
|
42
42
|
return typeof value === "string" && value in LEVEL_RANK;
|
|
43
43
|
}
|
|
44
|
+
var LOG_LEVEL_ENV_VAR = "LOVABLE_MCP_LOG_LEVEL";
|
|
44
45
|
function readEnvLevel() {
|
|
45
46
|
try {
|
|
46
|
-
const raw = typeof process !== "undefined" ? process.env?.[
|
|
47
|
+
const raw = typeof process !== "undefined" ? process.env?.[LOG_LEVEL_ENV_VAR] : void 0;
|
|
47
48
|
const normalized = raw?.trim().toLowerCase();
|
|
48
49
|
return isLogLevel(normalized) ? normalized : void 0;
|
|
49
50
|
} catch {
|
|
50
51
|
return void 0;
|
|
51
52
|
}
|
|
52
53
|
}
|
|
53
|
-
var currentLevel = readEnvLevel() ?? "
|
|
54
|
+
var currentLevel = readEnvLevel() ?? "debug";
|
|
54
55
|
function enabled(level) {
|
|
55
56
|
return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
|
|
56
57
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { M as McpRuntimeOptions } from '../authorize-BMeXd_Sh.js';
|
|
2
|
-
import { d as McpDefinition } from '../types-
|
|
2
|
+
import { d as McpDefinition } from '../types-CPkhCRxc.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
type OAuthProtectedResourceMetadataHandler = (request: Request) => Promise<Response>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { M as McpRuntimeOptions } from '../authorize-BMeXd_Sh.js';
|
|
2
|
-
import { d as McpDefinition } from '../types-
|
|
2
|
+
import { d as McpDefinition } from '../types-CPkhCRxc.js';
|
|
3
3
|
import 'zod';
|
|
4
4
|
|
|
5
5
|
type OAuthProtectedResourceMetadataHandler = (request: Request) => Promise<Response>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createOAuthProtectedResourceMetadataHandler
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-UEOBGHXF.js";
|
|
4
|
+
import "../chunk-5FX6IIQ6.js";
|
|
5
|
+
import "../chunk-H37EB22A.js";
|
|
6
6
|
import "../chunk-6DXGZZA4.js";
|
|
7
|
-
import "../chunk-
|
|
7
|
+
import "../chunk-CDZ7MBXC.js";
|
|
8
8
|
export {
|
|
9
9
|
createOAuthProtectedResourceMetadataHandler
|
|
10
10
|
};
|