fastmcp 1.25.0 → 1.26.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/README.md CHANGED
@@ -22,7 +22,7 @@ A TypeScript framework for building [MCP](https://glama.ai/mcp) servers capable
22
22
  - [Typed server events](#typed-server-events)
23
23
  - [Prompt argument auto-completion](#prompt-argument-auto-completion)
24
24
  - [Sampling](#requestsampling)
25
- - Automated SSE pings
25
+ - [Configurable ping behavior](#configurable-ping-behavior)
26
26
  - Roots
27
27
  - CLI for [testing](#test-with-mcp-cli) and [debugging](#inspect-with-mcp-inspector)
28
28
 
@@ -354,7 +354,32 @@ server.addTool({
354
354
  });
355
355
  ```
356
356
 
357
- #### Returning an audio
357
+ #### Configurable Ping Behavior
358
+
359
+ FastMCP includes a configurable ping mechanism to maintain connection health. The ping behavior can be customized through server options:
360
+
361
+ ```ts
362
+ const server = new FastMCP({
363
+ name: "My Server",
364
+ version: "1.0.0",
365
+ ping: {
366
+ // Explicitly enable or disable pings (defaults vary by transport)
367
+ enabled: true,
368
+ // Configure ping interval in milliseconds (default: 5000ms)
369
+ intervalMs: 10000,
370
+ // Set log level for ping-related messages (default: 'debug')
371
+ logLevel: 'debug'
372
+ }
373
+ });
374
+ ```
375
+
376
+ By default, ping behavior is optimized for each transport type:
377
+ - Enabled for SSE and HTTP streaming connections (which benefit from keep-alive)
378
+ - Disabled for `stdio` connections (where pings are typically unnecessary)
379
+
380
+ This configurable approach helps reduce log verbosity and optimize performance for different usage scenarios.
381
+
382
+ ### Returning an audio
358
383
 
359
384
  Use the `audioContent` to create a content object for an audio:
360
385
 
@@ -790,7 +815,7 @@ import { AuthError } from "fastmcp";
790
815
  const server = new FastMCP({
791
816
  name: "My Server",
792
817
  version: "1.0.0",
793
- authenticate: ({ request }) => {
818
+ authenticate: (request) => {
794
819
  const apiKey = request.headers["x-api-key"];
795
820
 
796
821
  if (apiKey !== "123") {
package/dist/FastMCP.d.ts CHANGED
@@ -184,6 +184,24 @@ type ServerOptions<T extends FastMCPSessionAuth> = {
184
184
  authenticate?: Authenticate<T>;
185
185
  instructions?: string;
186
186
  name: string;
187
+ ping?: {
188
+ /**
189
+ * Whether ping should be enabled by default.
190
+ * - true for SSE or HTTP Stream
191
+ * - false for stdio
192
+ */
193
+ enabled?: boolean;
194
+ /**
195
+ * Interval
196
+ * @default 5000 (5s)
197
+ */
198
+ intervalMs?: number;
199
+ /**
200
+ * Logging level for ping-related messages.
201
+ * @default 'debug'
202
+ */
203
+ logLevel?: LoggingLevel;
204
+ };
187
205
  version: `${number}.${number}.${number}`;
188
206
  };
189
207
  type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolParameters> = {
@@ -244,10 +262,11 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
244
262
  get loggingLevel(): LoggingLevel;
245
263
  get roots(): Root[];
246
264
  get server(): Server;
247
- constructor({ auth, instructions, name, prompts, resources, resourcesTemplates, tools, version, }: {
265
+ constructor({ auth, instructions, name, ping, prompts, resources, resourcesTemplates, tools, version, }: {
248
266
  auth?: T;
249
267
  instructions?: string;
250
268
  name: string;
269
+ ping?: ServerOptions<T>["ping"];
251
270
  prompts: Prompt[];
252
271
  resources: Resource[];
253
272
  resourcesTemplates: InputResourceTemplate[];
package/dist/FastMCP.js CHANGED
@@ -205,6 +205,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
205
205
  #capabilities = {};
206
206
  #clientCapabilities;
207
207
  #loggingLevel = "info";
208
+ #pingConfig;
208
209
  #pingInterval = null;
209
210
  #prompts = [];
210
211
  #resources = [];
@@ -215,6 +216,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
215
216
  auth,
216
217
  instructions,
217
218
  name,
219
+ ping,
218
220
  prompts,
219
221
  resources,
220
222
  resourcesTemplates,
@@ -223,6 +225,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
223
225
  }) {
224
226
  super();
225
227
  this.#auth = auth;
228
+ this.#pingConfig = ping;
226
229
  if (tools.length) {
227
230
  this.#capabilities.tools = {};
228
231
  }
@@ -303,18 +306,46 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
303
306
  }
304
307
  }
305
308
  if (this.#clientCapabilities) {
306
- this.#pingInterval = setInterval(async () => {
307
- try {
308
- await this.#server.ping();
309
- } catch {
310
- console.warn("[FastMCP warning] server is not responding to ping");
311
- }
312
- }, 1e3);
309
+ const pingConfig = this.#getPingConfig(transport);
310
+ if (pingConfig.enabled) {
311
+ this.#pingInterval = setInterval(async () => {
312
+ try {
313
+ await this.#server.ping();
314
+ } catch {
315
+ const logLevel = pingConfig.logLevel;
316
+ if (logLevel === "debug") {
317
+ console.debug("[FastMCP debug] server ping failed");
318
+ } else if (logLevel === "warning") {
319
+ console.warn(
320
+ "[FastMCP warning] server is not responding to ping"
321
+ );
322
+ } else if (logLevel === "error") {
323
+ console.error("[FastMCP error] server is not responding to ping");
324
+ } else {
325
+ console.info("[FastMCP info] server ping failed");
326
+ }
327
+ }
328
+ }, pingConfig.intervalMs);
329
+ }
313
330
  }
314
331
  }
315
332
  async requestSampling(message) {
316
333
  return this.#server.createMessage(message);
317
334
  }
335
+ #getPingConfig(transport) {
336
+ const pingConfig = this.#pingConfig || {};
337
+ let defaultEnabled = false;
338
+ if ("type" in transport) {
339
+ if (transport.type === "sse" || transport.type === "httpStream") {
340
+ defaultEnabled = true;
341
+ }
342
+ }
343
+ return {
344
+ enabled: pingConfig.enabled !== void 0 ? pingConfig.enabled : defaultEnabled,
345
+ intervalMs: pingConfig.intervalMs || 5e3,
346
+ logLevel: pingConfig.logLevel || "debug"
347
+ };
348
+ }
318
349
  addPrompt(inputPrompt) {
319
350
  const completers = {};
320
351
  const enums = {};
@@ -800,6 +831,7 @@ var FastMCP = class extends FastMCPEventEmitter {
800
831
  const session = new FastMCPSession({
801
832
  instructions: this.#options.instructions,
802
833
  name: this.#options.name,
834
+ ping: this.#options.ping,
803
835
  prompts: this.#prompts,
804
836
  resources: this.#resources,
805
837
  resourcesTemplates: this.#resourcesTemplates,
@@ -821,6 +853,7 @@ var FastMCP = class extends FastMCPEventEmitter {
821
853
  return new FastMCPSession({
822
854
  auth,
823
855
  name: this.#options.name,
856
+ ping: this.#options.ping,
824
857
  prompts: this.#prompts,
825
858
  resources: this.#resources,
826
859
  resourcesTemplates: this.#resourcesTemplates,
@@ -855,6 +888,7 @@ var FastMCP = class extends FastMCPEventEmitter {
855
888
  return new FastMCPSession({
856
889
  auth,
857
890
  name: this.#options.name,
891
+ ping: this.#options.ping,
858
892
  prompts: this.#prompts,
859
893
  resources: this.#resources,
860
894
  resourcesTemplates: this.#resourcesTemplates,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/FastMCP.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n AudioContent,\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n CreateMessageRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\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 { fileTypeFromBuffer } from \"file-type\";\nimport { readFile } from \"fs/promises\";\nimport Fuse from \"fuse.js\";\nimport http from \"http\";\nimport { startHTTPStreamServer, startSSEServer } 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 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 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}): ${error instanceof Error ? error.message : String(error)}`,\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}): ${error instanceof Error ? error.message : String(error)}`,\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 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: ${mimeType?.mime || \"unknown\"}`,\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}): ${error instanceof Error ? error.message : String(error)}`,\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}): ${error instanceof Error ? error.message : String(error)}`,\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 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: ${mimeType?.mime || \"unknown\"}`,\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 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 session: T | undefined;\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 Content = ImageContent | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\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 = (value: string) => Promise<Completion>;\n\ntype InputPrompt<\n Arguments extends InputPromptArgument[] = InputPromptArgument[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: InputPromptArgument[];\n description?: string;\n load: (args: Args) => Promise<string>;\n name: string;\n};\n\ntype InputPromptArgument = Readonly<{\n complete?: ArgumentValueCompleter;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n}>;\n\ntype InputResourceTemplate<\n Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],\n> = {\n arguments: Arguments;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n ) => Promise<ResourceResult>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype InputResourceTemplateArgument = Readonly<{\n complete?: ArgumentValueCompleter;\n description?: string;\n name: string;\n}>;\n\ntype LoggingLevel =\n | \"alert\"\n | \"critical\"\n | \"debug\"\n | \"emergency\"\n | \"error\"\n | \"info\"\n | \"notice\"\n | \"warning\";\n\ntype Prompt<\n Arguments extends PromptArgument[] = PromptArgument[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument[];\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: (args: Args) => Promise<string>;\n name: string;\n};\n\ntype PromptArgument = Readonly<{\n complete?: ArgumentValueCompleter;\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 Resource = {\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: () => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uri: string;\n};\n\ntype ResourceResult =\n | {\n blob: string;\n }\n | {\n text: string;\n };\n\ntype ResourceTemplate<\n Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n ) => Promise<ResourceResult>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype ResourceTemplateArgument = Readonly<{\n complete?: ArgumentValueCompleter;\n description?: string;\n name: string;\n}>;\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype ServerOptions<T extends FastMCPSessionAuth> = {\n authenticate?: Authenticate<T>;\n instructions?: string;\n name: string;\n version: `${number}.${number}.${number}`;\n};\n\ntype Tool<\n T extends FastMCPSessionAuth,\n Params extends ToolParameters = ToolParameters,\n> = {\n annotations?: ToolAnnotations;\n description?: string;\n execute: (\n args: StandardSchemaV1.InferOutput<Params>,\n context: Context<T>,\n ) => Promise<\n AudioContent | ContentResult | ImageContent | string | TextContent\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 FastMCPSessionAuth = Record<string, unknown> | undefined;\n\ntype SamplingResponse = {\n content: AudioContent | ImageContent | TextContent;\n model: string;\n role: \"assistant\" | \"user\";\n stopReason?: \"endTurn\" | \"maxTokens\" | \"stopSequence\" | string;\n};\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 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 #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #loggingLevel: LoggingLevel = \"info\";\n #pingInterval: null | ReturnType<typeof setInterval> = null;\n\n #prompts: Prompt[] = [];\n\n #resources: Resource[] = [];\n\n #resourceTemplates: ResourceTemplate[] = [];\n\n #roots: Root[] = [];\n\n #server: Server;\n\n constructor({\n auth,\n instructions,\n name,\n prompts,\n resources,\n resourcesTemplates,\n tools,\n version,\n }: {\n auth?: T;\n instructions?: string;\n name: string;\n prompts: Prompt[];\n resources: Resource[];\n resourcesTemplates: InputResourceTemplate[];\n tools: Tool<T>[];\n version: string;\n }) {\n super();\n\n this.#auth = auth;\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.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 if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n try {\n await this.#server.close();\n } catch (error) {\n console.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 await this.#server.connect(transport);\n\n let attempt = 0;\n\n while (attempt++ < 10) {\n const capabilities = await this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n\n break;\n }\n\n await delay(100);\n }\n\n if (!this.#clientCapabilities) {\n console.warn(\"[FastMCP warning] could not infer client capabilities\");\n }\n\n if (this.#clientCapabilities?.roots?.listChanged) {\n try {\n const roots = await this.#server.listRoots();\n this.#roots = roots.roots;\n } catch (e) {\n console.error(\n `[FastMCP error] received error listing roots.\\n\\n${e instanceof Error ? e.stack : JSON.stringify(e)}`,\n );\n }\n }\n\n if (this.#clientCapabilities) {\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 console.warn(\"[FastMCP warning] server is not responding to ping\");\n }\n }, 1000);\n }\n }\n\n public async requestSampling(\n message: z.infer<typeof CreateMessageRequestSchema>[\"params\"],\n ): Promise<SamplingResponse> {\n return this.#server.createMessage(message);\n }\n\n private addPrompt(inputPrompt: InputPrompt) {\n const completers: Record<string, ArgumentValueCompleter> = {};\n const enums: Record<string, 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 }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string) => {\n if (completers[name]) {\n return await completers[name](value);\n }\n\n if (enums[name]) {\n const fuse = new Fuse(enums[name], {\n keys: [\"value\"],\n });\n\n const result = fuse.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) {\n this.#resources.push(inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate) {\n const completers: Record<string, ArgumentValueCompleter> = {};\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) => {\n if (completers[name]) {\n return await completers[name](value);\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 ),\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 ),\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 console.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[]) {\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 `Missing required argument: ${arg.name}`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt[\"load\"]>>;\n\n try {\n result = await prompt.load(args as Record<string, string | undefined>);\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error loading prompt: ${error}`,\n );\n }\n\n return {\n description: prompt.description,\n messages: [\n {\n content: { text: result, type: \"text\" },\n role: \"user\",\n },\n ],\n };\n });\n }\n\n private setupResourceHandlers(resources: Resource[]) {\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: resources.map((resource) => {\n return {\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n };\n }),\n };\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);\n\n return {\n contents: [\n {\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uri: uri,\n ...result,\n },\n ],\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown resource: ${request.params.uri}`,\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[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load();\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error reading resource: ${error}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n if (Array.isArray(maybeArrayResult)) {\n return {\n contents: maybeArrayResult.map((result) => ({\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n ...result,\n })),\n };\n } else {\n return {\n contents: [\n {\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n ...maybeArrayResult,\n },\n ],\n };\n }\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n\n private setupResourceTemplateHandlers(resourceTemplates: ResourceTemplate[]) {\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n return {\n resourceTemplates: resourceTemplates.map((resourceTemplate) => {\n return {\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n };\n }),\n };\n },\n );\n }\n\n private setupRootsHandlers() {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server.listRoots().then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n });\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 : undefined,\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 throw new McpError(\n ErrorCode.InvalidParams,\n `Invalid ${request.params.name} parameters: ${JSON.stringify(parsed.issues)}`,\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 await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\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 const executeToolPromise = tool.execute(args, {\n log,\n reportProgress,\n session: this.#auth,\n });\n\n // Handle timeout if specified\n const maybeStringResult = await (tool.timeoutMs\n ? Promise.race([\n executeToolPromise,\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(\n new UserError(\n `Tool execution timed out after ${tool.timeoutMs}ms`,\n ),\n );\n }, tool.timeoutMs);\n }),\n ])\n : executeToolPromise);\n\n 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 };\n }\n\n return {\n content: [{ text: `Error: ${error}`, type: \"text\" }],\n isError: true,\n };\n }\n\n return result;\n });\n }\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;\n} = EventEmitter;\n\ntype Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP<\n T extends Record<string, unknown> | undefined = undefined,\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 #options: ServerOptions<T>;\n #prompts: InputPrompt[] = [];\n #resources: Resource[] = [];\n #resourcesTemplates: InputResourceTemplate[] = [];\n #sessions: FastMCPSession<T>[] = [];\n #sseServer: null | SSEServer = null;\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 }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument[]>(\n prompt: InputPrompt<Args>,\n ) {\n this.#prompts.push(prompt);\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource) {\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<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 * Starts the server.\n */\n public async start(\n options:\n | {\n httpStream: { endpoint: `/${string}`; port: number };\n transportType: \"httpStream\";\n }\n | {\n sse: { endpoint: `/${string}`; port: number };\n transportType: \"sse\";\n }\n | { transportType: \"stdio\" } = {\n transportType: \"stdio\",\n },\n ) {\n if (options.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n const session = new FastMCPSession<T>({\n instructions: this.#options.instructions,\n name: this.#options.name,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n tools: this.#tools,\n version: this.#options.version,\n });\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n } else if (options.transportType === \"sse\") {\n this.#sseServer = await startSSEServer<FastMCPSession<T>>({\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n }\n\n return new FastMCPSession<T>({\n auth,\n name: this.#options.name,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n tools: this.#tools,\n version: this.#options.version,\n });\n },\n endpoint: options.sse.endpoint as `/${string}`,\n onClose: (session) => {\n this.emit(\"disconnect\", {\n session,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n },\n port: options.sse.port,\n });\n\n console.info(\n `[FastMCP info] server is running on SSE at http://localhost:${options.sse.port}${options.sse.endpoint}`,\n );\n } else if (options.transportType === \"httpStream\") {\n this.#httpStreamServer = await startHTTPStreamServer<FastMCPSession<T>>({\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n }\n\n return new FastMCPSession<T>({\n auth,\n name: this.#options.name,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n tools: this.#tools,\n version: this.#options.version,\n });\n },\n endpoint: options.httpStream.endpoint as `/${string}`,\n onClose: (session) => {\n this.emit(\"disconnect\", {\n session,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n },\n port: options.httpStream.port,\n });\n\n console.info(\n `[FastMCP info] server is running on HTTP Stream at http://localhost:${options.httpStream.port}${options.httpStream.endpoint}`,\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.#sseServer) {\n await this.#sseServer.close();\n }\n if (this.#httpStreamServer) {\n await this.#httpStreamServer.close();\n }\n }\n}\n\nexport type { Context };\nexport type { Tool, ToolParameters };\nexport type { Content, ContentResult, ImageContent, TextContent };\nexport type { Progress, SerializableValue };\nexport type { Resource, ResourceResult };\nexport type { ResourceTemplate, ResourceTemplateArgument };\nexport type { Prompt, PromptArgument };\nexport type { InputPrompt, InputPromptArgument };\nexport type { LoggingLevel, ServerOptions };\nexport type { FastMCPEvents, FastMCPSessionEvents };\n"],"mappings":"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","names":["prompt","resource","tool"]}
1
+ {"version":3,"sources":["../src/FastMCP.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n AudioContent,\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n CreateMessageRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\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 { fileTypeFromBuffer } from \"file-type\";\nimport { readFile } from \"fs/promises\";\nimport Fuse from \"fuse.js\";\nimport http from \"http\";\nimport { startHTTPStreamServer, startSSEServer } 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 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 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}): ${error instanceof Error ? error.message : String(error)}`,\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}): ${error instanceof Error ? error.message : String(error)}`,\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 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: ${mimeType?.mime || \"unknown\"}`,\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}): ${error instanceof Error ? error.message : String(error)}`,\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}): ${error instanceof Error ? error.message : String(error)}`,\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 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: ${mimeType?.mime || \"unknown\"}`,\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 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 session: T | undefined;\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 Content = ImageContent | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\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 = (value: string) => Promise<Completion>;\n\ntype InputPrompt<\n Arguments extends InputPromptArgument[] = InputPromptArgument[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: InputPromptArgument[];\n description?: string;\n load: (args: Args) => Promise<string>;\n name: string;\n};\n\ntype InputPromptArgument = Readonly<{\n complete?: ArgumentValueCompleter;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n}>;\n\ntype InputResourceTemplate<\n Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],\n> = {\n arguments: Arguments;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n ) => Promise<ResourceResult>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype InputResourceTemplateArgument = Readonly<{\n complete?: ArgumentValueCompleter;\n description?: string;\n name: string;\n}>;\n\ntype LoggingLevel =\n | \"alert\"\n | \"critical\"\n | \"debug\"\n | \"emergency\"\n | \"error\"\n | \"info\"\n | \"notice\"\n | \"warning\";\n\ntype Prompt<\n Arguments extends PromptArgument[] = PromptArgument[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument[];\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: (args: Args) => Promise<string>;\n name: string;\n};\n\ntype PromptArgument = Readonly<{\n complete?: ArgumentValueCompleter;\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 Resource = {\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: () => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uri: string;\n};\n\ntype ResourceResult =\n | {\n blob: string;\n }\n | {\n text: string;\n };\n\ntype ResourceTemplate<\n Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n ) => Promise<ResourceResult>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype ResourceTemplateArgument = Readonly<{\n complete?: ArgumentValueCompleter;\n description?: string;\n name: string;\n}>;\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype ServerOptions<T extends FastMCPSessionAuth> = {\n authenticate?: Authenticate<T>;\n instructions?: string;\n name: string;\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 version: `${number}.${number}.${number}`;\n};\n\ntype Tool<\n T extends FastMCPSessionAuth,\n Params extends ToolParameters = ToolParameters,\n> = {\n annotations?: ToolAnnotations;\n description?: string;\n execute: (\n args: StandardSchemaV1.InferOutput<Params>,\n context: Context<T>,\n ) => Promise<\n AudioContent | ContentResult | ImageContent | string | TextContent\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 FastMCPSessionAuth = Record<string, unknown> | undefined;\n\ntype SamplingResponse = {\n content: AudioContent | ImageContent | TextContent;\n model: string;\n role: \"assistant\" | \"user\";\n stopReason?: \"endTurn\" | \"maxTokens\" | \"stopSequence\" | string;\n};\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 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 #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #loggingLevel: LoggingLevel = \"info\";\n #pingConfig?: ServerOptions<T>[\"ping\"];\n #pingInterval: null | ReturnType<typeof setInterval> = null;\n\n #prompts: Prompt[] = [];\n\n #resources: Resource[] = [];\n\n #resourceTemplates: ResourceTemplate[] = [];\n\n #roots: Root[] = [];\n\n #server: Server;\n\n constructor({\n auth,\n instructions,\n name,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n tools,\n version,\n }: {\n auth?: T;\n instructions?: string;\n name: string;\n ping?: ServerOptions<T>[\"ping\"];\n prompts: Prompt[];\n resources: Resource[];\n resourcesTemplates: InputResourceTemplate[];\n tools: Tool<T>[];\n version: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#pingConfig = ping;\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.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 if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n try {\n await this.#server.close();\n } catch (error) {\n console.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 await this.#server.connect(transport);\n\n let attempt = 0;\n\n while (attempt++ < 10) {\n const capabilities = await this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n\n break;\n }\n\n await delay(100);\n }\n\n if (!this.#clientCapabilities) {\n console.warn(\"[FastMCP warning] could not infer client capabilities\");\n }\n\n if (this.#clientCapabilities?.roots?.listChanged) {\n try {\n const roots = await this.#server.listRoots();\n this.#roots = roots.roots;\n } catch (e) {\n console.error(\n `[FastMCP error] received error listing roots.\\n\\n${e instanceof Error ? e.stack : JSON.stringify(e)}`,\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 if (logLevel === \"debug\") {\n console.debug(\"[FastMCP debug] server ping failed\");\n } else if (logLevel === \"warning\") {\n console.warn(\n \"[FastMCP warning] server is not responding to ping\",\n );\n } else if (logLevel === \"error\") {\n console.error(\"[FastMCP error] server is not responding to ping\");\n } else {\n console.info(\"[FastMCP info] server ping failed\");\n }\n }\n }, pingConfig.intervalMs);\n }\n }\n }\n\n public async requestSampling(\n message: z.infer<typeof CreateMessageRequestSchema>[\"params\"],\n ): Promise<SamplingResponse> {\n return this.#server.createMessage(message);\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 === \"sse\" || 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) {\n const completers: Record<string, ArgumentValueCompleter> = {};\n const enums: Record<string, 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 }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string) => {\n if (completers[name]) {\n return await completers[name](value);\n }\n\n if (enums[name]) {\n const fuse = new Fuse(enums[name], {\n keys: [\"value\"],\n });\n\n const result = fuse.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) {\n this.#resources.push(inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate) {\n const completers: Record<string, ArgumentValueCompleter> = {};\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) => {\n if (completers[name]) {\n return await completers[name](value);\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 ),\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 ),\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 console.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[]) {\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 `Missing required argument: ${arg.name}`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt[\"load\"]>>;\n\n try {\n result = await prompt.load(args as Record<string, string | undefined>);\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error loading prompt: ${error}`,\n );\n }\n\n return {\n description: prompt.description,\n messages: [\n {\n content: { text: result, type: \"text\" },\n role: \"user\",\n },\n ],\n };\n });\n }\n\n private setupResourceHandlers(resources: Resource[]) {\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: resources.map((resource) => {\n return {\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n };\n }),\n };\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);\n\n return {\n contents: [\n {\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uri: uri,\n ...result,\n },\n ],\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown resource: ${request.params.uri}`,\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[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load();\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error reading resource: ${error}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n if (Array.isArray(maybeArrayResult)) {\n return {\n contents: maybeArrayResult.map((result) => ({\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n ...result,\n })),\n };\n } else {\n return {\n contents: [\n {\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n ...maybeArrayResult,\n },\n ],\n };\n }\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n\n private setupResourceTemplateHandlers(resourceTemplates: ResourceTemplate[]) {\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n return {\n resourceTemplates: resourceTemplates.map((resourceTemplate) => {\n return {\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n };\n }),\n };\n },\n );\n }\n\n private setupRootsHandlers() {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server.listRoots().then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n });\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 : undefined,\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 throw new McpError(\n ErrorCode.InvalidParams,\n `Invalid ${request.params.name} parameters: ${JSON.stringify(parsed.issues)}`,\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 await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\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 const executeToolPromise = tool.execute(args, {\n log,\n reportProgress,\n session: this.#auth,\n });\n\n // Handle timeout if specified\n const maybeStringResult = await (tool.timeoutMs\n ? Promise.race([\n executeToolPromise,\n new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(\n new UserError(\n `Tool execution timed out after ${tool.timeoutMs}ms`,\n ),\n );\n }, tool.timeoutMs);\n }),\n ])\n : executeToolPromise);\n\n 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 };\n }\n\n return {\n content: [{ text: `Error: ${error}`, type: \"text\" }],\n isError: true,\n };\n }\n\n return result;\n });\n }\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;\n} = EventEmitter;\n\ntype Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP<\n T extends Record<string, unknown> | undefined = undefined,\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 #options: ServerOptions<T>;\n #prompts: InputPrompt[] = [];\n #resources: Resource[] = [];\n #resourcesTemplates: InputResourceTemplate[] = [];\n #sessions: FastMCPSession<T>[] = [];\n #sseServer: null | SSEServer = null;\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 }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument[]>(\n prompt: InputPrompt<Args>,\n ) {\n this.#prompts.push(prompt);\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource) {\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<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 * Starts the server.\n */\n public async start(\n options:\n | {\n httpStream: { endpoint: `/${string}`; port: number };\n transportType: \"httpStream\";\n }\n | {\n sse: { endpoint: `/${string}`; port: number };\n transportType: \"sse\";\n }\n | { transportType: \"stdio\" } = {\n transportType: \"stdio\",\n },\n ) {\n if (options.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n const session = new FastMCPSession<T>({\n instructions: this.#options.instructions,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n tools: this.#tools,\n version: this.#options.version,\n });\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n } else if (options.transportType === \"sse\") {\n this.#sseServer = await startSSEServer<FastMCPSession<T>>({\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n }\n\n return new FastMCPSession<T>({\n auth,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n tools: this.#tools,\n version: this.#options.version,\n });\n },\n endpoint: options.sse.endpoint as `/${string}`,\n onClose: (session) => {\n this.emit(\"disconnect\", {\n session,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n },\n port: options.sse.port,\n });\n\n console.info(\n `[FastMCP info] server is running on SSE at http://localhost:${options.sse.port}${options.sse.endpoint}`,\n );\n } else if (options.transportType === \"httpStream\") {\n this.#httpStreamServer = await startHTTPStreamServer<FastMCPSession<T>>({\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (this.#authenticate) {\n auth = await this.#authenticate(request);\n }\n\n return new FastMCPSession<T>({\n auth,\n name: this.#options.name,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n tools: this.#tools,\n version: this.#options.version,\n });\n },\n endpoint: options.httpStream.endpoint as `/${string}`,\n onClose: (session) => {\n this.emit(\"disconnect\", {\n session,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n },\n port: options.httpStream.port,\n });\n\n console.info(\n `[FastMCP info] server is running on HTTP Stream at http://localhost:${options.httpStream.port}${options.httpStream.endpoint}`,\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.#sseServer) {\n await this.#sseServer.close();\n }\n if (this.#httpStreamServer) {\n await this.#httpStreamServer.close();\n }\n }\n}\n\nexport type { Context };\nexport type { Tool, ToolParameters };\nexport type { Content, ContentResult, ImageContent, TextContent };\nexport type { Progress, SerializableValue };\nexport type { Resource, ResourceResult };\nexport type { ResourceTemplate, ResourceTemplateArgument };\nexport type { Prompt, PromptArgument };\nexport type { InputPrompt, InputPromptArgument };\nexport type { LoggingLevel, ServerOptions };\nexport type { FastMCPEvents, FastMCPSessionEvents };\n"],"mappings":"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","names":["prompt","resource","tool"]}
package/jsr.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glama/fastmcp",
3
- "version": "1.25.0",
3
+ "version": "1.26.0",
4
4
  "exports": "./src/FastMCP.ts",
5
5
  "include": ["src/FastMCP.ts", "src/bin/fastmcp.ts"]
6
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastmcp",
3
- "version": "1.25.0",
3
+ "version": "1.26.0",
4
4
  "main": "dist/FastMCP.js",
5
5
  "scripts": {
6
6
  "build": "tsup",
@@ -1004,6 +1004,17 @@ test("session listens to roots changes", async () => {
1004
1004
 
1005
1005
  test("session sends pings to the client", async () => {
1006
1006
  await runWithTestServer({
1007
+ server: async () => {
1008
+ const server = new FastMCP({
1009
+ name: "Test",
1010
+ version: "1.0.0",
1011
+ ping: {
1012
+ enabled: true,
1013
+ intervalMs: 1000,
1014
+ },
1015
+ });
1016
+ return server;
1017
+ },
1007
1018
  run: async ({ client }) => {
1008
1019
  const onPing = vi.fn().mockReturnValue({});
1009
1020
 
@@ -1011,7 +1022,8 @@ test("session sends pings to the client", async () => {
1011
1022
 
1012
1023
  await delay(2000);
1013
1024
 
1014
- expect(onPing).toHaveBeenCalledTimes(1);
1025
+ expect(onPing.mock.calls.length).toBeGreaterThanOrEqual(1);
1026
+ expect(onPing.mock.calls.length).toBeLessThanOrEqual(3);
1015
1027
  },
1016
1028
  });
1017
1029
  });
package/src/FastMCP.ts CHANGED
@@ -430,6 +430,24 @@ type ServerOptions<T extends FastMCPSessionAuth> = {
430
430
  authenticate?: Authenticate<T>;
431
431
  instructions?: string;
432
432
  name: string;
433
+ ping?: {
434
+ /**
435
+ * Whether ping should be enabled by default.
436
+ * - true for SSE or HTTP Stream
437
+ * - false for stdio
438
+ */
439
+ enabled?: boolean;
440
+ /**
441
+ * Interval
442
+ * @default 5000 (5s)
443
+ */
444
+ intervalMs?: number;
445
+ /**
446
+ * Logging level for ping-related messages.
447
+ * @default 'debug'
448
+ */
449
+ logLevel?: LoggingLevel;
450
+ };
433
451
  version: `${number}.${number}.${number}`;
434
452
  };
435
453
 
@@ -521,6 +539,7 @@ export class FastMCPSession<
521
539
  #capabilities: ServerCapabilities = {};
522
540
  #clientCapabilities?: ClientCapabilities;
523
541
  #loggingLevel: LoggingLevel = "info";
542
+ #pingConfig?: ServerOptions<T>["ping"];
524
543
  #pingInterval: null | ReturnType<typeof setInterval> = null;
525
544
 
526
545
  #prompts: Prompt[] = [];
@@ -537,6 +556,7 @@ export class FastMCPSession<
537
556
  auth,
538
557
  instructions,
539
558
  name,
559
+ ping,
540
560
  prompts,
541
561
  resources,
542
562
  resourcesTemplates,
@@ -546,6 +566,7 @@ export class FastMCPSession<
546
566
  auth?: T;
547
567
  instructions?: string;
548
568
  name: string;
569
+ ping?: ServerOptions<T>["ping"];
549
570
  prompts: Prompt[];
550
571
  resources: Resource[];
551
572
  resourcesTemplates: InputResourceTemplate[];
@@ -555,6 +576,7 @@ export class FastMCPSession<
555
576
  super();
556
577
 
557
578
  this.#auth = auth;
579
+ this.#pingConfig = ping;
558
580
 
559
581
  if (tools.length) {
560
582
  this.#capabilities.tools = {};
@@ -658,16 +680,31 @@ export class FastMCPSession<
658
680
  }
659
681
 
660
682
  if (this.#clientCapabilities) {
661
- this.#pingInterval = setInterval(async () => {
662
- try {
663
- await this.#server.ping();
664
- } catch {
665
- // The reason we are not emitting an error here is because some clients
666
- // seem to not respond to the ping request, and we don't want to crash the server,
667
- // e.g., https://github.com/punkpeye/fastmcp/issues/38.
668
- console.warn("[FastMCP warning] server is not responding to ping");
669
- }
670
- }, 1000);
683
+ const pingConfig = this.#getPingConfig(transport);
684
+
685
+ if (pingConfig.enabled) {
686
+ this.#pingInterval = setInterval(async () => {
687
+ try {
688
+ await this.#server.ping();
689
+ } catch {
690
+ // The reason we are not emitting an error here is because some clients
691
+ // seem to not respond to the ping request, and we don't want to crash the server,
692
+ // e.g., https://github.com/punkpeye/fastmcp/issues/38.
693
+ const logLevel = pingConfig.logLevel;
694
+ if (logLevel === "debug") {
695
+ console.debug("[FastMCP debug] server ping failed");
696
+ } else if (logLevel === "warning") {
697
+ console.warn(
698
+ "[FastMCP warning] server is not responding to ping",
699
+ );
700
+ } else if (logLevel === "error") {
701
+ console.error("[FastMCP error] server is not responding to ping");
702
+ } else {
703
+ console.info("[FastMCP info] server ping failed");
704
+ }
705
+ }
706
+ }, pingConfig.intervalMs);
707
+ }
671
708
  }
672
709
  }
673
710
 
@@ -677,6 +714,30 @@ export class FastMCPSession<
677
714
  return this.#server.createMessage(message);
678
715
  }
