@lovable.dev/mcp-js 0.21.0 → 0.21.1-rc.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.
@@ -12,6 +12,9 @@ interface InvocationRecord {
12
12
  durationMs: number;
13
13
  reqBytes?: number;
14
14
  resBytes?: number;
15
+ /** The app end-user that made the call (the access token `sub`), or
16
+ * `undefined` when the request is unauthenticated. Not a Lovable identity. */
17
+ endUserId?: string;
15
18
  /** The `tool_error` message (text content of an `isError` result). Local log
16
19
  * only — never sent to the collector, so it stays on-box for the operator. */
17
20
  errorText?: string;
@@ -13,7 +13,7 @@ import {
13
13
  methodNotAllowed,
14
14
  nowMs,
15
15
  withCors
16
- } from "./chunk-YLU2JTHL.js";
16
+ } from "./chunk-SJJDRA6X.js";
17
17
 
18
18
  // src/protocols/rest/invoke-tool.ts
19
19
  import { getParseErrorMessage, objectFromShape, safeParseAsync } from "@modelcontextprotocol/sdk/server/zod-compat.js";
@@ -36,6 +36,7 @@ function createInvokeToolHandler(mcp, options = {}) {
36
36
  const authResult = await authorizer.authorize(request, recorder);
37
37
  if (!authResult.ok)
38
38
  return authResult.response;
39
+ const endUserId = authResult.auth?.principal.sub;
39
40
  if (request.method !== "POST")
40
41
  return methodNotAllowed("POST, OPTIONS");
41
42
  const tool = mcp.tools.find((t) => t.name === toolName);
@@ -93,7 +94,8 @@ function createInvokeToolHandler(mcp, options = {}) {
93
94
  tool: tool.name,
94
95
  method: "tools/call",
95
96
  outcome: "handler_error",
96
- durationMs: nowMs() - start
97
+ durationMs: nowMs() - start,
98
+ endUserId
97
99
  });
98
100
  return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
99
101
  status: 500,
@@ -105,7 +107,8 @@ function createInvokeToolHandler(mcp, options = {}) {
105
107
  tool: tool.name,
106
108
  method: "tools/call",
107
109
  outcome: "handler_error",
108
- durationMs: nowMs() - start
110
+ durationMs: nowMs() - start,
111
+ endUserId
109
112
  });
110
113
  return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
111
114
  status: 500,
@@ -117,7 +120,8 @@ function createInvokeToolHandler(mcp, options = {}) {
117
120
  method: "tools/call",
118
121
  outcome: result.isError ? "tool_error" : "ok",
119
122
  durationMs: nowMs() - start,
120
- errorText: result.isError ? extractTextContent(result.content) : void 0
123
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
124
+ endUserId
121
125
  });
122
126
  return Response.json({
123
127
  content: result.content ?? [],
@@ -10,7 +10,7 @@ import {
10
10
  createRequestAuthorizer,
11
11
  nowMs,
12
12
  withCors
13
- } from "./chunk-YLU2JTHL.js";
13
+ } from "./chunk-SJJDRA6X.js";
14
14
  import {
15
15
  describeError,
16
16
  log
@@ -20,6 +20,7 @@ import {
20
20
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
21
21
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
22
22
  function adaptToolToSdkCallback(tool, auth, recorder) {
23
+ const endUserId = auth?.principal.sub;
23
24
  return async (first) => {
24
25
  const args = tool.inputSchema ? first ?? {} : {};
25
26
  const start = nowMs();
@@ -31,7 +32,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
31
32
  tool: tool.name,
32
33
  method: "tools/call",
33
34
  outcome: "handler_error",
34
- durationMs: nowMs() - start
35
+ durationMs: nowMs() - start,
36
+ endUserId
35
37
  });
36
38
  return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
37
39
  }
@@ -40,7 +42,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
40
42
  tool: tool.name,
41
43
  method: "tools/call",
42
44
  outcome: "handler_error",
43
- durationMs: nowMs() - start
45
+ durationMs: nowMs() - start,
46
+ endUserId
44
47
  });
45
48
  return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
46
49
  }
@@ -49,7 +52,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
49
52
  method: "tools/call",
50
53
  outcome: result.isError ? "tool_error" : "ok",
51
54
  durationMs: nowMs() - start,
