fastmcp 3.7.0 → 3.8.1

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/src/FastMCP.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
2
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { EventStore } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
3
4
  import { RequestOptions } from "@modelcontextprotocol/sdk/shared/protocol.js";
4
5
  import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
5
6
  import {
@@ -382,41 +383,49 @@ const CompletionZodSchema = z.object({
382
383
  values: z.array(z.string()).max(100),
383
384
  }) satisfies z.ZodType<Completion>;
384
385
 
385
- type ArgumentValueCompleter = (value: string) => Promise<Completion>;
386
+ type ArgumentValueCompleter<T extends FastMCPSessionAuth = FastMCPSessionAuth> =
387
+ (value: string, auth?: T) => Promise<Completion>;
386
388
 
387
389
  type InputPrompt<
388
- Arguments extends InputPromptArgument[] = InputPromptArgument[],
390
+ T extends FastMCPSessionAuth = FastMCPSessionAuth,
391
+ Arguments extends InputPromptArgument<T>[] = InputPromptArgument<T>[],
389
392
  Args = PromptArgumentsToObject<Arguments>,
390
393
  > = {
391
- arguments?: InputPromptArgument[];
394
+ arguments?: InputPromptArgument<T>[];
392
395
  description?: string;
393
- load: (args: Args) => Promise<PromptResult>;
396
+ load: (args: Args, auth?: T) => Promise<PromptResult>;
394
397
  name: string;
395
398
  };
396
399
 
397
- type InputPromptArgument = Readonly<{
398
- complete?: ArgumentValueCompleter;
399
- description?: string;
400
- enum?: string[];
401
- name: string;
402
- required?: boolean;
403
- }>;
400
+ type InputPromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =
401
+ Readonly<{
402
+ complete?: ArgumentValueCompleter<T>;
403
+ description?: string;
404
+ enum?: string[];
405
+ name: string;
406
+ required?: boolean;
407
+ }>;
404
408
 
405
409
  type InputResourceTemplate<
406
- Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],
410
+ T extends FastMCPSessionAuth,
411
+ Arguments extends
412
+ InputResourceTemplateArgument<T>[] = InputResourceTemplateArgument<T>[],
407
413
  > = {
408
414
  arguments: Arguments;
409
415
  description?: string;
410
416
  load: (
411
417
  args: ResourceTemplateArgumentsToObject<Arguments>,
418
+ auth?: T,
412
419
  ) => Promise<ResourceResult | ResourceResult[]>;
413
420
  mimeType?: string;
414
421
  name: string;
415
422
  uriTemplate: string;
416
423
  };
417
424
 
