@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.
@@ -82,6 +82,223 @@ function describeError(err) {
82
82
  return { value: String(err) };
83
83
  }
84
84
 
85
+ // src/metrics/config.ts
86
+ var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
87
+ var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
88
+ var METRICS_SAMPLE_RATE = 1;
89
+ var METRICS_FLUSH_INTERVAL_MS = 5e3;
90
+ var METRICS_MAX_BATCH_SIZE = 50;
91
+ function assertMetricsEndpoint(endpoint) {
92
+ let url;
93
+ try {
94
+ url = new URL(endpoint);
95
+ } catch {
96
+ throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
97
+ }
98
+ if (url.protocol !== "https:" && url.protocol !== "http:") {
99
+ throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
100
+ }
101
+ }
102
+ function resolveMetricsConfig(config = true) {
103
+ const options = typeof config === "boolean" ? { enabled: config } : config;
104
+ const endpoint = options.endpoint ?? DEFAULT_METRICS_ENDPOINT;
105
+ assertMetricsEndpoint(endpoint);
106
+ return Object.freeze({
107
+ enabled: options.enabled ?? true,
108
+ endpoint,
109
+ headers: options.headers ?? {},
110
+ apiKeyEnvVar: METRICS_API_KEY_ENV_VAR,
111
+ sampleRate: METRICS_SAMPLE_RATE,
112
+ flushIntervalMs: METRICS_FLUSH_INTERVAL_MS,
113
+ maxBatchSize: METRICS_MAX_BATCH_SIZE
114
+ });
115
+ }
116
+
117
+ // package.json
118
+ var version = "0.16.0";
119
+
120
+ // src/metrics/otlp.ts
121
+ var SCOPE_NAME = "@lovable.dev/mcp-js";
122
+ var EVENT_NAME = "mcp.tool.invocation";
123
+ var SEVERITY_INFO = 9;
124
+ function strAttr(key, value) {
125
+ return { key, value: { stringValue: value } };
126
+ }
127
+ function intAttr(key, value) {
128
+ return { key, value: { intValue: String(Math.round(value)) } };
129
+ }
130
+ function toLogRecord(rec) {
131
+ const attributes = [
132
+ strAttr("event.name", EVENT_NAME),
133
+ strAttr("mcp.method", rec.method),
134
+ strAttr("mcp.outcome", rec.outcome),
135
+ intAttr("mcp.duration_ms", rec.durationMs)
136
+ ];
137
+ if (rec.tool !== null)
138
+ attributes.push(strAttr("mcp.tool", rec.tool));
139
+ if (rec.reqBytes !== void 0)
140
+ attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
141
+ if (rec.resBytes !== void 0)
142
+ attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
143
+ return {
144
+ timeUnixNano: rec.timeUnixNano,
145
+ observedTimeUnixNano: rec.timeUnixNano,
146
+ severityNumber: SEVERITY_INFO,
147
+ severityText: "INFO",
148
+ body: { stringValue: EVENT_NAME },
149
+ attributes
150
+ };
151
+ }
152
+ function buildLogsPayload(records, server) {
153
+ return JSON.stringify({
154
+ resourceLogs: [
155
+ {
156
+ resource: {
157
+ attributes: [
158
+ strAttr("service.name", server.name),
159
+ strAttr("service.version", server.version),
160
+ strAttr("telemetry.sdk.name", SCOPE_NAME),
161
+ strAttr("telemetry.sdk.version", version),
162
+ strAttr("telemetry.sdk.language", "webjs")
163
+ ]
164
+ },
165
+ scopeLogs: [
166
+ {
167
+ scope: { name: SCOPE_NAME, version },
168
+ logRecords: records.map(toLogRecord)
169
+ }
170
+ ]
171
+ }
172
+ ]
173
+ });
174
+ }
175
+ function nowUnixNano() {
176
+ return `${Date.now()}000000`;
177
+ }
178
+
179
+ // src/metrics/recorder.ts
180
+ function nowMs() {
181
+ return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
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
+ }
187
+ var NOOP_RECORDER = {
188
+ record() {
189
+ },
190
+ async flush() {
191
+ }
192
+ };
193
+ function createNoopRecorder() {
194
+ return NOOP_RECORDER;
195
+ }
196
+ function readRuntimeEnv(name) {
197
+ try {
198
+ const denoEnv = globalThis.Deno?.env;
199
+ const value = denoEnv?.get?.(name);
200
+ if (value)
201
+ return value;
202
+ } catch {
203
+ }
204
+ try {
205
+ if (typeof process !== "undefined") {
206
+ const value = process.env?.[name];
207
+ if (value)
208
+ return value;
209
+ }
210
+ } catch {
211
+ }
212
+ return void 0;
213
+ }
214
+ function probeWaitUntil() {
215
+ const fn = globalThis.EdgeRuntime?.waitUntil;
216
+ return typeof fn === "function" ? fn.bind(globalThis.EdgeRuntime) : void 0;
217
+ }
218
+ function createMetricsRecorder(ctx, deps = {}) {
219
+ const { config, server } = ctx;
220
+ if (!config.enabled)
221
+ return NOOP_RECORDER;
222
+ const doFetch = deps.fetch ?? globalThis.fetch;
223
+ if (!doFetch) {
224
+ log.warn("metrics.disabled_no_fetch", { endpoint: config.endpoint });
225
+ return NOOP_RECORDER;
226
+ }
227
+ const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
228
+ const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
229
+ if (usesLovableEndpoint && !apiKey) {
230
+ log.warn("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar, endpoint: config.endpoint });
231
+ return NOOP_RECORDER;
232
+ }
233
+ const waitUntil = deps.waitUntil ?? probeWaitUntil();
234
+ const buffer = [];
235
+ let timer;
236
+ const schedule = (p) => {
237
+ if (waitUntil) {
238
+ try {
239
+ waitUntil(p);
240
+ return;
241
+ } catch (err) {
242
+ log.warn("metrics.wait_until_failed", describeError(err));
243
+ }
244
+ }
245
+ void p.catch(() => {
246
+ });
247
+ };
248
+ const headers = {};
249
+ if (!usesLovableEndpoint) {
250
+ for (const [key, value] of Object.entries(config.headers)) {
251
+ if (key.toLowerCase() !== "content-type")
252
+ headers[key] = value;
253
+ }
254
+ }
255
+ headers["content-type"] = "application/json";
256
+ if (apiKey)
257
+ headers.authorization = `Bearer ${apiKey}`;
258
+ const flush = async () => {
259
+ if (buffer.length === 0)
260
+ return;
261
+ const records = buffer.splice(0, buffer.length);
262
+ const dropped = records.length;
263
+ try {
264
+ const res = await doFetch(config.endpoint, {
265
+ method: "POST",
266
+ headers,
267
+ body: buildLogsPayload(records, server),
268
+ keepalive: true
269
+ });
270
+ if (!res.ok) {
271
+ log.warn("metrics.flush_rejected", { status: res.status, dropped, endpoint: config.endpoint });
272
+ }
273
+ } catch (err) {
274
+ log.warn("metrics.flush_failed", { ...describeError(err), dropped, endpoint: config.endpoint });
275
+ }
276
+ };
277
+ const ensureTimer = () => {
278
+ if (timer !== void 0)
279
+ return;
280
+ timer = setInterval(() => schedule(flush()), config.flushIntervalMs);
281
+ timer.unref?.();
282
+ };
283
+ return {
284
+ record(ev) {
285
+ if (config.sampleRate < 1 && Math.random() >= config.sampleRate)
286
+ return;
287
+ buffer.push({ ...ev, timeUnixNano: nowUnixNano() });
288
+ ensureTimer();
289
+ if (buffer.length >= config.maxBatchSize)
290
+ schedule(flush());
291
+ },
292
+ flush
293
+ };
294
+ }
295
+ function createRecorderForRuntime(mcp) {
296
+ const config = resolveMetricsConfig(mcp.metrics);
297
+ if (!config.enabled)
298
+ return createNoopRecorder();
299
+ return createMetricsRecorder({ config, server: { name: mcp.name, version: mcp.version } });
300
+ }
301
+
85
302
  // src/core/promise.ts
86
303
  function cachedPromise(load, label) {
87
304
  let settled = false;
@@ -510,12 +727,13 @@ function assertRequiredScopes(auth, context) {
510
727
  throw new OAuthTokenError(403, "insufficient_scope", "Additional OAuth scope is required");
511
728
  }
512
729
  }
513
- function createRequestAuthorizer(mcp, options = {}) {
730
+ function createRequestAuthorizer(mcp, options = {}, recorder) {
514
731
  const runtime = getOAuthRuntime(mcp, options);
515
732
  return {
516
733
  async authorize(request) {
517
734
  if (runtime.kind === "unconfigured")
518
735
  return { ok: true };
736
+ const startedAt = nowMs();
519
737
  const token = parseBearerToken(request);
520
738
  if (!token) {
521
739
  log.info("auth.no_bearer_token", { outcome: "401" });
@@ -528,6 +746,12 @@ function createRequestAuthorizer(mcp, options = {}) {
528
746
  } catch (err) {
529
747
  if (err instanceof OAuthConfigurationError) {
530
748
  log.error("auth.config_error", { ...describeError(err), outcome: "500" });
749
+ recorder?.record({
750
+ tool: null,
751
+ method: "authorize",
752
+ outcome: "auth_config_error",
753
+ durationMs: nowMs() - startedAt
754
+ });
531
755
  return { ok: false, response: oauthConfigurationErrorResponse() };
532
756
  }
533
757
  if (err instanceof OAuthTokenError) {
@@ -604,9 +828,9 @@ function buildMcpListing(mcp) {
604
828
  }))
605
829
  };
606
830
  }
607
- function createListToolsHandler(mcp, options = {}) {
831
+ function createListToolsHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
608
832
  assertRestResourceBinding(mcp, options);
609
- const authorizer = createRequestAuthorizer(mcp, options);
833
+ const authorizer = createRequestAuthorizer(mcp, options, recorder);
610
834
  const handle = async (request) => {
611
835
  const authResult = await authorizer.authorize(request);
612
836
  if (!authResult.ok)
@@ -669,214 +893,6 @@ var ToolContext = class {
669
893
  }
670
894
  };
671
895
 
672
- // src/metrics/config.ts
673
- var DEFAULT_METRICS_ENDPOINT = "https://api.lovable.dev/v1/app-mcp-usage";
674
- var METRICS_API_KEY_ENV_VAR = "LOVABLE_API_KEY";
675
- var METRICS_SAMPLE_RATE = 1;
676
- var METRICS_FLUSH_INTERVAL_MS = 5e3;
677
- var METRICS_MAX_BATCH_SIZE = 50;
678
- function assertMetricsEndpoint(endpoint) {
679
- let url;
680
- try {
681
- url = new URL(endpoint);
682
- } catch {
683
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be an absolute URL, got ${JSON.stringify(endpoint)}`);
684
- }
685
- if (url.protocol !== "https:" && url.protocol !== "http:") {
686
- throw new Error(`@lovable.dev/mcp-js: metrics.endpoint must be http(s), got ${JSON.stringify(endpoint)}`);
687
- }
688
- }
689
- function resolveMetricsConfig(config = true) {
690
- const options = typeof config === "boolean" ? { enabled: config } : config;
691
- const endpoint = options.endpoint ?? DEFAULT_METRICS_ENDPOINT;
692
- assertMetricsEndpoint(endpoint);
693
- return Object.freeze({
694
- enabled: options.enabled ?? true,
695
- endpoint,
696
- headers: options.headers ?? {},
697
- apiKeyEnvVar: METRICS_API_KEY_ENV_VAR,
698
- sampleRate: METRICS_SAMPLE_RATE,
699
- flushIntervalMs: METRICS_FLUSH_INTERVAL_MS,
700
- maxBatchSize: METRICS_MAX_BATCH_SIZE
701
- });
702
- }
703
-
704
- // package.json
705
- var version = "0.15.0";
706
-
707
- // src/metrics/otlp.ts
708
- var SCOPE_NAME = "@lovable.dev/mcp-js";
709
- var EVENT_NAME = "mcp.tool.invocation";
710
- var SEVERITY_INFO = 9;
711
- function strAttr(key, value) {
712
- return { key, value: { stringValue: value } };
713
- }
714
- function intAttr(key, value) {
715
- return { key, value: { intValue: String(Math.round(value)) } };
716
- }
717
- function toLogRecord(rec) {
718
- const attributes = [
719
- strAttr("event.name", EVENT_NAME),
720
- strAttr("mcp.method", rec.method),
721
- strAttr("mcp.outcome", rec.outcome),
722
- intAttr("mcp.duration_ms", rec.durationMs)
723
- ];
724
- if (rec.tool !== null)
725
- attributes.push(strAttr("mcp.tool", rec.tool));
726
- if (rec.reqBytes !== void 0)
727
- attributes.push(intAttr("mcp.request_size_bytes", rec.reqBytes));
728
- if (rec.resBytes !== void 0)
729
- attributes.push(intAttr("mcp.response_size_bytes", rec.resBytes));
730
- return {
731
- timeUnixNano: rec.timeUnixNano,
732
- observedTimeUnixNano: rec.timeUnixNano,
733
- severityNumber: SEVERITY_INFO,
734
- severityText: "INFO",
735
- body: { stringValue: EVENT_NAME },
736
- attributes
737
- };
738
- }
739
- function buildLogsPayload(records, server) {
740
- return JSON.stringify({
741
- resourceLogs: [
742
- {
743
- resource: {
744
- attributes: [
745
- strAttr("service.name", server.name),
746
- strAttr("service.version", server.version),
747
- strAttr("telemetry.sdk.name", SCOPE_NAME),
748
- strAttr("telemetry.sdk.version", version),
749
- strAttr("telemetry.sdk.language", "webjs")
750
- ]
751
- },
752
- scopeLogs: [
753
- {
754
- scope: { name: SCOPE_NAME, version },
755
- logRecords: records.map(toLogRecord)
756
- }
757
- ]
758
- }
759
- ]
760
- });
761
- }
762
- function nowUnixNano() {
763
- return `${Date.now()}000000`;
764
- }
765
-
766
- // src/metrics/recorder.ts
767
- function nowMs() {
768
- return typeof performance !== "undefined" && typeof performance.now === "function" ? performance.now() : Date.now();
769
- }
770
- var NOOP_RECORDER = {
771
- record() {
772
- },
773
- async flush() {
774
- }
775
- };
776
- function createNoopRecorder() {
777
- return NOOP_RECORDER;
778
- }
779
- function readRuntimeEnv(name) {
780
- try {
781
- const denoEnv = globalThis.Deno?.env;
782
- const value = denoEnv?.get?.(name);
783
- if (value)
784
- return value;
785
- } catch {
786
- }
787
- try {
788
- if (typeof process !== "undefined") {
789
- const value = process.env?.[name];
790
- if (value)
791
- return value;
792
- }
793
- } catch {
794
- }
795
- return void 0;
796
- }
797
- function probeWaitUntil() {
798
- const fn = globalThis.EdgeRuntime?.waitUntil;
799
- return typeof fn === "function" ? fn.bind(globalThis.EdgeRuntime) : void 0;
800
- }
801
- function createMetricsRecorder(ctx, deps = {}) {
802
- const { config, server } = ctx;
803
- if (!config.enabled)
804
- return NOOP_RECORDER;
805
- const doFetch = deps.fetch ?? globalThis.fetch;
806
- if (!doFetch)
807
- return NOOP_RECORDER;
808
- const usesLovableEndpoint = config.endpoint === DEFAULT_METRICS_ENDPOINT;
809
- const apiKey = usesLovableEndpoint ? (deps.getApiKey ?? (() => readRuntimeEnv(config.apiKeyEnvVar)))() : void 0;
810
- if (usesLovableEndpoint && !apiKey) {
811
- log.debug("metrics.disabled_no_api_key", { envVar: config.apiKeyEnvVar });
812
- return NOOP_RECORDER;
813
- }
814
- const waitUntil = deps.waitUntil ?? probeWaitUntil();
815
- const buffer = [];
816
- let timer;
817
- const schedule = (p) => {
818
- if (waitUntil) {
819
- try {
820
- waitUntil(p);
821
- return;
822
- } catch {
823
- }
824
- }
825
- void p.catch(() => {
826
- });
827
- };
828
- const headers = {};
829
- if (!usesLovableEndpoint) {
830
- for (const [key, value] of Object.entries(config.headers)) {
831
- if (key.toLowerCase() !== "content-type")
832
- headers[key] = value;
833
- }
834
- }
835
- headers["content-type"] = "application/json";
836
- if (apiKey)
837
- headers.authorization = `Bearer ${apiKey}`;
838
- const flush = async () => {
839
- if (buffer.length === 0)
840
- return;
841
- const records = buffer.splice(0, buffer.length);
842
- try {
843
- const res = await doFetch(config.endpoint, {
844
- method: "POST",
845
- headers,
846
- body: buildLogsPayload(records, server),
847
- keepalive: true
848
- });
849
- if (!res.ok)
850
- log.debug("metrics.flush_rejected", { status: res.status });
851
- } catch (err) {
852
- log.debug("metrics.flush_failed", describeError(err));
853
- }
854
- };
855
- const ensureTimer = () => {
856
- if (timer !== void 0)
857
- return;
858
- timer = setInterval(() => schedule(flush()), config.flushIntervalMs);
859
- timer.unref?.();
860
- };
861
- return {
862
- record(ev) {
863
- if (config.sampleRate < 1 && Math.random() >= config.sampleRate)
864
- return;
865
- buffer.push({ ...ev, timeUnixNano: nowUnixNano() });
866
- ensureTimer();
867
- if (buffer.length >= config.maxBatchSize)
868
- schedule(flush());
869
- },
870
- flush
871
- };
872
- }
873
- function createRecorderForRuntime(mcp) {
874
- const config = resolveMetricsConfig(mcp.metrics);
875
- if (!config.enabled)
876
- return createNoopRecorder();
877
- return createMetricsRecorder({ config, server: { name: mcp.name, version: mcp.version } });
878
- }
879
-
880
896
  // src/protocols/rest/invoke-tool.ts
881
897
  var MAX_REFLECTED_TOOL_NAME = 256;
882
898
  function safeReflectName(name) {
@@ -892,7 +908,7 @@ function isEmptyArgs(value) {
892
908
  }
893
909
  function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderForRuntime(mcp)) {
894
910
  assertRestResourceBinding(mcp, options);
895
- const authorizer = createRequestAuthorizer(mcp, options);
911
+ const authorizer = createRequestAuthorizer(mcp, options, recorder);
896
912
  const handle = async (request, toolName) => {
897
913
  const authResult = await authorizer.authorize(request);
898
914
  if (!authResult.ok)
@@ -950,20 +966,30 @@ function createInvokeToolHandler(mcp, options = {}, recorder = createRecorderFor
950
966
  try {
951
967
  result = await tool.handler(args, new ToolContext(authResult.auth));
952
968
  } catch {
953
- recorder.record({ tool: tool.name, method: "tools/call", outcome: "handler_error", durationMs: nowMs() - start });
969
+ reportInvocation(recorder, {
970
+ tool: tool.name,
971
+ method: "tools/call",
972
+ outcome: "handler_error",
973
+ durationMs: nowMs() - start
974
+ });
954
975
  return new Response(JSON.stringify({ error: "handler threw", tool: toolName }), {
955
976
  status: 500,
956
977
  headers: JSON_HEADERS
957
978
  });
958
979
  }
959
980
  if (result == null) {
960
- recorder.record({ tool: tool.name, method: "tools/call", outcome: "handler_error", durationMs: nowMs() - start });
981
+ reportInvocation(recorder, {
982
+ tool: tool.name,
983
+ method: "tools/call",
984
+ outcome: "handler_error",
985
+ durationMs: nowMs() - start
986
+ });
961
987
  return new Response(JSON.stringify({ error: `tool "${toolName}" returned no result` }), {
962
988
  status: 500,
963
989
  headers: JSON_HEADERS
964
990
  });
965
991
  }
966
- recorder.record({
992
+ reportInvocation(recorder, {
967
993
  tool: tool.name,
968
994
  method: "tools/call",
969
995
  outcome: result.isError ? "tool_error" : "ok",
@@ -1,10 +1,10 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-COY42xux.js';
3
- import { M as MetricsRecorder } from '../../recorder-B-eJU4Qu.js';
3
+ import { M as MetricsRecorder } from '../../recorder-qlzUKFxG.js';
4
4
  import 'zod';
5
5
 
6
6
  type RestListToolsHandler = (request: Request) => Promise<Response>;
7
- declare function createListToolsHandler(mcp: McpDefinition, options?: McpRuntimeOptions): RestListToolsHandler;
7
+ declare function createListToolsHandler(mcp: McpDefinition, options?: McpRuntimeOptions, recorder?: MetricsRecorder): RestListToolsHandler;
8
8
 
9
9
  type RestInvokeToolHandler = (request: Request, toolName: string) => Promise<Response>;
10
10
  declare function createInvokeToolHandler(mcp: McpDefinition, options?: McpRuntimeOptions, recorder?: MetricsRecorder): RestInvokeToolHandler;
@@ -1,10 +1,10 @@
1
1
  import { M as McpRuntimeOptions } from '../../authorize-BMeXd_Sh.js';
2
2
  import { d as McpDefinition } from '../../types-COY42xux.js';
3
- import { M as MetricsRecorder } from '../../recorder-B-eJU4Qu.js';
3
+ import { M as MetricsRecorder } from '../../recorder-qlzUKFxG.js';
4
4
  import 'zod';
5
5
 
6
6
  type RestListToolsHandler = (request: Request) => Promise<Response>;
7
- declare function createListToolsHandler(mcp: McpDefinition, options?: McpRuntimeOptions): RestListToolsHandler;
7
+ declare function createListToolsHandler(mcp: McpDefinition, options?: McpRuntimeOptions, recorder?: MetricsRecorder): RestListToolsHandler;
8
8
 
9
9
  type RestInvokeToolHandler = (request: Request, toolName: string) => Promise<Response>;
10
10
  declare function createInvokeToolHandler(mcp: McpDefinition, options?: McpRuntimeOptions, recorder?: MetricsRecorder): RestInvokeToolHandler;
@@ -1,15 +1,14 @@
1
1
  import {
2
2
  createInvokeToolHandler
3
- } from "../../chunk-T2RED2TG.js";
3
+ } from "../../chunk-W2EZWPJ5.js";
4
4
  import {
5
5
  createListToolsHandler
6
- } from "../../chunk-VNRQPA4K.js";
7
- import "../../chunk-XQSTN54Y.js";
8
- import "../../chunk-P3F324UC.js";
9
- import "../../chunk-G4XA7IJM.js";
10
- import "../../chunk-QC3DXQTH.js";
6
+ } from "../../chunk-I5CAQUQI.js";
7
+ import "../../chunk-MA5H6PSF.js";
8
+ import "../../chunk-H6BKTNJY.js";
9
+ import "../../chunk-DCWYK4CA.js";
11
10
  import "../../chunk-6DXGZZA4.js";
12
- import "../../chunk-LWHVXXKQ.js";
11
+ import "../../chunk-SKSKC747.js";
13
12
  export {
14
13
  createInvokeToolHandler,
15
14
  createListToolsHandler
@@ -1,10 +1,10 @@
1
- type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error";
1
+ type InvocationOutcome = "ok" | "tool_error" | "handler_error" | "transport_error" | "auth_config_error";
2
2
  /** One recorded MCP call. Carries no arguments or response payloads — only the
3
3
  * tool name, the JSON-RPC method, the result class, timing, and byte sizes. */
4
4
  interface InvocationRecord {
5
- /** Tool name for `tools/call`; `null` for list/initialize and transport faults. */
5
+ /** Tool name for `tools/call`; `null` for list/initialize, transport faults, and auth-config failures. */
6
6
  tool: string | null;
7
- /** JSON-RPC method, e.g. `tools/call`. */
7
+ /** JSON-RPC method, e.g. `tools/call`; `authorize` for auth-config failures. */
8
8
  method: string;
9
9
  outcome: InvocationOutcome;
10
10
  durationMs: number;