52
- errorText: result.isError ? extractTextContent(result.content) : void 0
55
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
56
+ endUserId
53
57
  });
54
58
  return { content: result.content ?? [], structuredContent: result.structuredContent, isError: result.isError };
55
59
  };
@@ -84,7 +88,13 @@ function createMcpProtocolHandler(mcp, options = {}) {
84
88
  await server.connect(transport);
85
89
  return await transport.handleRequest(request);
86
90
  } catch (err) {
87
- await recorder.emit({ tool: null, method: "transport", outcome: "transport_error", durationMs: 0 });
91
+ await recorder.emit({
92
+ tool: null,
93
+ method: "transport",
94
+ outcome: "transport_error",
95
+ durationMs: 0,
96
+ endUserId: authResult.auth?.principal.sub
97
+ });
88
98
  log.error("mcp.transport_error", { ...describeError(err), outcome: "500 internal error" });
89
99
  return Response.json(
90
100
  { jsonrpc: "2.0", id: null, error: { code: -32603, message: "internal error" } },
@@ -7,7 +7,7 @@ import {
7
7
  oauthConfigurationErrorResponse,
8
8
  resolveProtectedResource,
9
9
  withCors
10
- } from "./chunk-YLU2JTHL.js";
10
+ } from "./chunk-SJJDRA6X.js";
11
11
  import {
12
12
  describeError,
13
13
  log
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.21.0";
2
+ var version = "0.21.1-rc.0";
3
3
 
4
4
  export {
5
5
  version
@@ -13,7 +13,7 @@ import {
13
13
  } from "./chunk-6DXGZZA4.js";
14
14
  import {
15
15
  version
16
- } from "./chunk-E3Q3FRKQ.js";
16
+ } from "./chunk-L5ZOZKAL.js";
17
17
 
18
18
  // src/core/http.ts
19
19
  var JSON_HEADERS = { "Content-Type": "application/json" };
@@ -75,6 +75,8 @@ function toLogRecord(rec) {
75
75
  if (rec.resBytes !== void 0)
76
76
  attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
77
77
  attributes.push(strAttr("mcp.stack", rec.stack));
78
+ if (rec.endUserId !== void 0)
79
+ attributes.push(strAttr("mcp.end_user_id", rec.endUserId));
78
80
  return {
79
81
  timeUnixNano: rec.timeUnixNano,
80
82
  observedTimeUnixNano: rec.timeUnixNano,
@@ -6,7 +6,7 @@ import {
6
6
  headResponse,
7
7
  methodNotAllowed,
8
8
  withCors
9
- } from "./chunk-YLU2JTHL.js";
9
+ } from "./chunk-SJJDRA6X.js";
10
10
 
11
11
  // src/protocols/rest/list-tools.ts
12
12
  import { objectFromShape } from "@modelcontextprotocol/sdk/server/zod-compat.js";
@@ -13,7 +13,7 @@ function isFileMissing(err) {
13
13
  }
14
14
 
15
15
  // package.json
16
- var version = "0.21.0";
16
+ var version = "0.21.1-rc.0";
17
17
 
18
18
  // src/protocols/rest/list-tools.ts
19
19
  var import_zod_compat = require("@modelcontextprotocol/sdk/server/zod-compat.js");
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  buildMcpListing
4
- } from "../chunk-LFXK3FNF.js";
5
- import "../chunk-YLU2JTHL.js";
4
+ } from "../chunk-ZLWXDYOZ.js";
5
+ import "../chunk-SJJDRA6X.js";
6
6
  import "../chunk-H37EB22A.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-E3Q3FRKQ.js";
13
+ } from "../chunk-L5ZOZKAL.js";
14
14
 
15
15
  // src/manifest/io.ts
16
16
  import { randomUUID } from "crypto";
@@ -656,6 +656,7 @@ function corsPreflightResponse(allowMethods) {
656
656
 
657
657
  // src/protocols/mcp/protocol.ts
658
658
  function adaptToolToSdkCallback(tool, auth, recorder) {
659
+ const endUserId = auth?.principal.sub;
659
660
  return async (first) => {
660
661
  const args = tool.inputSchema ? first ?? {} : {};
661
662
  const start = nowMs();
@@ -667,7 +668,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
667
668
  tool: tool.name,
668
669
  method: "tools/call",
669
670
  outcome: "handler_error",
670
- durationMs: nowMs() - start
671
+ durationMs: nowMs() - start,
672
+ endUserId
671
673
  });
672
674
  return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
673
675
  }