679
716
 
717
+ #getPingConfig(transport: Transport): {
718
+ enabled: boolean;
719
+ intervalMs: number;
720
+ logLevel: LoggingLevel;
721
+ } {
722
+ const pingConfig = this.#pingConfig || {};
723
+
724
+ let defaultEnabled = false;
725
+
726
+ if ("type" in transport) {
727
+ // Enable by default for SSE and HTTP streaming
728
+ if (transport.type === "sse" || transport.type === "httpStream") {
729
+ defaultEnabled = true;
730
+ }
731
+ }
732
+
733
+ return {
734
+ enabled:
735
+ pingConfig.enabled !== undefined ? pingConfig.enabled : defaultEnabled,
736
+ intervalMs: pingConfig.intervalMs || 5000,
737
+ logLevel: pingConfig.logLevel || "debug",
738
+ };
739
+ }
740
+
680
741
  private addPrompt(inputPrompt: InputPrompt) {
681
742
  const completers: Record<string, ArgumentValueCompleter> = {};
682
743
  const enums: Record<string, string[]> = {};
@@ -1270,6 +1331,7 @@ export class FastMCP<
1270
1331
  const session = new FastMCPSession<T>({
1271
1332
  instructions: this.#options.instructions,
1272
1333
  name: this.#options.name,
1334
+ ping: this.#options.ping,
1273
1335
  prompts: this.#prompts,
1274
1336
  resources: this.#resources,
1275
1337
  resourcesTemplates: this.#resourcesTemplates,
@@ -1296,6 +1358,7 @@ export class FastMCP<
1296
1358
  return new FastMCPSession<T>({
1297
1359
  auth,
1298
1360
  name: this.#options.name,
1361
+ ping: this.#options.ping,
1299
1362
  prompts: this.#prompts,
1300
1363
  resources: this.#resources,
1301
1364
  resourcesTemplates: this.#resourcesTemplates,
@@ -1334,6 +1397,7 @@ export class FastMCP<
1334
1397
  return new FastMCPSession<T>({
1335
1398
  auth,
1336
1399
  name: this.#options.name,
1400
+ ping: this.#options.ping,
1337
1401
  prompts: this.#prompts,
1338
1402
  resources: this.#resources,
1339
1403
  resourcesTemplates: this.#resourcesTemplates,
@@ -1,10 +1,19 @@
1
1
  import { type } from "arktype";
2
2
  import * as v from "valibot";
3
3
  import { z } from "zod";
4
+
4
5
  import { FastMCP } from "../FastMCP.js";
5
6
 
6
7
  const server = new FastMCP({
7
8
  name: "Addition",
9
+ ping: {
10
+ // enabled: undefined,
11
+ // Automatically enabled/disabled based on transport type
12
+ // Using a longer interval to reduce log noise
13
+ intervalMs: 10000, // default is 5000ms
14
+ // Reduce log verbosity
15
+ logLevel: "debug", // default
16
+ },
8
17
  version: "1.0.0",
9
18
  });
10
19
 
@@ -156,9 +165,19 @@ if (transportType === "httpStream") {
156
165
 
157
166
  await client.connect(transport);
158
167
  `);
168
+ } else if (process.argv.includes("--explicit-ping-config")) {
169
+ server.start({
170
+ transportType: "stdio",
171
+ });
172
+
173
+ console.log(
174
+ "Started stdio transport with explicit ping configuration from server options",
175
+ );
159
176
  } else {
160
- // Default to stdio transport
177
+ // Disable by default for:
161
178
  server.start({
162
179
  transportType: "stdio",
163
180
  });
181
+
182
+ console.log("Started stdio transport with ping disabled by default");
164
183
  }