418
- type InputResourceTemplateArgument = Readonly<{
419
- complete?: ArgumentValueCompleter;
425
+ type InputResourceTemplateArgument<
426
+ T extends FastMCPSessionAuth = FastMCPSessionAuth,
427
+ > = Readonly<{
428
+ complete?: ArgumentValueCompleter<T>;
420
429
  description?: string;
421
430
  name: string;
422
431
  required?: boolean;
@@ -433,23 +442,25 @@ type LoggingLevel =
433
442
  | "warning";
434
443
 
435
444
  type Prompt<
436
- Arguments extends PromptArgument[] = PromptArgument[],
445
+ T extends FastMCPSessionAuth = FastMCPSessionAuth,
446
+ Arguments extends PromptArgument<T>[] = PromptArgument<T>[],
437
447
  Args = PromptArgumentsToObject<Arguments>,
438
448
  > = {
439
- arguments?: PromptArgument[];
440
- complete?: (name: string, value: string) => Promise<Completion>;
449
+ arguments?: PromptArgument<T>[];
450
+ complete?: (name: string, value: string, auth?: T) => Promise<Completion>;
441
451
  description?: string;
442
- load: (args: Args) => Promise<PromptResult>;
452
+ load: (args: Args, auth?: T) => Promise<PromptResult>;
443
453
  name: string;
444
454
  };
445
455
 
446
- type PromptArgument = Readonly<{
447
- complete?: ArgumentValueCompleter;
448
- description?: string;
449
- enum?: string[];
450
- name: string;
451
- required?: boolean;
452
- }>;
456
+ type PromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =
457
+ Readonly<{
458
+ complete?: ArgumentValueCompleter<T>;
459
+ description?: string;
460
+ enum?: string[];
461
+ name: string;
462
+ required?: boolean;
463
+ }>;
453
464
 
454
465
  type PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =
455
466
  {
@@ -463,10 +474,10 @@ type PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =
463
474
 
464
475
  type PromptResult = Pick<GetPromptResult, "messages"> | string;
465
476
 
466
- type Resource = {
467
- complete?: (name: string, value: string) => Promise<Completion>;
477
+ type Resource<T extends FastMCPSessionAuth> = {
478
+ complete?: (name: string, value: string, auth?: T) => Promise<Completion>;
468
479
  description?: string;
469
- load: () => Promise<ResourceResult | ResourceResult[]>;
480
+ load: (auth?: T) => Promise<ResourceResult | ResourceResult[]>;
470
481
  mimeType?: string;
471
482
  name: string;
472
483
  uri: string;
@@ -485,21 +496,26 @@ type ResourceResult =
485
496
  };
486
497
 
487
498
  type ResourceTemplate<
488
- Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],
499
+ T extends FastMCPSessionAuth,
500
+ Arguments extends
501
+ ResourceTemplateArgument<T>[] = ResourceTemplateArgument<T>[],
489
502
  > = {
490
503
  arguments: Arguments;
491
- complete?: (name: string, value: string) => Promise<Completion>;
504
+ complete?: (name: string, value: string, auth?: T) => Promise<Completion>;
492
505
  description?: string;
493
506
  load: (
494
507
  args: ResourceTemplateArgumentsToObject<Arguments>,
508
+ auth?: T,
495
509
  ) => Promise<ResourceResult | ResourceResult[]>;
496
510
  mimeType?: string;
497
511
  name: string;
498
512
  uriTemplate: string;
499
513
  };
500
514
 
501
- type ResourceTemplateArgument = Readonly<{
502
- complete?: ArgumentValueCompleter;
515
+ type ResourceTemplateArgument<
516
+ T extends FastMCPSessionAuth = FastMCPSessionAuth,
517
+ > = Readonly<{
518
+ complete?: ArgumentValueCompleter<T>;
503
519
  description?: string;
504
520
  name: string;
505
521
  required?: boolean;
@@ -728,6 +744,8 @@ const FastMCPSessionEventEmitterBase: {
728
744
  new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;
729
745
  } = EventEmitter;
730
746
 
747
+ type Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;
748
+
731
749
  type FastMCPSessionAuth = Record<string, unknown> | undefined;
732
750
 
733
751
  class FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}
@@ -760,11 +778,11 @@ export class FastMCPSession<
760
778
 
761
779
  #pingInterval: null | ReturnType<typeof setInterval> = null;
762
780
 
763
- #prompts: Prompt[] = [];
781
+ #prompts: Prompt<T>[] = [];
764
782
 
765
- #resources: Resource[] = [];
783
+ #resources: Resource<T>[] = [];
766
784
 
767
- #resourceTemplates: ResourceTemplate[] = [];
785
+ #resourceTemplates: ResourceTemplate<T>[] = [];
768
786
 
769
787
  #roots: Root[] = [];
770
788
 
@@ -789,9 +807,9 @@ export class FastMCPSession<
789
807
  instructions?: string;
790
808
  name: string;
791
809
  ping?: ServerOptions<T>["ping"];
792
- prompts: Prompt[];
793
- resources: Resource[];
794
- resourcesTemplates: InputResourceTemplate[];
810
+ prompts: Prompt<T>[];
811
+ resources: Resource<T>[];
812
+ resourcesTemplates: InputResourceTemplate<T>[];
795
813
  roots?: ServerOptions<T>["roots"];
796
814
  tools: Tool<T>[];
797
815
  transportType?: "httpStream" | "stdio";
@@ -1034,8 +1052,8 @@ export class FastMCPSession<
1034
1052
  };
1035
1053
  }
1036
1054
 
1037
- private addPrompt(inputPrompt: InputPrompt) {
1038
- const completers: Record<string, ArgumentValueCompleter> = {};
1055
+ private addPrompt(inputPrompt: InputPrompt<T>) {
1056
+ const completers: Record<string, ArgumentValueCompleter<T>> = {};
1039
1057
  const enums: Record<string, string[]> = {};
1040
1058
  const fuseInstances: Record<string, Fuse<string>> = {};
1041
1059
 
@@ -1055,9 +1073,9 @@ export class FastMCPSession<
1055
1073
 
1056
1074
  const prompt = {
1057
1075
  ...inputPrompt,
1058
- complete: async (name: string, value: string) => {
1076
+ complete: async (name: string, value: string, auth?: T) => {
1059
1077
  if (completers[name]) {
1060
- return await completers[name](value);
1078
+ return await completers[name](value, auth);
1061
1079
  }
1062
1080
 
1063
1081
  if (fuseInstances[name]) {
@@ -1078,12 +1096,12 @@ export class FastMCPSession<
1078
1096
  this.#prompts.push(prompt);
1079
1097
  }
1080
1098
 
1081
- private addResource(inputResource: Resource) {
1099
+ private addResource(inputResource: Resource<T>) {
1082
1100
  this.#resources.push(inputResource);
1083
1101
  }
1084
1102
 
1085
- private addResourceTemplate(inputResourceTemplate: InputResourceTemplate) {
1086
- const completers: Record<string, ArgumentValueCompleter> = {};
1103
+ private addResourceTemplate(inputResourceTemplate: InputResourceTemplate<T>) {
1104
+ const completers: Record<string, ArgumentValueCompleter<T>> = {};
1087
1105
 
1088
1106
  for (const argument of inputResourceTemplate.arguments ?? []) {
1089
1107
  if (argument.complete) {
@@ -1093,9 +1111,9 @@ export class FastMCPSession<
1093
1111
 
1094
1112
  const resourceTemplate = {
1095
1113
  ...inputResourceTemplate,
1096
- complete: async (name: string, value: string) => {
1114
+ complete: async (name: string, value: string, auth?: T) => {
1097
1115
  if (completers[name]) {
1098
- return await completers[name](value);
1116
+ return await completers[name](value, auth);
1099
1117
  }
1100
1118
 
1101
1119
  return {
@@ -1130,6 +1148,7 @@ export class FastMCPSession<
1130
1148
  await prompt.complete(
1131
1149
  request.params.argument.name,
1132
1150
  request.params.argument.value,
1151
+ this.#auth,
1133
1152
  ),
1134
1153
  );
1135
1154
 
@@ -1166,6 +1185,7 @@ export class FastMCPSession<
1166
1185
  await resource.complete(
1167
1186
  request.params.argument.name,
1168
1187
  request.params.argument.value,
1188
+ this.#auth,
1169
1189
  ),
1170
1190
  );
1171
1191
 
@@ -1194,7 +1214,7 @@ export class FastMCPSession<
1194
1214
  });
1195
1215
  }
1196
1216
 
1197
- private setupPromptHandlers(prompts: Prompt[]) {
1217
+ private setupPromptHandlers(prompts: Prompt<T>[]) {
1198
1218
  this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {
1199
1219
  return {
1200
1220
  prompts: prompts.map((prompt) => {
@@ -1233,10 +1253,13 @@ export class FastMCPSession<
1233
1253
  }
1234
1254
  }
1235
1255
 
1236
- let result: Awaited<ReturnType<Prompt["load"]>>;
1256
+ let result: Awaited<ReturnType<Prompt<T>["load"]>>;
1237
1257
 
1238
1258
  try {
1239
- result = await prompt.load(args as Record<string, string | undefined>);
1259
+ result = await prompt.load(
1260
+ args as Record<string, string | undefined>,
1261
+ this.#auth,
1262
+ );
1240
1263
  } catch (error) {
1241
1264
  const errorMessage =
1242
1265
  error instanceof Error ? error.message : String(error);
@@ -1265,7 +1288,7 @@ export class FastMCPSession<
1265
1288
  });
1266
1289
  }
1267
1290
 
1268
- private setupResourceHandlers(resources: Resource[]) {
1291
+ private setupResourceHandlers(resources: Resource<T>[]) {
1269
1292
  this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {
1270
1293
  return {
1271
1294
  resources: resources.map((resource) => ({
@@ -1300,7 +1323,7 @@ export class FastMCPSession<
1300
1323
 
1301
1324
  const uri = uriTemplate.fill(match);
1302
1325
 
1303
- const result = await resourceTemplate.load(match);
1326
+ const result = await resourceTemplate.load(match, this.#auth);
1304
1327
 
1305
1328
  const resources = Array.isArray(result) ? result : [result];
1306
1329
  return {
@@ -1326,10 +1349,10 @@ export class FastMCPSession<
1326
1349
  throw new UnexpectedStateError("Resource does not support reading");
1327
1350
  }
1328
1351
 
1329
- let maybeArrayResult: Awaited<ReturnType<Resource["load"]>>;
1352
+ let maybeArrayResult: Awaited<ReturnType<Resource<T>["load"]>>;
1330
1353
 
1331
1354
  try {
1332
- maybeArrayResult = await resource.load();
1355
+ maybeArrayResult = await resource.load(this.#auth);
1333
1356
  } catch (error) {
1334
1357
  const errorMessage =
1335
1358
  error instanceof Error ? error.message : String(error);
@@ -1363,7 +1386,9 @@ export class FastMCPSession<
1363
1386
  );
1364
1387
  }
1365
1388
 
1366
- private setupResourceTemplateHandlers(resourceTemplates: ResourceTemplate[]) {
1389
+ private setupResourceTemplateHandlers(
1390
+ resourceTemplates: ResourceTemplate<T>[],
1391
+ ) {
1367
1392
  this.#server.setRequestHandler(
1368
1393
  ListResourceTemplatesRequestSchema,
1369
1394
  async () => {
@@ -1676,12 +1701,10 @@ const FastMCPEventEmitterBase: {
1676
1701
  new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;
1677
1702
  } = EventEmitter;
1678
1703
 
1679
- type Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;
1680
-
1681
1704
  class FastMCPEventEmitter extends FastMCPEventEmitterBase {}
1682
1705
 
1683
1706
  export class FastMCP<
1684
- T extends Record<string, unknown> | undefined = undefined,
1707
+ T extends FastMCPSessionAuth = FastMCPSessionAuth,
1685
1708
  > extends FastMCPEventEmitter {
1686
1709
  public get sessions(): FastMCPSession<T>[] {
1687
1710
  return this.#sessions;
@@ -1689,9 +1712,9 @@ export class FastMCP<
1689
1712
  #authenticate: Authenticate<T> | undefined;
1690
1713
  #httpStreamServer: null | SSEServer = null;
1691
1714
  #options: ServerOptions<T>;
1692
- #prompts: InputPrompt[] = [];
1693
- #resources: Resource[] = [];
1694
- #resourcesTemplates: InputResourceTemplate[] = [];
1715
+ #prompts: InputPrompt<T>[] = [];
1716
+ #resources: Resource<T>[] = [];
1717
+ #resourcesTemplates: InputResourceTemplate<T>[] = [];
1695
1718
  #sessions: FastMCPSession<T>[] = [];
1696
1719
 
1697
1720
  #tools: Tool<T>[] = [];
@@ -1706,8 +1729,8 @@ export class FastMCP<
1706
1729
  /**
1707
1730
  * Adds a prompt to the server.
1708
1731
  */
1709
- public addPrompt<const Args extends InputPromptArgument[]>(
1710
- prompt: InputPrompt<Args>,
1732
+ public addPrompt<const Args extends InputPromptArgument<T>[]>(
1733
+ prompt: InputPrompt<T, Args>,
1711
1734
  ) {
1712
1735
  this.#prompts.push(prompt);
1713
1736
  }
@@ -1715,7 +1738,7 @@ export class FastMCP<
1715
1738
  /**
1716
1739
  * Adds a resource to the server.
1717
1740
  */
1718
- public addResource(resource: Resource) {
1741
+ public addResource(resource: Resource<T>) {
1719
1742
  this.#resources.push(resource);
1720
1743
  }
1721
1744
 
@@ -1724,7 +1747,7 @@ export class FastMCP<
1724
1747
  */
1725
1748
  public addResourceTemplate<
1726
1749
  const Args extends InputResourceTemplateArgument[],
1727
- >(resource: InputResourceTemplate<Args>) {
1750
+ >(resource: InputResourceTemplate<T, Args>) {
1728
1751
  this.#resourcesTemplates.push(resource);
1729
1752
  }
1730
1753
 
@@ -1822,7 +1845,11 @@ export class FastMCP<
1822
1845
  */
1823
1846
  public async start(
1824
1847
  options?: Partial<{
1825
- httpStream: { endpoint?: `/${string}`; port: number };
1848
+ httpStream: {
1849
+ endpoint?: `/${string}`;
1850
+ eventStore?: EventStore;
1851
+ port: number;
1852
+ };
1826
1853
  transportType: "httpStream" | "stdio";
1827
1854
  }>,
1828
1855
  ) {
@@ -1848,7 +1875,7 @@ export class FastMCP<
1848
1875
  this.#sessions.push(session);
1849
1876
 
1850
1877
  this.emit("connect", {
1851
- session,
1878
+ session: session as FastMCPSession<FastMCPSessionAuth>,
1852
1879
  });
1853
1880
  } else if (config.transportType === "httpStream") {
1854
1881
  const httpConfig = config.httpStream;
@@ -1874,9 +1901,10 @@ export class FastMCP<
1874
1901
  version: this.#options.version,
1875
1902
  });
1876
1903
  },
1904
+ eventStore: httpConfig.eventStore,
1877
1905
  onClose: async (session) => {
1878
1906
  this.emit("disconnect", {
1879
- session,
1907
+ session: session as FastMCPSession<FastMCPSessionAuth>,
1880
1908
  });
1881
1909
  },
1882
1910
  onConnect: async (session) => {
@@ -1885,9 +1913,10 @@ export class FastMCP<
1885
1913
  console.info(`[FastMCP info] HTTP Stream session established`);
1886
1914
 
1887
1915
  this.emit("connect", {
1888
- session,
1916
+ session: session as FastMCPSession<FastMCPSessionAuth>,
1889
1917
  });
1890
1918
  },
1919
+
1891
1920
  onUnhandledRequest: async (req, res) => {
1892
1921
  const healthConfig = this.#options.health ?? {};
1893
1922
 
@@ -1980,7 +2009,6 @@ export class FastMCP<
1980
2009
  // If the request was not handled above, return 404
1981
2010
  res.writeHead(404).end();
1982
2011
  },
1983
-
1984
2012
  port: httpConfig.port,
1985
2013
  streamEndpoint: httpConfig.endpoint,
1986
2014
  });
@@ -2012,7 +2040,11 @@ export class FastMCP<
2012
2040
  }>,
2013
2041
  ):
2014
2042
  | {
2015
- httpStream: { endpoint: `/${string}`; port: number };
2043
+ httpStream: {
2044
+ endpoint: `/${string}`;
2045
+ eventStore?: EventStore;
2046
+ port: number;
2047
+ };
2016
2048
  transportType: "httpStream";
2017
2049
  }
2018
2050
  | { transportType: "stdio" } {