@@ -676,7 +678,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
676
678
  tool: tool.name,
677
679
  method: "tools/call",
678
680
  outcome: "handler_error",
679
- durationMs: nowMs() - start
681
+ durationMs: nowMs() - start,
682
+ endUserId
680
683
  });
681
684
  return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
682
685
  }
@@ -685,7 +688,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
685
688
  method: "tools/call",
686
689
  outcome: result.isError ? "tool_error" : "ok",
687
690
  durationMs: nowMs() - start,
688
- errorText: result.isError ? extractTextContent(result.content) : void 0
691
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
692
+ endUserId
689
693
  });
690
694
  return { content: result.content ?? [], structuredContent: result.structuredContent, isError: result.isError };
691
695
  };
@@ -720,7 +724,13 @@ function createMcpProtocolHandler(mcp, options = {}) {
720
724
  await server.connect(transport);
721
725
  return await transport.handleRequest(request);
722
726
  } catch (err) {
723
- await recorder.emit({ tool: null, method: "transport", outcome: "transport_error", durationMs: 0 });
727
+ await recorder.emit({
728
+ tool: null,
729
+ method: "transport",
730
+ outcome: "transport_error",
731
+ durationMs: 0,
732
+ endUserId: authResult.auth?.principal.sub
733
+ });
724
734
  log.error("mcp.transport_error", { ...describeError(err), outcome: "500 internal error" });
725
735
  return Response.json(
726
736
  { jsonrpc: "2.0", id: null, error: { code: -32603, message: "internal error" } },
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-qqrmJ736.js';
3
- import { M as MetricsRecorder } from '../../base-CFy5vZ5Z.js';
3
+ import { M as MetricsRecorder } from '../../base-CM-KCpp6.js';
4
4
  import 'zod';
5
5
 
6
6
  type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-qqrmJ736.js';
3
- import { M as MetricsRecorder } from '../../base-CFy5vZ5Z.js';
3
+ import { M as MetricsRecorder } from '../../base-CM-KCpp6.js';
4
4
  import 'zod';
5
5
 
6
6
  type McpProtocolHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  createMcpProtocolHandler
3
- } from "../../chunk-CI7JYLV3.js";
3
+ } from "../../chunk-ACFNK34P.js";
4
4
  import "../../chunk-6QFZYYUV.js";
5
5
  import "../../chunk-MA5H6PSF.js";
6
- import "../../chunk-YLU2JTHL.js";
6
+ import "../../chunk-SJJDRA6X.js";
7
7
  import "../../chunk-H37EB22A.js";
8
8
  import "../../chunk-6DXGZZA4.js";
9
- import "../../chunk-E3Q3FRKQ.js";
9
+ import "../../chunk-L5ZOZKAL.js";
10
10
  export {
11
11
  createMcpProtocolHandler
12
12
  };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  createOAuthProtectedResourceMetadataHandler
3
- } from "../chunk-ENJDNFEB.js";
4
- import "../chunk-YLU2JTHL.js";
3
+ } from "../chunk-BLY5L4KI.js";
4
+ import "../chunk-SJJDRA6X.js";
5
5
  import "../chunk-H37EB22A.js";
6
6
  import "../chunk-6DXGZZA4.js";
7
- import "../chunk-E3Q3FRKQ.js";
7
+ import "../chunk-L5ZOZKAL.js";
8
8
  export {
9
9
  createOAuthProtectedResourceMetadataHandler
10
10
  };
@@ -737,6 +737,7 @@ function createInvokeToolHandler(mcp, options = {}) {
737
737
  const authResult = await authorizer.authorize(request, recorder);
738
738
  if (!authResult.ok)
739
739
  return authResult.response;
740
+ const endUserId = authResult.auth?.principal.sub;
740
741
  if (request.method !== "POST")
741
742
  return methodNotAllowed("POST, OPTIONS");
742
743
  const tool = mcp.tools.find((t) => t.name === toolName);
@@ -794,7 +795,8 @@ function createInvokeToolHandler(mcp, options = {}) {
794
795
  tool: tool.name,
795
796
  method: "tools/call",
796
797
  outcome: "handler_error",
797
- durationMs: nowMs() - start
798
+ durationMs: nowMs() - start,
799
+ endUserId
798
800
  });
