fastmcp 4.23.4 → 4.23.6

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.
@@ -23,6 +23,11 @@ var _stdiojs = require('@modelcontextprotocol/sdk/server/stdio.js');
23
23
 
24
24
 
25
25
 
26
+
27
+
28
+
29
+
30
+
26
31
  var _typesjs = require('@modelcontextprotocol/sdk/types.js');
27
32
  var _events = require('events');
28
33
  var _promises = require('fs/promises');
@@ -220,6 +225,16 @@ function unwrapDefault(value) {
220
225
 
221
226
  // src/FastMCP.ts
222
227
  var MEDIA_FETCH_TIMEOUT_MS = 3e4;
228
+ var isSvg = (buffer) => {
229
+ let text = buffer.toString("utf8").trimStart();
230
+ const preamble = /^(?:<\?[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE\s[^[>]*(?:\[[\s\S]*?\]\s*)?>)/;
231
+ let match = preamble.exec(text);
232
+ while (match) {
233
+ text = text.slice(match[0].length).trimStart();
234
+ match = preamble.exec(text);
235
+ }
236
+ return /^<svg(?:\s|\/?>)/.test(text);
237
+ };
223
238
  var imageContent = async (input) => {
224
239
  let rawData;
225
240
  try {
@@ -262,16 +277,17 @@ var imageContent = async (input) => {
262
277
  );
263
278
  }
264
279
  const { fileTypeFromBuffer } = await Promise.resolve().then(() => _interopRequireWildcard(require("file-type")));
265
- const mimeType = await fileTypeFromBuffer(rawData);
266
- if (!mimeType || !mimeType.mime.startsWith("image/")) {
280
+ const fileType = await fileTypeFromBuffer(rawData);
281
+ const mimeType = (!fileType || fileType.mime === "application/xml") && isSvg(rawData) ? "image/svg+xml" : _optionalChain([fileType, 'optionalAccess', _4 => _4.mime]);
282
+ if (!mimeType || !mimeType.startsWith("image/")) {
267
283
  console.warn(
268
- `Warning: Content may not be a valid image. Detected MIME: ${_optionalChain([mimeType, 'optionalAccess', _4 => _4.mime]) || "unknown"}`
284
+ `Warning: Content may not be a valid image. Detected MIME: ${mimeType || "unknown"}`
269
285
  );
270
286
  }
271
287
  const base64Data = rawData.toString("base64");
272
288
  return {
273
289
  data: base64Data,
274
- mimeType: _nullishCoalesce(_optionalChain([mimeType, 'optionalAccess', _5 => _5.mime]), () => ( "image/png")),
290
+ mimeType: _nullishCoalesce(mimeType, () => ( "image/png")),
275
291
  type: "image"
276
292
  };
277
293
  } catch (error) {
@@ -282,8 +298,27 @@ var imageContent = async (input) => {
282
298
  }
283
299
  }
284
300
  };
301
+ var AUDIO_CONTAINER_TYPES = /* @__PURE__ */ new Map([
302
+ ["video/3gpp", "audio/3gpp"],
303
+ ["video/3gpp2", "audio/3gpp2"],
304
+ ["video/matroska", "audio/matroska"],
305
+ ["video/mp4", "audio/mp4"],
306
+ ["video/ogg", "audio/ogg"],
307
+ ["video/webm", "audio/webm"]
308
+ ]);
309
+ var resolveAudioMimeType = (detected, declared) => {
310
+ if (_optionalChain([detected, 'optionalAccess', _5 => _5.startsWith, 'call', _6 => _6("audio/")])) {
311
+ return detected;
312
+ }
313
+ const declaredMime = _optionalChain([declared, 'optionalAccess', _7 => _7.split, 'call', _8 => _8(";", 1), 'access', _9 => _9[0], 'access', _10 => _10.trim, 'call', _11 => _11(), 'access', _12 => _12.toLowerCase, 'call', _13 => _13()]);
314
+ if (_optionalChain([declaredMime, 'optionalAccess', _14 => _14.startsWith, 'call', _15 => _15("audio/")])) {
315
+ return declaredMime;
316
+ }
317
+ return _nullishCoalesce((detected && AUDIO_CONTAINER_TYPES.get(detected)), () => ( detected));
318
+ };
285
319
  var audioContent = async (input) => {
286
320
  let rawData;
321
+ let declaredMimeType = null;
287
322
  try {
288
323
  if ("url" in input) {
289
324
  const timeoutMs = _nullishCoalesce(input.timeoutMs, () => ( MEDIA_FETCH_TIMEOUT_MS));
@@ -297,6 +332,7 @@ var audioContent = async (input) => {
297
332
  `Server responded with status: ${response.status} - ${response.statusText}`
298
333
  );
299
334
  }
335
+ declaredMimeType = response.headers.get("content-type");
300
336
  rawData = Buffer.from(await response.arrayBuffer());
301
337
  } catch (error) {
302
338
  if (error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError")) {
@@ -324,16 +360,17 @@ var audioContent = async (input) => {
324
360
  );
325
361
  }
326
362
  const { fileTypeFromBuffer } = await Promise.resolve().then(() => _interopRequireWildcard(require("file-type")));
327
- const mimeType = await fileTypeFromBuffer(rawData);
328
- if (!mimeType || !mimeType.mime.startsWith("audio/")) {
363
+ const detected = await fileTypeFromBuffer(rawData);
364
+ const mimeType = resolveAudioMimeType(_optionalChain([detected, 'optionalAccess', _16 => _16.mime]), declaredMimeType);
365
+ if (!mimeType || !mimeType.startsWith("audio/")) {
329
366
  console.warn(
330
- `Warning: Content may not be a valid audio file. Detected MIME: ${_optionalChain([mimeType, 'optionalAccess', _6 => _6.mime]) || "unknown"}`
367
+ `Warning: Content may not be a valid audio file. Detected MIME: ${mimeType || "unknown"}`
331
368
  );
332
369
  }
333
370
  const base64Data = rawData.toString("base64");
334
371
  return {
335
372
  data: base64Data,
336
- mimeType: _nullishCoalesce(_optionalChain([mimeType, 'optionalAccess', _7 => _7.mime]), () => ( "audio/mpeg")),
373
+ mimeType: _nullishCoalesce(mimeType, () => ( "audio/mpeg")),
337
374
  type: "audio"
338
375
  };
339
376
  } catch (error) {
@@ -364,7 +401,7 @@ var UserError = class extends UnexpectedStateError {
364
401
  };
365
402
  function assertStandardSchema(toolName, schemaName, schema) {
366
403
  const standard = schema["~standard"];
367
- if (typeof _optionalChain([standard, 'optionalAccess', _8 => _8.validate]) === "function") {
404
+ if (typeof _optionalChain([standard, 'optionalAccess', _17 => _17.validate]) === "function") {
368
405
  return;
369
406
  }
370
407
  throw new UserError(
@@ -381,55 +418,20 @@ function assertToolSchemas(tool) {
381
418
  }
382
419
  var STREAM_KEEPALIVE_LOGGER = "fastmcp-keepalive";
383
420
  var STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS = 2e4;
384
- var TextContentZodSchema = _zod.z.object({
385
- /**
386
- * The text content of the message.
387
- */
388
- text: _zod.z.string(),
389
- type: _zod.z.literal("text")
390
- }).strict();
391
- var ImageContentZodSchema = _zod.z.object({
392
- /**
393
- * The base64-encoded image data.
394
- */
395
- data: _zod.z.string().base64(),
396
- /**
397
- * The MIME type of the image. Different providers may support different image types.
398
- */
399
- mimeType: _zod.z.string(),
400
- type: _zod.z.literal("image")
401
- }).strict();
402
- var AudioContentZodSchema = _zod.z.object({
403
- /**
404
- * The base64-encoded audio data.
405
- */
406
- data: _zod.z.string().base64(),
407
- mimeType: _zod.z.string(),
408
- type: _zod.z.literal("audio")
421
+ var TextContentZodSchema = _typesjs.TextContentSchema.strict();
422
+ var ImageContentZodSchema = _typesjs.ImageContentSchema.extend({
423
+ data: _zod.z.string().base64()
409
424
  }).strict();
410
- var ResourceContentZodSchema = _zod.z.object({
411
- resource: _zod.z.object({
412
- blob: _zod.z.string().optional(),
413
- mimeType: _zod.z.string().optional(),
414
- text: _zod.z.string().optional(),
415
- uri: _zod.z.string()
416
- }),
417
- type: _zod.z.literal("resource")
425
+ var AudioContentZodSchema = _typesjs.AudioContentSchema.extend({
426
+ data: _zod.z.string().base64()
418
427
  }).strict();
419
- var ResourceLinkZodSchema = _zod.z.object({
420
- description: _zod.z.string().optional(),
421
- mimeType: _zod.z.string().optional(),
422
- name: _zod.z.string(),
423
- title: _zod.z.string().optional(),
424
- type: _zod.z.literal("resource_link"),
425
- uri: _zod.z.string()
426
- });
428
+ var ResourceContentZodSchema = _typesjs.EmbeddedResourceSchema.strict();
427
429
  var ContentZodSchema = _zod.z.discriminatedUnion("type", [
428
430
  TextContentZodSchema,
429
431
  ImageContentZodSchema,
430
432
  AudioContentZodSchema,
431
433
  ResourceContentZodSchema,
432
- ResourceLinkZodSchema
434
+ _typesjs.ResourceLinkSchema
433
435
  ]);
434
436
  var ContentResultZodSchema = _zod.z.object({
435
437
  _meta: _zod.z.record(_zod.z.string(), _zod.z.unknown()).optional(),
@@ -516,7 +518,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
516
518
  */
517
519
  get sessionId() {
518
520
  if (this.#sessionId === void 0) {
519
- const transportSessionId = _optionalChain([this, 'access', _9 => _9.#server, 'access', _10 => _10.transport, 'optionalAccess', _11 => _11.sessionId]);
521
+ const transportSessionId = _optionalChain([this, 'access', _18 => _18.#server, 'access', _19 => _19.transport, 'optionalAccess', _20 => _20.sessionId]);
520
522
  if (typeof transportSessionId === "string") {
521
523
  this.#sessionId = transportSessionId;
522
524
  }
@@ -575,6 +577,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
575
577
  * to interested clients only.
576
578
  */
577
579
  #subscriptions = /* @__PURE__ */ new Set();
580
+ #tools;
578
581
  #transportType;
579
582
  /**
580
583
  * Capabilities this session has already warned about in `#canRefresh`, so a
@@ -583,6 +586,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
583
586
  */
584
587
  #unnegotiatedWarnings = /* @__PURE__ */ new Set();
585
588
  #utils;
589
+ #visibleTools = [];
586
590
  constructor({
587
591
  auth,
588
592
  authRequired = false,
@@ -617,6 +621,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
617
621
  this.#sessionId = sessionId;
618
622
  this.#stateless = stateless;
619
623
  this.#streamKeepaliveConfig = streamKeepalive;
624
+ this.#tools = tools;
620
625
  this.#transportType = transportType;
621
626
  this.#needsEventLoopFlush = transportType === "httpStream";
622
627
  const supportsTools = _nullishCoalesce(hasTools, () => ( tools.length > 0));
@@ -650,7 +655,9 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
650
655
  this.setupRootsHandlers();
651
656
  this.setupCompleteHandlers();
652
657
  if (supportsTools) {
653
- this.setupToolHandlers(tools);
658
+ this.setupToolHandlers(
659
+ toolsVisibleTo(tools, this.#auth, this.#authRequired)
660
+ );
654
661
  }
655
662
  if (resources.length || resourcesTemplates.length) {
656
663
  for (const resource of resources) {
@@ -771,6 +778,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
771
778
  if (!this.#canRefresh("tools")) {
772
779
  return;
773
780
  }
781
+ this.#tools = tools;
774
782
  this.setupToolHandlers(
775
783
  toolsVisibleTo(tools, this.#auth, this.#authRequired)
776
784
  );
@@ -795,6 +803,11 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
795
803
  */
796
804
  updateAuth(auth) {
797
805
  this.#auth = auth;
806
+ const tools = toolsVisibleTo(this.#tools, auth, this.#authRequired);
807
+ if (tools.length !== this.#visibleTools.length || tools.some((tool, index) => tool !== this.#visibleTools[index])) {
808
+ this.setupToolHandlers(tools);
809
+ this.triggerListChangedNotification("notifications/tools/list_changed");
810
+ }
798
811
  }
799
812
  waitForReady() {
800
813
  if (this.isReady) {
@@ -872,37 +885,37 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
872
885
  * are tied to a tool call's progress token / streaming notification,
873
886
  * which resource and prompt reads do not have.
874
887
  */
875
- #createLoadContext(meta) {
888
+ #createLoadContext(meta, sendNotification) {
876
889
  return {
877
890
  client: {
878
891
  version: this.#server.getClientVersion()
879
892
  },
880
893
  elicit: (params, options) => this.#server.elicitInput(params, options),
881
- log: this.#createLog(),
882
- requestId: typeof _optionalChain([meta, 'optionalAccess', _12 => _12.requestId]) === "string" ? meta.requestId : void 0,
894
+ log: this.#createLog(sendNotification),
895
+ requestId: typeof _optionalChain([meta, 'optionalAccess', _21 => _21.requestId]) === "string" ? meta.requestId : void 0,
883
896
  session: this.#auth,
884
897
  sessionId: this.sessionId
885
898
  };
886
899
  }
887
- #createLog() {
900
+ #createLog(sendNotification) {
888
901
  return {
889
902
  debug: (message, context) => {
890
- this.#sendLog("debug", message, context);
903
+ this.#sendLog(sendNotification, "debug", message, context);
891
904
  },
892
905
  error: (message, context) => {
893
- this.#sendLog("error", message, context);
906
+ this.#sendLog(sendNotification, "error", message, context);
894
907
  },
895
908
  info: (message, context) => {
896
- this.#sendLog("info", message, context);
909
+ this.#sendLog(sendNotification, "info", message, context);
897
910
  },
898
911
  warn: (message, context) => {
899
- this.#sendLog("warning", message, context);
912
+ this.#sendLog(sendNotification, "warning", message, context);
900
913
  }
901
914
  };
902
915
  }
903
916
  #formatSchemaIssues(issues) {
904
- return _optionalChain([this, 'access', _13 => _13.#utils, 'optionalAccess', _14 => _14.formatInvalidParamsErrorMessage]) ? this.#utils.formatInvalidParamsErrorMessage(issues) : issues.map((issue) => {
905
- const path = _optionalChain([issue, 'access', _15 => _15.path, 'optionalAccess', _16 => _16.join, 'call', _17 => _17(".")]) || "root";
917
+ return _optionalChain([this, 'access', _22 => _22.#utils, 'optionalAccess', _23 => _23.formatInvalidParamsErrorMessage]) ? this.#utils.formatInvalidParamsErrorMessage(issues) : issues.map((issue) => {
918
+ const path = _optionalChain([issue, 'access', _24 => _24.path, 'optionalAccess', _25 => _25.join, 'call', _26 => _26(".")]) || "root";
906
919
  return `${path}: ${issue.message}`;
907
920
  }).join(", ");
908
921
  }
@@ -924,7 +937,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
924
937
  * is bounded and retried, and the result is announced with `rootsChanged`.
925
938
  */
926
939
  async #loadRoots(streamableHttp) {
927
- if (_optionalChain([this, 'access', _18 => _18.#rootsConfig, 'optionalAccess', _19 => _19.enabled]) === false || !_optionalChain([this, 'access', _20 => _20.#clientCapabilities, 'optionalAccess', _21 => _21.roots, 'optionalAccess', _22 => _22.listChanged]) || typeof this.#server.listRoots !== "function") {
940
+ if (_optionalChain([this, 'access', _27 => _27.#rootsConfig, 'optionalAccess', _28 => _28.enabled]) === false || !_optionalChain([this, 'access', _29 => _29.#clientCapabilities, 'optionalAccess', _30 => _30.roots, 'optionalAccess', _31 => _31.listChanged]) || typeof this.#server.listRoots !== "function") {
928
941
  return;
929
942
  }
930
943
  const maxAttempts = streamableHttp ? 5 : 1;
@@ -934,7 +947,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
934
947
  void 0,
935
948
  streamableHttp ? { timeout: 1e3 } : void 0
936
949
  );
937
- this.#roots = _optionalChain([roots, 'optionalAccess', _23 => _23.roots]) || [];
950
+ this.#roots = _optionalChain([roots, 'optionalAccess', _32 => _32.roots]) || [];
938
951
  if (streamableHttp) {
939
952
  this.emit("rootsChanged", { roots: this.#roots });
940
953
  }
@@ -962,22 +975,23 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
962
975
  }
963
976
  }
964
977
  /**
965
- * `sendLoggingMessage` rejects once the client has hung up, and these four
978
+ * Sending rejects once the client has hung up, and these four
966
979
  * callers are synchronous, so the rejection has nowhere to go. Swallow it the
967
980
  * way every other notification sender in this class does, or a client that
968
981
  * disconnects mid-tool takes the server process down with it.
969
982
  */
970
- #sendLog(level, message, context) {
983
+ #sendLog(sendNotification, level, message, context) {
971
984
  if (this.#loggingLevel && LOGGING_LEVEL_SEVERITY[level] < LOGGING_LEVEL_SEVERITY[this.#loggingLevel]) {
972
985
  return;
973
986
  }
974
- this.#server.sendLoggingMessage({
987
+ const params = {
975
988
  data: {
976
989
  context,
977
990
  message
978
991
  },
979
992
  level
980
- }).catch((error) => {
993
+ };
994
+ sendNotification({ method: "notifications/message", params }).catch(() => this.#server.sendLoggingMessage(params)).catch((error) => {
981
995
  this.#logger.error(
982
996
  `[FastMCP error] failed to send ${level} log notification.
983
997
 
@@ -1071,7 +1085,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1071
1085
  */
1072
1086
  #startStreamKeepalive(extra, toolName) {
1073
1087
  const config = this.#streamKeepaliveConfig;
1074
- if (!_optionalChain([config, 'optionalAccess', _24 => _24.enabled])) {
1088
+ if (!_optionalChain([config, 'optionalAccess', _33 => _33.enabled])) {
1075
1089
  return () => {
1076
1090
  };
1077
1091
  }
@@ -1091,9 +1105,9 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1091
1105
  );
1092
1106
  });
1093
1107
  }, intervalMs);
1094
- _optionalChain([timer, 'access', _25 => _25.unref, 'optionalCall', _26 => _26()]);
1108
+ _optionalChain([timer, 'access', _34 => _34.unref, 'optionalCall', _35 => _35()]);
1095
1109
  const stop = () => clearInterval(timer);
1096
- _optionalChain([extra, 'access', _27 => _27.signal, 'optionalAccess', _28 => _28.addEventListener, 'call', _29 => _29("abort", stop, { once: true })]);
1110
+ _optionalChain([extra, 'access', _36 => _36.signal, 'optionalAccess', _37 => _37.addEventListener, 'call', _38 => _38("abort", stop, { once: true })]);
1097
1111
  return stop;
1098
1112
  }
1099
1113
  async #validateStructuredContent(tool, value, toolName) {
@@ -1288,54 +1302,60 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1288
1302
  prompts: cachedPromptsList
1289
1303
  };
1290
1304
  });
1291
- this.#server.setRequestHandler(_typesjs.GetPromptRequestSchema, async (request) => {
1292
- const prompt = this.#prompts.get(request.params.name);
1293
- if (!prompt) {
1294
- throw new (0, _typesjs.McpError)(
1295
- _typesjs.ErrorCode.InvalidParams,
1296
- `Unknown prompt: ${request.params.name}`
1297
- );
1298
- }
1299
- const args = request.params.arguments;
1300
- for (const arg of _nullishCoalesce(prompt.arguments, () => ( []))) {
1301
- if (arg.required && !(args && Object.hasOwn(args, arg.name))) {
1305
+ this.#server.setRequestHandler(
1306
+ _typesjs.GetPromptRequestSchema,
1307
+ async (request, extra) => {
1308
+ const prompt = this.#prompts.get(request.params.name);
1309
+ if (!prompt) {
1302
1310
  throw new (0, _typesjs.McpError)(
1303
1311
  _typesjs.ErrorCode.InvalidParams,
1304
- `Prompt '${request.params.name}' requires argument '${arg.name}': ${arg.description || "No description provided"}`
1312
+ `Unknown prompt: ${request.params.name}`
1305
1313
  );
1306
1314
  }
1315
+ const args = request.params.arguments;
1316
+ for (const arg of _nullishCoalesce(prompt.arguments, () => ( []))) {
1317
+ if (arg.required && !(args && Object.hasOwn(args, arg.name))) {
1318
+ throw new (0, _typesjs.McpError)(
1319
+ _typesjs.ErrorCode.InvalidParams,
1320
+ `Prompt '${request.params.name}' requires argument '${arg.name}': ${arg.description || "No description provided"}`
1321
+ );
1322
+ }
1323
+ }
1324
+ let result;
1325
+ try {
1326
+ result = await prompt.load(
1327
+ _nullishCoalesce(args, () => ( {})),
1328
+ this.#auth,
1329
+ this.#createLoadContext(
1330
+ _optionalChain([request, 'access', _39 => _39.params, 'optionalAccess', _40 => _40._meta]),
1331
+ extra.sendNotification
1332
+ )
1333
+ );
1334
+ } catch (error) {
1335
+ const errorMessage = error instanceof Error ? error.message : String(error);
1336
+ throw new (0, _typesjs.McpError)(
1337
+ _typesjs.ErrorCode.InternalError,
1338
+ `Failed to load prompt '${request.params.name}': ${errorMessage}`
1339
+ );
1340
+ }
1341
+ if (typeof result === "string") {
1342
+ return {
1343
+ description: prompt.description,
1344
+ messages: [
1345
+ {
1346
+ content: { text: result, type: "text" },
1347
+ role: "user"
1348
+ }
1349
+ ]
1350
+ };
1351
+ } else {
1352
+ return {
1353
+ description: prompt.description,
1354
+ messages: result.messages
1355
+ };
1356
+ }
1307
1357
  }
1308
- let result;
1309
- try {
1310
- result = await prompt.load(
1311
- _nullishCoalesce(args, () => ( {})),
1312
- this.#auth,
1313
- this.#createLoadContext(_optionalChain([request, 'access', _30 => _30.params, 'optionalAccess', _31 => _31._meta]))
1314
- );
1315
- } catch (error) {
1316
- const errorMessage = error instanceof Error ? error.message : String(error);
1317
- throw new (0, _typesjs.McpError)(
1318
- _typesjs.ErrorCode.InternalError,
1319
- `Failed to load prompt '${request.params.name}': ${errorMessage}`
1320
- );
1321
- }
1322
- if (typeof result === "string") {
1323
- return {
1324
- description: prompt.description,
1325
- messages: [
1326
- {
1327
- content: { text: result, type: "text" },
1328
- role: "user"
1329
- }
1330
- ]
1331
- };
1332
- } else {
1333
- return {
1334
- description: prompt.description,
1335
- messages: result.messages
1336
- };
1337
- }
1338
- });
1358
+ );
1339
1359
  }
1340
1360
  setupResourceHandlers() {
1341
1361
  let cachedResourcesList = null;
@@ -1359,7 +1379,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1359
1379
  });
1360
1380
  this.#server.setRequestHandler(
1361
1381
  _typesjs.ReadResourceRequestSchema,
1362
- async (request) => {
1382
+ async (request, extra) => {
1363
1383
  if ("uri" in request.params) {
1364
1384
  const resource = this.#resources.get(request.params.uri);
1365
1385
  if (!resource) {
@@ -1375,7 +1395,10 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1375
1395
  const result = await resourceTemplate.load(
1376
1396
  match,
1377
1397
  this.#auth,
1378
- this.#createLoadContext(_optionalChain([request, 'access', _32 => _32.params, 'optionalAccess', _33 => _33._meta]))
1398
+ this.#createLoadContext(
1399
+ _optionalChain([request, 'access', _41 => _41.params, 'optionalAccess', _42 => _42._meta]),
1400
+ extra.sendNotification
1401
+ )
1379
1402
  );
1380
1403
  const resources = Array.isArray(result) ? result : [result];
1381
1404
  return {
@@ -1401,7 +1424,10 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1401
1424
  try {
1402
1425
  maybeArrayResult = await resource.load(
1403
1426
  this.#auth,
1404
- this.#createLoadContext(_optionalChain([request, 'access', _34 => _34.params, 'optionalAccess', _35 => _35._meta]))
1427
+ this.#createLoadContext(
1428
+ _optionalChain([request, 'access', _43 => _43.params, 'optionalAccess', _44 => _44._meta]),
1429
+ extra.sendNotification
1430
+ )
1405
1431
  );
1406
1432
  } catch (error) {
1407
1433
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -1464,7 +1490,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1464
1490
  );
1465
1491
  }
1466
1492
  setupRootsHandlers() {
1467
- if (_optionalChain([this, 'access', _36 => _36.#rootsConfig, 'optionalAccess', _37 => _37.enabled]) === false) {
1493
+ if (_optionalChain([this, 'access', _45 => _45.#rootsConfig, 'optionalAccess', _46 => _46.enabled]) === false) {
1468
1494
  this.#logger.debug(
1469
1495
  "[FastMCP debug] roots capability explicitly disabled via config"
1470
1496
  );
@@ -1501,6 +1527,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1501
1527
  }
1502
1528
  }
1503
1529
  setupToolHandlers(tools) {
1530
+ this.#visibleTools = tools;
1504
1531
  const toolsMap = new Map(tools.map((tool) => [tool.name, tool]));
1505
1532
  let cachedToolsList = null;
1506
1533
  this.#server.setRequestHandler(_typesjs.ListToolsRequestSchema, async () => {
@@ -1558,7 +1585,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1558
1585
  }
1559
1586
  args = parsed.value;
1560
1587
  }
1561
- const progressToken = _optionalChain([request, 'access', _38 => _38.params, 'optionalAccess', _39 => _39._meta, 'optionalAccess', _40 => _40.progressToken]);
1588
+ const progressToken = _optionalChain([request, 'access', _47 => _47.params, 'optionalAccess', _48 => _48._meta, 'optionalAccess', _49 => _49.progressToken]);
1562
1589
  let result;
1563
1590
  try {
1564
1591
  const reportProgress = async (progress) => {
@@ -1583,7 +1610,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1583
1610
  );
1584
1611
  }
1585
1612
  };
1586
- const log = this.#createLog();
1613
+ const log = this.#createLog(extra.sendNotification);
1587
1614
  const streamContent = async (content) => {
1588
1615
  const contentArray = Array.isArray(content) ? content : [content];
1589
1616
  try {
@@ -1626,7 +1653,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
1626
1653
  elicit: (params, options) => this.#server.elicitInput(params, options),
1627
1654
  log,
1628
1655
  reportProgress,
1629
- requestId: typeof _optionalChain([request, 'access', _41 => _41.params, 'optionalAccess', _42 => _42._meta, 'optionalAccess', _43 => _43.requestId]) === "string" ? request.params._meta.requestId : void 0,
1656
+ requestId: typeof _optionalChain([request, 'access', _50 => _50.params, 'optionalAccess', _51 => _51._meta, 'optionalAccess', _52 => _52.requestId]) === "string" ? request.params._meta.requestId : void 0,
1630
1657
  session: this.#auth,
1631
1658
  sessionId: this.sessionId,
1632
1659
  signal,
@@ -1768,7 +1795,7 @@ function normalizePath(path) {
1768
1795
  return path.startsWith("/") ? path : `/${path}`;
1769
1796
  }
1770
1797
  function parseBasicAuthHeader(authHeader) {
1771
- const basicMatch = _optionalChain([authHeader, 'optionalAccess', _44 => _44.match, 'call', _45 => _45(/^Basic\s+(.+)$/)]);
1798
+ const basicMatch = _optionalChain([authHeader, 'optionalAccess', _53 => _53.match, 'call', _54 => _54(/^Basic\s+(.+)$/)]);
1772
1799
  if (!basicMatch) return null;
1773
1800
  try {
1774
1801
  const credentials = Buffer.from(basicMatch[1], "base64").toString("utf-8");
@@ -2247,7 +2274,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2247
2274
  roots: this.#options.roots,
2248
2275
  streamKeepalive: this.#options.streamKeepalive,
2249
2276
  title: this.#options.title,
2250
- tools: toolsVisibleTo(this.#tools, auth, authRequired),
2277
+ tools: this.#tools,
2251
2278
  transportType: "stdio",
2252
2279
  utils: this.#options.utils,
2253
2280
  version: this.#options.version,
@@ -2414,9 +2441,9 @@ var FastMCP = class extends FastMCPEventEmitter {
2414
2441
  const originalOnClose = transport.onclose;
2415
2442
  transport.onclose = () => {
2416
2443
  closed = true;
2417
- _optionalChain([onClose, 'optionalCall', _46 => _46()]);
2444
+ _optionalChain([onClose, 'optionalCall', _55 => _55()]);
2418
2445
  this.#removeSession(session);
2419
- _optionalChain([originalOnClose, 'optionalCall', _47 => _47()]);
2446
+ _optionalChain([originalOnClose, 'optionalCall', _56 => _56()]);
2420
2447
  };
2421
2448
  await session.connect(transport);
2422
2449
  if (closed) {
@@ -2458,7 +2485,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2458
2485
  stateless,
2459
2486
  streamKeepalive: this.#options.streamKeepalive,
2460
2487
  title: this.#options.title,
2461
- tools: toolsVisibleTo(this.#tools, auth, authRequired),
2488
+ tools: this.#tools,
2462
2489
  transportType: "httpStream",
2463
2490
  utils: this.#options.utils,
2464
2491
  version: this.#options.version,
@@ -2480,7 +2507,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2480
2507
  */
2481
2508
  #createUnauthorizedResponse(message) {
2482
2509
  const oauth = this.#options.oauth;
2483
- const resource = _optionalChain([oauth, 'optionalAccess', _48 => _48.enabled]) ? _optionalChain([oauth, 'access', _49 => _49.protectedResource, 'optionalAccess', _50 => _50.resource]) : void 0;
2510
+ const resource = _optionalChain([oauth, 'optionalAccess', _57 => _57.enabled]) ? _optionalChain([oauth, 'access', _58 => _58.protectedResource, 'optionalAccess', _59 => _59.resource]) : void 0;
2484
2511
  const wwwAuthenticateParts = [
2485
2512
  'error="invalid_token"',
2486
2513
  `error_description="${message.replace(/"/g, '\\"')}"`
@@ -2619,7 +2646,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2619
2646
  }
2620
2647
  }
2621
2648
  const oauthConfig = this.#options.oauth;
2622
- if (_optionalChain([oauthConfig, 'optionalAccess', _51 => _51.enabled]) && req.method === "GET") {
2649
+ if (_optionalChain([oauthConfig, 'optionalAccess', _60 => _60.enabled]) && req.method === "GET") {
2623
2650
  const url2 = new URL(req.url || "", `http://${host}`);
2624
2651
  const authorizationServerMetadataPath = joinPaths(
2625
2652
  "",
@@ -2653,8 +2680,8 @@ var FastMCP = class extends FastMCPEventEmitter {
2653
2680
  }
2654
2681
  }
2655
2682
  }
2656
- const oauthProxy = _optionalChain([oauthConfig, 'optionalAccess', _52 => _52.proxy]);
2657
- if (oauthProxy && _optionalChain([oauthConfig, 'optionalAccess', _53 => _53.enabled])) {
2683
+ const oauthProxy = _optionalChain([oauthConfig, 'optionalAccess', _61 => _61.proxy]);
2684
+ if (oauthProxy && _optionalChain([oauthConfig, 'optionalAccess', _62 => _62.enabled])) {
2658
2685
  const url2 = new URL(req.url || "", `http://${host}`);
2659
2686
  const oauthPath = basePathRelativePath;
2660
2687
  try {
@@ -2707,7 +2734,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2707
2734
  const statusCode = error.statusCode || 400;
2708
2735
  res.writeHead(statusCode, OAUTH_CREDENTIAL_RESPONSE_HEADERS).end(
2709
2736
  JSON.stringify(
2710
- _optionalChain([error, 'access', _54 => _54.toJSON, 'optionalCall', _55 => _55()]) || {
2737
+ _optionalChain([error, 'access', _63 => _63.toJSON, 'optionalCall', _64 => _64()]) || {
2711
2738
  error: "invalid_request"
2712
2739
  }
2713
2740
  )
@@ -2734,7 +2761,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2734
2761
  } catch (error) {
2735
2762
  res.writeHead(400, { "Content-Type": "application/json" }).end(
2736
2763
  JSON.stringify(
2737
- _optionalChain([error, 'access', _56 => _56.toJSON, 'optionalCall', _57 => _57()]) || {
2764
+ _optionalChain([error, 'access', _65 => _65.toJSON, 'optionalCall', _66 => _66()]) || {
2738
2765
  error: "invalid_request"
2739
2766
  }
2740
2767
  )
@@ -2756,7 +2783,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2756
2783
  } catch (error) {
2757
2784
  res.writeHead(400, { "Content-Type": "application/json" }).end(
2758
2785
  JSON.stringify(
2759
- _optionalChain([error, 'access', _58 => _58.toJSON, 'optionalCall', _59 => _59()]) || {
2786
+ _optionalChain([error, 'access', _67 => _67.toJSON, 'optionalCall', _68 => _68()]) || {
2760
2787
  error: "server_error"
2761
2788
  }
2762
2789
  )
@@ -2825,7 +2852,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2825
2852
  } catch (error) {
2826
2853
  res.writeHead(400, { "Content-Type": "application/json" }).end(
2827
2854
  JSON.stringify(
2828
- _optionalChain([error, 'access', _60 => _60.toJSON, 'optionalCall', _61 => _61()]) || {
2855
+ _optionalChain([error, 'access', _69 => _69.toJSON, 'optionalCall', _70 => _70()]) || {
2829
2856
  error: "server_error"
2830
2857
  }
2831
2858
  )
@@ -2883,8 +2910,8 @@ var FastMCP = class extends FastMCPEventEmitter {
2883
2910
  const basicAuth = parseBasicAuthHeader(
2884
2911
  req.headers.authorization
2885
2912
  );
2886
- const clientId = _optionalChain([basicAuth, 'optionalAccess', _62 => _62.clientId]) || params.get("client_id") || "";
2887
- const clientSecret = _nullishCoalesce(_nullishCoalesce(_optionalChain([basicAuth, 'optionalAccess', _63 => _63.clientSecret]), () => ( params.get("client_secret"))), () => ( void 0));
2913
+ const clientId = _optionalChain([basicAuth, 'optionalAccess', _71 => _71.clientId]) || params.get("client_id") || "";
2914
+ const clientSecret = _nullishCoalesce(_nullishCoalesce(_optionalChain([basicAuth, 'optionalAccess', _72 => _72.clientSecret]), () => ( params.get("client_secret"))), () => ( void 0));
2888
2915
  let response;
2889
2916
  if (grantType === "authorization_code") {
2890
2917
  response = await oauthProxy.exchangeAuthorizationCode({
@@ -2914,7 +2941,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2914
2941
  const statusCode = error.statusCode || 400;
2915
2942
  res.writeHead(statusCode, OAUTH_CREDENTIAL_RESPONSE_HEADERS).end(
2916
2943
  JSON.stringify(
2917
- _optionalChain([error, 'access', _64 => _64.toJSON, 'optionalCall', _65 => _65()]) || {
2944
+ _optionalChain([error, 'access', _73 => _73.toJSON, 'optionalCall', _74 => _74()]) || {
2918
2945
  error: "invalid_request"
2919
2946
  }
2920
2947
  )
@@ -2940,7 +2967,7 @@ var FastMCP = class extends FastMCPEventEmitter {
2940
2967
  * regardless (RFC 7235), so no config is needed just to get the header.
2941
2968
  */
2942
2969
  #httpStreamOAuthConfig() {
2943
- const resource = _optionalChain([this, 'access', _66 => _66.#options, 'access', _67 => _67.oauth, 'optionalAccess', _68 => _68.enabled]) ? _optionalChain([this, 'access', _69 => _69.#options, 'access', _70 => _70.oauth, 'access', _71 => _71.protectedResource, 'optionalAccess', _72 => _72.resource]) : void 0;
2970
+ const resource = _optionalChain([this, 'access', _75 => _75.#options, 'access', _76 => _76.oauth, 'optionalAccess', _77 => _77.enabled]) ? _optionalChain([this, 'access', _78 => _78.#options, 'access', _79 => _79.oauth, 'access', _80 => _80.protectedResource, 'optionalAccess', _81 => _81.resource]) : void 0;
2944
2971
  if (!resource) {
2945
2972
  return {};
2946
2973
  }
@@ -3048,24 +3075,24 @@ var FastMCP = class extends FastMCPEventEmitter {
3048
3075
  const envBasePath = process.env.FASTMCP_BASE_PATH;
3049
3076
  const envStateless = process.env.FASTMCP_STATELESS;
3050
3077
  const envHost = process.env.FASTMCP_HOST;
3051
- const transportType = _optionalChain([overrides, 'optionalAccess', _73 => _73.transportType]) || parseTransportSetting(transportArg, "--transport") || parseTransportSetting(envTransport, "FASTMCP_TRANSPORT") || "stdio";
3078
+ const transportType = _optionalChain([overrides, 'optionalAccess', _82 => _82.transportType]) || parseTransportSetting(transportArg, "--transport") || parseTransportSetting(envTransport, "FASTMCP_TRANSPORT") || "stdio";
3052
3079
  if (transportType === "httpStream") {
3053
3080
  const port = parseInt(
3054
- _optionalChain([overrides, 'optionalAccess', _74 => _74.httpStream, 'optionalAccess', _75 => _75.port, 'optionalAccess', _76 => _76.toString, 'call', _77 => _77()]) || portArg || envPort || "8080"
3081
+ _optionalChain([overrides, 'optionalAccess', _83 => _83.httpStream, 'optionalAccess', _84 => _84.port, 'optionalAccess', _85 => _85.toString, 'call', _86 => _86()]) || portArg || envPort || "8080"
3055
3082
  );
3056
- const host = _optionalChain([overrides, 'optionalAccess', _78 => _78.httpStream, 'optionalAccess', _79 => _79.host]) || hostArg || envHost || "localhost";
3057
- const endpoint = _optionalChain([overrides, 'optionalAccess', _80 => _80.httpStream, 'optionalAccess', _81 => _81.endpoint]) || endpointArg || envEndpoint || "/mcp";
3083
+ const host = _optionalChain([overrides, 'optionalAccess', _87 => _87.httpStream, 'optionalAccess', _88 => _88.host]) || hostArg || envHost || "localhost";
3084
+ const endpoint = _optionalChain([overrides, 'optionalAccess', _89 => _89.httpStream, 'optionalAccess', _90 => _90.endpoint]) || endpointArg || envEndpoint || "/mcp";
3058
3085
  const basePath = normalizeBasePath(
3059
- _optionalChain([overrides, 'optionalAccess', _82 => _82.httpStream, 'optionalAccess', _83 => _83.basePath]) || basePathArg || envBasePath
3086
+ _optionalChain([overrides, 'optionalAccess', _91 => _91.httpStream, 'optionalAccess', _92 => _92.basePath]) || basePathArg || envBasePath
3060
3087
  );
3061
- const enableJsonResponse = _optionalChain([overrides, 'optionalAccess', _84 => _84.httpStream, 'optionalAccess', _85 => _85.enableJsonResponse]) || false;
3062
- const stateless = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([overrides, 'optionalAccess', _86 => _86.httpStream, 'optionalAccess', _87 => _87.stateless]), () => ( // A bare `--stateless` means `--stateless true`.
3088
+ const enableJsonResponse = _optionalChain([overrides, 'optionalAccess', _93 => _93.httpStream, 'optionalAccess', _94 => _94.enableJsonResponse]) || false;
3089
+ const stateless = _nullishCoalesce(_nullishCoalesce(_nullishCoalesce(_optionalChain([overrides, 'optionalAccess', _95 => _95.httpStream, 'optionalAccess', _96 => _96.stateless]), () => ( // A bare `--stateless` means `--stateless true`.
3063
3090
  (statelessArg === "" ? true : parseBooleanSetting(statelessArg, "--stateless")))), () => ( parseBooleanSetting(envStateless, "FASTMCP_STATELESS"))), () => ( false));
3064
- const cors = _optionalChain([overrides, 'optionalAccess', _88 => _88.httpStream, 'optionalAccess', _89 => _89.cors]);
3065
- const eventStore = _optionalChain([overrides, 'optionalAccess', _90 => _90.httpStream, 'optionalAccess', _91 => _91.eventStore]);
3066
- const sslCa = _optionalChain([overrides, 'optionalAccess', _92 => _92.httpStream, 'optionalAccess', _93 => _93.sslCa]);
3067
- const sslCert = _optionalChain([overrides, 'optionalAccess', _94 => _94.httpStream, 'optionalAccess', _95 => _95.sslCert]);
3068
- const sslKey = _optionalChain([overrides, 'optionalAccess', _96 => _96.httpStream, 'optionalAccess', _97 => _97.sslKey]);
3091
+ const cors = _optionalChain([overrides, 'optionalAccess', _97 => _97.httpStream, 'optionalAccess', _98 => _98.cors]);
3092
+ const eventStore = _optionalChain([overrides, 'optionalAccess', _99 => _99.httpStream, 'optionalAccess', _100 => _100.eventStore]);
3093
+ const sslCa = _optionalChain([overrides, 'optionalAccess', _101 => _101.httpStream, 'optionalAccess', _102 => _102.sslCa]);
3094
+ const sslCert = _optionalChain([overrides, 'optionalAccess', _103 => _103.httpStream, 'optionalAccess', _104 => _104.sslCert]);
3095
+ const sslKey = _optionalChain([overrides, 'optionalAccess', _105 => _105.httpStream, 'optionalAccess', _106 => _106.sslKey]);
3069
3096
  return {
3070
3097
  httpStream: {
3071
3098
  basePath,
@@ -3157,7 +3184,7 @@ var FastMCP = class extends FastMCPEventEmitter {
3157
3184
  */
3158
3185
  #useEndpointAsResource(endpoint) {
3159
3186
  const oauth = this.#options.oauth;
3160
- if (this.#providerResourceBase === void 0 || !_optionalChain([oauth, 'optionalAccess', _98 => _98.protectedResource]))
3187
+ if (this.#providerResourceBase === void 0 || !_optionalChain([oauth, 'optionalAccess', _107 => _107.protectedResource]))
3161
3188
  return;
3162
3189
  this.#options = {
3163
3190
  ...this.#options,
@@ -3186,4 +3213,4 @@ var FastMCP = class extends FastMCPEventEmitter {
3186
3213
 
3187
3214
 
3188
3215
  exports.DiscoveryDocumentCache = DiscoveryDocumentCache; exports.jsonSchemaAdapter = jsonSchemaAdapter; exports.MEDIA_FETCH_TIMEOUT_MS = MEDIA_FETCH_TIMEOUT_MS; exports.imageContent = imageContent; exports.audioContent = audioContent; exports.FastMCPError = FastMCPError; exports.SessionError = SessionError; exports.UnexpectedStateError = UnexpectedStateError; exports.UserError = UserError; exports.ServerState = ServerState; exports.FastMCPSession = FastMCPSession; exports.FastMCP = FastMCP;
3189
- //# sourceMappingURL=chunk-TBJSX5UF.cjs.map
3216
+ //# sourceMappingURL=chunk-2PXF6JQB.cjs.map