fastmcp 3.21.0 → 3.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/FastMCP.d.ts +60 -1
- package/dist/FastMCP.js +244 -0
- package/dist/FastMCP.js.map +1 -1
- package/package.json +1 -1
package/dist/FastMCP.d.ts
CHANGED
|
@@ -581,6 +581,11 @@ type ToolAnnotations = {
|
|
|
581
581
|
declare const FastMCPSessionEventEmitterBase: {
|
|
582
582
|
new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;
|
|
583
583
|
};
|
|
584
|
+
declare enum ServerState {
|
|
585
|
+
Error = "error",
|
|
586
|
+
Running = "running",
|
|
587
|
+
Stopped = "stopped"
|
|
588
|
+
}
|
|
584
589
|
type Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;
|
|
585
590
|
type FastMCPSessionAuth = Record<string, unknown> | undefined;
|
|
586
591
|
declare class FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {
|
|
@@ -612,7 +617,12 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
612
617
|
});
|
|
613
618
|
close(): Promise<void>;
|
|
614
619
|
connect(transport: Transport): Promise<void>;
|
|
620
|
+
promptsListChanged(prompts: Prompt<T>[]): void;
|
|
615
621
|
requestSampling(message: z.infer<typeof CreateMessageRequestSchema>["params"], options?: RequestOptions): Promise<SamplingResponse>;
|
|
622
|
+
resourcesListChanged(resources: Resource<T>[]): void;
|
|
623
|
+
resourceTemplatesListChanged(resourceTemplates: ResourceTemplate<T>[]): void;
|
|
624
|
+
toolsListChanged(tools: Tool<T>[]): void;
|
|
625
|
+
triggerListChangedNotification(method: string): Promise<void>;
|
|
616
626
|
waitForReady(): Promise<void>;
|
|
617
627
|
private addPrompt;
|
|
618
628
|
private addResource;
|
|
@@ -634,24 +644,41 @@ declare class FastMCPEventEmitter extends FastMCPEventEmitterBase {
|
|
|
634
644
|
declare class FastMCP<T extends FastMCPSessionAuth = FastMCPSessionAuth> extends FastMCPEventEmitter {
|
|
635
645
|
#private;
|
|
636
646
|
options: ServerOptions<T>;
|
|
647
|
+
get serverState(): ServerState;
|
|
637
648
|
get sessions(): FastMCPSession<T>[];
|
|
638
649
|
constructor(options: ServerOptions<T>);
|
|
639
650
|
/**
|
|
640
651
|
* Adds a prompt to the server.
|
|
641
652
|
*/
|
|
642
653
|
addPrompt<const Args extends InputPromptArgument<T>[]>(prompt: InputPrompt<T, Args>): void;
|
|
654
|
+
/**
|
|
655
|
+
* Adds prompts to the server.
|
|
656
|
+
*/
|
|
657
|
+
addPrompts<const Args extends InputPromptArgument<T>[]>(prompts: InputPrompt<T, Args>[]): void;
|
|
643
658
|
/**
|
|
644
659
|
* Adds a resource to the server.
|
|
645
660
|
*/
|
|
646
661
|
addResource(resource: Resource<T>): void;
|
|
662
|
+
/**
|
|
663
|
+
* Adds resources to the server.
|
|
664
|
+
*/
|
|
665
|
+
addResources(resources: Resource<T>[]): void;
|
|
647
666
|
/**
|
|
648
667
|
* Adds a resource template to the server.
|
|
649
668
|
*/
|
|
650
669
|
addResourceTemplate<const Args extends InputResourceTemplateArgument[]>(resource: InputResourceTemplate<T, Args>): void;
|
|
670
|
+
/**
|
|
671
|
+
* Adds resource templates to the server.
|
|
672
|
+
*/
|
|
673
|
+
addResourceTemplates<const Args extends InputResourceTemplateArgument[]>(resources: InputResourceTemplate<T, Args>[]): void;
|
|
651
674
|
/**
|
|
652
675
|
* Adds a tool to the server.
|
|
653
676
|
*/
|
|
654
677
|
addTool<Params extends ToolParameters>(tool: Tool<T, Params>): void;
|
|
678
|
+
/**
|
|
679
|
+
* Adds tools to the server.
|
|
680
|
+
*/
|
|
681
|
+
addTools<Params extends ToolParameters>(tools: Tool<T, Params>[]): void;
|
|
655
682
|
/**
|
|
656
683
|
* Embeds a resource by URI, making it easy to include resources in tool responses.
|
|
657
684
|
*
|
|
@@ -659,6 +686,38 @@ declare class FastMCP<T extends FastMCPSessionAuth = FastMCPSessionAuth> extends
|
|
|
659
686
|
* @returns Promise<ResourceContent> - The embedded resource content
|
|
660
687
|
*/
|
|
661
688
|
embedded(uri: string): Promise<ResourceContent["resource"]>;
|
|
689
|
+
/**
|
|
690
|
+
* Removes a prompt from the server.
|
|
691
|
+
*/
|
|
692
|
+
removePrompt(name: string): void;
|
|
693
|
+
/**
|
|
694
|
+
* Removes prompts from the server.
|
|
695
|
+
*/
|
|
696
|
+
removePrompts(names: string[]): void;
|
|
697
|
+
/**
|
|
698
|
+
* Removes a resource from the server.
|
|
699
|
+
*/
|
|
700
|
+
removeResource(name: string): void;
|
|
701
|
+
/**
|
|
702
|
+
* Removes resources from the server.
|
|
703
|
+
*/
|
|
704
|
+
removeResources(names: string[]): void;
|
|
705
|
+
/**
|
|
706
|
+
* Removes a resource template from the server.
|
|
707
|
+
*/
|
|
708
|
+
removeResourceTemplate(name: string): void;
|
|
709
|
+
/**
|
|
710
|
+
* Removes resource templates from the server.
|
|
711
|
+
*/
|
|
712
|
+
removeResourceTemplates(names: string[]): void;
|
|
713
|
+
/**
|
|
714
|
+
* Removes a tool from the server.
|
|
715
|
+
*/
|
|
716
|
+
removeTool(name: string): void;
|
|
717
|
+
/**
|
|
718
|
+
* Removes tools from the server.
|
|
719
|
+
*/
|
|
720
|
+
removeTools(names: string[]): void;
|
|
662
721
|
/**
|
|
663
722
|
* Starts the server.
|
|
664
723
|
*/
|
|
@@ -679,4 +738,4 @@ declare class FastMCP<T extends FastMCPSessionAuth = FastMCPSessionAuth> extends
|
|
|
679
738
|
stop(): Promise<void>;
|
|
680
739
|
}
|
|
681
740
|
|
|
682
|
-
export { type AudioContent, type Content, type ContentResult, type Context, DiscoveryDocumentCache, FastMCP, type FastMCPEvents, FastMCPSession, type FastMCPSessionEvents, type ImageContent, type InputPrompt, type InputPromptArgument, type Logger, type LoggingLevel, type Progress, type Prompt, type PromptArgument, type Resource, type ResourceContent, type ResourceResult, type ResourceTemplate, type ResourceTemplateArgument, type SSEServer, type SerializableValue, type ServerOptions, type TextContent, type Tool, type ToolParameters, UnexpectedStateError, UserError, audioContent, imageContent };
|
|
741
|
+
export { type AudioContent, type Content, type ContentResult, type Context, DiscoveryDocumentCache, FastMCP, type FastMCPEvents, FastMCPSession, type FastMCPSessionEvents, type ImageContent, type InputPrompt, type InputPromptArgument, type Logger, type LoggingLevel, type Progress, type Prompt, type PromptArgument, type Resource, type ResourceContent, type ResourceResult, type ResourceTemplate, type ResourceTemplateArgument, type SSEServer, type SerializableValue, type ServerOptions, ServerState, type TextContent, type Tool, type ToolParameters, UnexpectedStateError, UserError, audioContent, imageContent };
|
package/dist/FastMCP.js
CHANGED
|
@@ -303,6 +303,12 @@ var CompletionZodSchema = z.object({
|
|
|
303
303
|
values: z.array(z.string()).max(100)
|
|
304
304
|
});
|
|
305
305
|
var FastMCPSessionEventEmitterBase = EventEmitter;
|
|
306
|
+
var ServerState = /* @__PURE__ */ ((ServerState2) => {
|
|
307
|
+
ServerState2["Error"] = "error";
|
|
308
|
+
ServerState2["Running"] = "running";
|
|
309
|
+
ServerState2["Stopped"] = "stopped";
|
|
310
|
+
return ServerState2;
|
|
311
|
+
})(ServerState || {});
|
|
306
312
|
var FastMCPSessionEventEmitter = class extends FastMCPSessionEventEmitterBase {
|
|
307
313
|
};
|
|
308
314
|
var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
@@ -506,9 +512,53 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
|
506
512
|
throw error;
|
|
507
513
|
}
|
|
508
514
|
}
|
|
515
|
+
promptsListChanged(prompts) {
|
|
516
|
+
this.#prompts = [];
|
|
517
|
+
for (const prompt of prompts) {
|
|
518
|
+
this.addPrompt(prompt);
|
|
519
|
+
}
|
|
520
|
+
this.setupPromptHandlers(prompts);
|
|
521
|
+
this.triggerListChangedNotification("notifications/prompts/list_changed");
|
|
522
|
+
}
|
|
509
523
|
async requestSampling(message, options) {
|
|
510
524
|
return this.#server.createMessage(message, options);
|
|
511
525
|
}
|
|
526
|
+
resourcesListChanged(resources) {
|
|
527
|
+
this.#resources = [];
|
|
528
|
+
for (const resource of resources) {
|
|
529
|
+
this.addResource(resource);
|
|
530
|
+
}
|
|
531
|
+
this.setupResourceHandlers(resources);
|
|
532
|
+
this.triggerListChangedNotification("notifications/resources/list_changed");
|
|
533
|
+
}
|
|
534
|
+
resourceTemplatesListChanged(resourceTemplates) {
|
|
535
|
+
this.#resourceTemplates = [];
|
|
536
|
+
for (const resourceTemplate of resourceTemplates) {
|
|
537
|
+
this.addResourceTemplate(resourceTemplate);
|
|
538
|
+
}
|
|
539
|
+
this.setupResourceTemplateHandlers(resourceTemplates);
|
|
540
|
+
this.triggerListChangedNotification("notifications/resources/list_changed");
|
|
541
|
+
}
|
|
542
|
+
toolsListChanged(tools) {
|
|
543
|
+
const allowedTools = tools.filter(
|
|
544
|
+
(tool) => tool.canAccess ? tool.canAccess(this.#auth) : true
|
|
545
|
+
);
|
|
546
|
+
this.setupToolHandlers(allowedTools);
|
|
547
|
+
this.triggerListChangedNotification("notifications/tools/list_changed");
|
|
548
|
+
}
|
|
549
|
+
async triggerListChangedNotification(method) {
|
|
550
|
+
try {
|
|
551
|
+
await this.#server.notification({
|
|
552
|
+
method
|
|
553
|
+
});
|
|
554
|
+
} catch (error) {
|
|
555
|
+
this.#logger.error(
|
|
556
|
+
`[FastMCP error] failed to send ${method} notification.
|
|
557
|
+
|
|
558
|
+
${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
512
562
|
waitForReady() {
|
|
513
563
|
if (this.isReady) {
|
|
514
564
|
return Promise.resolve();
|
|
@@ -1086,6 +1136,9 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1086
1136
|
this.#authenticate = options.authenticate;
|
|
1087
1137
|
this.#logger = options.logger || console;
|
|
1088
1138
|
}
|
|
1139
|
+
get serverState() {
|
|
1140
|
+
return this.#serverState;
|
|
1141
|
+
}
|
|
1089
1142
|
get sessions() {
|
|
1090
1143
|
return this.#sessions;
|
|
1091
1144
|
}
|
|
@@ -1096,31 +1149,102 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1096
1149
|
#prompts = [];
|
|
1097
1150
|
#resources = [];
|
|
1098
1151
|
#resourcesTemplates = [];
|
|
1152
|
+
#serverState = "stopped" /* Stopped */;
|
|
1099
1153
|
#sessions = [];
|
|
1100
1154
|
#tools = [];
|
|
1101
1155
|
/**
|
|
1102
1156
|
* Adds a prompt to the server.
|
|
1103
1157
|
*/
|
|
1104
1158
|
addPrompt(prompt) {
|
|
1159
|
+
this.#prompts = this.#prompts.filter((p) => p.name !== prompt.name);
|
|
1105
1160
|
this.#prompts.push(prompt);
|
|
1161
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1162
|
+
this.#promptsListChanged(this.#prompts);
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Adds prompts to the server.
|
|
1167
|
+
*/
|
|
1168
|
+
addPrompts(prompts) {
|
|
1169
|
+
const newPromptNames = new Set(prompts.map((prompt) => prompt.name));
|
|
1170
|
+
this.#prompts = this.#prompts.filter((p) => !newPromptNames.has(p.name));
|
|
1171
|
+
this.#prompts.push(...prompts);
|
|
1172
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1173
|
+
this.#promptsListChanged(this.#prompts);
|
|
1174
|
+
}
|
|
1106
1175
|
}
|
|
1107
1176
|
/**
|
|
1108
1177
|
* Adds a resource to the server.
|
|
1109
1178
|
*/
|
|
1110
1179
|
addResource(resource) {
|
|
1180
|
+
this.#resources = this.#resources.filter((r) => r.name !== resource.name);
|
|
1111
1181
|
this.#resources.push(resource);
|
|
1182
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1183
|
+
this.#resourcesListChanged(this.#resources);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Adds resources to the server.
|
|
1188
|
+
*/
|
|
1189
|
+
addResources(resources) {
|
|
1190
|
+
const newResourceNames = new Set(
|
|
1191
|
+
resources.map((resource) => resource.name)
|
|
1192
|
+
);
|
|
1193
|
+
this.#resources = this.#resources.filter(
|
|
1194
|
+
(r) => !newResourceNames.has(r.name)
|
|
1195
|
+
);
|
|
1196
|
+
this.#resources.push(...resources);
|
|
1197
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1198
|
+
this.#resourcesListChanged(this.#resources);
|
|
1199
|
+
}
|
|
1112
1200
|
}
|
|
1113
1201
|
/**
|
|
1114
1202
|
* Adds a resource template to the server.
|
|
1115
1203
|
*/
|
|
1116
1204
|
addResourceTemplate(resource) {
|
|
1205
|
+
this.#resourcesTemplates = this.#resourcesTemplates.filter(
|
|
1206
|
+
(t) => t.name !== resource.name
|
|
1207
|
+
);
|
|
1117
1208
|
this.#resourcesTemplates.push(resource);
|
|
1209
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1210
|
+
this.#resourceTemplatesListChanged(this.#resourcesTemplates);
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
/**
|
|
1214
|
+
* Adds resource templates to the server.
|
|
1215
|
+
*/
|
|
1216
|
+
addResourceTemplates(resources) {
|
|
1217
|
+
const newResourceTemplateNames = new Set(
|
|
1218
|
+
resources.map((resource) => resource.name)
|
|
1219
|
+
);
|
|
1220
|
+
this.#resourcesTemplates = this.#resourcesTemplates.filter(
|
|
1221
|
+
(t) => !newResourceTemplateNames.has(t.name)
|
|
1222
|
+
);
|
|
1223
|
+
this.#resourcesTemplates.push(...resources);
|
|
1224
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1225
|
+
this.#resourceTemplatesListChanged(this.#resourcesTemplates);
|
|
1226
|
+
}
|
|
1118
1227
|
}
|
|
1119
1228
|
/**
|
|
1120
1229
|
* Adds a tool to the server.
|
|
1121
1230
|
*/
|
|
1122
1231
|
addTool(tool) {
|
|
1232
|
+
this.#tools = this.#tools.filter((t) => t.name !== tool.name);
|
|
1123
1233
|
this.#tools.push(tool);
|
|
1234
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1235
|
+
this.#toolsListChanged(this.#tools);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* Adds tools to the server.
|
|
1240
|
+
*/
|
|
1241
|
+
addTools(tools) {
|
|
1242
|
+
const newToolNames = new Set(tools.map((tool) => tool.name));
|
|
1243
|
+
this.#tools = this.#tools.filter((t) => !newToolNames.has(t.name));
|
|
1244
|
+
this.#tools.push(...tools);
|
|
1245
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1246
|
+
this.#toolsListChanged(this.#tools);
|
|
1247
|
+
}
|
|
1124
1248
|
}
|
|
1125
1249
|
/**
|
|
1126
1250
|
* Embeds a resource by URI, making it easy to include resources in tool responses.
|
|
@@ -1171,6 +1295,90 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1171
1295
|
}
|
|
1172
1296
|
throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });
|
|
1173
1297
|
}
|
|
1298
|
+
/**
|
|
1299
|
+
* Removes a prompt from the server.
|
|
1300
|
+
*/
|
|
1301
|
+
removePrompt(name) {
|
|
1302
|
+
this.#prompts = this.#prompts.filter((p) => p.name !== name);
|
|
1303
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1304
|
+
this.#promptsListChanged(this.#prompts);
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Removes prompts from the server.
|
|
1309
|
+
*/
|
|
1310
|
+
removePrompts(names) {
|
|
1311
|
+
for (const name of names) {
|
|
1312
|
+
this.#prompts = this.#prompts.filter((p) => p.name !== name);
|
|
1313
|
+
}
|
|
1314
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1315
|
+
this.#promptsListChanged(this.#prompts);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
/**
|
|
1319
|
+
* Removes a resource from the server.
|
|
1320
|
+
*/
|
|
1321
|
+
removeResource(name) {
|
|
1322
|
+
this.#resources = this.#resources.filter((r) => r.name !== name);
|
|
1323
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1324
|
+
this.#resourcesListChanged(this.#resources);
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
/**
|
|
1328
|
+
* Removes resources from the server.
|
|
1329
|
+
*/
|
|
1330
|
+
removeResources(names) {
|
|
1331
|
+
for (const name of names) {
|
|
1332
|
+
this.#resources = this.#resources.filter((r) => r.name !== name);
|
|
1333
|
+
}
|
|
1334
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1335
|
+
this.#resourcesListChanged(this.#resources);
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
/**
|
|
1339
|
+
* Removes a resource template from the server.
|
|
1340
|
+
*/
|
|
1341
|
+
removeResourceTemplate(name) {
|
|
1342
|
+
this.#resourcesTemplates = this.#resourcesTemplates.filter(
|
|
1343
|
+
(t) => t.name !== name
|
|
1344
|
+
);
|
|
1345
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1346
|
+
this.#resourceTemplatesListChanged(this.#resourcesTemplates);
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
/**
|
|
1350
|
+
* Removes resource templates from the server.
|
|
1351
|
+
*/
|
|
1352
|
+
removeResourceTemplates(names) {
|
|
1353
|
+
for (const name of names) {
|
|
1354
|
+
this.#resourcesTemplates = this.#resourcesTemplates.filter(
|
|
1355
|
+
(t) => t.name !== name
|
|
1356
|
+
);
|
|
1357
|
+
}
|
|
1358
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1359
|
+
this.#resourceTemplatesListChanged(this.#resourcesTemplates);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
/**
|
|
1363
|
+
* Removes a tool from the server.
|
|
1364
|
+
*/
|
|
1365
|
+
removeTool(name) {
|
|
1366
|
+
this.#tools = this.#tools.filter((t) => t.name !== name);
|
|
1367
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1368
|
+
this.#toolsListChanged(this.#tools);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* Removes tools from the server.
|
|
1373
|
+
*/
|
|
1374
|
+
removeTools(names) {
|
|
1375
|
+
for (const name of names) {
|
|
1376
|
+
this.#tools = this.#tools.filter((t) => t.name !== name);
|
|
1377
|
+
}
|
|
1378
|
+
if (this.#serverState === "running" /* Running */) {
|
|
1379
|
+
this.#toolsListChanged(this.#tools);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1174
1382
|
/**
|
|
1175
1383
|
* Starts the server.
|
|
1176
1384
|
*/
|
|
@@ -1227,6 +1435,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1227
1435
|
this.emit("connect", {
|
|
1228
1436
|
session
|
|
1229
1437
|
});
|
|
1438
|
+
this.#serverState = "running" /* Running */;
|
|
1230
1439
|
} else if (config.transportType === "httpStream") {
|
|
1231
1440
|
const httpConfig = config.httpStream;
|
|
1232
1441
|
if (httpConfig.stateless) {
|
|
@@ -1308,6 +1517,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1308
1517
|
`[FastMCP info] server is running on HTTP Stream at http://${httpConfig.host}:${httpConfig.port}${httpConfig.endpoint}`
|
|
1309
1518
|
);
|
|
1310
1519
|
}
|
|
1520
|
+
this.#serverState = "running" /* Running */;
|
|
1311
1521
|
} else {
|
|
1312
1522
|
throw new Error("Invalid transport type");
|
|
1313
1523
|
}
|
|
@@ -1319,6 +1529,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1319
1529
|
if (this.#httpStreamServer) {
|
|
1320
1530
|
await this.#httpStreamServer.close();
|
|
1321
1531
|
}
|
|
1532
|
+
this.#serverState = "stopped" /* Stopped */;
|
|
1322
1533
|
}
|
|
1323
1534
|
/**
|
|
1324
1535
|
* Creates a new FastMCPSession instance with the current configuration.
|
|
@@ -1459,6 +1670,14 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1459
1670
|
}
|
|
1460
1671
|
return { transportType: "stdio" };
|
|
1461
1672
|
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Notifies all sessions that the prompts list has changed.
|
|
1675
|
+
*/
|
|
1676
|
+
#promptsListChanged(prompts) {
|
|
1677
|
+
for (const session of this.#sessions) {
|
|
1678
|
+
session.promptsListChanged(prompts);
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1462
1681
|
#removeSession(session) {
|
|
1463
1682
|
const sessionIndex = this.#sessions.indexOf(session);
|
|
1464
1683
|
if (sessionIndex !== -1) {
|
|
@@ -1468,11 +1687,36 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1468
1687
|
});
|
|
1469
1688
|
}
|
|
1470
1689
|
}
|
|
1690
|
+
/**
|
|
1691
|
+
* Notifies all sessions that the resources list has changed.
|
|
1692
|
+
*/
|
|
1693
|
+
#resourcesListChanged(resources) {
|
|
1694
|
+
for (const session of this.#sessions) {
|
|
1695
|
+
session.resourcesListChanged(resources);
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
/**
|
|
1699
|
+
* Notifies all sessions that the resource templates list has changed.
|
|
1700
|
+
*/
|
|
1701
|
+
#resourceTemplatesListChanged(templates) {
|
|
1702
|
+
for (const session of this.#sessions) {
|
|
1703
|
+
session.resourceTemplatesListChanged(templates);
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
/**
|
|
1707
|
+
* Notifies all sessions that the tools list has changed.
|
|
1708
|
+
*/
|
|
1709
|
+
#toolsListChanged(tools) {
|
|
1710
|
+
for (const session of this.#sessions) {
|
|
1711
|
+
session.toolsListChanged(tools);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1471
1714
|
};
|
|
1472
1715
|
export {
|
|
1473
1716
|
DiscoveryDocumentCache,
|
|
1474
1717
|
FastMCP,
|
|
1475
1718
|
FastMCPSession,
|
|
1719
|
+
ServerState,
|
|
1476
1720
|
UnexpectedStateError,
|
|
1477
1721
|
UserError,
|
|
1478
1722
|
audioContent,
|
package/dist/FastMCP.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/FastMCP.ts","../src/DiscoveryDocumentCache.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n CreateMessageRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n GetPromptResult,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourcesResult,\n ListResourceTemplatesRequestSchema,\n ListResourceTemplatesResult,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\n ResourceLink,\n Root,\n RootsListChangedNotificationSchema,\n ServerCapabilities,\n SetLevelRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { EventEmitter } from \"events\";\nimport { readFile } from \"fs/promises\";\nimport Fuse from \"fuse.js\";\nimport http from \"http\";\nimport { startHTTPServer } from \"mcp-proxy\";\nimport { StrictEventEmitter } from \"strict-event-emitter-types\";\nimport { setTimeout as delay } from \"timers/promises\";\nimport { fetch } from \"undici\";\nimport parseURITemplate from \"uri-templates\";\nimport { toJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\n\nexport interface Logger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype FastMCPEvents<T extends FastMCPSessionAuth> = {\n connect: (event: { session: FastMCPSession<T> }) => void;\n disconnect: (event: { session: FastMCPSession<T> }) => void;\n};\n\ntype FastMCPSessionEvents = {\n error: (event: { error: Error }) => void;\n ready: () => void;\n rootsChanged: (event: { roots: Root[] }) => void;\n};\n\nexport const imageContent = async (\n input: { buffer: Buffer } | { path: string } | { url: string },\n): Promise<ImageContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n try {\n const response = await fetch(input.url);\n\n if (!response.ok) {\n throw new Error(\n `Server responded with status: ${response.status} - ${response.statusText}`,\n );\n }\n\n rawData = Buffer.from(await response.arrayBuffer());\n } catch (error) {\n throw new Error(\n `Failed to fetch image from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read image from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"image/\")) {\n console.warn(\n `Warning: Content may not be a valid image. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"image/png\",\n type: \"image\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing image: ${String(error)}`);\n }\n }\n};\n\nexport const audioContent = async (\n input: { buffer: Buffer } | { path: string } | { url: string },\n): Promise<AudioContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n try {\n const response = await fetch(input.url);\n\n if (!response.ok) {\n throw new Error(\n `Server responded with status: ${response.status} - ${response.statusText}`,\n );\n }\n\n rawData = Buffer.from(await response.arrayBuffer());\n } catch (error) {\n throw new Error(\n `Failed to fetch audio from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read audio from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"audio/\")) {\n console.warn(\n `Warning: Content may not be a valid audio file. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"audio/mpeg\",\n type: \"audio\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing audio: ${String(error)}`);\n }\n }\n};\n\ntype Context<T extends FastMCPSessionAuth> = {\n client: {\n version: ReturnType<Server[\"getClientVersion\"]>;\n };\n log: {\n debug: (message: string, data?: SerializableValue) => void;\n error: (message: string, data?: SerializableValue) => void;\n info: (message: string, data?: SerializableValue) => void;\n warn: (message: string, data?: SerializableValue) => void;\n };\n reportProgress: (progress: Progress) => Promise<void>;\n /**\n * Request ID from the current MCP request.\n * Available for all transports when the client provides it.\n */\n requestId?: string;\n session: T | undefined;\n /**\n * Session ID from the Mcp-Session-Id header.\n * Only available for HTTP-based transports (SSE, HTTP Stream).\n * Can be used to track per-session state, implement session-specific\n * counters, or maintain user-specific data across multiple requests.\n */\n sessionId?: string;\n streamContent: (content: Content | Content[]) => Promise<void>;\n};\n\ntype Extra = unknown;\n\ntype Extras = Record<string, Extra>;\n\ntype Literal = boolean | null | number | string | undefined;\n\ntype Progress = {\n /**\n * The progress thus far. This should increase every time progress is made, even if the total is unknown.\n */\n progress: number;\n /**\n * Total number of items to process (or total progress required), if known.\n */\n total?: number;\n};\n\ntype SerializableValue =\n | { [key: string]: SerializableValue }\n | Literal\n | SerializableValue[];\n\ntype TextContent = {\n text: string;\n type: \"text\";\n};\n\ntype ToolParameters = StandardSchemaV1;\n\nabstract class FastMCPError extends Error {\n public constructor(message?: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class UnexpectedStateError extends FastMCPError {\n public extras?: Extras;\n\n public constructor(message: string, extras?: Extras) {\n super(message);\n this.name = new.target.name;\n this.extras = extras;\n }\n}\n\n/**\n * An error that is meant to be surfaced to the user.\n */\nexport class UserError extends UnexpectedStateError {}\n\nconst TextContentZodSchema = z\n .object({\n /**\n * The text content of the message.\n */\n text: z.string(),\n type: z.literal(\"text\"),\n })\n .strict() satisfies z.ZodType<TextContent>;\n\ntype ImageContent = {\n data: string;\n mimeType: string;\n type: \"image\";\n};\n\nconst ImageContentZodSchema = z\n .object({\n /**\n * The base64-encoded image data.\n */\n data: z.string().base64(),\n /**\n * The MIME type of the image. Different providers may support different image types.\n */\n mimeType: z.string(),\n type: z.literal(\"image\"),\n })\n .strict() satisfies z.ZodType<ImageContent>;\n\ntype AudioContent = {\n data: string;\n mimeType: string;\n type: \"audio\";\n};\n\nconst AudioContentZodSchema = z\n .object({\n /**\n * The base64-encoded audio data.\n */\n data: z.string().base64(),\n mimeType: z.string(),\n type: z.literal(\"audio\"),\n })\n .strict() satisfies z.ZodType<AudioContent>;\n\ntype ResourceContent = {\n resource: {\n blob?: string;\n mimeType?: string;\n text?: string;\n uri: string;\n };\n type: \"resource\";\n};\n\nconst ResourceContentZodSchema = z\n .object({\n resource: z.object({\n blob: z.string().optional(),\n mimeType: z.string().optional(),\n text: z.string().optional(),\n uri: z.string(),\n }),\n type: z.literal(\"resource\"),\n })\n .strict() satisfies z.ZodType<ResourceContent>;\n\nconst ResourceLinkZodSchema = z.object({\n description: z.string().optional(),\n mimeType: z.string().optional(),\n name: z.string(),\n title: z.string().optional(),\n type: z.literal(\"resource_link\"),\n uri: z.string(),\n}) satisfies z.ZodType<ResourceLink>;\n\ntype Content =\n | AudioContent\n | ImageContent\n | ResourceContent\n | ResourceLink\n | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n AudioContentZodSchema,\n ResourceContentZodSchema,\n ResourceLinkZodSchema,\n]) satisfies z.ZodType<Content>;\n\ntype ContentResult = {\n content: Content[];\n isError?: boolean;\n};\n\nconst ContentResultZodSchema = z\n .object({\n content: ContentZodSchema.array(),\n isError: z.boolean().optional(),\n })\n .strict() satisfies z.ZodType<ContentResult>;\n\ntype Completion = {\n hasMore?: boolean;\n total?: number;\n values: string[];\n};\n\n/**\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/3164da64d085ec4e022ae881329eee7b72f208d4/src/types.ts#L983-L1003\n */\nconst CompletionZodSchema = z.object({\n /**\n * Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.\n */\n hasMore: z.optional(z.boolean()),\n /**\n * The total number of completion options available. This can exceed the number of values actually sent in the response.\n */\n total: z.optional(z.number().int()),\n /**\n * An array of completion values. Must not exceed 100 items.\n */\n values: z.array(z.string()).max(100),\n}) satisfies z.ZodType<Completion>;\n\ntype ArgumentValueCompleter<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n (value: string, auth?: T) => Promise<Completion>;\n\ntype InputPrompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends InputPromptArgument<T>[] = InputPromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: InputPromptArgument<T>[];\n description?: string;\n load: (args: Args, auth?: T) => Promise<PromptResult>;\n name: string;\n};\n\ntype InputPromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype InputResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends\n InputResourceTemplateArgument<T>[] = InputResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype InputResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype LoggingLevel =\n | \"alert\"\n | \"critical\"\n | \"debug\"\n | \"emergency\"\n | \"error\"\n | \"info\"\n | \"notice\"\n | \"warning\";\n\ntype Prompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends PromptArgument<T>[] = PromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument<T>[];\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (args: Args, auth?: T) => Promise<PromptResult>;\n name: string;\n};\n\ntype PromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =\n {\n [K in T[number][\"name\"]]: Extract<\n T[number],\n { name: K }\n >[\"required\"] extends true\n ? string\n : string | undefined;\n };\n\ntype PromptResult = Pick<GetPromptResult, \"messages\"> | string;\n\ntype Resource<T extends FastMCPSessionAuth> = {\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (auth?: T) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uri: string;\n};\n\ntype ResourceResult =\n | {\n blob: string;\n mimeType?: string;\n uri?: string;\n }\n | {\n mimeType?: string;\n text: string;\n uri?: string;\n };\n\ntype ResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends\n ResourceTemplateArgument<T>[] = ResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype ResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype SamplingResponse = {\n content: AudioContent | ImageContent | TextContent;\n model: string;\n role: \"assistant\" | \"user\";\n stopReason?: \"endTurn\" | \"maxTokens\" | \"stopSequence\" | string;\n};\n\ntype ServerOptions<T extends FastMCPSessionAuth> = {\n authenticate?: Authenticate<T>;\n /**\n * Configuration for the health-check endpoint that can be exposed when the\n * server is running using the HTTP Stream transport. When enabled, the\n * server will respond to an HTTP GET request with the configured path (by\n * default \"/health\") rendering a plain-text response (by default \"ok\") and\n * the configured status code (by default 200).\n *\n * The endpoint is only added when the server is started with\n * `transportType: \"httpStream\"` – it is ignored for the stdio transport.\n */\n health?: {\n /**\n * When set to `false` the health-check endpoint is disabled.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Plain-text body returned by the endpoint.\n * @default \"ok\"\n */\n message?: string;\n\n /**\n * HTTP path that should be handled.\n * @default \"/health\"\n */\n path?: string;\n\n /**\n * HTTP response status that will be returned.\n * @default 200\n */\n status?: number;\n };\n instructions?: string;\n /**\n * Custom logger instance. If not provided, defaults to console.\n * Use this to integrate with your own logging system.\n */\n logger?: Logger;\n name: string;\n\n /**\n * Configuration for OAuth well-known discovery endpoints that can be exposed\n * when the server is running using HTTP-based transports (SSE or HTTP Stream).\n * When enabled, the server will respond to requests for OAuth discovery endpoints\n * with the configured metadata.\n *\n * The endpoints are only added when the server is started with\n * `transportType: \"httpStream\"` – they are ignored for the stdio transport.\n * Both SSE and HTTP Stream transports support OAuth endpoints.\n */\n oauth?: {\n /**\n * OAuth Authorization Server metadata for /.well-known/oauth-authorization-server\n *\n * This endpoint follows RFC 8414 (OAuth 2.0 Authorization Server Metadata)\n * and provides metadata about the OAuth 2.0 authorization server.\n *\n * Required by MCP Specification 2025-03-26\n */\n authorizationServer?: {\n authorizationEndpoint: string;\n codeChallengeMethodsSupported?: string[];\n // DPoP support\n dpopSigningAlgValuesSupported?: string[];\n grantTypesSupported?: string[];\n\n introspectionEndpoint?: string;\n // Required\n issuer: string;\n // Common optional\n jwksUri?: string;\n opPolicyUri?: string;\n opTosUri?: string;\n registrationEndpoint?: string;\n responseModesSupported?: string[];\n responseTypesSupported: string[];\n revocationEndpoint?: string;\n scopesSupported?: string[];\n serviceDocumentation?: string;\n tokenEndpoint: string;\n tokenEndpointAuthMethodsSupported?: string[];\n tokenEndpointAuthSigningAlgValuesSupported?: string[];\n\n uiLocalesSupported?: string[];\n };\n\n /**\n * Whether OAuth discovery endpoints should be enabled.\n */\n enabled: boolean;\n\n /**\n * OAuth Protected Resource metadata for `/.well-known/oauth-protected-resource`\n *\n * This endpoint follows {@link https://www.rfc-editor.org/rfc/rfc9728.html | RFC 9728}\n * and provides metadata describing how an OAuth 2.0 protected resource (in this case,\n * an MCP server) expects to be accessed.\n *\n * When configured, FastMCP will automatically serve this metadata at the\n * `/.well-known/oauth-protected-resource` endpoint. The `authorizationServers` and `resource`\n * fields are required. All others are optional and will be omitted from the published\n * metadata if not specified.\n *\n * This satisfies the requirements of the MCP Authorization specification's\n * {@link https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#authorization-server-location | Authorization Server Location section}.\n *\n * Clients consuming this metadata MUST validate that any presented values comply with\n * RFC 9728, including strict validation of the `resource` identifier and intended audience\n * when access tokens are issued and presented (per RFC 8707 §2).\n *\n * @remarks Required by MCP Specification version 2025-06-18\n */\n protectedResource?: {\n /**\n * Allows for additional metadata fields beyond those defined in RFC 9728.\n *\n * @remarks This supports vendor-specific or experimental extensions.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2.3 | RFC 9728 §2.3}\n */\n [key: string]: unknown;\n\n /**\n * Supported values for the `authorization_details` parameter (RFC 9396).\n *\n * @remarks Used when fine-grained access control is in play.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.23 | RFC 9728 §2.2.23}\n */\n authorizationDetailsTypesSupported?: string[];\n\n /**\n * List of OAuth 2.0 authorization server issuer identifiers.\n *\n * These correspond to ASes that can issue access tokens for this protected resource.\n * MCP clients use these values to locate the relevant `/.well-known/oauth-authorization-server`\n * metadata for initiating the OAuth flow.\n *\n * @remarks Required by the MCP spec. MCP servers MUST provide at least one issuer.\n * Clients are responsible for choosing among them (see RFC 9728 §7.6).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.3 | RFC 9728 §2.2.3}\n */\n authorizationServers: string[];\n\n /**\n * List of supported methods for presenting OAuth 2.0 bearer tokens.\n *\n * @remarks Valid values are `header`, `body`, and `query`.\n * If omitted, clients MAY assume only `header` is supported, per RFC 6750.\n * This is a client-side interpretation and not a serialization default.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.9 | RFC 9728 §2.2.9}\n */\n bearerMethodsSupported?: string[];\n\n /**\n * Whether this resource requires all access tokens to be DPoP-bound.\n *\n * @remarks If omitted, clients SHOULD assume this is `false`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.27 | RFC 9728 §2.2.27}\n */\n dpopBoundAccessTokensRequired?: boolean;\n\n /**\n * Supported algorithms for verifying DPoP proofs (RFC 9449).\n *\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.25 | RFC 9728 §2.2.25}\n */\n dpopSigningAlgValuesSupported?: string[];\n\n /**\n * JWKS URI of this resource. Used to validate access tokens or sign responses.\n *\n * @remarks When present, this MUST be an `https:` URI pointing to a valid JWK Set (RFC 7517).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.5 | RFC 9728 §2.2.5}\n */\n jwksUri?: string;\n\n /**\n * Canonical OAuth resource identifier for this protected resource (the MCP server).\n *\n * @remarks Typically the base URL of the MCP server. Clients MUST use this as the\n * `resource` parameter in authorization and token requests (per RFC 8707).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.1 | RFC 9728 §2.2.1}\n */\n resource: string;\n\n /**\n * URL to developer-accessible documentation for this resource.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n resourceDocumentation?: string;\n\n /**\n * Human-readable name for display purposes (e.g., in UIs).\n *\n * @remarks This field MAY be localized using language tags (`resource_name#en`, etc.).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.13 | RFC 9728 §2.2.13}\n */\n resourceName?: string;\n\n /**\n * URL to a human-readable policy page describing acceptable use.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.17 | RFC 9728 §2.2.17}\n */\n resourcePolicyUri?: string;\n\n /**\n * Supported JWS algorithms for signed responses from this resource (e.g., response signing).\n *\n * @remarks MUST NOT include `none`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.11 | RFC 9728 §2.2.11}\n */\n resourceSigningAlgValuesSupported?: string[];\n\n /**\n * URL to the protected resource’s Terms of Service.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.19 | RFC 9728 §2.2.19}\n */\n resourceTosUri?: string;\n\n /**\n * Supported OAuth scopes for requesting access to this resource.\n *\n * @remarks Useful for discovery, but clients SHOULD still request the minimal scope required.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.7 | RFC 9728 §2.2.7}\n */\n scopesSupported?: string[];\n\n /**\n * Developer-accessible documentation for how to use the service (not end-user docs).\n *\n * @remarks Semantically equivalent to `resourceDocumentation`, but included under its\n * alternate name for compatibility with tools or schemas expecting either.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n serviceDocumentation?: string;\n\n /**\n * Whether mutual-TLS-bound access tokens are required.\n *\n * @remarks If omitted, clients SHOULD assume this is `false` (client-side behavior).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.21 | RFC 9728 §2.2.21}\n */\n tlsClientCertificateBoundAccessTokens?: boolean;\n };\n };\n\n ping?: {\n /**\n * Whether ping should be enabled by default.\n * - true for SSE or HTTP Stream\n * - false for stdio\n */\n enabled?: boolean;\n /**\n * Interval\n * @default 5000 (5s)\n */\n intervalMs?: number;\n /**\n * Logging level for ping-related messages.\n * @default 'debug'\n */\n logLevel?: LoggingLevel;\n };\n /**\n * Configuration for roots capability\n */\n roots?: {\n /**\n * Whether roots capability should be enabled\n * Set to false to completely disable roots support\n * @default true\n */\n enabled?: boolean;\n };\n /**\n * General utilities\n */\n utils?: {\n formatInvalidParamsErrorMessage?: (\n issues: readonly StandardSchemaV1.Issue[],\n ) => string;\n };\n version: `${number}.${number}.${number}`;\n};\n\ntype Tool<\n T extends FastMCPSessionAuth,\n Params extends ToolParameters = ToolParameters,\n> = {\n annotations?: {\n /**\n * When true, the tool leverages incremental content streaming\n * Return void for tools that handle all their output via streaming\n */\n streamingHint?: boolean;\n } & ToolAnnotations;\n canAccess?: (auth: T) => boolean;\n description?: string;\n\n execute: (\n args: StandardSchemaV1.InferOutput<Params>,\n context: Context<T>,\n ) => Promise<\n | AudioContent\n | ContentResult\n | ImageContent\n | ResourceContent\n | ResourceLink\n | string\n | TextContent\n | void\n >;\n name: string;\n parameters?: Params;\n timeoutMs?: number;\n};\n\n/**\n * Tool annotations as defined in MCP Specification (2025-03-26)\n * These provide hints about a tool's behavior.\n */\ntype ToolAnnotations = {\n /**\n * If true, the tool may perform destructive updates\n * Only meaningful when readOnlyHint is false\n * @default true\n */\n destructiveHint?: boolean;\n\n /**\n * If true, calling the tool repeatedly with the same arguments has no additional effect\n * Only meaningful when readOnlyHint is false\n * @default false\n */\n idempotentHint?: boolean;\n\n /**\n * If true, the tool may interact with an \"open world\" of external entities\n * @default true\n */\n openWorldHint?: boolean;\n\n /**\n * If true, indicates the tool does not modify its environment\n * @default false\n */\n readOnlyHint?: boolean;\n\n /**\n * A human-readable title for the tool, useful for UI display\n */\n title?: string;\n};\n\nconst FastMCPSessionEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;\n} = EventEmitter;\n\ntype Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;\n\ntype FastMCPSessionAuth = Record<string, unknown> | undefined;\n\nclass FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}\n\nexport class FastMCPSession<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPSessionEventEmitter {\n public get clientCapabilities(): ClientCapabilities | null {\n return this.#clientCapabilities ?? null;\n }\n public get isReady(): boolean {\n return this.#connectionState === \"ready\";\n }\n public get loggingLevel(): LoggingLevel {\n return this.#loggingLevel;\n }\n public get roots(): Root[] {\n return this.#roots;\n }\n public get server(): Server {\n return this.#server;\n }\n public get sessionId(): string | undefined {\n return this.#sessionId;\n }\n public set sessionId(value: string | undefined) {\n this.#sessionId = value;\n }\n #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #connectionState: \"closed\" | \"connecting\" | \"error\" | \"ready\" = \"connecting\";\n #logger: Logger;\n #loggingLevel: LoggingLevel = \"info\";\n #needsEventLoopFlush: boolean = false;\n #pingConfig?: ServerOptions<T>[\"ping\"];\n\n #pingInterval: null | ReturnType<typeof setInterval> = null;\n\n #prompts: Prompt<T>[] = [];\n\n #resources: Resource<T>[] = [];\n\n #resourceTemplates: ResourceTemplate<T>[] = [];\n\n #roots: Root[] = [];\n\n #rootsConfig?: ServerOptions<T>[\"roots\"];\n\n #server: Server;\n\n /**\n * Session ID from the Mcp-Session-Id header (HTTP transports only).\n * Used to track per-session state across multiple requests.\n */\n #sessionId?: string;\n\n #utils?: ServerOptions<T>[\"utils\"];\n\n constructor({\n auth,\n instructions,\n logger,\n name,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n roots,\n sessionId,\n tools,\n transportType,\n utils,\n version,\n }: {\n auth?: T;\n instructions?: string;\n logger: Logger;\n name: string;\n ping?: ServerOptions<T>[\"ping\"];\n prompts: Prompt<T>[];\n resources: Resource<T>[];\n resourcesTemplates: InputResourceTemplate<T>[];\n roots?: ServerOptions<T>[\"roots\"];\n sessionId?: string;\n tools: Tool<T>[];\n transportType?: \"httpStream\" | \"stdio\";\n utils?: ServerOptions<T>[\"utils\"];\n version: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#logger = logger;\n this.#pingConfig = ping;\n this.#rootsConfig = roots;\n this.#sessionId = sessionId;\n this.#needsEventLoopFlush = transportType === \"httpStream\";\n\n if (tools.length) {\n this.#capabilities.tools = {};\n }\n\n if (resources.length || resourcesTemplates.length) {\n this.#capabilities.resources = {};\n }\n\n if (prompts.length) {\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n\n this.#capabilities.prompts = {};\n }\n\n this.#capabilities.logging = {};\n\n this.#server = new Server(\n { name: name, version: version },\n { capabilities: this.#capabilities, instructions: instructions },\n );\n\n this.#utils = utils;\n\n this.setupErrorHandling();\n this.setupLoggingHandlers();\n this.setupRootsHandlers();\n this.setupCompleteHandlers();\n\n if (tools.length) {\n this.setupToolHandlers(tools);\n }\n\n if (resources.length || resourcesTemplates.length) {\n for (const resource of resources) {\n this.addResource(resource);\n }\n\n this.setupResourceHandlers(resources);\n\n if (resourcesTemplates.length) {\n for (const resourceTemplate of resourcesTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n\n this.setupResourceTemplateHandlers(resourcesTemplates);\n }\n }\n\n if (prompts.length) {\n this.setupPromptHandlers(prompts);\n }\n }\n\n public async close() {\n this.#connectionState = \"closed\";\n\n if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n try {\n await this.#server.close();\n } catch (error) {\n this.#logger.error(\"[FastMCP error]\", \"could not close server\", error);\n }\n }\n\n public async connect(transport: Transport) {\n if (this.#server.transport) {\n throw new UnexpectedStateError(\"Server is already connected\");\n }\n\n this.#connectionState = \"connecting\";\n\n try {\n await this.#server.connect(transport);\n\n // Extract session ID from transport if available (HTTP transports only)\n if (\"sessionId\" in transport) {\n const transportWithSessionId = transport as {\n sessionId?: string;\n } & Transport;\n if (typeof transportWithSessionId.sessionId === \"string\") {\n this.#sessionId = transportWithSessionId.sessionId;\n }\n }\n\n let attempt = 0;\n const maxAttempts = 10;\n const retryDelay = 100;\n\n while (attempt++ < maxAttempts) {\n const capabilities = this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n break;\n }\n\n await delay(retryDelay);\n }\n\n if (!this.#clientCapabilities) {\n this.#logger.warn(\n `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`,\n );\n }\n\n if (\n this.#rootsConfig?.enabled !== false &&\n this.#clientCapabilities?.roots?.listChanged &&\n typeof this.#server.listRoots === \"function\"\n ) {\n try {\n const roots = await this.#server.listRoots();\n this.#roots = roots?.roots || [];\n } catch (e) {\n if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n e instanceof Error ? e.stack : JSON.stringify(e)\n }`,\n );\n }\n }\n }\n\n if (this.#clientCapabilities) {\n const pingConfig = this.#getPingConfig(transport);\n\n if (pingConfig.enabled) {\n this.#pingInterval = setInterval(async () => {\n try {\n await this.#server.ping();\n } catch {\n // The reason we are not emitting an error here is because some clients\n // seem to not respond to the ping request, and we don't want to crash the server,\n // e.g., https://github.com/punkpeye/fastmcp/issues/38.\n const logLevel = pingConfig.logLevel;\n\n if (logLevel === \"debug\") {\n this.#logger.debug(\"[FastMCP debug] server ping failed\");\n } else if (logLevel === \"warning\") {\n this.#logger.warn(\n \"[FastMCP warning] server is not responding to ping\",\n );\n } else if (logLevel === \"error\") {\n this.#logger.error(\n \"[FastMCP error] server is not responding to ping\",\n );\n } else {\n this.#logger.info(\"[FastMCP info] server ping failed\");\n }\n }\n }, pingConfig.intervalMs);\n }\n }\n\n // Mark connection as ready and emit event\n this.#connectionState = \"ready\";\n this.emit(\"ready\");\n } catch (error) {\n this.#connectionState = \"error\";\n const errorEvent = {\n error: error instanceof Error ? error : new Error(String(error)),\n };\n this.emit(\"error\", errorEvent);\n throw error;\n }\n }\n\n public async requestSampling(\n message: z.infer<typeof CreateMessageRequestSchema>[\"params\"],\n options?: RequestOptions,\n ): Promise<SamplingResponse> {\n return this.#server.createMessage(message, options);\n }\n\n public waitForReady(): Promise<void> {\n if (this.isReady) {\n return Promise.resolve();\n }\n\n if (\n this.#connectionState === \"error\" ||\n this.#connectionState === \"closed\"\n ) {\n return Promise.reject(\n new Error(`Connection is in ${this.#connectionState} state`),\n );\n }\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(\n new Error(\n \"Connection timeout: Session failed to become ready within 5 seconds\",\n ),\n );\n }, 5000);\n\n this.once(\"ready\", () => {\n clearTimeout(timeout);\n resolve();\n });\n\n this.once(\"error\", (event) => {\n clearTimeout(timeout);\n reject(event.error);\n });\n });\n }\n\n #getPingConfig(transport: Transport): {\n enabled: boolean;\n intervalMs: number;\n logLevel: LoggingLevel;\n } {\n const pingConfig = this.#pingConfig || {};\n\n let defaultEnabled = false;\n\n if (\"type\" in transport) {\n // Enable by default for SSE and HTTP streaming\n if (transport.type === \"httpStream\") {\n defaultEnabled = true;\n }\n }\n\n return {\n enabled:\n pingConfig.enabled !== undefined ? pingConfig.enabled : defaultEnabled,\n intervalMs: pingConfig.intervalMs || 5000,\n logLevel: pingConfig.logLevel || \"debug\",\n };\n }\n\n private addPrompt(inputPrompt: InputPrompt<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n const enums: Record<string, string[]> = {};\n const fuseInstances: Record<string, Fuse<string>> = {};\n\n for (const argument of inputPrompt.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n\n if (argument.enum) {\n enums[argument.name] = argument.enum;\n fuseInstances[argument.name] = new Fuse(argument.enum, {\n includeScore: true,\n threshold: 0.3, // More flexible matching!\n });\n }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n if (fuseInstances[name]) {\n const result = fuseInstances[name].search(value);\n\n return {\n total: result.length,\n values: result.map((item) => item.item),\n };\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#prompts.push(prompt);\n }\n\n private addResource(inputResource: Resource<T>) {\n this.#resources.push(inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n\n for (const argument of inputResourceTemplate.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n }\n\n const resourceTemplate = {\n ...inputResourceTemplate,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#resourceTemplates.push(resourceTemplate);\n }\n\n private setupCompleteHandlers() {\n this.#server.setRequestHandler(CompleteRequestSchema, async (request) => {\n if (request.params.ref.type === \"ref/prompt\") {\n const prompt = this.#prompts.find(\n (prompt) => prompt.name === request.params.ref.name,\n );\n\n if (!prompt) {\n throw new UnexpectedStateError(\"Unknown prompt\", {\n request,\n });\n }\n\n if (!prompt.complete) {\n throw new UnexpectedStateError(\"Prompt does not support completion\", {\n request,\n });\n }\n\n const completion = CompletionZodSchema.parse(\n await prompt.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n );\n\n return {\n completion,\n };\n }\n\n if (request.params.ref.type === \"ref/resource\") {\n const resource = this.#resourceTemplates.find(\n (resource) => resource.uriTemplate === request.params.ref.uri,\n );\n\n if (!resource) {\n throw new UnexpectedStateError(\"Unknown resource\", {\n request,\n });\n }\n\n if (!(\"uriTemplate\" in resource)) {\n throw new UnexpectedStateError(\"Unexpected resource\");\n }\n\n if (!resource.complete) {\n throw new UnexpectedStateError(\n \"Resource does not support completion\",\n {\n request,\n },\n );\n }\n\n const completion = CompletionZodSchema.parse(\n await resource.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n );\n\n return {\n completion,\n };\n }\n\n throw new UnexpectedStateError(\"Unexpected completion request\", {\n request,\n });\n });\n }\n\n private setupErrorHandling() {\n this.#server.onerror = (error) => {\n this.#logger.error(\"[FastMCP error]\", error);\n };\n }\n\n private setupLoggingHandlers() {\n this.#server.setRequestHandler(SetLevelRequestSchema, (request) => {\n this.#loggingLevel = request.params.level;\n\n return {};\n });\n }\n\n private setupPromptHandlers(prompts: Prompt<T>[]) {\n this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return {\n prompts: prompts.map((prompt) => {\n return {\n arguments: prompt.arguments,\n complete: prompt.complete,\n description: prompt.description,\n name: prompt.name,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = prompts.find(\n (prompt) => prompt.name === request.params.name,\n );\n\n if (!prompt) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown prompt: ${request.params.name}`,\n );\n }\n\n const args = request.params.arguments;\n\n for (const arg of prompt.arguments ?? []) {\n if (arg.required && !(args && arg.name in args)) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Prompt '${request.params.name}' requires argument '${arg.name}': ${\n arg.description || \"No description provided\"\n }`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt<T>[\"load\"]>>;\n\n try {\n result = await prompt.load(\n args as Record<string, string | undefined>,\n this.#auth,\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load prompt '${request.params.name}': ${errorMessage}`,\n );\n }\n\n if (typeof result === \"string\") {\n return {\n description: prompt.description,\n messages: [\n {\n content: { text: result, type: \"text\" },\n role: \"user\",\n },\n ],\n };\n } else {\n return {\n description: prompt.description,\n messages: result.messages,\n };\n }\n });\n }\n\n private setupResourceHandlers(resources: Resource<T>[]) {\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: resources.map((resource) => ({\n description: resource.description,\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n })),\n } satisfies ListResourcesResult;\n });\n\n this.#server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n if (\"uri\" in request.params) {\n const resource = resources.find(\n (resource) =>\n \"uri\" in resource && resource.uri === request.params.uri,\n );\n\n if (!resource) {\n for (const resourceTemplate of this.#resourceTemplates) {\n const uriTemplate = parseURITemplate(\n resourceTemplate.uriTemplate,\n );\n\n const match = uriTemplate.fromUri(request.params.uri);\n\n if (!match) {\n continue;\n }\n\n const uri = uriTemplate.fill(match);\n\n const result = await resourceTemplate.load(match, this.#auth);\n\n const resources = Array.isArray(result) ? result : [result];\n return {\n contents: resources.map((resource) => ({\n ...resource,\n description: resourceTemplate.description,\n mimeType: resource.mimeType ?? resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uri: resource.uri ?? uri,\n })),\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Resource not found: '${request.params.uri}'. Available resources: ${\n resources.map((r) => r.uri).join(\", \") || \"none\"\n }`,\n );\n }\n\n if (!(\"uri\" in resource)) {\n throw new UnexpectedStateError(\"Resource does not support reading\");\n }\n\n let maybeArrayResult: Awaited<ReturnType<Resource<T>[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load(this.#auth);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load resource '${resource.name}' (${resource.uri}): ${errorMessage}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n const resourceResults = Array.isArray(maybeArrayResult)\n ? maybeArrayResult\n : [maybeArrayResult];\n\n return {\n contents: resourceResults.map((result) => ({\n ...result,\n mimeType: result.mimeType ?? resource.mimeType,\n name: resource.name,\n uri: result.uri ?? resource.uri,\n })),\n };\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n\n private setupResourceTemplateHandlers(\n resourceTemplates: ResourceTemplate<T>[],\n ) {\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n return {\n resourceTemplates: resourceTemplates.map((resourceTemplate) => ({\n description: resourceTemplate.description,\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n })),\n } satisfies ListResourceTemplatesResult;\n },\n );\n }\n\n private setupRootsHandlers() {\n if (this.#rootsConfig?.enabled === false) {\n this.#logger.debug(\n \"[FastMCP debug] roots capability explicitly disabled via config\",\n );\n return;\n }\n\n // Only set up roots notification handling if the server supports it\n if (typeof this.#server.listRoots === \"function\") {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server\n .listRoots()\n .then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n })\n .catch((error) => {\n if (\n error instanceof McpError &&\n error.code === ErrorCode.MethodNotFound\n ) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n });\n },\n );\n } else {\n this.#logger.debug(\n \"[FastMCP debug] roots capability not available, not setting up notification handler\",\n );\n }\n }\n\n private setupToolHandlers(tools: Tool<T>[]) {\n this.#server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: await Promise.all(\n tools.map(async (tool) => {\n return {\n annotations: tool.annotations,\n description: tool.description,\n inputSchema: tool.parameters\n ? await toJsonSchema(tool.parameters)\n : {\n additionalProperties: false,\n properties: {},\n type: \"object\",\n }, // More complete schema for Cursor compatibility\n name: tool.name,\n };\n }),\n ),\n };\n });\n\n this.#server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tool = tools.find((tool) => tool.name === request.params.name);\n\n if (!tool) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n\n let args: unknown = undefined;\n\n if (tool.parameters) {\n const parsed = await tool.parameters[\"~standard\"].validate(\n request.params.arguments,\n );\n\n if (parsed.issues) {\n const friendlyErrors = this.#utils?.formatInvalidParamsErrorMessage\n ? this.#utils.formatInvalidParamsErrorMessage(parsed.issues)\n : parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n throw new McpError(\n ErrorCode.InvalidParams,\n `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n const progressToken = request.params?._meta?.progressToken;\n\n let result: ContentResult;\n\n try {\n const reportProgress = async (progress: Progress) => {\n try {\n await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (progressError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to report progress for tool '${request.params.name}':`,\n progressError instanceof Error\n ? progressError.message\n : String(progressError),\n );\n }\n };\n\n const log = {\n debug: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"debug\",\n });\n },\n error: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"error\",\n });\n },\n info: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"info\",\n });\n },\n warn: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"warning\",\n });\n },\n };\n\n // Create a promise for tool execution\n // Streams partial results while a tool is still executing\n // Enables progressive rendering and real-time feedback\n const streamContent = async (content: Content | Content[]) => {\n const contentArray = Array.isArray(content) ? content : [content];\n\n try {\n await this.#server.notification({\n method: \"notifications/tool/streamContent\",\n params: {\n content: contentArray,\n toolName: request.params.name,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (streamError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to stream content for tool '${request.params.name}':`,\n streamError instanceof Error\n ? streamError.message\n : String(streamError),\n );\n }\n };\n\n const executeToolPromise = tool.execute(args, {\n client: {\n version: this.#server.getClientVersion(),\n },\n log,\n reportProgress,\n requestId:\n typeof request.params?._meta?.requestId === \"string\"\n ? request.params._meta.requestId\n : undefined,\n session: this.#auth,\n sessionId: this.#sessionId,\n streamContent,\n });\n\n // Handle timeout if specified\n const maybeStringResult = (await (tool.timeoutMs\n ? Promise.race([\n executeToolPromise,\n new Promise<never>((_, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new UserError(\n `Tool '${request.params.name}' timed out after ${tool.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`,\n ),\n );\n }, tool.timeoutMs);\n\n // If promise resolves first\n executeToolPromise.finally(() => clearTimeout(timeoutId));\n }),\n ])\n : executeToolPromise)) as\n | AudioContent\n | ContentResult\n | ImageContent\n | null\n | ResourceContent\n | ResourceLink\n | string\n | TextContent\n | undefined;\n\n // Without this test, we are running into situations where the last progress update is not reported.\n // See the 'reports multiple progress updates without buffering' test in FastMCP.test.ts before refactoring.\n await delay(1);\n\n if (maybeStringResult === undefined || maybeStringResult === null) {\n result = ContentResultZodSchema.parse({\n content: [],\n });\n } else if (typeof maybeStringResult === \"string\") {\n result = ContentResultZodSchema.parse({\n content: [{ text: maybeStringResult, type: \"text\" }],\n });\n } else if (\"type\" in maybeStringResult) {\n result = ContentResultZodSchema.parse({\n content: [maybeStringResult],\n });\n } else {\n result = ContentResultZodSchema.parse(maybeStringResult);\n }\n } catch (error) {\n if (error instanceof UserError) {\n return {\n content: [{ text: error.message, type: \"text\" }],\n isError: true,\n ...(error.extras ? { structuredContent: error.extras } : {}),\n };\n }\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n text: `Tool '${request.params.name}' execution failed: ${errorMessage}`,\n type: \"text\",\n },\n ],\n isError: true,\n };\n }\n\n return result;\n });\n }\n}\n\n/**\n * Converts camelCase to snake_case for OAuth endpoint responses\n */\nfunction camelToSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Converts an object with camelCase keys to snake_case keys\n */\nfunction convertObjectToSnakeCase(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = camelToSnakeCase(key);\n result[snakeKey] = value;\n }\n\n return result;\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;\n} = EventEmitter;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPEventEmitter {\n public get sessions(): FastMCPSession<T>[] {\n return this.#sessions;\n }\n #authenticate: Authenticate<T> | undefined;\n #httpStreamServer: null | SSEServer = null;\n #logger: Logger;\n #options: ServerOptions<T>;\n #prompts: InputPrompt<T>[] = [];\n #resources: Resource<T>[] = [];\n #resourcesTemplates: InputResourceTemplate<T>[] = [];\n #sessions: FastMCPSession<T>[] = [];\n\n #tools: Tool<T>[] = [];\n\n constructor(public options: ServerOptions<T>) {\n super();\n\n this.#options = options;\n this.#authenticate = options.authenticate;\n this.#logger = options.logger || console;\n }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument<T>[]>(\n prompt: InputPrompt<T, Args>,\n ) {\n this.#prompts.push(prompt);\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource<T>) {\n this.#resources.push(resource);\n }\n\n /**\n * Adds a resource template to the server.\n */\n public addResourceTemplate<\n const Args extends InputResourceTemplateArgument[],\n >(resource: InputResourceTemplate<T, Args>) {\n this.#resourcesTemplates.push(resource);\n }\n\n /**\n * Adds a tool to the server.\n */\n public addTool<Params extends ToolParameters>(tool: Tool<T, Params>) {\n this.#tools.push(tool as unknown as Tool<T>);\n }\n\n /**\n * Embeds a resource by URI, making it easy to include resources in tool responses.\n *\n * @param uri - The URI of the resource to embed\n * @returns Promise<ResourceContent> - The embedded resource content\n */\n public async embedded(uri: string): Promise<ResourceContent[\"resource\"]> {\n // First, try to find a direct resource match\n const directResource = this.#resources.find(\n (resource) => resource.uri === uri,\n );\n\n if (directResource) {\n const result = await directResource.load();\n const results = Array.isArray(result) ? result : [result];\n const firstResult = results[0];\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: directResource.mimeType,\n uri,\n };\n\n if (\"text\" in firstResult) {\n resourceData.text = firstResult.text;\n }\n\n if (\"blob\" in firstResult) {\n resourceData.blob = firstResult.blob;\n }\n\n return resourceData;\n }\n\n // Try to match against resource templates\n for (const template of this.#resourcesTemplates) {\n const parsedTemplate = parseURITemplate(template.uriTemplate);\n const params = parsedTemplate.fromUri(uri);\n if (!params) {\n continue;\n }\n\n const result = await template.load(\n params as ResourceTemplateArgumentsToObject<typeof template.arguments>,\n );\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: template.mimeType,\n uri,\n };\n\n if (\"text\" in result) {\n resourceData.text = result.text;\n }\n\n if (\"blob\" in result) {\n resourceData.blob = result.blob;\n }\n\n return resourceData; // The resource we're looking for\n }\n\n throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options?: Partial<{\n httpStream: {\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n eventStore?: EventStore;\n host?: string;\n port: number;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ) {\n const config = this.#parseRuntimeConfig(options);\n\n if (config.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n // For stdio transport, if authenticate function is provided, call it\n // with undefined request (since stdio doesn't have HTTP request context)\n let auth: T | undefined;\n\n if (this.#authenticate) {\n try {\n auth = await this.#authenticate(\n undefined as unknown as http.IncomingMessage,\n );\n } catch (error) {\n this.#logger.error(\n \"[FastMCP error] Authentication failed for stdio transport:\",\n error instanceof Error ? error.message : String(error),\n );\n // Continue without auth if authentication fails\n }\n }\n\n const session = new FastMCPSession<T>({\n auth,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n tools: this.#tools,\n transportType: \"stdio\",\n utils: this.#options.utils,\n version: this.#options.version,\n });\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n session.once(\"error\", () => {\n this.#removeSession(session);\n });\n\n // Monitor the underlying transport for close events\n if (transport.onclose) {\n const originalOnClose = transport.onclose;\n\n transport.onclose = () => {\n this.#removeSession(session);\n\n if (originalOnClose) {\n originalOnClose();\n }\n };\n } else {\n transport.onclose = () => {\n this.#removeSession(session);\n };\n }\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n } else if (config.transportType === \"httpStream\") {\n const httpConfig = config.httpStream;\n\n if (httpConfig.stateless) {\n // Stateless mode - create new server instance for each request\n this.#logger.info(\n `[FastMCP info] Starting server in stateless mode on HTTP Stream at http://${httpConfig.host}:${httpConfig.port}${httpConfig.endpoint}`,\n );\n\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(this.#authenticate ? { authenticate: this.#authenticate } : {}),\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n\n // In stateless mode, authentication is REQUIRED\n // mcp-proxy will catch this error and return 401\n if (auth === undefined || auth === null) {\n throw new Error(\"Authentication required\");\n }\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n // In stateless mode, create a new session for each request\n // without persisting it in the sessions array\n return this.#createSession(auth, sessionId);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n // In stateless mode, we don't track sessions\n onClose: async () => {\n // No session tracking in stateless mode\n },\n onConnect: async () => {\n // No persistent session tracking in stateless mode\n this.#logger.debug(\n `[FastMCP debug] Stateless HTTP Stream request handled`,\n );\n },\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(req, res, true, httpConfig.host);\n },\n port: httpConfig.port,\n stateless: true,\n streamEndpoint: httpConfig.endpoint,\n });\n } else {\n // Regular mode with session management\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(this.#authenticate ? { authenticate: this.#authenticate } : {}),\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n return this.#createSession(auth, sessionId);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n onClose: async (session) => {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) this.#sessions.splice(sessionIndex, 1);\n\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.#logger.info(`[FastMCP info] HTTP Stream session established`);\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(\n req,\n res,\n false,\n httpConfig.host,\n );\n },\n port: httpConfig.port,\n stateless: httpConfig.stateless,\n streamEndpoint: httpConfig.endpoint,\n });\n\n this.#logger.info(\n `[FastMCP info] server is running on HTTP Stream at http://${httpConfig.host}:${httpConfig.port}${httpConfig.endpoint}`,\n );\n }\n } else {\n throw new Error(\"Invalid transport type\");\n }\n }\n\n /**\n * Stops the server.\n */\n public async stop() {\n if (this.#httpStreamServer) {\n await this.#httpStreamServer.close();\n }\n }\n\n /**\n * Creates a new FastMCPSession instance with the current configuration.\n * Used both for regular sessions and stateless requests.\n */\n #createSession(auth?: T, sessionId?: string): FastMCPSession<T> {\n // Check if authentication failed\n if (\n auth &&\n typeof auth === \"object\" &&\n \"authenticated\" in auth &&\n !(auth as { authenticated: unknown }).authenticated\n ) {\n const errorMessage =\n \"error\" in auth &&\n typeof (auth as { error: unknown }).error === \"string\"\n ? (auth as { error: string }).error\n : \"Authentication failed\";\n throw new Error(errorMessage);\n }\n\n const allowedTools = auth\n ? this.#tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(auth) : true,\n )\n : this.#tools;\n return new FastMCPSession<T>({\n auth,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n sessionId,\n tools: allowedTools,\n transportType: \"httpStream\",\n utils: this.#options.utils,\n version: this.#options.version,\n });\n }\n\n /**\n * Handles unhandled HTTP requests with health, readiness, and OAuth endpoints\n */\n #handleUnhandledRequest = async (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n isStateless = false,\n host: string,\n ) => {\n const healthConfig = this.#options.health ?? {};\n\n const enabled =\n healthConfig.enabled === undefined ? true : healthConfig.enabled;\n\n if (enabled) {\n const path = healthConfig.path ?? \"/health\";\n const url = new URL(req.url || \"\", `http://${host}`);\n\n try {\n if (req.method === \"GET\" && url.pathname === path) {\n res\n .writeHead(healthConfig.status ?? 200, {\n \"Content-Type\": \"text/plain\",\n })\n .end(healthConfig.message ?? \"✓ Ok\");\n\n return;\n }\n\n // Enhanced readiness check endpoint\n if (req.method === \"GET\" && url.pathname === \"/ready\") {\n if (isStateless) {\n // In stateless mode, we're always ready if the server is running\n const response = {\n mode: \"stateless\",\n ready: 1,\n status: \"ready\",\n total: 1,\n };\n\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(response));\n } else {\n const readySessions = this.#sessions.filter(\n (s) => s.isReady,\n ).length;\n const totalSessions = this.#sessions.length;\n const allReady =\n readySessions === totalSessions && totalSessions > 0;\n\n const response = {\n ready: readySessions,\n status: allReady\n ? \"ready\"\n : totalSessions === 0\n ? \"no_sessions\"\n : \"initializing\",\n total: totalSessions,\n };\n\n res\n .writeHead(allReady ? 200 : 503, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(response));\n }\n\n return;\n }\n } catch (error) {\n this.#logger.error(\"[FastMCP error] health endpoint error\", error);\n }\n }\n\n // Handle OAuth well-known endpoints\n const oauthConfig = this.#options.oauth;\n if (oauthConfig?.enabled && req.method === \"GET\") {\n const url = new URL(req.url || \"\", `http://${host}`);\n\n if (\n url.pathname === \"/.well-known/oauth-authorization-server\" &&\n oauthConfig.authorizationServer\n ) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.authorizationServer,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n\n if (\n url.pathname === \"/.well-known/oauth-protected-resource\" &&\n oauthConfig.protectedResource\n ) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.protectedResource,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n }\n\n // If the request was not handled above, return 404\n res.writeHead(404).end();\n };\n\n #parseRuntimeConfig(\n overrides?: Partial<{\n httpStream: {\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n host?: string;\n port: number;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ):\n | {\n httpStream: {\n enableJsonResponse?: boolean;\n endpoint: `/${string}`;\n eventStore?: EventStore;\n host: string;\n port: number;\n stateless?: boolean;\n };\n transportType: \"httpStream\";\n }\n | { transportType: \"stdio\" } {\n const args = process.argv.slice(2);\n const getArg = (name: string) => {\n const index = args.findIndex((arg) => arg === `--${name}`);\n\n return index !== -1 && index + 1 < args.length\n ? args[index + 1]\n : undefined;\n };\n\n const transportArg = getArg(\"transport\");\n const portArg = getArg(\"port\");\n const endpointArg = getArg(\"endpoint\");\n const statelessArg = getArg(\"stateless\");\n const hostArg = getArg(\"host\");\n\n const envTransport = process.env.FASTMCP_TRANSPORT;\n const envPort = process.env.FASTMCP_PORT;\n const envEndpoint = process.env.FASTMCP_ENDPOINT;\n const envStateless = process.env.FASTMCP_STATELESS;\n const envHost = process.env.FASTMCP_HOST;\n // Overrides > CLI > env > defaults\n const transportType =\n overrides?.transportType ||\n (transportArg === \"http-stream\" ? \"httpStream\" : transportArg) ||\n envTransport ||\n \"stdio\";\n\n if (transportType === \"httpStream\") {\n const port = parseInt(\n overrides?.httpStream?.port?.toString() || portArg || envPort || \"8080\",\n );\n const host =\n overrides?.httpStream?.host || hostArg || envHost || \"localhost\";\n const endpoint =\n overrides?.httpStream?.endpoint || endpointArg || envEndpoint || \"/mcp\";\n const enableJsonResponse =\n overrides?.httpStream?.enableJsonResponse || false;\n const stateless =\n overrides?.httpStream?.stateless ||\n statelessArg === \"true\" ||\n envStateless === \"true\" ||\n false;\n\n return {\n httpStream: {\n enableJsonResponse,\n endpoint: endpoint as `/${string}`,\n host,\n port,\n stateless,\n },\n transportType: \"httpStream\" as const,\n };\n }\n\n return { transportType: \"stdio\" as const };\n }\n\n #removeSession(session: FastMCPSession<T>): void {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) {\n this.#sessions.splice(sessionIndex, 1);\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n }\n }\n}\n\nexport { DiscoveryDocumentCache } from \"./DiscoveryDocumentCache.js\";\n\nexport type {\n AudioContent,\n Content,\n ContentResult,\n Context,\n FastMCPEvents,\n FastMCPSessionEvents,\n ImageContent,\n InputPrompt,\n InputPromptArgument,\n LoggingLevel,\n Progress,\n Prompt,\n PromptArgument,\n Resource,\n ResourceContent,\n ResourceLink,\n ResourceResult,\n ResourceTemplate,\n ResourceTemplateArgument,\n SerializableValue,\n ServerOptions,\n TextContent,\n Tool,\n ToolParameters,\n};\n","export class DiscoveryDocumentCache {\n public get size(): number {\n return this.#cache.size;\n }\n\n #cache: Map<\n string,\n {\n data: unknown;\n expiresAt: number;\n }\n > = new Map();\n\n #inFlight: Map<string, Promise<unknown>> = new Map();\n\n #ttl: number;\n\n /**\n * @param options - configuration options\n * @param options.ttl - time-to-live in miliseconds\n */\n public constructor(options: { ttl?: number } = {}) {\n this.#ttl = options.ttl ?? 3600000; // default 1 hour\n }\n\n /**\n * @param url - optional URL to clear. if omitted, clears all cached documents.\n */\n public clear(url?: string): void {\n if (url) {\n this.#cache.delete(url);\n } else {\n this.#cache.clear();\n }\n }\n\n /**\n * fetches a discovery document from the given URL.\n * uses cached value if available and not expired.\n * coalesces concurrent requests for the same URL to prevent duplicate fetches.\n *\n * @param url - the discovery document URL (e.g., /.well-known/openid-configuration)\n * @returns the discovery document as a JSON object\n * @throws Error if the fetch fails or returns non-OK status\n */\n public async get(url: string): Promise<unknown> {\n const now = Date.now();\n const cached = this.#cache.get(url);\n\n // return cached value if still valid\n if (cached && cached.expiresAt > now) {\n return cached.data;\n }\n\n // check if there’s already an in-flight request for this URL\n const inFlight = this.#inFlight.get(url);\n\n if (inFlight) {\n return inFlight;\n }\n\n // create a new fetch promise and store it\n const fetchPromise = this.#fetchAndCache(url);\n\n this.#inFlight.set(url, fetchPromise);\n\n try {\n const data = await fetchPromise;\n return data;\n } finally {\n // clean up in-flight promise after completion\n // (success or failure)\n this.#inFlight.delete(url);\n }\n }\n\n /**\n * @param url - the URL to check\n * @returns true if the URL is cached and nott expired\n */\n public has(url: string): boolean {\n const cached = this.#cache.get(url);\n\n if (!cached) {\n return false;\n }\n\n const now = Date.now();\n\n if (cached.expiresAt <= now) {\n // expired, remove from cache\n this.#cache.delete(url);\n return false;\n }\n\n return true;\n }\n\n async #fetchAndCache(url: string): Promise<unknown> {\n // fetch fresh document\n const res = await fetch(url);\n\n if (!res.ok) {\n throw new Error(\n `Failed to fetch discovery document from ${url}: ${res.status} ${res.statusText}`,\n );\n }\n\n const data = await res.json();\n // calculate expiration time AFTER fetch completes\n const expiresAt = Date.now() + this.#ttl;\n\n // store in cache with expiration\n this.#cache.set(url, {\n data,\n expiresAt,\n });\n\n return data;\n }\n}\n"],"mappings":"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","names":["fetch","fetch","prompt","resource","resources","tool"]}
|
|
1
|
+
{"version":3,"sources":["../src/FastMCP.ts","../src/DiscoveryDocumentCache.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n CreateMessageRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n GetPromptResult,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourcesResult,\n ListResourceTemplatesRequestSchema,\n ListResourceTemplatesResult,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\n ResourceLink,\n Root,\n RootsListChangedNotificationSchema,\n ServerCapabilities,\n SetLevelRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { EventEmitter } from \"events\";\nimport { readFile } from \"fs/promises\";\nimport Fuse from \"fuse.js\";\nimport http from \"http\";\nimport { startHTTPServer } from \"mcp-proxy\";\nimport { StrictEventEmitter } from \"strict-event-emitter-types\";\nimport { setTimeout as delay } from \"timers/promises\";\nimport { fetch } from \"undici\";\nimport parseURITemplate from \"uri-templates\";\nimport { toJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\n\nexport interface Logger {\n debug(...args: unknown[]): void;\n error(...args: unknown[]): void;\n info(...args: unknown[]): void;\n log(...args: unknown[]): void;\n warn(...args: unknown[]): void;\n}\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype FastMCPEvents<T extends FastMCPSessionAuth> = {\n connect: (event: { session: FastMCPSession<T> }) => void;\n disconnect: (event: { session: FastMCPSession<T> }) => void;\n};\n\ntype FastMCPSessionEvents = {\n error: (event: { error: Error }) => void;\n ready: () => void;\n rootsChanged: (event: { roots: Root[] }) => void;\n};\n\nexport const imageContent = async (\n input: { buffer: Buffer } | { path: string } | { url: string },\n): Promise<ImageContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n try {\n const response = await fetch(input.url);\n\n if (!response.ok) {\n throw new Error(\n `Server responded with status: ${response.status} - ${response.statusText}`,\n );\n }\n\n rawData = Buffer.from(await response.arrayBuffer());\n } catch (error) {\n throw new Error(\n `Failed to fetch image from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read image from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"image/\")) {\n console.warn(\n `Warning: Content may not be a valid image. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"image/png\",\n type: \"image\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing image: ${String(error)}`);\n }\n }\n};\n\nexport const audioContent = async (\n input: { buffer: Buffer } | { path: string } | { url: string },\n): Promise<AudioContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n try {\n const response = await fetch(input.url);\n\n if (!response.ok) {\n throw new Error(\n `Server responded with status: ${response.status} - ${response.statusText}`,\n );\n }\n\n rawData = Buffer.from(await response.arrayBuffer());\n } catch (error) {\n throw new Error(\n `Failed to fetch audio from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read audio from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"audio/\")) {\n console.warn(\n `Warning: Content may not be a valid audio file. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"audio/mpeg\",\n type: \"audio\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing audio: ${String(error)}`);\n }\n }\n};\n\ntype Context<T extends FastMCPSessionAuth> = {\n client: {\n version: ReturnType<Server[\"getClientVersion\"]>;\n };\n log: {\n debug: (message: string, data?: SerializableValue) => void;\n error: (message: string, data?: SerializableValue) => void;\n info: (message: string, data?: SerializableValue) => void;\n warn: (message: string, data?: SerializableValue) => void;\n };\n reportProgress: (progress: Progress) => Promise<void>;\n /**\n * Request ID from the current MCP request.\n * Available for all transports when the client provides it.\n */\n requestId?: string;\n session: T | undefined;\n /**\n * Session ID from the Mcp-Session-Id header.\n * Only available for HTTP-based transports (SSE, HTTP Stream).\n * Can be used to track per-session state, implement session-specific\n * counters, or maintain user-specific data across multiple requests.\n */\n sessionId?: string;\n streamContent: (content: Content | Content[]) => Promise<void>;\n};\n\ntype Extra = unknown;\n\ntype Extras = Record<string, Extra>;\n\ntype Literal = boolean | null | number | string | undefined;\n\ntype Progress = {\n /**\n * The progress thus far. This should increase every time progress is made, even if the total is unknown.\n */\n progress: number;\n /**\n * Total number of items to process (or total progress required), if known.\n */\n total?: number;\n};\n\ntype SerializableValue =\n | { [key: string]: SerializableValue }\n | Literal\n | SerializableValue[];\n\ntype TextContent = {\n text: string;\n type: \"text\";\n};\n\ntype ToolParameters = StandardSchemaV1;\n\nabstract class FastMCPError extends Error {\n public constructor(message?: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\nexport class UnexpectedStateError extends FastMCPError {\n public extras?: Extras;\n\n public constructor(message: string, extras?: Extras) {\n super(message);\n this.name = new.target.name;\n this.extras = extras;\n }\n}\n\n/**\n * An error that is meant to be surfaced to the user.\n */\nexport class UserError extends UnexpectedStateError {}\n\nconst TextContentZodSchema = z\n .object({\n /**\n * The text content of the message.\n */\n text: z.string(),\n type: z.literal(\"text\"),\n })\n .strict() satisfies z.ZodType<TextContent>;\n\ntype ImageContent = {\n data: string;\n mimeType: string;\n type: \"image\";\n};\n\nconst ImageContentZodSchema = z\n .object({\n /**\n * The base64-encoded image data.\n */\n data: z.string().base64(),\n /**\n * The MIME type of the image. Different providers may support different image types.\n */\n mimeType: z.string(),\n type: z.literal(\"image\"),\n })\n .strict() satisfies z.ZodType<ImageContent>;\n\ntype AudioContent = {\n data: string;\n mimeType: string;\n type: \"audio\";\n};\n\nconst AudioContentZodSchema = z\n .object({\n /**\n * The base64-encoded audio data.\n */\n data: z.string().base64(),\n mimeType: z.string(),\n type: z.literal(\"audio\"),\n })\n .strict() satisfies z.ZodType<AudioContent>;\n\ntype ResourceContent = {\n resource: {\n blob?: string;\n mimeType?: string;\n text?: string;\n uri: string;\n };\n type: \"resource\";\n};\n\nconst ResourceContentZodSchema = z\n .object({\n resource: z.object({\n blob: z.string().optional(),\n mimeType: z.string().optional(),\n text: z.string().optional(),\n uri: z.string(),\n }),\n type: z.literal(\"resource\"),\n })\n .strict() satisfies z.ZodType<ResourceContent>;\n\nconst ResourceLinkZodSchema = z.object({\n description: z.string().optional(),\n mimeType: z.string().optional(),\n name: z.string(),\n title: z.string().optional(),\n type: z.literal(\"resource_link\"),\n uri: z.string(),\n}) satisfies z.ZodType<ResourceLink>;\n\ntype Content =\n | AudioContent\n | ImageContent\n | ResourceContent\n | ResourceLink\n | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n AudioContentZodSchema,\n ResourceContentZodSchema,\n ResourceLinkZodSchema,\n]) satisfies z.ZodType<Content>;\n\ntype ContentResult = {\n content: Content[];\n isError?: boolean;\n};\n\nconst ContentResultZodSchema = z\n .object({\n content: ContentZodSchema.array(),\n isError: z.boolean().optional(),\n })\n .strict() satisfies z.ZodType<ContentResult>;\n\ntype Completion = {\n hasMore?: boolean;\n total?: number;\n values: string[];\n};\n\n/**\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/3164da64d085ec4e022ae881329eee7b72f208d4/src/types.ts#L983-L1003\n */\nconst CompletionZodSchema = z.object({\n /**\n * Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.\n */\n hasMore: z.optional(z.boolean()),\n /**\n * The total number of completion options available. This can exceed the number of values actually sent in the response.\n */\n total: z.optional(z.number().int()),\n /**\n * An array of completion values. Must not exceed 100 items.\n */\n values: z.array(z.string()).max(100),\n}) satisfies z.ZodType<Completion>;\n\ntype ArgumentValueCompleter<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n (value: string, auth?: T) => Promise<Completion>;\n\ntype InputPrompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends InputPromptArgument<T>[] = InputPromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: InputPromptArgument<T>[];\n description?: string;\n load: (args: Args, auth?: T) => Promise<PromptResult>;\n name: string;\n};\n\ntype InputPromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype InputResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends\n InputResourceTemplateArgument<T>[] = InputResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype InputResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype LoggingLevel =\n | \"alert\"\n | \"critical\"\n | \"debug\"\n | \"emergency\"\n | \"error\"\n | \"info\"\n | \"notice\"\n | \"warning\";\n\ntype Prompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends PromptArgument<T>[] = PromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument<T>[];\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (args: Args, auth?: T) => Promise<PromptResult>;\n name: string;\n};\n\ntype PromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =\n {\n [K in T[number][\"name\"]]: Extract<\n T[number],\n { name: K }\n >[\"required\"] extends true\n ? string\n : string | undefined;\n };\n\ntype PromptResult = Pick<GetPromptResult, \"messages\"> | string;\n\ntype Resource<T extends FastMCPSessionAuth> = {\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (auth?: T) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uri: string;\n};\n\ntype ResourceResult =\n | {\n blob: string;\n mimeType?: string;\n uri?: string;\n }\n | {\n mimeType?: string;\n text: string;\n uri?: string;\n };\n\ntype ResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends\n ResourceTemplateArgument<T>[] = ResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype ResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype SamplingResponse = {\n content: AudioContent | ImageContent | TextContent;\n model: string;\n role: \"assistant\" | \"user\";\n stopReason?: \"endTurn\" | \"maxTokens\" | \"stopSequence\" | string;\n};\n\ntype ServerOptions<T extends FastMCPSessionAuth> = {\n authenticate?: Authenticate<T>;\n /**\n * Configuration for the health-check endpoint that can be exposed when the\n * server is running using the HTTP Stream transport. When enabled, the\n * server will respond to an HTTP GET request with the configured path (by\n * default \"/health\") rendering a plain-text response (by default \"ok\") and\n * the configured status code (by default 200).\n *\n * The endpoint is only added when the server is started with\n * `transportType: \"httpStream\"` – it is ignored for the stdio transport.\n */\n health?: {\n /**\n * When set to `false` the health-check endpoint is disabled.\n * @default true\n */\n enabled?: boolean;\n\n /**\n * Plain-text body returned by the endpoint.\n * @default \"ok\"\n */\n message?: string;\n\n /**\n * HTTP path that should be handled.\n * @default \"/health\"\n */\n path?: string;\n\n /**\n * HTTP response status that will be returned.\n * @default 200\n */\n status?: number;\n };\n instructions?: string;\n /**\n * Custom logger instance. If not provided, defaults to console.\n * Use this to integrate with your own logging system.\n */\n logger?: Logger;\n name: string;\n\n /**\n * Configuration for OAuth well-known discovery endpoints that can be exposed\n * when the server is running using HTTP-based transports (SSE or HTTP Stream).\n * When enabled, the server will respond to requests for OAuth discovery endpoints\n * with the configured metadata.\n *\n * The endpoints are only added when the server is started with\n * `transportType: \"httpStream\"` – they are ignored for the stdio transport.\n * Both SSE and HTTP Stream transports support OAuth endpoints.\n */\n oauth?: {\n /**\n * OAuth Authorization Server metadata for /.well-known/oauth-authorization-server\n *\n * This endpoint follows RFC 8414 (OAuth 2.0 Authorization Server Metadata)\n * and provides metadata about the OAuth 2.0 authorization server.\n *\n * Required by MCP Specification 2025-03-26\n */\n authorizationServer?: {\n authorizationEndpoint: string;\n codeChallengeMethodsSupported?: string[];\n // DPoP support\n dpopSigningAlgValuesSupported?: string[];\n grantTypesSupported?: string[];\n\n introspectionEndpoint?: string;\n // Required\n issuer: string;\n // Common optional\n jwksUri?: string;\n opPolicyUri?: string;\n opTosUri?: string;\n registrationEndpoint?: string;\n responseModesSupported?: string[];\n responseTypesSupported: string[];\n revocationEndpoint?: string;\n scopesSupported?: string[];\n serviceDocumentation?: string;\n tokenEndpoint: string;\n tokenEndpointAuthMethodsSupported?: string[];\n tokenEndpointAuthSigningAlgValuesSupported?: string[];\n\n uiLocalesSupported?: string[];\n };\n\n /**\n * Whether OAuth discovery endpoints should be enabled.\n */\n enabled: boolean;\n\n /**\n * OAuth Protected Resource metadata for `/.well-known/oauth-protected-resource`\n *\n * This endpoint follows {@link https://www.rfc-editor.org/rfc/rfc9728.html | RFC 9728}\n * and provides metadata describing how an OAuth 2.0 protected resource (in this case,\n * an MCP server) expects to be accessed.\n *\n * When configured, FastMCP will automatically serve this metadata at the\n * `/.well-known/oauth-protected-resource` endpoint. The `authorizationServers` and `resource`\n * fields are required. All others are optional and will be omitted from the published\n * metadata if not specified.\n *\n * This satisfies the requirements of the MCP Authorization specification's\n * {@link https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#authorization-server-location | Authorization Server Location section}.\n *\n * Clients consuming this metadata MUST validate that any presented values comply with\n * RFC 9728, including strict validation of the `resource` identifier and intended audience\n * when access tokens are issued and presented (per RFC 8707 §2).\n *\n * @remarks Required by MCP Specification version 2025-06-18\n */\n protectedResource?: {\n /**\n * Allows for additional metadata fields beyond those defined in RFC 9728.\n *\n * @remarks This supports vendor-specific or experimental extensions.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2.3 | RFC 9728 §2.3}\n */\n [key: string]: unknown;\n\n /**\n * Supported values for the `authorization_details` parameter (RFC 9396).\n *\n * @remarks Used when fine-grained access control is in play.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.23 | RFC 9728 §2.2.23}\n */\n authorizationDetailsTypesSupported?: string[];\n\n /**\n * List of OAuth 2.0 authorization server issuer identifiers.\n *\n * These correspond to ASes that can issue access tokens for this protected resource.\n * MCP clients use these values to locate the relevant `/.well-known/oauth-authorization-server`\n * metadata for initiating the OAuth flow.\n *\n * @remarks Required by the MCP spec. MCP servers MUST provide at least one issuer.\n * Clients are responsible for choosing among them (see RFC 9728 §7.6).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.3 | RFC 9728 §2.2.3}\n */\n authorizationServers: string[];\n\n /**\n * List of supported methods for presenting OAuth 2.0 bearer tokens.\n *\n * @remarks Valid values are `header`, `body`, and `query`.\n * If omitted, clients MAY assume only `header` is supported, per RFC 6750.\n * This is a client-side interpretation and not a serialization default.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.9 | RFC 9728 §2.2.9}\n */\n bearerMethodsSupported?: string[];\n\n /**\n * Whether this resource requires all access tokens to be DPoP-bound.\n *\n * @remarks If omitted, clients SHOULD assume this is `false`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.27 | RFC 9728 §2.2.27}\n */\n dpopBoundAccessTokensRequired?: boolean;\n\n /**\n * Supported algorithms for verifying DPoP proofs (RFC 9449).\n *\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.25 | RFC 9728 §2.2.25}\n */\n dpopSigningAlgValuesSupported?: string[];\n\n /**\n * JWKS URI of this resource. Used to validate access tokens or sign responses.\n *\n * @remarks When present, this MUST be an `https:` URI pointing to a valid JWK Set (RFC 7517).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.5 | RFC 9728 §2.2.5}\n */\n jwksUri?: string;\n\n /**\n * Canonical OAuth resource identifier for this protected resource (the MCP server).\n *\n * @remarks Typically the base URL of the MCP server. Clients MUST use this as the\n * `resource` parameter in authorization and token requests (per RFC 8707).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.1 | RFC 9728 §2.2.1}\n */\n resource: string;\n\n /**\n * URL to developer-accessible documentation for this resource.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n resourceDocumentation?: string;\n\n /**\n * Human-readable name for display purposes (e.g., in UIs).\n *\n * @remarks This field MAY be localized using language tags (`resource_name#en`, etc.).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.13 | RFC 9728 §2.2.13}\n */\n resourceName?: string;\n\n /**\n * URL to a human-readable policy page describing acceptable use.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.17 | RFC 9728 §2.2.17}\n */\n resourcePolicyUri?: string;\n\n /**\n * Supported JWS algorithms for signed responses from this resource (e.g., response signing).\n *\n * @remarks MUST NOT include `none`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.11 | RFC 9728 §2.2.11}\n */\n resourceSigningAlgValuesSupported?: string[];\n\n /**\n * URL to the protected resource’s Terms of Service.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.19 | RFC 9728 §2.2.19}\n */\n resourceTosUri?: string;\n\n /**\n * Supported OAuth scopes for requesting access to this resource.\n *\n * @remarks Useful for discovery, but clients SHOULD still request the minimal scope required.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.7 | RFC 9728 §2.2.7}\n */\n scopesSupported?: string[];\n\n /**\n * Developer-accessible documentation for how to use the service (not end-user docs).\n *\n * @remarks Semantically equivalent to `resourceDocumentation`, but included under its\n * alternate name for compatibility with tools or schemas expecting either.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n serviceDocumentation?: string;\n\n /**\n * Whether mutual-TLS-bound access tokens are required.\n *\n * @remarks If omitted, clients SHOULD assume this is `false` (client-side behavior).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.21 | RFC 9728 §2.2.21}\n */\n tlsClientCertificateBoundAccessTokens?: boolean;\n };\n };\n\n ping?: {\n /**\n * Whether ping should be enabled by default.\n * - true for SSE or HTTP Stream\n * - false for stdio\n */\n enabled?: boolean;\n /**\n * Interval\n * @default 5000 (5s)\n */\n intervalMs?: number;\n /**\n * Logging level for ping-related messages.\n * @default 'debug'\n */\n logLevel?: LoggingLevel;\n };\n /**\n * Configuration for roots capability\n */\n roots?: {\n /**\n * Whether roots capability should be enabled\n * Set to false to completely disable roots support\n * @default true\n */\n enabled?: boolean;\n };\n /**\n * General utilities\n */\n utils?: {\n formatInvalidParamsErrorMessage?: (\n issues: readonly StandardSchemaV1.Issue[],\n ) => string;\n };\n version: `${number}.${number}.${number}`;\n};\n\ntype Tool<\n T extends FastMCPSessionAuth,\n Params extends ToolParameters = ToolParameters,\n> = {\n annotations?: {\n /**\n * When true, the tool leverages incremental content streaming\n * Return void for tools that handle all their output via streaming\n */\n streamingHint?: boolean;\n } & ToolAnnotations;\n canAccess?: (auth: T) => boolean;\n description?: string;\n\n execute: (\n args: StandardSchemaV1.InferOutput<Params>,\n context: Context<T>,\n ) => Promise<\n | AudioContent\n | ContentResult\n | ImageContent\n | ResourceContent\n | ResourceLink\n | string\n | TextContent\n | void\n >;\n name: string;\n parameters?: Params;\n timeoutMs?: number;\n};\n\n/**\n * Tool annotations as defined in MCP Specification (2025-03-26)\n * These provide hints about a tool's behavior.\n */\ntype ToolAnnotations = {\n /**\n * If true, the tool may perform destructive updates\n * Only meaningful when readOnlyHint is false\n * @default true\n */\n destructiveHint?: boolean;\n\n /**\n * If true, calling the tool repeatedly with the same arguments has no additional effect\n * Only meaningful when readOnlyHint is false\n * @default false\n */\n idempotentHint?: boolean;\n\n /**\n * If true, the tool may interact with an \"open world\" of external entities\n * @default true\n */\n openWorldHint?: boolean;\n\n /**\n * If true, indicates the tool does not modify its environment\n * @default false\n */\n readOnlyHint?: boolean;\n\n /**\n * A human-readable title for the tool, useful for UI display\n */\n title?: string;\n};\n\nconst FastMCPSessionEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;\n} = EventEmitter;\n\nexport enum ServerState {\n Error = \"error\",\n Running = \"running\",\n Stopped = \"stopped\",\n}\n\ntype Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;\n\ntype FastMCPSessionAuth = Record<string, unknown> | undefined;\n\nclass FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}\nexport class FastMCPSession<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPSessionEventEmitter {\n public get clientCapabilities(): ClientCapabilities | null {\n return this.#clientCapabilities ?? null;\n }\n public get isReady(): boolean {\n return this.#connectionState === \"ready\";\n }\n public get loggingLevel(): LoggingLevel {\n return this.#loggingLevel;\n }\n public get roots(): Root[] {\n return this.#roots;\n }\n public get server(): Server {\n return this.#server;\n }\n public get sessionId(): string | undefined {\n return this.#sessionId;\n }\n public set sessionId(value: string | undefined) {\n this.#sessionId = value;\n }\n #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #connectionState: \"closed\" | \"connecting\" | \"error\" | \"ready\" = \"connecting\";\n #logger: Logger;\n #loggingLevel: LoggingLevel = \"info\";\n #needsEventLoopFlush: boolean = false;\n #pingConfig?: ServerOptions<T>[\"ping\"];\n\n #pingInterval: null | ReturnType<typeof setInterval> = null;\n\n #prompts: Prompt<T>[] = [];\n\n #resources: Resource<T>[] = [];\n\n #resourceTemplates: ResourceTemplate<T>[] = [];\n\n #roots: Root[] = [];\n\n #rootsConfig?: ServerOptions<T>[\"roots\"];\n\n #server: Server;\n\n /**\n * Session ID from the Mcp-Session-Id header (HTTP transports only).\n * Used to track per-session state across multiple requests.\n */\n #sessionId?: string;\n\n #utils?: ServerOptions<T>[\"utils\"];\n\n constructor({\n auth,\n instructions,\n logger,\n name,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n roots,\n sessionId,\n tools,\n transportType,\n utils,\n version,\n }: {\n auth?: T;\n instructions?: string;\n logger: Logger;\n name: string;\n ping?: ServerOptions<T>[\"ping\"];\n prompts: Prompt<T>[];\n resources: Resource<T>[];\n resourcesTemplates: InputResourceTemplate<T>[];\n roots?: ServerOptions<T>[\"roots\"];\n sessionId?: string;\n tools: Tool<T>[];\n transportType?: \"httpStream\" | \"stdio\";\n utils?: ServerOptions<T>[\"utils\"];\n version: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#logger = logger;\n this.#pingConfig = ping;\n this.#rootsConfig = roots;\n this.#sessionId = sessionId;\n this.#needsEventLoopFlush = transportType === \"httpStream\";\n\n if (tools.length) {\n this.#capabilities.tools = {};\n }\n\n if (resources.length || resourcesTemplates.length) {\n this.#capabilities.resources = {};\n }\n\n if (prompts.length) {\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n\n this.#capabilities.prompts = {};\n }\n\n this.#capabilities.logging = {};\n\n this.#server = new Server(\n { name: name, version: version },\n { capabilities: this.#capabilities, instructions: instructions },\n );\n\n this.#utils = utils;\n\n this.setupErrorHandling();\n this.setupLoggingHandlers();\n this.setupRootsHandlers();\n this.setupCompleteHandlers();\n\n if (tools.length) {\n this.setupToolHandlers(tools);\n }\n\n if (resources.length || resourcesTemplates.length) {\n for (const resource of resources) {\n this.addResource(resource);\n }\n\n this.setupResourceHandlers(resources);\n\n if (resourcesTemplates.length) {\n for (const resourceTemplate of resourcesTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n\n this.setupResourceTemplateHandlers(resourcesTemplates);\n }\n }\n\n if (prompts.length) {\n this.setupPromptHandlers(prompts);\n }\n }\n\n public async close() {\n this.#connectionState = \"closed\";\n\n if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n try {\n await this.#server.close();\n } catch (error) {\n this.#logger.error(\"[FastMCP error]\", \"could not close server\", error);\n }\n }\n\n public async connect(transport: Transport) {\n if (this.#server.transport) {\n throw new UnexpectedStateError(\"Server is already connected\");\n }\n\n this.#connectionState = \"connecting\";\n\n try {\n await this.#server.connect(transport);\n\n // Extract session ID from transport if available (HTTP transports only)\n if (\"sessionId\" in transport) {\n const transportWithSessionId = transport as {\n sessionId?: string;\n } & Transport;\n if (typeof transportWithSessionId.sessionId === \"string\") {\n this.#sessionId = transportWithSessionId.sessionId;\n }\n }\n\n let attempt = 0;\n const maxAttempts = 10;\n const retryDelay = 100;\n\n while (attempt++ < maxAttempts) {\n const capabilities = this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n break;\n }\n\n await delay(retryDelay);\n }\n\n if (!this.#clientCapabilities) {\n this.#logger.warn(\n `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`,\n );\n }\n\n if (\n this.#rootsConfig?.enabled !== false &&\n this.#clientCapabilities?.roots?.listChanged &&\n typeof this.#server.listRoots === \"function\"\n ) {\n try {\n const roots = await this.#server.listRoots();\n this.#roots = roots?.roots || [];\n } catch (e) {\n if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n e instanceof Error ? e.stack : JSON.stringify(e)\n }`,\n );\n }\n }\n }\n\n if (this.#clientCapabilities) {\n const pingConfig = this.#getPingConfig(transport);\n\n if (pingConfig.enabled) {\n this.#pingInterval = setInterval(async () => {\n try {\n await this.#server.ping();\n } catch {\n // The reason we are not emitting an error here is because some clients\n // seem to not respond to the ping request, and we don't want to crash the server,\n // e.g., https://github.com/punkpeye/fastmcp/issues/38.\n const logLevel = pingConfig.logLevel;\n\n if (logLevel === \"debug\") {\n this.#logger.debug(\"[FastMCP debug] server ping failed\");\n } else if (logLevel === \"warning\") {\n this.#logger.warn(\n \"[FastMCP warning] server is not responding to ping\",\n );\n } else if (logLevel === \"error\") {\n this.#logger.error(\n \"[FastMCP error] server is not responding to ping\",\n );\n } else {\n this.#logger.info(\"[FastMCP info] server ping failed\");\n }\n }\n }, pingConfig.intervalMs);\n }\n }\n\n // Mark connection as ready and emit event\n this.#connectionState = \"ready\";\n this.emit(\"ready\");\n } catch (error) {\n this.#connectionState = \"error\";\n const errorEvent = {\n error: error instanceof Error ? error : new Error(String(error)),\n };\n this.emit(\"error\", errorEvent);\n throw error;\n }\n }\n\n promptsListChanged(prompts: Prompt<T>[]) {\n this.#prompts = [];\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n this.setupPromptHandlers(prompts);\n this.triggerListChangedNotification(\"notifications/prompts/list_changed\");\n }\n\n public async requestSampling(\n message: z.infer<typeof CreateMessageRequestSchema>[\"params\"],\n options?: RequestOptions,\n ): Promise<SamplingResponse> {\n return this.#server.createMessage(message, options);\n }\n\n resourcesListChanged(resources: Resource<T>[]) {\n this.#resources = [];\n for (const resource of resources) {\n this.addResource(resource);\n }\n this.setupResourceHandlers(resources);\n this.triggerListChangedNotification(\"notifications/resources/list_changed\");\n }\n\n resourceTemplatesListChanged(resourceTemplates: ResourceTemplate<T>[]) {\n this.#resourceTemplates = [];\n for (const resourceTemplate of resourceTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n this.setupResourceTemplateHandlers(resourceTemplates);\n this.triggerListChangedNotification(\"notifications/resources/list_changed\");\n }\n\n toolsListChanged(tools: Tool<T>[]) {\n const allowedTools = tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(this.#auth as T) : true,\n );\n this.setupToolHandlers(allowedTools);\n this.triggerListChangedNotification(\"notifications/tools/list_changed\");\n }\n\n async triggerListChangedNotification(method: string) {\n try {\n await this.#server.notification({\n method,\n });\n } catch (error) {\n this.#logger.error(\n `[FastMCP error] failed to send ${method} notification.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n }\n\n public waitForReady(): Promise<void> {\n if (this.isReady) {\n return Promise.resolve();\n }\n\n if (\n this.#connectionState === \"error\" ||\n this.#connectionState === \"closed\"\n ) {\n return Promise.reject(\n new Error(`Connection is in ${this.#connectionState} state`),\n );\n }\n\n return new Promise((resolve, reject) => {\n const timeout = setTimeout(() => {\n reject(\n new Error(\n \"Connection timeout: Session failed to become ready within 5 seconds\",\n ),\n );\n }, 5000);\n\n this.once(\"ready\", () => {\n clearTimeout(timeout);\n resolve();\n });\n\n this.once(\"error\", (event) => {\n clearTimeout(timeout);\n reject(event.error);\n });\n });\n }\n\n #getPingConfig(transport: Transport): {\n enabled: boolean;\n intervalMs: number;\n logLevel: LoggingLevel;\n } {\n const pingConfig = this.#pingConfig || {};\n\n let defaultEnabled = false;\n\n if (\"type\" in transport) {\n // Enable by default for SSE and HTTP streaming\n if (transport.type === \"httpStream\") {\n defaultEnabled = true;\n }\n }\n\n return {\n enabled:\n pingConfig.enabled !== undefined ? pingConfig.enabled : defaultEnabled,\n intervalMs: pingConfig.intervalMs || 5000,\n logLevel: pingConfig.logLevel || \"debug\",\n };\n }\n\n private addPrompt(inputPrompt: InputPrompt<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n const enums: Record<string, string[]> = {};\n const fuseInstances: Record<string, Fuse<string>> = {};\n\n for (const argument of inputPrompt.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n\n if (argument.enum) {\n enums[argument.name] = argument.enum;\n fuseInstances[argument.name] = new Fuse(argument.enum, {\n includeScore: true,\n threshold: 0.3, // More flexible matching!\n });\n }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n if (fuseInstances[name]) {\n const result = fuseInstances[name].search(value);\n\n return {\n total: result.length,\n values: result.map((item) => item.item),\n };\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#prompts.push(prompt);\n }\n\n private addResource(inputResource: Resource<T>) {\n this.#resources.push(inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n\n for (const argument of inputResourceTemplate.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n }\n\n const resourceTemplate = {\n ...inputResourceTemplate,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#resourceTemplates.push(resourceTemplate);\n }\n\n private setupCompleteHandlers() {\n this.#server.setRequestHandler(CompleteRequestSchema, async (request) => {\n if (request.params.ref.type === \"ref/prompt\") {\n const prompt = this.#prompts.find(\n (prompt) => prompt.name === request.params.ref.name,\n );\n\n if (!prompt) {\n throw new UnexpectedStateError(\"Unknown prompt\", {\n request,\n });\n }\n\n if (!prompt.complete) {\n throw new UnexpectedStateError(\"Prompt does not support completion\", {\n request,\n });\n }\n\n const completion = CompletionZodSchema.parse(\n await prompt.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n );\n\n return {\n completion,\n };\n }\n\n if (request.params.ref.type === \"ref/resource\") {\n const resource = this.#resourceTemplates.find(\n (resource) => resource.uriTemplate === request.params.ref.uri,\n );\n\n if (!resource) {\n throw new UnexpectedStateError(\"Unknown resource\", {\n request,\n });\n }\n\n if (!(\"uriTemplate\" in resource)) {\n throw new UnexpectedStateError(\"Unexpected resource\");\n }\n\n if (!resource.complete) {\n throw new UnexpectedStateError(\n \"Resource does not support completion\",\n {\n request,\n },\n );\n }\n\n const completion = CompletionZodSchema.parse(\n await resource.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n );\n\n return {\n completion,\n };\n }\n\n throw new UnexpectedStateError(\"Unexpected completion request\", {\n request,\n });\n });\n }\n\n private setupErrorHandling() {\n this.#server.onerror = (error) => {\n this.#logger.error(\"[FastMCP error]\", error);\n };\n }\n\n private setupLoggingHandlers() {\n this.#server.setRequestHandler(SetLevelRequestSchema, (request) => {\n this.#loggingLevel = request.params.level;\n\n return {};\n });\n }\n private setupPromptHandlers(prompts: Prompt<T>[]) {\n this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return {\n prompts: prompts.map((prompt) => {\n return {\n arguments: prompt.arguments,\n complete: prompt.complete,\n description: prompt.description,\n name: prompt.name,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = prompts.find(\n (prompt) => prompt.name === request.params.name,\n );\n\n if (!prompt) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown prompt: ${request.params.name}`,\n );\n }\n\n const args = request.params.arguments;\n\n for (const arg of prompt.arguments ?? []) {\n if (arg.required && !(args && arg.name in args)) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Prompt '${request.params.name}' requires argument '${arg.name}': ${\n arg.description || \"No description provided\"\n }`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt<T>[\"load\"]>>;\n\n try {\n result = await prompt.load(\n args as Record<string, string | undefined>,\n this.#auth,\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load prompt '${request.params.name}': ${errorMessage}`,\n );\n }\n\n if (typeof result === \"string\") {\n return {\n description: prompt.description,\n messages: [\n {\n content: { text: result, type: \"text\" },\n role: \"user\",\n },\n ],\n };\n } else {\n return {\n description: prompt.description,\n messages: result.messages,\n };\n }\n });\n }\n private setupResourceHandlers(resources: Resource<T>[]) {\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: resources.map((resource) => ({\n description: resource.description,\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n })),\n } satisfies ListResourcesResult;\n });\n\n this.#server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n if (\"uri\" in request.params) {\n const resource = resources.find(\n (resource) =>\n \"uri\" in resource && resource.uri === request.params.uri,\n );\n\n if (!resource) {\n for (const resourceTemplate of this.#resourceTemplates) {\n const uriTemplate = parseURITemplate(\n resourceTemplate.uriTemplate,\n );\n\n const match = uriTemplate.fromUri(request.params.uri);\n\n if (!match) {\n continue;\n }\n\n const uri = uriTemplate.fill(match);\n\n const result = await resourceTemplate.load(match, this.#auth);\n\n const resources = Array.isArray(result) ? result : [result];\n return {\n contents: resources.map((resource) => ({\n ...resource,\n description: resourceTemplate.description,\n mimeType: resource.mimeType ?? resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uri: resource.uri ?? uri,\n })),\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Resource not found: '${request.params.uri}'. Available resources: ${\n resources.map((r) => r.uri).join(\", \") || \"none\"\n }`,\n );\n }\n\n if (!(\"uri\" in resource)) {\n throw new UnexpectedStateError(\"Resource does not support reading\");\n }\n\n let maybeArrayResult: Awaited<ReturnType<Resource<T>[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load(this.#auth);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load resource '${resource.name}' (${resource.uri}): ${errorMessage}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n const resourceResults = Array.isArray(maybeArrayResult)\n ? maybeArrayResult\n : [maybeArrayResult];\n\n return {\n contents: resourceResults.map((result) => ({\n ...result,\n mimeType: result.mimeType ?? resource.mimeType,\n name: resource.name,\n uri: result.uri ?? resource.uri,\n })),\n };\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n private setupResourceTemplateHandlers(\n resourceTemplates: ResourceTemplate<T>[],\n ) {\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n return {\n resourceTemplates: resourceTemplates.map((resourceTemplate) => ({\n description: resourceTemplate.description,\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n })),\n } satisfies ListResourceTemplatesResult;\n },\n );\n }\n private setupRootsHandlers() {\n if (this.#rootsConfig?.enabled === false) {\n this.#logger.debug(\n \"[FastMCP debug] roots capability explicitly disabled via config\",\n );\n return;\n }\n\n // Only set up roots notification handling if the server supports it\n if (typeof this.#server.listRoots === \"function\") {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server\n .listRoots()\n .then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n })\n .catch((error) => {\n if (\n error instanceof McpError &&\n error.code === ErrorCode.MethodNotFound\n ) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n });\n },\n );\n } else {\n this.#logger.debug(\n \"[FastMCP debug] roots capability not available, not setting up notification handler\",\n );\n }\n }\n private setupToolHandlers(tools: Tool<T>[]) {\n this.#server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: await Promise.all(\n tools.map(async (tool) => {\n return {\n annotations: tool.annotations,\n description: tool.description,\n inputSchema: tool.parameters\n ? await toJsonSchema(tool.parameters)\n : {\n additionalProperties: false,\n properties: {},\n type: \"object\",\n }, // More complete schema for Cursor compatibility\n name: tool.name,\n };\n }),\n ),\n };\n });\n\n this.#server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tool = tools.find((tool) => tool.name === request.params.name);\n\n if (!tool) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n\n let args: unknown = undefined;\n\n if (tool.parameters) {\n const parsed = await tool.parameters[\"~standard\"].validate(\n request.params.arguments,\n );\n\n if (parsed.issues) {\n const friendlyErrors = this.#utils?.formatInvalidParamsErrorMessage\n ? this.#utils.formatInvalidParamsErrorMessage(parsed.issues)\n : parsed.issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\n\n throw new McpError(\n ErrorCode.InvalidParams,\n `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,\n );\n }\n\n args = parsed.value;\n }\n\n const progressToken = request.params?._meta?.progressToken;\n\n let result: ContentResult;\n\n try {\n const reportProgress = async (progress: Progress) => {\n try {\n await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (progressError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to report progress for tool '${request.params.name}':`,\n progressError instanceof Error\n ? progressError.message\n : String(progressError),\n );\n }\n };\n\n const log = {\n debug: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"debug\",\n });\n },\n error: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"error\",\n });\n },\n info: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"info\",\n });\n },\n warn: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n data: {\n context,\n message,\n },\n level: \"warning\",\n });\n },\n };\n\n // Create a promise for tool execution\n // Streams partial results while a tool is still executing\n // Enables progressive rendering and real-time feedback\n const streamContent = async (content: Content | Content[]) => {\n const contentArray = Array.isArray(content) ? content : [content];\n\n try {\n await this.#server.notification({\n method: \"notifications/tool/streamContent\",\n params: {\n content: contentArray,\n toolName: request.params.name,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (streamError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to stream content for tool '${request.params.name}':`,\n streamError instanceof Error\n ? streamError.message\n : String(streamError),\n );\n }\n };\n\n const executeToolPromise = tool.execute(args, {\n client: {\n version: this.#server.getClientVersion(),\n },\n log,\n reportProgress,\n requestId:\n typeof request.params?._meta?.requestId === \"string\"\n ? request.params._meta.requestId\n : undefined,\n session: this.#auth,\n sessionId: this.#sessionId,\n streamContent,\n });\n\n // Handle timeout if specified\n const maybeStringResult = (await (tool.timeoutMs\n ? Promise.race([\n executeToolPromise,\n new Promise<never>((_, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new UserError(\n `Tool '${request.params.name}' timed out after ${tool.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`,\n ),\n );\n }, tool.timeoutMs);\n\n // If promise resolves first\n executeToolPromise.finally(() => clearTimeout(timeoutId));\n }),\n ])\n : executeToolPromise)) as\n | AudioContent\n | ContentResult\n | ImageContent\n | null\n | ResourceContent\n | ResourceLink\n | string\n | TextContent\n | undefined;\n\n // Without this test, we are running into situations where the last progress update is not reported.\n // See the 'reports multiple progress updates without buffering' test in FastMCP.test.ts before refactoring.\n await delay(1);\n\n if (maybeStringResult === undefined || maybeStringResult === null) {\n result = ContentResultZodSchema.parse({\n content: [],\n });\n } else if (typeof maybeStringResult === \"string\") {\n result = ContentResultZodSchema.parse({\n content: [{ text: maybeStringResult, type: \"text\" }],\n });\n } else if (\"type\" in maybeStringResult) {\n result = ContentResultZodSchema.parse({\n content: [maybeStringResult],\n });\n } else {\n result = ContentResultZodSchema.parse(maybeStringResult);\n }\n } catch (error) {\n if (error instanceof UserError) {\n return {\n content: [{ text: error.message, type: \"text\" }],\n isError: true,\n ...(error.extras ? { structuredContent: error.extras } : {}),\n };\n }\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n text: `Tool '${request.params.name}' execution failed: ${errorMessage}`,\n type: \"text\",\n },\n ],\n isError: true,\n };\n }\n\n return result;\n });\n }\n}\n\n/**\n * Converts camelCase to snake_case for OAuth endpoint responses\n */\nfunction camelToSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Converts an object with camelCase keys to snake_case keys\n */\nfunction convertObjectToSnakeCase(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = camelToSnakeCase(key);\n result[snakeKey] = value;\n }\n\n return result;\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;\n} = EventEmitter;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPEventEmitter {\n public get serverState(): ServerState {\n return this.#serverState;\n }\n\n public get sessions(): FastMCPSession<T>[] {\n return this.#sessions;\n }\n #authenticate: Authenticate<T> | undefined;\n #httpStreamServer: null | SSEServer = null;\n #logger: Logger;\n #options: ServerOptions<T>;\n #prompts: InputPrompt<T>[] = [];\n #resources: Resource<T>[] = [];\n #resourcesTemplates: InputResourceTemplate<T>[] = [];\n #serverState: ServerState = ServerState.Stopped;\n\n #sessions: FastMCPSession<T>[] = [];\n\n #tools: Tool<T>[] = [];\n\n constructor(public options: ServerOptions<T>) {\n super();\n\n this.#options = options;\n this.#authenticate = options.authenticate;\n this.#logger = options.logger || console;\n }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument<T>[]>(\n prompt: InputPrompt<T, Args>,\n ) {\n this.#prompts = this.#prompts.filter((p) => p.name !== prompt.name);\n this.#prompts.push(prompt);\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n /**\n * Adds prompts to the server.\n */\n public addPrompts<const Args extends InputPromptArgument<T>[]>(\n prompts: InputPrompt<T, Args>[],\n ) {\n const newPromptNames = new Set(prompts.map((prompt) => prompt.name));\n this.#prompts = this.#prompts.filter((p) => !newPromptNames.has(p.name));\n this.#prompts.push(...prompts);\n\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource<T>) {\n this.#resources = this.#resources.filter((r) => r.name !== resource.name);\n\n this.#resources.push(resource);\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n /**\n * Adds resources to the server.\n */\n public addResources(resources: Resource<T>[]) {\n const newResourceNames = new Set(\n resources.map((resource) => resource.name),\n );\n this.#resources = this.#resources.filter(\n (r) => !newResourceNames.has(r.name),\n );\n this.#resources.push(...resources);\n\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n /**\n * Adds a resource template to the server.\n */\n public addResourceTemplate<\n const Args extends InputResourceTemplateArgument[],\n >(resource: InputResourceTemplate<T, Args>) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== resource.name,\n );\n\n this.#resourcesTemplates.push(resource);\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n /**\n * Adds resource templates to the server.\n */\n public addResourceTemplates<\n const Args extends InputResourceTemplateArgument[],\n >(resources: InputResourceTemplate<T, Args>[]) {\n const newResourceTemplateNames = new Set(\n resources.map((resource) => resource.name),\n );\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => !newResourceTemplateNames.has(t.name),\n );\n this.#resourcesTemplates.push(...resources);\n\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n /**\n * Adds a tool to the server.\n */\n public addTool<Params extends ToolParameters>(tool: Tool<T, Params>) {\n // Remove existing tool with the same name\n this.#tools = this.#tools.filter((t) => t.name !== tool.name);\n this.#tools.push(tool as unknown as Tool<T>);\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n /**\n * Adds tools to the server.\n */\n public addTools<Params extends ToolParameters>(tools: Tool<T, Params>[]) {\n const newToolNames = new Set(tools.map((tool) => tool.name));\n this.#tools = this.#tools.filter((t) => !newToolNames.has(t.name));\n this.#tools.push(...(tools as unknown as Tool<T>[]));\n\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Embeds a resource by URI, making it easy to include resources in tool responses.\n *\n * @param uri - The URI of the resource to embed\n * @returns Promise<ResourceContent> - The embedded resource content\n */\n public async embedded(uri: string): Promise<ResourceContent[\"resource\"]> {\n // First, try to find a direct resource match\n const directResource = this.#resources.find(\n (resource) => resource.uri === uri,\n );\n\n if (directResource) {\n const result = await directResource.load();\n const results = Array.isArray(result) ? result : [result];\n const firstResult = results[0];\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: directResource.mimeType,\n uri,\n };\n\n if (\"text\" in firstResult) {\n resourceData.text = firstResult.text;\n }\n\n if (\"blob\" in firstResult) {\n resourceData.blob = firstResult.blob;\n }\n\n return resourceData;\n }\n\n // Try to match against resource templates\n for (const template of this.#resourcesTemplates) {\n const parsedTemplate = parseURITemplate(template.uriTemplate);\n const params = parsedTemplate.fromUri(uri);\n if (!params) {\n continue;\n }\n\n const result = await template.load(\n params as ResourceTemplateArgumentsToObject<typeof template.arguments>,\n );\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: template.mimeType,\n uri,\n };\n\n if (\"text\" in result) {\n resourceData.text = result.text;\n }\n\n if (\"blob\" in result) {\n resourceData.blob = result.blob;\n }\n\n return resourceData; // The resource we're looking for\n }\n\n throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });\n }\n /**\n * Removes a prompt from the server.\n */\n public removePrompt(name: string) {\n this.#prompts = this.#prompts.filter((p) => p.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n /**\n * Removes prompts from the server.\n */\n public removePrompts(names: string[]) {\n for (const name of names) {\n this.#prompts = this.#prompts.filter((p) => p.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n /**\n * Removes a resource from the server.\n */\n public removeResource(name: string) {\n this.#resources = this.#resources.filter((r) => r.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Removes resources from the server.\n */\n public removeResources(names: string[]) {\n for (const name of names) {\n this.#resources = this.#resources.filter((r) => r.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n /**\n * Removes a resource template from the server.\n */\n public removeResourceTemplate(name: string) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== name,\n );\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n /**\n * Removes resource templates from the server.\n */\n public removeResourceTemplates(names: string[]) {\n for (const name of names) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== name,\n );\n }\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n /**\n * Removes a tool from the server.\n */\n public removeTool(name: string) {\n // Remove existing tool with the same name\n this.#tools = this.#tools.filter((t) => t.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Removes tools from the server.\n */\n public removeTools(names: string[]) {\n for (const name of names) {\n this.#tools = this.#tools.filter((t) => t.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options?: Partial<{\n httpStream: {\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n eventStore?: EventStore;\n host?: string;\n port: number;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ) {\n const config = this.#parseRuntimeConfig(options);\n\n if (config.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n // For stdio transport, if authenticate function is provided, call it\n // with undefined request (since stdio doesn't have HTTP request context)\n let auth: T | undefined;\n\n if (this.#authenticate) {\n try {\n auth = await this.#authenticate(\n undefined as unknown as http.IncomingMessage,\n );\n } catch (error) {\n this.#logger.error(\n \"[FastMCP error] Authentication failed for stdio transport:\",\n error instanceof Error ? error.message : String(error),\n );\n // Continue without auth if authentication fails\n }\n }\n\n const session = new FastMCPSession<T>({\n auth,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n tools: this.#tools,\n transportType: \"stdio\",\n utils: this.#options.utils,\n version: this.#options.version,\n });\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n session.once(\"error\", () => {\n this.#removeSession(session);\n });\n\n // Monitor the underlying transport for close events\n if (transport.onclose) {\n const originalOnClose = transport.onclose;\n\n transport.onclose = () => {\n this.#removeSession(session);\n\n if (originalOnClose) {\n originalOnClose();\n }\n };\n } else {\n transport.onclose = () => {\n this.#removeSession(session);\n };\n }\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n this.#serverState = ServerState.Running;\n } else if (config.transportType === \"httpStream\") {\n const httpConfig = config.httpStream;\n\n if (httpConfig.stateless) {\n // Stateless mode - create new server instance for each request\n this.#logger.info(\n `[FastMCP info] Starting server in stateless mode on HTTP Stream at http://${httpConfig.host}:${httpConfig.port}${httpConfig.endpoint}`,\n );\n\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(this.#authenticate ? { authenticate: this.#authenticate } : {}),\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n\n // In stateless mode, authentication is REQUIRED\n // mcp-proxy will catch this error and return 401\n if (auth === undefined || auth === null) {\n throw new Error(\"Authentication required\");\n }\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n // In stateless mode, create a new session for each request\n // without persisting it in the sessions array\n return this.#createSession(auth, sessionId);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n // In stateless mode, we don't track sessions\n onClose: async () => {\n // No session tracking in stateless mode\n },\n onConnect: async () => {\n // No persistent session tracking in stateless mode\n this.#logger.debug(\n `[FastMCP debug] Stateless HTTP Stream request handled`,\n );\n },\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(req, res, true, httpConfig.host);\n },\n port: httpConfig.port,\n stateless: true,\n streamEndpoint: httpConfig.endpoint,\n });\n } else {\n // Regular mode with session management\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(this.#authenticate ? { authenticate: this.#authenticate } : {}),\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n return this.#createSession(auth, sessionId);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n onClose: async (session) => {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) this.#sessions.splice(sessionIndex, 1);\n\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.#logger.info(`[FastMCP info] HTTP Stream session established`);\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(\n req,\n res,\n false,\n httpConfig.host,\n );\n },\n port: httpConfig.port,\n stateless: httpConfig.stateless,\n streamEndpoint: httpConfig.endpoint,\n });\n\n this.#logger.info(\n `[FastMCP info] server is running on HTTP Stream at http://${httpConfig.host}:${httpConfig.port}${httpConfig.endpoint}`,\n );\n }\n this.#serverState = ServerState.Running;\n } else {\n throw new Error(\"Invalid transport type\");\n }\n }\n\n /**\n * Stops the server.\n */\n public async stop() {\n if (this.#httpStreamServer) {\n await this.#httpStreamServer.close();\n }\n this.#serverState = ServerState.Stopped;\n }\n\n /**\n * Creates a new FastMCPSession instance with the current configuration.\n * Used both for regular sessions and stateless requests.\n */\n #createSession(auth?: T, sessionId?: string): FastMCPSession<T> {\n // Check if authentication failed\n if (\n auth &&\n typeof auth === \"object\" &&\n \"authenticated\" in auth &&\n !(auth as { authenticated: unknown }).authenticated\n ) {\n const errorMessage =\n \"error\" in auth &&\n typeof (auth as { error: unknown }).error === \"string\"\n ? (auth as { error: string }).error\n : \"Authentication failed\";\n throw new Error(errorMessage);\n }\n\n const allowedTools = auth\n ? this.#tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(auth) : true,\n )\n : this.#tools;\n return new FastMCPSession<T>({\n auth,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n sessionId,\n tools: allowedTools,\n transportType: \"httpStream\",\n utils: this.#options.utils,\n version: this.#options.version,\n });\n }\n\n /**\n * Handles unhandled HTTP requests with health, readiness, and OAuth endpoints\n */\n #handleUnhandledRequest = async (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n isStateless = false,\n host: string,\n ) => {\n const healthConfig = this.#options.health ?? {};\n\n const enabled =\n healthConfig.enabled === undefined ? true : healthConfig.enabled;\n\n if (enabled) {\n const path = healthConfig.path ?? \"/health\";\n const url = new URL(req.url || \"\", `http://${host}`);\n\n try {\n if (req.method === \"GET\" && url.pathname === path) {\n res\n .writeHead(healthConfig.status ?? 200, {\n \"Content-Type\": \"text/plain\",\n })\n .end(healthConfig.message ?? \"✓ Ok\");\n\n return;\n }\n\n // Enhanced readiness check endpoint\n if (req.method === \"GET\" && url.pathname === \"/ready\") {\n if (isStateless) {\n // In stateless mode, we're always ready if the server is running\n const response = {\n mode: \"stateless\",\n ready: 1,\n status: \"ready\",\n total: 1,\n };\n\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(response));\n } else {\n const readySessions = this.#sessions.filter(\n (s) => s.isReady,\n ).length;\n const totalSessions = this.#sessions.length;\n const allReady =\n readySessions === totalSessions && totalSessions > 0;\n\n const response = {\n ready: readySessions,\n status: allReady\n ? \"ready\"\n : totalSessions === 0\n ? \"no_sessions\"\n : \"initializing\",\n total: totalSessions,\n };\n\n res\n .writeHead(allReady ? 200 : 503, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(response));\n }\n\n return;\n }\n } catch (error) {\n this.#logger.error(\"[FastMCP error] health endpoint error\", error);\n }\n }\n\n // Handle OAuth well-known endpoints\n const oauthConfig = this.#options.oauth;\n if (oauthConfig?.enabled && req.method === \"GET\") {\n const url = new URL(req.url || \"\", `http://${host}`);\n\n if (\n url.pathname === \"/.well-known/oauth-authorization-server\" &&\n oauthConfig.authorizationServer\n ) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.authorizationServer,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n\n if (\n url.pathname === \"/.well-known/oauth-protected-resource\" &&\n oauthConfig.protectedResource\n ) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.protectedResource,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n }\n\n // If the request was not handled above, return 404\n res.writeHead(404).end();\n };\n\n #parseRuntimeConfig(\n overrides?: Partial<{\n httpStream: {\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n host?: string;\n port: number;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ):\n | {\n httpStream: {\n enableJsonResponse?: boolean;\n endpoint: `/${string}`;\n eventStore?: EventStore;\n host: string;\n port: number;\n stateless?: boolean;\n };\n transportType: \"httpStream\";\n }\n | { transportType: \"stdio\" } {\n const args = process.argv.slice(2);\n const getArg = (name: string) => {\n const index = args.findIndex((arg) => arg === `--${name}`);\n\n return index !== -1 && index + 1 < args.length\n ? args[index + 1]\n : undefined;\n };\n\n const transportArg = getArg(\"transport\");\n const portArg = getArg(\"port\");\n const endpointArg = getArg(\"endpoint\");\n const statelessArg = getArg(\"stateless\");\n const hostArg = getArg(\"host\");\n\n const envTransport = process.env.FASTMCP_TRANSPORT;\n const envPort = process.env.FASTMCP_PORT;\n const envEndpoint = process.env.FASTMCP_ENDPOINT;\n const envStateless = process.env.FASTMCP_STATELESS;\n const envHost = process.env.FASTMCP_HOST;\n // Overrides > CLI > env > defaults\n const transportType =\n overrides?.transportType ||\n (transportArg === \"http-stream\" ? \"httpStream\" : transportArg) ||\n envTransport ||\n \"stdio\";\n\n if (transportType === \"httpStream\") {\n const port = parseInt(\n overrides?.httpStream?.port?.toString() || portArg || envPort || \"8080\",\n );\n const host =\n overrides?.httpStream?.host || hostArg || envHost || \"localhost\";\n const endpoint =\n overrides?.httpStream?.endpoint || endpointArg || envEndpoint || \"/mcp\";\n const enableJsonResponse =\n overrides?.httpStream?.enableJsonResponse || false;\n const stateless =\n overrides?.httpStream?.stateless ||\n statelessArg === \"true\" ||\n envStateless === \"true\" ||\n false;\n\n return {\n httpStream: {\n enableJsonResponse,\n endpoint: endpoint as `/${string}`,\n host,\n port,\n stateless,\n },\n transportType: \"httpStream\" as const,\n };\n }\n\n return { transportType: \"stdio\" as const };\n }\n\n /**\n * Notifies all sessions that the prompts list has changed.\n */\n #promptsListChanged(prompts: Prompt<T>[]) {\n for (const session of this.#sessions) {\n session.promptsListChanged(prompts);\n }\n }\n #removeSession(session: FastMCPSession<T>): void {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) {\n this.#sessions.splice(sessionIndex, 1);\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n }\n }\n /**\n * Notifies all sessions that the resources list has changed.\n */\n #resourcesListChanged(resources: Resource<T>[]) {\n for (const session of this.#sessions) {\n session.resourcesListChanged(resources);\n }\n }\n /**\n * Notifies all sessions that the resource templates list has changed.\n */\n #resourceTemplatesListChanged(templates: InputResourceTemplate<T>[]) {\n for (const session of this.#sessions) {\n session.resourceTemplatesListChanged(templates);\n }\n }\n /**\n * Notifies all sessions that the tools list has changed.\n */\n #toolsListChanged(tools: Tool<T>[]) {\n for (const session of this.#sessions) {\n session.toolsListChanged(tools);\n }\n }\n}\n\nexport { DiscoveryDocumentCache } from \"./DiscoveryDocumentCache.js\";\n\nexport type {\n AudioContent,\n Content,\n ContentResult,\n Context,\n FastMCPEvents,\n FastMCPSessionEvents,\n ImageContent,\n InputPrompt,\n InputPromptArgument,\n LoggingLevel,\n Progress,\n Prompt,\n PromptArgument,\n Resource,\n ResourceContent,\n ResourceLink,\n ResourceResult,\n ResourceTemplate,\n ResourceTemplateArgument,\n SerializableValue,\n ServerOptions,\n TextContent,\n Tool,\n ToolParameters,\n};\n","export class DiscoveryDocumentCache {\n public get size(): number {\n return this.#cache.size;\n }\n\n #cache: Map<\n string,\n {\n data: unknown;\n expiresAt: number;\n }\n > = new Map();\n\n #inFlight: Map<string, Promise<unknown>> = new Map();\n\n #ttl: number;\n\n /**\n * @param options - configuration options\n * @param options.ttl - time-to-live in miliseconds\n */\n public constructor(options: { ttl?: number } = {}) {\n this.#ttl = options.ttl ?? 3600000; // default 1 hour\n }\n\n /**\n * @param url - optional URL to clear. if omitted, clears all cached documents.\n */\n public clear(url?: string): void {\n if (url) {\n this.#cache.delete(url);\n } else {\n this.#cache.clear();\n }\n }\n\n /**\n * fetches a discovery document from the given URL.\n * uses cached value if available and not expired.\n * coalesces concurrent requests for the same URL to prevent duplicate fetches.\n *\n * @param url - the discovery document URL (e.g., /.well-known/openid-configuration)\n * @returns the discovery document as a JSON object\n * @throws Error if the fetch fails or returns non-OK status\n */\n public async get(url: string): Promise<unknown> {\n const now = Date.now();\n const cached = this.#cache.get(url);\n\n // return cached value if still valid\n if (cached && cached.expiresAt > now) {\n return cached.data;\n }\n\n // check if there’s already an in-flight request for this URL\n const inFlight = this.#inFlight.get(url);\n\n if (inFlight) {\n return inFlight;\n }\n\n // create a new fetch promise and store it\n const fetchPromise = this.#fetchAndCache(url);\n\n this.#inFlight.set(url, fetchPromise);\n\n try {\n const data = await fetchPromise;\n return data;\n } finally {\n // clean up in-flight promise after completion\n // (success or failure)\n this.#inFlight.delete(url);\n }\n }\n\n /**\n * @param url - the URL to check\n * @returns true if the URL is cached and nott expired\n */\n public has(url: string): boolean {\n const cached = this.#cache.get(url);\n\n if (!cached) {\n return false;\n }\n\n const now = Date.now();\n\n if (cached.expiresAt <= now) {\n // expired, remove from cache\n this.#cache.delete(url);\n return false;\n }\n\n return true;\n }\n\n async #fetchAndCache(url: string): Promise<unknown> {\n // fetch fresh document\n const res = await fetch(url);\n\n if (!res.ok) {\n throw new Error(\n `Failed to fetch discovery document from ${url}: ${res.status} ${res.statusText}`,\n );\n }\n\n const data = await res.json();\n // calculate expiration time AFTER fetch completes\n const expiresAt = Date.now() + this.#ttl;\n\n // store in cache with expiration\n this.#cache.set(url, {\n data,\n expiresAt,\n });\n\n return data;\n }\n}\n"],"mappings":"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","names":["fetch","fetch","ServerState","prompt","resource","resources","tool"]}
|