799
801
  return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
800
802
  status: 500,
@@ -806,7 +808,8 @@ function createInvokeToolHandler(mcp, options = {}) {
806
808
  tool: tool.name,
807
809
  method: "tools/call",
808
810
  outcome: "handler_error",
809
- durationMs: nowMs() - start
811
+ durationMs: nowMs() - start,
812
+ endUserId
810
813
  });
811
814
  return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
812
815
  status: 500,
@@ -818,7 +821,8 @@ function createInvokeToolHandler(mcp, options = {}) {
818
821
  method: "tools/call",
819
822
  outcome: result.isError ? "tool_error" : "ok",
820
823
  durationMs: nowMs() - start,
821
- errorText: result.isError ? extractTextContent(result.content) : void 0
824
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
825
+ endUserId
822
826
  });
823
827
  return Response.json({
824
828
  content: result.content ?? [],
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-qqrmJ736.js';
3
- import { M as MetricsRecorder } from '../../base-CFy5vZ5Z.js';
3
+ import { M as MetricsRecorder } from '../../base-CM-KCpp6.js';
4
4
  import 'zod';
5
5
 
6
6
  type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,6 +1,6 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-qqrmJ736.js';
3
- import { M as MetricsRecorder } from '../../base-CFy5vZ5Z.js';
3
+ import { M as MetricsRecorder } from '../../base-CM-KCpp6.js';
4
4
  import 'zod';
5
5
 
6
6
  type RestListToolsHandler = (request: Request, recorder?: MetricsRecorder) => Promise<Response>;
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  createInvokeToolHandler
3
- } from "../../chunk-QPKPYDPB.js";
3
+ } from "../../chunk-4QNNVJBZ.js";
4
4
  import {
5
5
  createListToolsHandler
6
- } from "../../chunk-LFXK3FNF.js";
6
+ } from "../../chunk-ZLWXDYOZ.js";
7
7
  import "../../chunk-6QFZYYUV.js";
8
8
  import "../../chunk-MA5H6PSF.js";
9
- import "../../chunk-YLU2JTHL.js";
9
+ import "../../chunk-SJJDRA6X.js";
10
10
  import "../../chunk-H37EB22A.js";
11
11
  import "../../chunk-6DXGZZA4.js";
12
- import "../../chunk-E3Q3FRKQ.js";
12
+ import "../../chunk-L5ZOZKAL.js";
13
13
  export {
14
14
  createInvokeToolHandler,
15
15
  createListToolsHandler
@@ -174,7 +174,7 @@ function describeError(err) {
174
174
  }
175
175
 
176
176
  // package.json
177
- var version = "0.21.0";
177
+ var version = "0.21.1-rc.0";
178
178
 
179
179
  // src/metrics/otlp.ts
180
180
  var SCOPE_NAME = "@lovable.dev/mcp-js";
@@ -200,6 +200,8 @@ function toLogRecord(rec) {
200
200
  if (rec.resBytes !== void 0)
201
201
  attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
202
202
  attributes.push(strAttr("mcp.stack", rec.stack));
203
+ if (rec.endUserId !== void 0)
204
+ attributes.push(strAttr("mcp.end_user_id", rec.endUserId));
203
205
  return {
204
206
  timeUnixNano: rec.timeUnixNano,
205
207
  observedTimeUnixNano: rec.timeUnixNano,
@@ -930,6 +932,7 @@ function corsPreflightResponse(allowMethods) {
930
932
 
931
933
  // src/protocols/mcp/protocol.ts
932
934
  function adaptToolToSdkCallback(tool, auth, recorder) {
935
+ const endUserId = auth?.principal.sub;
933
936
  return async (first) => {
934
937
  const args = tool.inputSchema ? first ?? {} : {};
935
938
  const start = nowMs();
@@ -941,7 +944,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
941
944
  tool: tool.name,
942
945
  method: "tools/call",
943
946
  outcome: "handler_error",
944
- durationMs: nowMs() - start
947
+ durationMs: nowMs() - start,
948
+ endUserId
945
949
  });
946
950
  return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
947
951
  }
@@ -950,7 +954,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
950
954
  tool: tool.name,
951
955
  method: "tools/call",
952
956
  outcome: "handler_error",
953
- durationMs: nowMs() - start
957
+ durationMs: nowMs() - start,
958
+ endUserId
954
959
  });
955
960
  return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
956
961
  }
@@ -959,7 +964,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
959
964
  method: "tools/call",
960
965
  outcome: result.isError ? "tool_error" : "ok",
961
966
  durationMs: nowMs() - start,
962
- errorText: result.isError ? extractTextContent(result.content) : void 0
967
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
968
+ endUserId
963
969
  });
964
970
  return { content: result.content ?? [], structuredContent: result.structuredContent, isError: result.isError };
965
971
  };
@@ -994,7 +1000,13 @@ function createMcpProtocolHandler(mcp, options = {}) {
994
1000
  await server.connect(transport);
995
1001
  return await transport.handleRequest(request);
996
1002
  } catch (err) {
997
- await recorder.emit({ tool: null, method: "transport", outcome: "transport_error", durationMs: 0 });
1003
+ await recorder.emit({
1004
+ tool: null,
1005
+ method: "transport",
1006
+ outcome: "transport_error",
1007
+ durationMs: 0,
1008
+ endUserId: authResult.auth?.principal.sub
1009
+ });
998
1010
  log.error("mcp.transport_error", { ...describeError(err), outcome: "500 internal error" });
999
1011
  return Response.json(
1000
1012
  { jsonrpc: "2.0", id: null, error: { code: -32603, message: "internal error" } },
@@ -1135,6 +1147,7 @@ function createInvokeToolHandler(mcp, options = {}) {
1135
1147
  const authResult = await authorizer.authorize(request, recorder);
1136
1148
  if (!authResult.ok)
1137
1149
  return authResult.response;
1150
+ const endUserId = authResult.auth?.principal.sub;
1138
1151
  if (request.method !== "POST")
1139
1152
  return methodNotAllowed("POST, OPTIONS");
1140
1153
  const tool = mcp.tools.find((t) => t.name === toolName);
@@ -1192,7 +1205,8 @@ function createInvokeToolHandler(mcp, options = {}) {
1192
1205
  tool: tool.name,
1193
1206
  method: "tools/call",
1194
1207
  outcome: "handler_error",
1195
- durationMs: nowMs() - start
1208
+ durationMs: nowMs() - start,
1209
+ endUserId
1196
1210
  });
1197
1211
  return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
1198
1212
  status: 500,
@@ -1204,7 +1218,8 @@ function createInvokeToolHandler(mcp, options = {}) {
1204
1218
  tool: tool.name,
1205
1219
  method: "tools/call",
1206
1220
  outcome: "handler_error",
1207
- durationMs: nowMs() - start
1221
+ durationMs: nowMs() - start,
1222
+ endUserId
1208
1223
  });
1209
1224
  return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
1210
1225
  status: 500,
@@ -1216,7 +1231,8 @@ function createInvokeToolHandler(mcp, options = {}) {
1216
1231
  method: "tools/call",
1217
1232
  outcome: result.isError ? "tool_error" : "ok",
1218
1233
  durationMs: nowMs() - start,
1219
- errorText: result.isError ? extractTextContent(result.content) : void 0
1234
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
1235
+ endUserId
1220
1236
  });
1221
1237
  return Response.json({
1222
1238
  content: result.content ?? [],
@@ -3,22 +3,22 @@ import {
3
3
  } from "../../chunk-UQK5UO6C.js";
4
4
  import {
5
5
  createMcpProtocolHandler
6
- } from "../../chunk-CI7JYLV3.js";
6
+ } from "../../chunk-ACFNK34P.js";
7
7
  import {
8
8
  createOAuthProtectedResourceMetadataHandler
9
- } from "../../chunk-ENJDNFEB.js";
9
+ } from "../../chunk-BLY5L4KI.js";
10
10
  import {
11
11
  createInvokeToolHandler
12
- } from "../../chunk-QPKPYDPB.js";
12
+ } from "../../chunk-4QNNVJBZ.js";
13
13
  import {
14
14
  createListToolsHandler
15
- } from "../../chunk-LFXK3FNF.js";
15
+ } from "../../chunk-ZLWXDYOZ.js";
16
16
  import "../../chunk-6QFZYYUV.js";
17
17
  import "../../chunk-MA5H6PSF.js";
18
18
  import {
19
19
  assertResourcePathShape,
20
20
  createRecorderForRuntime
21
- } from "../../chunk-YLU2JTHL.js";
21
+ } from "../../chunk-SJJDRA6X.js";
22
22
  import {
23
23
  trimTrailingSlash
24
24
  } from "../../chunk-H37EB22A.js";
@@ -29,7 +29,7 @@ import {
29
29
  FUNCTIONS_MOUNT_PREFIX,
30
30
  assertFunctionName
31
31
  } from "../../chunk-XQWJN6DC.js";
32
- import "../../chunk-E3Q3FRKQ.js";
32
+ import "../../chunk-L5ZOZKAL.js";
33
33
 
34
34
  // src/stacks/supabase/handler.ts
35
35
  function deriveResourcePath(options) {
@@ -33,7 +33,7 @@ var import_node_fs = require("fs");
33
33
  var import_node_path = require("path");
34
34
 
35
35
  // package.json
36
- var version = "0.21.0";
36
+ var version = "0.21.1-rc.0";
37
37
 
38
38
  // src/core/fs-errors.ts
39
39
  function isFileMissing(err) {
@@ -7,7 +7,7 @@ import {
7
7
  } from "../../chunk-XQWJN6DC.js";
8
8
  import {
9
9
  version
10
- } from "../../chunk-E3Q3FRKQ.js";
10
+ } from "../../chunk-L5ZOZKAL.js";
11
11
 
12
12
  // src/stacks/supabase/vite.ts
13
13
  import { resolve as resolve2, sep as sep2 } from "path";
@@ -129,7 +129,7 @@ function describeError(err) {
129
129
  }
130
130
 
131
131
  // package.json
132
- var version = "0.21.0";
132
+ var version = "0.21.1-rc.0";
133
133
 
134
134
  // src/metrics/otlp.ts
135
135
  var SCOPE_NAME = "@lovable.dev/mcp-js";
@@ -155,6 +155,8 @@ function toLogRecord(rec) {
155
155
  if (rec.resBytes !== void 0)
156
156
  attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
157
157
  attributes.push(strAttr("mcp.stack", rec.stack));
158
+ if (rec.endUserId !== void 0)
159
+ attributes.push(strAttr("mcp.end_user_id", rec.endUserId));
158
160
  return {
159
161
  timeUnixNano: rec.timeUnixNano,
160
162
  observedTimeUnixNano: rec.timeUnixNano,
@@ -933,6 +935,7 @@ function corsPreflightResponse(allowMethods) {
933
935
 
934
936
  // src/protocols/mcp/protocol.ts
935
937
  function adaptToolToSdkCallback(tool, auth, recorder) {
938
+ const endUserId = auth?.principal.sub;
936
939
  return async (first) => {
937
940
  const args = tool.inputSchema ? first ?? {} : {};
938
941
  const start = nowMs();
@@ -944,7 +947,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
944
947
  tool: tool.name,
945
948
  method: "tools/call",
946
949
  outcome: "handler_error",
947
- durationMs: nowMs() - start
950
+ durationMs: nowMs() - start,
951
+ endUserId
948
952
  });
949
953
  return { content: [{ type: "text", text: "tool execution failed" }], isError: true };
950
954
  }
@@ -953,7 +957,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
953
957
  tool: tool.name,
954
958
  method: "tools/call",
955
959
  outcome: "handler_error",
956
- durationMs: nowMs() - start
960
+ durationMs: nowMs() - start,
961
+ endUserId
957
962
  });
958
963
  return { content: [{ type: "text", text: `tool "${tool.name}" returned no result` }], isError: true };
959
964
  }
@@ -962,7 +967,8 @@ function adaptToolToSdkCallback(tool, auth, recorder) {
962
967
  method: "tools/call",
963
968
  outcome: result.isError ? "tool_error" : "ok",
964
969
  durationMs: nowMs() - start,
965
- errorText: result.isError ? extractTextContent(result.content) : void 0
970
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
971
+ endUserId
966
972
  });
967
973
  return { content: result.content ?? [], structuredContent: result.structuredContent, isError: result.isError };
968
974
  };
@@ -997,7 +1003,13 @@ function createMcpProtocolHandler(mcp, options = {}) {
997
1003
  await server.connect(transport);
998
1004
  return await transport.handleRequest(request);
999
1005
  } catch (err) {
1000
- await recorder.emit({ tool: null, method: "transport", outcome: "transport_error", durationMs: 0 });
1006
+ await recorder.emit({
1007
+ tool: null,
1008
+ method: "transport",
1009
+ outcome: "transport_error",
1010
+ durationMs: 0,
1011
+ endUserId: authResult.auth?.principal.sub
1012
+ });
1001
1013
  log.error("mcp.transport_error", { ...describeError(err), outcome: "500 internal error" });
1002
1014
  return Response.json(
1003
1015
  { jsonrpc: "2.0", id: null, error: { code: -32603, message: "internal error" } },
@@ -1138,6 +1150,7 @@ function createInvokeToolHandler(mcp, options = {}) {
1138
1150
  const authResult = await authorizer.authorize(request, recorder);
1139
1151
  if (!authResult.ok)
1140
1152
  return authResult.response;
1153
+ const endUserId = authResult.auth?.principal.sub;
1141
1154
  if (request.method !== "POST")
1142
1155
  return methodNotAllowed("POST, OPTIONS");
1143
1156
  const tool = mcp.tools.find((t) => t.name === toolName);
@@ -1195,7 +1208,8 @@ function createInvokeToolHandler(mcp, options = {}) {
1195
1208
  tool: tool.name,
1196
1209
  method: "tools/call",
1197
1210
  outcome: "handler_error",
1198
- durationMs: nowMs() - start
1211
+ durationMs: nowMs() - start,
1212
+ endUserId
1199
1213
  });
1200
1214
  return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
1201
1215
  status: 500,
@@ -1207,7 +1221,8 @@ function createInvokeToolHandler(mcp, options = {}) {
1207
1221
  tool: tool.name,
1208
1222
  method: "tools/call",
1209
1223
  outcome: "handler_error",
1210
- durationMs: nowMs() - start
1224
+ durationMs: nowMs() - start,
1225
+ endUserId
1211
1226
  });
1212
1227
  return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
1213
1228
  status: 500,
@@ -1219,7 +1234,8 @@ function createInvokeToolHandler(mcp, options = {}) {
1219
1234
  method: "tools/call",
1220
1235
  outcome: result.isError ? "tool_error" : "ok",
1221
1236
  durationMs: nowMs() - start,
1222
- errorText: result.isError ? extractTextContent(result.content) : void 0
1237
+ errorText: result.isError ? extractTextContent(result.content) : void 0,
1238
+ endUserId
1223
1239
  });
1224
1240
  return Response.json({
1225
1241
  content: result.content ?? [],
@@ -3,24 +3,24 @@ import {
3
3
  } from "../../chunk-UQK5UO6C.js";
4
4
  import {
5
5
  createMcpProtocolHandler
6
- } from "../../chunk-CI7JYLV3.js";
6
+ } from "../../chunk-ACFNK34P.js";
7
7
  import {
8
8
  createOAuthProtectedResourceMetadataHandler
9
- } from "../../chunk-ENJDNFEB.js";
9
+ } from "../../chunk-BLY5L4KI.js";
10
10
  import {
11
11
  createInvokeToolHandler
12
- } from "../../chunk-QPKPYDPB.js";
12
+ } from "../../chunk-4QNNVJBZ.js";
13
13
  import {
14
14
  createListToolsHandler
15
- } from "../../chunk-LFXK3FNF.js";
15
+ } from "../../chunk-ZLWXDYOZ.js";
16
16
  import "../../chunk-6QFZYYUV.js";
17
17
  import "../../chunk-MA5H6PSF.js";
18
18
  import {
19
19
  createRecorderForRuntime
20
- } from "../../chunk-YLU2JTHL.js";
20
+ } from "../../chunk-SJJDRA6X.js";
21
21
  import "../../chunk-H37EB22A.js";
22
22
  import "../../chunk-6DXGZZA4.js";
23
- import "../../chunk-E3Q3FRKQ.js";
23
+ import "../../chunk-L5ZOZKAL.js";
24
24
 
25
25
  // src/stacks/tanstack/handlers.ts
26
26
  var STACK = "tanstack";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lovable.dev/mcp-js",
3
- "version": "0.21.0",
3
+ "version": "0.21.1-rc.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": {