fastmcp 3.0.1 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/FastMCP.js CHANGED
@@ -314,21 +314,25 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
314
314
  try {
315
315
  await this.#server.connect(transport);
316
316
  let attempt = 0;
317
- while (attempt++ < 10) {
317
+ const maxAttempts = 10;
318
+ const retryDelay = 100;
319
+ while (attempt++ < maxAttempts) {
318
320
  const capabilities = this.#server.getClientCapabilities();
319
321
  if (capabilities) {
320
322
  this.#clientCapabilities = capabilities;
321
323
  break;
322
324
  }
323
- await delay(100);
325
+ await delay(retryDelay);
324
326
  }
325
327
  if (!this.#clientCapabilities) {
326
- console.warn("[FastMCP warning] could not infer client capabilities");
328
+ console.warn(
329
+ `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`
330
+ );
327
331
  }
328
332
  if (this.#clientCapabilities?.roots?.listChanged && typeof this.#server.listRoots === "function") {
329
333
  try {
330
334
  const roots = await this.#server.listRoots();
331
- this.#roots = roots.roots;
335
+ this.#roots = roots?.roots || [];
332
336
  } catch (e) {
333
337
  if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {
334
338
  console.debug(
@@ -426,12 +430,18 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
426
430
  addPrompt(inputPrompt) {
427
431
  const completers = {};
428
432
  const enums = {};
433
+ const fuseInstances = {};
429
434
  for (const argument of inputPrompt.arguments ?? []) {
430
435
  if (argument.complete) {
431
436
  completers[argument.name] = argument.complete;
432
437
  }
433
438
  if (argument.enum) {
434
439
  enums[argument.name] = argument.enum;
440
+ fuseInstances[argument.name] = new Fuse(argument.enum, {
441
+ includeScore: true,
442
+ threshold: 0.3
443
+ // More flexible matching!
444
+ });
435
445
  }
436
446
  }
437
447
  const prompt = {
@@ -440,11 +450,8 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
440
450
  if (completers[name]) {
441
451
  return await completers[name](value);
442
452
  }
443
- if (enums[name]) {
444
- const fuse = new Fuse(enums[name], {
445
- keys: ["value"]
446
- });
447
- const result = fuse.search(value);
453
+ if (fuseInstances[name]) {
454
+ const result = fuseInstances[name].search(value);
448
455
  return {
449
456
  total: result.length,
450
457
  values: result.map((item) => item.item)
@@ -783,7 +790,7 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
783
790
  }).join(", ");
784
791
  throw new McpError(
785
792
  ErrorCode.InvalidParams,
786
- `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}`
793
+ `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`
787
794
  );
788
795
  }
789
796
  args = parsed.value;
@@ -792,15 +799,22 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
792
799
  let result;
793
800
  try {
794
801
  const reportProgress = async (progress) => {
795
- await this.#server.notification({
796
- method: "notifications/progress",
797
- params: {
798
- ...progress,
799
- progressToken
802
+ try {
803
+ await this.#server.notification({
804
+ method: "notifications/progress",
805
+ params: {
806
+ ...progress,
807
+ progressToken
808
+ }
809
+ });
810
+ if (this.#needsEventLoopFlush) {
811
+ await new Promise((resolve) => setImmediate(resolve));
800
812
  }
801
- });
802
- if (this.#needsEventLoopFlush) {
803
- await new Promise((resolve) => setImmediate(resolve));
813
+ } catch (progressError) {
814
+ console.warn(
815
+ `[FastMCP warning] Failed to report progress for tool '${request.params.name}':`,
816
+ progressError instanceof Error ? progressError.message : String(progressError)
817
+ );
804
818
  }
805
819
  };
806
820
  const log = {
@@ -843,15 +857,22 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
843
857
  };
844
858
  const streamContent = async (content) => {
845
859
  const contentArray = Array.isArray(content) ? content : [content];
846
- await this.#server.notification({
847
- method: "notifications/tool/streamContent",
848
- params: {
849
- content: contentArray,
850
- toolName: request.params.name
860
+ try {
861
+ await this.#server.notification({
862
+ method: "notifications/tool/streamContent",
863
+ params: {
864
+ content: contentArray,
865
+ toolName: request.params.name
866
+ }
867
+ });
868
+ if (this.#needsEventLoopFlush) {
869
+ await new Promise((resolve) => setImmediate(resolve));
851
870
  }
852
- });
853
- if (this.#needsEventLoopFlush) {
854
- await new Promise((resolve) => setImmediate(resolve));
871
+ } catch (streamError) {
872
+ console.warn(
873
+ `[FastMCP warning] Failed to stream content for tool '${request.params.name}':`,
874
+ streamError instanceof Error ? streamError.message : String(streamError)
875
+ );
855
876
  }
856
877
  };
857
878
  const executeToolPromise = tool.execute(args, {
@@ -863,13 +884,14 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
863
884
  const maybeStringResult = await (tool.timeoutMs ? Promise.race([
864
885
  executeToolPromise,
865
886
  new Promise((_, reject) => {
866
- setTimeout(() => {
887
+ const timeoutId = setTimeout(() => {
867
888
  reject(
868
889
  new UserError(
869
890
  `Tool '${request.params.name}' timed out after ${tool.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`
870
891
  )
871
892
  );
872
893
  }, tool.timeoutMs);
894
+ executeToolPromise.finally(() => clearTimeout(timeoutId));
873
895
  })
874
896
  ]) : executeToolPromise);
875
897
  if (maybeStringResult === void 0 || maybeStringResult === null) {
@@ -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 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 { 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 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}): ${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 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\ntype Content = AudioContent | ImageContent | ResourceContent | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n AudioContentZodSchema,\n ResourceContentZodSchema,\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 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 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 required?: boolean;\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 /**\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 name: string;\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 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 description?: string;\n execute: (\n args: StandardSchemaV1.InferOutput<Params>,\n context: Context<T>,\n ) => Promise<\n | AudioContent\n | ContentResult\n | ImageContent\n | ResourceContent\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 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 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 #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #connectionState: \"closed\" | \"connecting\" | \"error\" | \"ready\" = \"connecting\";\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[] = [];\n\n #resources: Resource[] = [];\n\n #resourceTemplates: ResourceTemplate[] = [];\n\n #roots: Root[] = [];\n\n #rootsConfig?: ServerOptions<T>[\"roots\"];\n\n #server: Server;\n\n constructor({\n auth,\n instructions,\n name,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n roots,\n tools,\n transportType,\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 roots?: ServerOptions<T>[\"roots\"];\n tools: Tool<T>[];\n transportType?: \"httpStream\" | \"stdio\";\n version: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#pingConfig = ping;\n this.#rootsConfig = roots;\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.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 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 this.#connectionState = \"connecting\";\n\n try {\n await this.#server.connect(transport);\n\n let attempt = 0;\n\n while (attempt++ < 10) {\n const capabilities = 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 (\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 console.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\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\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 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(\n \"[FastMCP error] server is not responding to ping\",\n );\n } else {\n console.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 ): Promise<SamplingResponse> {\n return this.#server.createMessage(message);\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) {\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 `Prompt '${request.params.name}' requires argument '${arg.name}': ${arg.description || \"No description provided\"}`,\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 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 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 `Resource not found: '${request.params.uri}'. Available resources: ${resources.map((r) => r.uri).join(\", \") || \"none\"}`,\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 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 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 if (this.#rootsConfig?.enabled === false) {\n console.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 console.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n console.error(\"[FastMCP error] Error listing roots\", error);\n }\n });\n },\n );\n } else {\n console.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 = 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}`,\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 if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\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 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 };\n\n const executeToolPromise = tool.execute(args, {\n log,\n reportProgress,\n session: this.#auth,\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 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 ])\n : executeToolPromise)) as\n | AudioContent\n | ContentResult\n | ImageContent\n | null\n | ResourceContent\n | string\n | TextContent\n | undefined;\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 };\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\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\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 * 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 // Check if the URI starts with the template base\n const templateBase = template.uriTemplate.split(\"{\")[0];\n\n if (uri.startsWith(templateBase)) {\n const params: Record<string, string> = {};\n const templateParts = template.uriTemplate.split(\"/\");\n const uriParts = uri.split(\"/\");\n\n for (let i = 0; i < templateParts.length; i++) {\n const templatePart = templateParts[i];\n\n if (templatePart?.startsWith(\"{\") && templatePart.endsWith(\"}\")) {\n const paramName = templatePart.slice(1, -1);\n const paramValue = uriParts[i];\n\n if (paramValue) {\n params[paramName] = paramValue;\n }\n }\n }\n\n const result = await template.load(\n params as ResourceTemplateArgumentsToObject<\n typeof template.arguments\n >,\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\n throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options:\n | {\n httpStream: { port: number };\n transportType: \"httpStream\";\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 roots: this.#options.roots,\n tools: this.#tools,\n transportType: \"stdio\",\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 === \"httpStream\") {\n this.#httpStreamServer = await startHTTPServer<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 roots: this.#options.roots,\n tools: this.#tools,\n transportType: \"httpStream\",\n version: this.#options.version,\n });\n },\n onClose: async (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 onUnhandledRequest: async (req, res) => {\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://localhost\");\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 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 return;\n }\n } catch (error) {\n console.error(\"[FastMCP error] health endpoint error\", error);\n }\n }\n\n // If the request was not handled above, return 404\n res.writeHead(404).end();\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}/mcp`,\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\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 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 { 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 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}): ${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 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\ntype Content = AudioContent | ImageContent | ResourceContent | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n AudioContentZodSchema,\n ResourceContentZodSchema,\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 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 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 required?: boolean;\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 /**\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 name: string;\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 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 description?: string;\n execute: (\n args: StandardSchemaV1.InferOutput<Params>,\n context: Context<T>,\n ) => Promise<\n | AudioContent\n | ContentResult\n | ImageContent\n | ResourceContent\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 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 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 #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #connectionState: \"closed\" | \"connecting\" | \"error\" | \"ready\" = \"connecting\";\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[] = [];\n\n #resources: Resource[] = [];\n\n #resourceTemplates: ResourceTemplate[] = [];\n\n #roots: Root[] = [];\n\n #rootsConfig?: ServerOptions<T>[\"roots\"];\n\n #server: Server;\n\n constructor({\n auth,\n instructions,\n name,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n roots,\n tools,\n transportType,\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 roots?: ServerOptions<T>[\"roots\"];\n tools: Tool<T>[];\n transportType?: \"httpStream\" | \"stdio\";\n version: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#pingConfig = ping;\n this.#rootsConfig = roots;\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.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 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 this.#connectionState = \"connecting\";\n\n try {\n await this.#server.connect(transport);\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 console.warn(\n `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`,\n );\n }\n\n if (\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 console.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\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\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 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(\n \"[FastMCP error] server is not responding to ping\",\n );\n } else {\n console.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 ): Promise<SamplingResponse> {\n return this.#server.createMessage(message);\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) {\n const completers: Record<string, ArgumentValueCompleter> = {};\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) => {\n if (completers[name]) {\n return await completers[name](value);\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) {\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 `Prompt '${request.params.name}' requires argument '${arg.name}': ${arg.description || \"No description provided\"}`,\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 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 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 `Resource not found: '${request.params.uri}'. Available resources: ${resources.map((r) => r.uri).join(\", \") || \"none\"}`,\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 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 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 if (this.#rootsConfig?.enabled === false) {\n console.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 console.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n console.error(\"[FastMCP error] Error listing roots\", error);\n }\n });\n },\n );\n } else {\n console.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 = 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 console.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 console.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 log,\n reportProgress,\n session: this.#auth,\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 | string\n | TextContent\n | undefined;\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 };\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\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\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 * 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 // Check if the URI starts with the template base\n const templateBase = template.uriTemplate.split(\"{\")[0];\n\n if (uri.startsWith(templateBase)) {\n const params: Record<string, string> = {};\n const templateParts = template.uriTemplate.split(\"/\");\n const uriParts = uri.split(\"/\");\n\n for (let i = 0; i < templateParts.length; i++) {\n const templatePart = templateParts[i];\n\n if (templatePart?.startsWith(\"{\") && templatePart.endsWith(\"}\")) {\n const paramName = templatePart.slice(1, -1);\n const paramValue = uriParts[i];\n\n if (paramValue) {\n params[paramName] = paramValue;\n }\n }\n }\n\n const result = await template.load(\n params as ResourceTemplateArgumentsToObject<\n typeof template.arguments\n >,\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\n throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options:\n | {\n httpStream: { port: number };\n transportType: \"httpStream\";\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 roots: this.#options.roots,\n tools: this.#tools,\n transportType: \"stdio\",\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 === \"httpStream\") {\n this.#httpStreamServer = await startHTTPServer<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 roots: this.#options.roots,\n tools: this.#tools,\n transportType: \"httpStream\",\n version: this.#options.version,\n });\n },\n onClose: async (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 onUnhandledRequest: async (req, res) => {\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://localhost\");\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 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 return;\n }\n } catch (error) {\n console.error(\"[FastMCP error] health endpoint error\", error);\n }\n }\n\n // If the request was not handled above, return 404\n res.writeHead(404).end();\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}/mcp`,\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\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":";AAAA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AAErC;AAAA,EACE;AAAA,EAEA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EAEA;AAAA,OACK;AAEP,SAAS,oBAAoB;AAC7B,SAAS,0BAA0B;AACnC,SAAS,gBAAgB;AACzB,OAAO,UAAU;AAEjB,SAAS,uBAAuB;AAEhC,SAAS,cAAc,aAAa;AACpC,SAAS,aAAa;AACtB,OAAO,sBAAsB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAiBX,IAAM,eAAe,OAC1B,UAC0B;AAC1B,MAAI;AAEJ,MAAI;AACF,QAAI,SAAS,OAAO;AAClB,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,MAAM,GAAG;AAEtC,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI;AAAA,YACR,iCAAiC,SAAS,MAAM,MAAM,SAAS,UAAU;AAAA,UAC3E;AAAA,QACF;AAEA,kBAAU,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAAA,MACpD,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,mCAAmC,MAAM,GAAG,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC1G;AAAA,MACF;AAAA,IACF,WAAW,UAAU,OAAO;AAC1B,UAAI;AACF,kBAAU,MAAM,SAAS,MAAM,IAAI;AAAA,MACrC,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,mCAAmC,MAAM,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC3G;AAAA,MACF;AAAA,IACF,WAAW,YAAY,OAAO;AAC5B,gBAAU,MAAM;AAAA,IAClB,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,mBAAmB,OAAO;AAEjD,QAAI,CAAC,YAAY,CAAC,SAAS,KAAK,WAAW,QAAQ,GAAG;AACpD,cAAQ;AAAA,QACN,6DAA6D,UAAU,QAAQ,SAAS;AAAA,MAC1F;AAAA,IACF;AAEA,UAAM,aAAa,QAAQ,SAAS,QAAQ;AAE5C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,UAAU,QAAQ;AAAA,MAC5B,MAAM;AAAA,IACR;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,YAAM;AAAA,IACR,OAAO;AACL,YAAM,IAAI,MAAM,sCAAsC,OAAO,KAAK,CAAC,EAAE;AAAA,IACvE;AAAA,EACF;AACF;AAEO,IAAM,eAAe,OAC1B,UAC0B;AAC1B,MAAI;AAEJ,MAAI;AACF,QAAI,SAAS,OAAO;AAClB,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,MAAM,GAAG;AAEtC,YAAI,CAAC,SAAS,IAAI;AAChB,gBAAM,IAAI;AAAA,YACR,iCAAiC,SAAS,MAAM,MAAM,SAAS,UAAU;AAAA,UAC3E;AAAA,QACF;AAEA,kBAAU,OAAO,KAAK,MAAM,SAAS,YAAY,CAAC;AAAA,MACpD,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,mCAAmC,MAAM,GAAG,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC1G;AAAA,MACF;AAAA,IACF,WAAW,UAAU,OAAO;AAC1B,UAAI;AACF,kBAAU,MAAM,SAAS,MAAM,IAAI;AAAA,MACrC,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,mCAAmC,MAAM,IAAI,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAC3G;AAAA,MACF;AAAA,IACF,WAAW,YAAY,OAAO;AAC5B,gBAAU,MAAM;AAAA,IAClB,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,mBAAmB,OAAO;AAEjD,QAAI,CAAC,YAAY,CAAC,SAAS,KAAK,WAAW,QAAQ,GAAG;AACpD,cAAQ;AAAA,QACN,kEAAkE,UAAU,QAAQ,SAAS;AAAA,MAC/F;AAAA,IACF;AAEA,UAAM,aAAa,QAAQ,SAAS,QAAQ;AAE5C,WAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU,UAAU,QAAQ;AAAA,MAC5B,MAAM;AAAA,IACR;AAAA,EACF,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,YAAM;AAAA,IACR,OAAO;AACL,YAAM,IAAI,MAAM,sCAAsC,OAAO,KAAK,CAAC,EAAE;AAAA,IACvE;AAAA,EACF;AACF;AA2CA,IAAe,eAAf,cAAoC,MAAM;AAAA,EACjC,YAAY,SAAkB;AACnC,UAAM,OAAO;AACb,SAAK,OAAO,WAAW;AAAA,EACzB;AACF;AAEO,IAAM,uBAAN,cAAmC,aAAa;AAAA,EAC9C;AAAA,EAEA,YAAY,SAAiB,QAAiB;AACnD,UAAM,OAAO;AACb,SAAK,OAAO,WAAW;AACvB,SAAK,SAAS;AAAA,EAChB;AACF;AAKO,IAAM,YAAN,cAAwB,qBAAqB;AAAC;AAErD,IAAM,uBAAuB,EAC1B,OAAO;AAAA;AAAA;AAAA;AAAA,EAIN,MAAM,EAAE,OAAO;AAAA,EACf,MAAM,EAAE,QAAQ,MAAM;AACxB,CAAC,EACA,OAAO;AAQV,IAAM,wBAAwB,EAC3B,OAAO;AAAA;AAAA;AAAA;AAAA,EAIN,MAAM,EAAE,OAAO,EAAE,OAAO;AAAA;AAAA;AAAA;AAAA,EAIxB,UAAU,EAAE,OAAO;AAAA,EACnB,MAAM,EAAE,QAAQ,OAAO;AACzB,CAAC,EACA,OAAO;AAQV,IAAM,wBAAwB,EAC3B,OAAO;AAAA;AAAA;AAAA;AAAA,EAIN,MAAM,EAAE,OAAO,EAAE,OAAO;AAAA,EACxB,UAAU,EAAE,OAAO;AAAA,EACnB,MAAM,EAAE,QAAQ,OAAO;AACzB,CAAC,EACA,OAAO;AAYV,IAAM,2BAA2B,EAC9B,OAAO;AAAA,EACN,UAAU,EAAE,OAAO;AAAA,IACjB,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,UAAU,EAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,MAAM,EAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,KAAK,EAAE,OAAO;AAAA,EAChB,CAAC;AAAA,EACD,MAAM,EAAE,QAAQ,UAAU;AAC5B,CAAC,EACA,OAAO;AAIV,IAAM,mBAAmB,EAAE,mBAAmB,QAAQ;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAOD,IAAM,yBAAyB,EAC5B,OAAO;AAAA,EACN,SAAS,iBAAiB,MAAM;AAAA,EAChC,SAAS,EAAE,QAAQ,EAAE,SAAS;AAChC,CAAC,EACA,OAAO;AAWV,IAAM,sBAAsB,EAAE,OAAO;AAAA;AAAA;AAAA;AAAA,EAInC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,EAI/B,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,EAIlC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG;AACrC,CAAC;AAqQD,IAAM,iCAEF;AAWJ,IAAM,6BAAN,cAAyC,+BAA+B;AAAC;AAElE,IAAM,iBAAN,cAEG,2BAA2B;AAAA,EACnC,IAAW,qBAAgD;AACzD,WAAO,KAAK,uBAAuB;AAAA,EACrC;AAAA,EACA,IAAW,UAAmB;AAC5B,WAAO,KAAK,qBAAqB;AAAA,EACnC;AAAA,EACA,IAAW,eAA6B;AACtC,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAW,QAAgB;AACzB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAW,SAAiB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EACA;AAAA,EACA,gBAAoC,CAAC;AAAA,EACrC;AAAA,EACA,mBAAgE;AAAA,EAChE,gBAA8B;AAAA,EAC9B,uBAAgC;AAAA,EAChC;AAAA,EAEA,gBAAuD;AAAA,EAEvD,WAAqB,CAAC;AAAA,EAEtB,aAAyB,CAAC;AAAA,EAE1B,qBAAyC,CAAC;AAAA,EAE1C,SAAiB,CAAC;AAAA,EAElB;AAAA,EAEA;AAAA,EAEA,YAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAYG;AACD,UAAM;AAEN,SAAK,QAAQ;AACb,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,uBAAuB,kBAAkB;AAE9C,QAAI,MAAM,QAAQ;AAChB,WAAK,cAAc,QAAQ,CAAC;AAAA,IAC9B;AAEA,QAAI,UAAU,UAAU,mBAAmB,QAAQ;AACjD,WAAK,cAAc,YAAY,CAAC;AAAA,IAClC;AAEA,QAAI,QAAQ,QAAQ;AAClB,iBAAW,UAAU,SAAS;AAC5B,aAAK,UAAU,MAAM;AAAA,MACvB;AAEA,WAAK,cAAc,UAAU,CAAC;AAAA,IAChC;AAEA,SAAK,cAAc,UAAU,CAAC;AAE9B,SAAK,UAAU,IAAI;AAAA,MACjB,EAAE,MAAY,QAAiB;AAAA,MAC/B,EAAE,cAAc,KAAK,eAAe,aAA2B;AAAA,IACjE;AAEA,SAAK,mBAAmB;AACxB,SAAK,qBAAqB;AAC1B,SAAK,mBAAmB;AACxB,SAAK,sBAAsB;AAE3B,QAAI,MAAM,QAAQ;AAChB,WAAK,kBAAkB,KAAK;AAAA,IAC9B;AAEA,QAAI,UAAU,UAAU,mBAAmB,QAAQ;AACjD,iBAAW,YAAY,WAAW;AAChC,aAAK,YAAY,QAAQ;AAAA,MAC3B;AAEA,WAAK,sBAAsB,SAAS;AAEpC,UAAI,mBAAmB,QAAQ;AAC7B,mBAAW,oBAAoB,oBAAoB;AACjD,eAAK,oBAAoB,gBAAgB;AAAA,QAC3C;AAEA,aAAK,8BAA8B,kBAAkB;AAAA,MACvD;AAAA,IACF;AAEA,QAAI,QAAQ,QAAQ;AAClB,WAAK,oBAAoB,OAAO;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAa,QAAQ;AACnB,SAAK,mBAAmB;AAExB,QAAI,KAAK,eAAe;AACtB,oBAAc,KAAK,aAAa;AAAA,IAClC;AAEA,QAAI;AACF,YAAM,KAAK,QAAQ,MAAM;AAAA,IAC3B,SAAS,OAAO;AACd,cAAQ,MAAM,mBAAmB,0BAA0B,KAAK;AAAA,IAClE;AAAA,EACF;AAAA,EAEA,MAAa,QAAQ,WAAsB;AACzC,QAAI,KAAK,QAAQ,WAAW;AAC1B,YAAM,IAAI,qBAAqB,6BAA6B;AAAA,IAC9D;AAEA,SAAK,mBAAmB;AAExB,QAAI;AACF,YAAM,KAAK,QAAQ,QAAQ,SAAS;AAEpC,UAAI,UAAU;AACd,YAAM,cAAc;AACpB,YAAM,aAAa;AAEnB,aAAO,YAAY,aAAa;AAC9B,cAAM,eAAe,KAAK,QAAQ,sBAAsB;AAExD,YAAI,cAAc;AAChB,eAAK,sBAAsB;AAC3B;AAAA,QACF;AAEA,cAAM,MAAM,UAAU;AAAA,MACxB;AAEA,UAAI,CAAC,KAAK,qBAAqB;AAC7B,gBAAQ;AAAA,UACN,+DAA+D,WAAW;AAAA,QAC5E;AAAA,MACF;AAEA,UACE,KAAK,qBAAqB,OAAO,eACjC,OAAO,KAAK,QAAQ,cAAc,YAClC;AACA,YAAI;AACF,gBAAM,QAAQ,MAAM,KAAK,QAAQ,UAAU;AAC3C,eAAK,SAAS,OAAO,SAAS,CAAC;AAAA,QACjC,SAAS,GAAG;AACV,cAAI,aAAa,YAAY,EAAE,SAAS,UAAU,gBAAgB;AAChE,oBAAQ;AAAA,cACN;AAAA,YACF;AAAA,UACF,OAAO;AACL,oBAAQ;AAAA,cACN;AAAA;AAAA,EAAoD,aAAa,QAAQ,EAAE,QAAQ,KAAK,UAAU,CAAC,CAAC;AAAA,YACtG;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,UAAI,KAAK,qBAAqB;AAC5B,cAAM,aAAa,KAAK,eAAe,SAAS;AAEhD,YAAI,WAAW,SAAS;AACtB,eAAK,gBAAgB,YAAY,YAAY;AAC3C,gBAAI;AACF,oBAAM,KAAK,QAAQ,KAAK;AAAA,YAC1B,QAAQ;AAIN,oBAAM,WAAW,WAAW;AAE5B,kBAAI,aAAa,SAAS;AACxB,wBAAQ,MAAM,oCAAoC;AAAA,cACpD,WAAW,aAAa,WAAW;AACjC,wBAAQ;AAAA,kBACN;AAAA,gBACF;AAAA,cACF,WAAW,aAAa,SAAS;AAC/B,wBAAQ;AAAA,kBACN;AAAA,gBACF;AAAA,cACF,OAAO;AACL,wBAAQ,KAAK,mCAAmC;AAAA,cAClD;AAAA,YACF;AAAA,UACF,GAAG,WAAW,UAAU;AAAA,QAC1B;AAAA,MACF;AAGA,WAAK,mBAAmB;AACxB,WAAK,KAAK,OAAO;AAAA,IACnB,SAAS,OAAO;AACd,WAAK,mBAAmB;AACxB,YAAM,aAAa;AAAA,QACjB,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MACjE;AACA,WAAK,KAAK,SAAS,UAAU;AAC7B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAa,gBACX,SAC2B;AAC3B,WAAO,KAAK,QAAQ,cAAc,OAAO;AAAA,EAC3C;AAAA,EAEO,eAA8B;AACnC,QAAI,KAAK,SAAS;AAChB,aAAO,QAAQ,QAAQ;AAAA,IACzB;AAEA,QACE,KAAK,qBAAqB,WAC1B,KAAK,qBAAqB,UAC1B;AACA,aAAO,QAAQ;AAAA,QACb,IAAI,MAAM,oBAAoB,KAAK,gBAAgB,QAAQ;AAAA,MAC7D;AAAA,IACF;AAEA,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,UAAU,WAAW,MAAM;AAC/B;AAAA,UACE,IAAI;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,GAAG,GAAI;AAEP,WAAK,KAAK,SAAS,MAAM;AACvB,qBAAa,OAAO;AACpB,gBAAQ;AAAA,MACV,CAAC;AAED,WAAK,KAAK,SAAS,CAAC,UAAU;AAC5B,qBAAa,OAAO;AACpB,eAAO,MAAM,KAAK;AAAA,MACpB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEA,eAAe,WAIb;AACA,UAAM,aAAa,KAAK,eAAe,CAAC;AAExC,QAAI,iBAAiB;AAErB,QAAI,UAAU,WAAW;AAEvB,UAAI,UAAU,SAAS,cAAc;AACnC,yBAAiB;AAAA,MACnB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,SACE,WAAW,YAAY,SAAY,WAAW,UAAU;AAAA,MAC1D,YAAY,WAAW,cAAc;AAAA,MACrC,UAAU,WAAW,YAAY;AAAA,IACnC;AAAA,EACF;AAAA,EAEQ,UAAU,aAA0B;AAC1C,UAAM,aAAqD,CAAC;AAC5D,UAAM,QAAkC,CAAC;AACzC,UAAM,gBAA8C,CAAC;AAErD,eAAW,YAAY,YAAY,aAAa,CAAC,GAAG;AAClD,UAAI,SAAS,UAAU;AACrB,mBAAW,SAAS,IAAI,IAAI,SAAS;AAAA,MACvC;AAEA,UAAI,SAAS,MAAM;AACjB,cAAM,SAAS,IAAI,IAAI,SAAS;AAChC,sBAAc,SAAS,IAAI,IAAI,IAAI,KAAK,SAAS,MAAM;AAAA,UACrD,cAAc;AAAA,UACd,WAAW;AAAA;AAAA,QACb,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb,GAAG;AAAA,MACH,UAAU,OAAO,MAAc,UAAkB;AAC/C,YAAI,WAAW,IAAI,GAAG;AACpB,iBAAO,MAAM,WAAW,IAAI,EAAE,KAAK;AAAA,QACrC;AAEA,YAAI,cAAc,IAAI,GAAG;AACvB,gBAAM,SAAS,cAAc,IAAI,EAAE,OAAO,KAAK;AAE/C,iBAAO;AAAA,YACL,OAAO,OAAO;AAAA,YACd,QAAQ,OAAO,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,UACxC;AAAA,QACF;AAEA,eAAO;AAAA,UACL,QAAQ,CAAC;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,SAAK,SAAS,KAAK,MAAM;AAAA,EAC3B;AAAA,EAEQ,YAAY,eAAyB;AAC3C,SAAK,WAAW,KAAK,aAAa;AAAA,EACpC;AAAA,EAEQ,oBAAoB,uBAA8C;AACxE,UAAM,aAAqD,CAAC;AAE5D,eAAW,YAAY,sBAAsB,aAAa,CAAC,GAAG;AAC5D,UAAI,SAAS,UAAU;AACrB,mBAAW,SAAS,IAAI,IAAI,SAAS;AAAA,MACvC;AAAA,IACF;AAEA,UAAM,mBAAmB;AAAA,MACvB,GAAG;AAAA,MACH,UAAU,OAAO,MAAc,UAAkB;AAC/C,YAAI,WAAW,IAAI,GAAG;AACpB,iBAAO,MAAM,WAAW,IAAI,EAAE,KAAK;AAAA,QACrC;AAEA,eAAO;AAAA,UACL,QAAQ,CAAC;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAEA,SAAK,mBAAmB,KAAK,gBAAgB;AAAA,EAC/C;AAAA,EAEQ,wBAAwB;AAC9B,SAAK,QAAQ,kBAAkB,uBAAuB,OAAO,YAAY;AACvE,UAAI,QAAQ,OAAO,IAAI,SAAS,cAAc;AAC5C,cAAM,SAAS,KAAK,SAAS;AAAA,UAC3B,CAACA,YAAWA,QAAO,SAAS,QAAQ,OAAO,IAAI;AAAA,QACjD;AAEA,YAAI,CAAC,QAAQ;AACX,gBAAM,IAAI,qBAAqB,kBAAkB;AAAA,YAC/C;AAAA,UACF,CAAC;AAAA,QACH;AAEA,YAAI,CAAC,OAAO,UAAU;AACpB,gBAAM,IAAI,qBAAqB,sCAAsC;AAAA,YACnE;AAAA,UACF,CAAC;AAAA,QACH;AAEA,cAAM,aAAa,oBAAoB;AAAA,UACrC,MAAM,OAAO;AAAA,YACX,QAAQ,OAAO,SAAS;AAAA,YACxB,QAAQ,OAAO,SAAS;AAAA,UAC1B;AAAA,QACF;AAEA,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAEA,UAAI,QAAQ,OAAO,IAAI,SAAS,gBAAgB;AAC9C,cAAM,WAAW,KAAK,mBAAmB;AAAA,UACvC,CAACC,cAAaA,UAAS,gBAAgB,QAAQ,OAAO,IAAI;AAAA,QAC5D;AAEA,YAAI,CAAC,UAAU;AACb,gBAAM,IAAI,qBAAqB,oBAAoB;AAAA,YACjD;AAAA,UACF,CAAC;AAAA,QACH;AAEA,YAAI,EAAE,iBAAiB,WAAW;AAChC,gBAAM,IAAI,qBAAqB,qBAAqB;AAAA,QACtD;AAEA,YAAI,CAAC,SAAS,UAAU;AACtB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,cACE;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,aAAa,oBAAoB;AAAA,UACrC,MAAM,SAAS;AAAA,YACb,QAAQ,OAAO,SAAS;AAAA,YACxB,QAAQ,OAAO,SAAS;AAAA,UAC1B;AAAA,QACF;AAEA,eAAO;AAAA,UACL;AAAA,QACF;AAAA,MACF;AAEA,YAAM,IAAI,qBAAqB,iCAAiC;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,qBAAqB;AAC3B,SAAK,QAAQ,UAAU,CAAC,UAAU;AAChC,cAAQ,MAAM,mBAAmB,KAAK;AAAA,IACxC;AAAA,EACF;AAAA,EAEQ,uBAAuB;AAC7B,SAAK,QAAQ,kBAAkB,uBAAuB,CAAC,YAAY;AACjE,WAAK,gBAAgB,QAAQ,OAAO;AAEpC,aAAO,CAAC;AAAA,IACV,CAAC;AAAA,EACH;AAAA,EAEQ,oBAAoB,SAAmB;AAC7C,SAAK,QAAQ,kBAAkB,0BAA0B,YAAY;AACnE,aAAO;AAAA,QACL,SAAS,QAAQ,IAAI,CAAC,WAAW;AAC/B,iBAAO;AAAA,YACL,WAAW,OAAO;AAAA,YAClB,UAAU,OAAO;AAAA,YACjB,aAAa,OAAO;AAAA,YACpB,MAAM,OAAO;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,SAAK,QAAQ,kBAAkB,wBAAwB,OAAO,YAAY;AACxE,YAAM,SAAS,QAAQ;AAAA,QACrB,CAACD,YAAWA,QAAO,SAAS,QAAQ,OAAO;AAAA,MAC7C;AAEA,UAAI,CAAC,QAAQ;AACX,cAAM,IAAI;AAAA,UACR,UAAU;AAAA,UACV,mBAAmB,QAAQ,OAAO,IAAI;AAAA,QACxC;AAAA,MACF;AAEA,YAAM,OAAO,QAAQ,OAAO;AAE5B,iBAAW,OAAO,OAAO,aAAa,CAAC,GAAG;AACxC,YAAI,IAAI,YAAY,EAAE,QAAQ,IAAI,QAAQ,OAAO;AAC/C,gBAAM,IAAI;AAAA,YACR,UAAU;AAAA,YACV,WAAW,QAAQ,OAAO,IAAI,wBAAwB,IAAI,IAAI,MAAM,IAAI,eAAe,yBAAyB;AAAA,UAClH;AAAA,QACF;AAAA,MACF;AAEA,UAAI;AAEJ,UAAI;AACF,iBAAS,MAAM,OAAO,KAAK,IAA0C;AAAA,MACvE,SAAS,OAAO;AACd,cAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,cAAM,IAAI;AAAA,UACR,UAAU;AAAA,UACV,0BAA0B,QAAQ,OAAO,IAAI,MAAM,YAAY;AAAA,QACjE;AAAA,MACF;AAEA,aAAO;AAAA,QACL,aAAa,OAAO;AAAA,QACpB,UAAU;AAAA,UACR;AAAA,YACE,SAAS,EAAE,MAAM,QAAQ,MAAM,OAAO;AAAA,YACtC,MAAM;AAAA,UACR;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,sBAAsB,WAAuB;AACnD,SAAK,QAAQ,kBAAkB,4BAA4B,YAAY;AACrE,aAAO;AAAA,QACL,WAAW,UAAU,IAAI,CAAC,aAAa;AACrC,iBAAO;AAAA,YACL,UAAU,SAAS;AAAA,YACnB,MAAM,SAAS;AAAA,YACf,KAAK,SAAS;AAAA,UAChB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,SAAK,QAAQ;AAAA,MACX;AAAA,MACA,OAAO,YAAY;AACjB,YAAI,SAAS,QAAQ,QAAQ;AAC3B,gBAAM,WAAW,UAAU;AAAA,YACzB,CAACC,cACC,SAASA,aAAYA,UAAS,QAAQ,QAAQ,OAAO;AAAA,UACzD;AAEA,cAAI,CAAC,UAAU;AACb,uBAAW,oBAAoB,KAAK,oBAAoB;AACtD,oBAAM,cAAc;AAAA,gBAClB,iBAAiB;AAAA,cACnB;AAEA,oBAAM,QAAQ,YAAY,QAAQ,QAAQ,OAAO,GAAG;AAEpD,kBAAI,CAAC,OAAO;AACV;AAAA,cACF;AAEA,oBAAM,MAAM,YAAY,KAAK,KAAK;AAElC,oBAAM,SAAS,MAAM,iBAAiB,KAAK,KAAK;AAEhD,qBAAO;AAAA,gBACL,UAAU;AAAA,kBACR;AAAA,oBACE,UAAU,iBAAiB;AAAA,oBAC3B,MAAM,iBAAiB;AAAA,oBACvB;AAAA,oBACA,GAAG;AAAA,kBACL;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAEA,kBAAM,IAAI;AAAA,cACR,UAAU;AAAA,cACV,wBAAwB,QAAQ,OAAO,GAAG,2BAA2B,UAAU,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,KAAK,MAAM;AAAA,YACvH;AAAA,UACF;AAEA,cAAI,EAAE,SAAS,WAAW;AACxB,kBAAM,IAAI,qBAAqB,mCAAmC;AAAA,UACpE;AAEA,cAAI;AAEJ,cAAI;AACF,+BAAmB,MAAM,SAAS,KAAK;AAAA,UACzC,SAAS,OAAO;AACd,kBAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,kBAAM,IAAI;AAAA,cACR,UAAU;AAAA,cACV,4BAA4B,SAAS,IAAI,MAAM,SAAS,GAAG,MAAM,YAAY;AAAA,cAC7E;AAAA,gBACE,KAAK,SAAS;AAAA,cAChB;AAAA,YACF;AAAA,UACF;AAEA,cAAI,MAAM,QAAQ,gBAAgB,GAAG;AACnC,mBAAO;AAAA,cACL,UAAU,iBAAiB,IAAI,CAAC,YAAY;AAAA,gBAC1C,UAAU,SAAS;AAAA,gBACnB,MAAM,SAAS;AAAA,gBACf,KAAK,SAAS;AAAA,gBACd,GAAG;AAAA,cACL,EAAE;AAAA,YACJ;AAAA,UACF,OAAO;AACL,mBAAO;AAAA,cACL,UAAU;AAAA,gBACR;AAAA,kBACE,UAAU,SAAS;AAAA,kBACnB,MAAM,SAAS;AAAA,kBACf,KAAK,SAAS;AAAA,kBACd,GAAG;AAAA,gBACL;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,cAAM,IAAI,qBAAqB,4BAA4B;AAAA,UACzD;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,8BAA8B,mBAAuC;AAC3E,SAAK,QAAQ;AAAA,MACX;AAAA,MACA,YAAY;AACV,eAAO;AAAA,UACL,mBAAmB,kBAAkB,IAAI,CAAC,qBAAqB;AAC7D,mBAAO;AAAA,cACL,MAAM,iBAAiB;AAAA,cACvB,aAAa,iBAAiB;AAAA,YAChC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,qBAAqB;AAC3B,QAAI,KAAK,cAAc,YAAY,OAAO;AACxC,cAAQ;AAAA,QACN;AAAA,MACF;AACA;AAAA,IACF;AAGA,QAAI,OAAO,KAAK,QAAQ,cAAc,YAAY;AAChD,WAAK,QAAQ;AAAA,QACX;AAAA,QACA,MAAM;AACJ,eAAK,QACF,UAAU,EACV,KAAK,CAAC,UAAU;AACf,iBAAK,SAAS,MAAM;AAEpB,iBAAK,KAAK,gBAAgB;AAAA,cACxB,OAAO,MAAM;AAAA,YACf,CAAC;AAAA,UACH,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,gBACE,iBAAiB,YACjB,MAAM,SAAS,UAAU,gBACzB;AACA,sBAAQ;AAAA,gBACN;AAAA,cACF;AAAA,YACF,OAAO;AACL,sBAAQ,MAAM,uCAAuC,KAAK;AAAA,YAC5D;AAAA,UACF,CAAC;AAAA,QACL;AAAA,MACF;AAAA,IACF,OAAO;AACL,cAAQ;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAAkB;AAC1C,SAAK,QAAQ,kBAAkB,wBAAwB,YAAY;AACjE,aAAO;AAAA,QACL,OAAO,MAAM,QAAQ;AAAA,UACnB,MAAM,IAAI,OAAO,SAAS;AACxB,mBAAO;AAAA,cACL,aAAa,KAAK;AAAA,cAClB,aAAa,KAAK;AAAA,cAClB,aAAa,KAAK,aACd,MAAM,aAAa,KAAK,UAAU,IAClC;AAAA,gBACE,sBAAsB;AAAA,gBACtB,YAAY,CAAC;AAAA,gBACb,MAAM;AAAA,cACR;AAAA;AAAA,cACJ,MAAM,KAAK;AAAA,YACb;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,QAAQ,kBAAkB,uBAAuB,OAAO,YAAY;AACvE,YAAM,OAAO,MAAM,KAAK,CAACC,UAASA,MAAK,SAAS,QAAQ,OAAO,IAAI;AAEnE,UAAI,CAAC,MAAM;AACT,cAAM,IAAI;AAAA,UACR,UAAU;AAAA,UACV,iBAAiB,QAAQ,OAAO,IAAI;AAAA,QACtC;AAAA,MACF;AAEA,UAAI,OAAgB;AAEpB,UAAI,KAAK,YAAY;AACnB,cAAM,SAAS,MAAM,KAAK,WAAW,WAAW,EAAE;AAAA,UAChD,QAAQ,OAAO;AAAA,QACjB;AAEA,YAAI,OAAO,QAAQ;AACjB,gBAAM,iBAAiB,OAAO,OAC3B,IAAI,CAAC,UAAU;AACd,kBAAM,OAAO,MAAM,MAAM,KAAK,GAAG,KAAK;AACtC,mBAAO,GAAG,IAAI,KAAK,MAAM,OAAO;AAAA,UAClC,CAAC,EACA,KAAK,IAAI;AAEZ,gBAAM,IAAI;AAAA,YACR,UAAU;AAAA,YACV,SAAS,QAAQ,OAAO,IAAI,kCAAkC,cAAc;AAAA,UAC9E;AAAA,QACF;AAEA,eAAO,OAAO;AAAA,MAChB;AAEA,YAAM,gBAAgB,QAAQ,QAAQ,OAAO;AAE7C,UAAI;AAEJ,UAAI;AACF,cAAM,iBAAiB,OAAO,aAAuB;AACnD,cAAI;AACF,kBAAM,KAAK,QAAQ,aAAa;AAAA,cAC9B,QAAQ;AAAA,cACR,QAAQ;AAAA,gBACN,GAAG;AAAA,gBACH;AAAA,cACF;AAAA,YACF,CAAC;AAED,gBAAI,KAAK,sBAAsB;AAC7B,oBAAM,IAAI,QAAQ,CAAC,YAAY,aAAa,OAAO,CAAC;AAAA,YACtD;AAAA,UACF,SAAS,eAAe;AACtB,oBAAQ;AAAA,cACN,yDAAyD,QAAQ,OAAO,IAAI;AAAA,cAC5E,yBAAyB,QACrB,cAAc,UACd,OAAO,aAAa;AAAA,YAC1B;AAAA,UACF;AAAA,QACF;AAEA,cAAM,MAAM;AAAA,UACV,OAAO,CAAC,SAAiB,YAAgC;AACvD,iBAAK,QAAQ,mBAAmB;AAAA,cAC9B,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,cACF;AAAA,cACA,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,UACA,OAAO,CAAC,SAAiB,YAAgC;AACvD,iBAAK,QAAQ,mBAAmB;AAAA,cAC9B,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,cACF;AAAA,cACA,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,UACA,MAAM,CAAC,SAAiB,YAAgC;AACtD,iBAAK,QAAQ,mBAAmB;AAAA,cAC9B,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,cACF;AAAA,cACA,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,UACA,MAAM,CAAC,SAAiB,YAAgC;AACtD,iBAAK,QAAQ,mBAAmB;AAAA,cAC9B,MAAM;AAAA,gBACJ;AAAA,gBACA;AAAA,cACF;AAAA,cACA,OAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,QACF;AAKA,cAAM,gBAAgB,OAAO,YAAiC;AAC5D,gBAAM,eAAe,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AAEhE,cAAI;AACF,kBAAM,KAAK,QAAQ,aAAa;AAAA,cAC9B,QAAQ;AAAA,cACR,QAAQ;AAAA,gBACN,SAAS;AAAA,gBACT,UAAU,QAAQ,OAAO;AAAA,cAC3B;AAAA,YACF,CAAC;AAED,gBAAI,KAAK,sBAAsB;AAC7B,oBAAM,IAAI,QAAQ,CAAC,YAAY,aAAa,OAAO,CAAC;AAAA,YACtD;AAAA,UACF,SAAS,aAAa;AACpB,oBAAQ;AAAA,cACN,wDAAwD,QAAQ,OAAO,IAAI;AAAA,cAC3E,uBAAuB,QACnB,YAAY,UACZ,OAAO,WAAW;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAEA,cAAM,qBAAqB,KAAK,QAAQ,MAAM;AAAA,UAC5C;AAAA,UACA;AAAA,UACA,SAAS,KAAK;AAAA,UACd;AAAA,QACF,CAAC;AAGD,cAAM,oBAAqB,OAAO,KAAK,YACnC,QAAQ,KAAK;AAAA,UACX;AAAA,UACA,IAAI,QAAe,CAAC,GAAG,WAAW;AAChC,kBAAM,YAAY,WAAW,MAAM;AACjC;AAAA,gBACE,IAAI;AAAA,kBACF,SAAS,QAAQ,OAAO,IAAI,qBAAqB,KAAK,SAAS;AAAA,gBACjE;AAAA,cACF;AAAA,YACF,GAAG,KAAK,SAAS;AAGjB,+BAAmB,QAAQ,MAAM,aAAa,SAAS,CAAC;AAAA,UAC1D,CAAC;AAAA,QACH,CAAC,IACD;AAUJ,YAAI,sBAAsB,UAAa,sBAAsB,MAAM;AACjE,mBAAS,uBAAuB,MAAM;AAAA,YACpC,SAAS,CAAC;AAAA,UACZ,CAAC;AAAA,QACH,WAAW,OAAO,sBAAsB,UAAU;AAChD,mBAAS,uBAAuB,MAAM;AAAA,YACpC,SAAS,CAAC,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,UACrD,CAAC;AAAA,QACH,WAAW,UAAU,mBAAmB;AACtC,mBAAS,uBAAuB,MAAM;AAAA,YACpC,SAAS,CAAC,iBAAiB;AAAA,UAC7B,CAAC;AAAA,QACH,OAAO;AACL,mBAAS,uBAAuB,MAAM,iBAAiB;AAAA,QACzD;AAAA,MACF,SAAS,OAAO;AACd,YAAI,iBAAiB,WAAW;AAC9B,iBAAO;AAAA,YACL,SAAS,CAAC,EAAE,MAAM,MAAM,SAAS,MAAM,OAAO,CAAC;AAAA,YAC/C,SAAS;AAAA,UACX;AAAA,QACF;AAEA,cAAM,eACJ,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACvD,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM,SAAS,QAAQ,OAAO,IAAI,uBAAuB,YAAY;AAAA,cACrE,MAAM;AAAA,YACR;AAAA,UACF;AAAA,UACA,SAAS;AAAA,QACX;AAAA,MACF;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;AAEA,IAAM,0BAEF;AAIJ,IAAM,sBAAN,cAAkC,wBAAwB;AAAC;AAEpD,IAAM,UAAN,cAEG,oBAAoB;AAAA,EAc5B,YAAmB,SAA2B;AAC5C,UAAM;AADW;AAGjB,SAAK,WAAW;AAChB,SAAK,gBAAgB,QAAQ;AAAA,EAC/B;AAAA,EAlBA,IAAW,WAAgC;AACzC,WAAO,KAAK;AAAA,EACd;AAAA,EACA;AAAA,EACA,oBAAsC;AAAA,EACtC;AAAA,EACA,WAA0B,CAAC;AAAA,EAC3B,aAAyB,CAAC;AAAA,EAC1B,sBAA+C,CAAC;AAAA,EAChD,YAAiC,CAAC;AAAA,EAElC,SAAoB,CAAC;AAAA;AAAA;AAAA;AAAA,EAYd,UACL,QACA;AACA,SAAK,SAAS,KAAK,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA,EAKO,YAAY,UAAoB;AACrC,SAAK,WAAW,KAAK,QAAQ;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKO,oBAEL,UAAuC;AACvC,SAAK,oBAAoB,KAAK,QAAQ;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKO,QAAuC,MAAuB;AACnE,SAAK,OAAO,KAAK,IAA0B;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,SAAS,KAAmD;AAEvE,UAAM,iBAAiB,KAAK,WAAW;AAAA,MACrC,CAAC,aAAa,SAAS,QAAQ;AAAA,IACjC;AAEA,QAAI,gBAAgB;AAClB,YAAM,SAAS,MAAM,eAAe,KAAK;AACzC,YAAM,UAAU,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AACxD,YAAM,cAAc,QAAQ,CAAC;AAE7B,YAAM,eAA4C;AAAA,QAChD,UAAU,eAAe;AAAA,QACzB;AAAA,MACF;AAEA,UAAI,UAAU,aAAa;AACzB,qBAAa,OAAO,YAAY;AAAA,MAClC;AAEA,UAAI,UAAU,aAAa;AACzB,qBAAa,OAAO,YAAY;AAAA,MAClC;AAEA,aAAO;AAAA,IACT;AAGA,eAAW,YAAY,KAAK,qBAAqB;AAE/C,YAAM,eAAe,SAAS,YAAY,MAAM,GAAG,EAAE,CAAC;AAEtD,UAAI,IAAI,WAAW,YAAY,GAAG;AAChC,cAAM,SAAiC,CAAC;AACxC,cAAM,gBAAgB,SAAS,YAAY,MAAM,GAAG;AACpD,cAAM,WAAW,IAAI,MAAM,GAAG;AAE9B,iBAAS,IAAI,GAAG,IAAI,cAAc,QAAQ,KAAK;AAC7C,gBAAM,eAAe,cAAc,CAAC;AAEpC,cAAI,cAAc,WAAW,GAAG,KAAK,aAAa,SAAS,GAAG,GAAG;AAC/D,kBAAM,YAAY,aAAa,MAAM,GAAG,EAAE;AAC1C,kBAAM,aAAa,SAAS,CAAC;AAE7B,gBAAI,YAAY;AACd,qBAAO,SAAS,IAAI;AAAA,YACtB;AAAA,UACF;AAAA,QACF;AAEA,cAAM,SAAS,MAAM,SAAS;AAAA,UAC5B;AAAA,QAGF;AAEA,cAAM,eAA4C;AAAA,UAChD,UAAU,SAAS;AAAA,UACnB;AAAA,QACF;AAEA,YAAI,UAAU,QAAQ;AACpB,uBAAa,OAAO,OAAO;AAAA,QAC7B;AAEA,YAAI,UAAU,QAAQ;AACpB,uBAAa,OAAO,OAAO;AAAA,QAC7B;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,IAAI,qBAAqB,uBAAuB,GAAG,IAAI,EAAE,IAAI,CAAC;AAAA,EACtE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,MACX,UAKiC;AAAA,IAC/B,eAAe;AAAA,EACjB,GACA;AACA,QAAI,QAAQ,kBAAkB,SAAS;AACrC,YAAM,YAAY,IAAI,qBAAqB;AAE3C,YAAM,UAAU,IAAI,eAAkB;AAAA,QACpC,cAAc,KAAK,SAAS;AAAA,QAC5B,MAAM,KAAK,SAAS;AAAA,QACpB,MAAM,KAAK,SAAS;AAAA,QACpB,SAAS,KAAK;AAAA,QACd,WAAW,KAAK;AAAA,QAChB,oBAAoB,KAAK;AAAA,QACzB,OAAO,KAAK,SAAS;AAAA,QACrB,OAAO,KAAK;AAAA,QACZ,eAAe;AAAA,QACf,SAAS,KAAK,SAAS;AAAA,MACzB,CAAC;AAED,YAAM,QAAQ,QAAQ,SAAS;AAE/B,WAAK,UAAU,KAAK,OAAO;AAE3B,WAAK,KAAK,WAAW;AAAA,QACnB;AAAA,MACF,CAAC;AAAA,IACH,WAAW,QAAQ,kBAAkB,cAAc;AACjD,WAAK,oBAAoB,MAAM,gBAAmC;AAAA,QAChE,cAAc,OAAO,YAAY;AAC/B,cAAI;AAEJ,cAAI,KAAK,eAAe;AACtB,mBAAO,MAAM,KAAK,cAAc,OAAO;AAAA,UACzC;AAEA,iBAAO,IAAI,eAAkB;AAAA,YAC3B;AAAA,YACA,MAAM,KAAK,SAAS;AAAA,YACpB,MAAM,KAAK,SAAS;AAAA,YACpB,SAAS,KAAK;AAAA,YACd,WAAW,KAAK;AAAA,YAChB,oBAAoB,KAAK;AAAA,YACzB,OAAO,KAAK,SAAS;AAAA,YACrB,OAAO,KAAK;AAAA,YACZ,eAAe;AAAA,YACf,SAAS,KAAK,SAAS;AAAA,UACzB,CAAC;AAAA,QACH;AAAA,QACA,SAAS,OAAO,YAAY;AAC1B,eAAK,KAAK,cAAc;AAAA,YACtB;AAAA,UACF,CAAC;AAAA,QACH;AAAA,QACA,WAAW,OAAO,YAAY;AAC5B,eAAK,UAAU,KAAK,OAAO;AAE3B,eAAK,KAAK,WAAW;AAAA,YACnB;AAAA,UACF,CAAC;AAAA,QACH;AAAA,QACA,oBAAoB,OAAO,KAAK,QAAQ;AACtC,gBAAM,eAAe,KAAK,SAAS,UAAU,CAAC;AAE9C,gBAAM,UACJ,aAAa,YAAY,SAAY,OAAO,aAAa;AAE3D,cAAI,SAAS;AACX,kBAAM,OAAO,aAAa,QAAQ;AAClC,kBAAM,MAAM,IAAI,IAAI,IAAI,OAAO,IAAI,kBAAkB;AAErD,gBAAI;AACF,kBAAI,IAAI,WAAW,SAAS,IAAI,aAAa,MAAM;AACjD,oBACG,UAAU,aAAa,UAAU,KAAK;AAAA,kBACrC,gBAAgB;AAAA,gBAClB,CAAC,EACA,IAAI,aAAa,WAAW,IAAI;AAEnC;AAAA,cACF;AAGA,kBAAI,IAAI,WAAW,SAAS,IAAI,aAAa,UAAU;AACrD,sBAAM,gBAAgB,KAAK,UAAU;AAAA,kBACnC,CAAC,MAAM,EAAE;AAAA,gBACX,EAAE;AACF,sBAAM,gBAAgB,KAAK,UAAU;AACrC,sBAAM,WACJ,kBAAkB,iBAAiB,gBAAgB;AAErD,sBAAM,WAAW;AAAA,kBACf,OAAO;AAAA,kBACP,QAAQ,WACJ,UACA,kBAAkB,IAChB,gBACA;AAAA,kBACN,OAAO;AAAA,gBACT;AAEA,oBACG,UAAU,WAAW,MAAM,KAAK;AAAA,kBAC/B,gBAAgB;AAAA,gBAClB,CAAC,EACA,IAAI,KAAK,UAAU,QAAQ,CAAC;AAE/B;AAAA,cACF;AAAA,YACF,SAAS,OAAO;AACd,sBAAQ,MAAM,yCAAyC,KAAK;AAAA,YAC9D;AAAA,UACF;AAGA,cAAI,UAAU,GAAG,EAAE,IAAI;AAAA,QACzB;AAAA,QACA,MAAM,QAAQ,WAAW;AAAA,MAC3B,CAAC;AAED,cAAQ;AAAA,QACN,uEAAuE,QAAQ,WAAW,IAAI;AAAA,MAChG;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAa,OAAO;AAClB,QAAI,KAAK,mBAAmB;AAC1B,YAAM,KAAK,kBAAkB,MAAM;AAAA,IACrC;AAAA,EACF;AACF;","names":["prompt","resource","tool"]}
@@ -12,20 +12,42 @@ await yargs(hideBin(process.argv)).scriptName("fastmcp").command(
12
12
  demandOption: true,
13
13
  describe: "The path to the server file",
14
14
  type: "string"
15
+ }).option("watch", {
16
+ alias: "w",
17
+ default: false,
18
+ describe: "Watch for file changes and restart server",
19
+ type: "boolean"
20
+ }).option("verbose", {
21
+ alias: "v",
22
+ default: false,
23
+ describe: "Enable verbose logging",
24
+ type: "boolean"
15
25
  });
16
26
  },
17
27
  async (argv) => {
18
28
  try {
29
+ const command = argv.watch ? `npx @wong2/mcp-cli npx tsx --watch ${argv.file}` : `npx @wong2/mcp-cli npx tsx ${argv.file}`;
30
+ if (argv.verbose) {
31
+ console.log(`[FastMCP] Starting server: ${command}`);
32
+ console.log(`[FastMCP] File: ${argv.file}`);
33
+ console.log(
34
+ `[FastMCP] Watch mode: ${argv.watch ? "enabled" : "disabled"}`
35
+ );
36
+ }
19
37
  await execa({
38
+ shell: true,
20
39
  stderr: "inherit",
21
40
  stdin: "inherit",
22
41
  stdout: "inherit"
23
- })`npx @wong2/mcp-cli npx tsx ${argv.file}`;
42
+ })`${command}`;
24
43
  } catch (error) {
25
44
  console.error(
26
45
  "[FastMCP Error] Failed to start development server:",
27
46
  error instanceof Error ? error.message : String(error)
28
47
  );
48
+ if (argv.verbose && error instanceof Error && error.stack) {
49
+ console.error("[FastMCP Debug] Stack trace:", error.stack);
50
+ }
29
51
  process.exit(1);
30
52
  }
31
53
  }
@@ -53,5 +75,78 @@ await yargs(hideBin(process.argv)).scriptName("fastmcp").command(
53
75
  process.exit(1);
54
76
  }
55
77
  }
78
+ ).command(
79
+ "validate <file>",
80
+ "Validate a FastMCP server file for syntax and basic structure",
81
+ (yargs2) => {
82
+ return yargs2.positional("file", {
83
+ demandOption: true,
84
+ describe: "The path to the server file",
85
+ type: "string"
86
+ }).option("strict", {
87
+ alias: "s",
88
+ default: false,
89
+ describe: "Enable strict validation (type checking)",
90
+ type: "boolean"
91
+ });
92
+ },
93
+ async (argv) => {
94
+ try {
95
+ const { existsSync } = await import("fs");
96
+ const { resolve } = await import("path");
97
+ const filePath = resolve(argv.file);
98
+ if (!existsSync(filePath)) {
99
+ console.error(`[FastMCP Error] File not found: ${filePath}`);
100
+ process.exit(1);
101
+ }
102
+ console.log(`[FastMCP] Validating server file: ${filePath}`);
103
+ const command = argv.strict ? `npx tsc --noEmit --strict ${filePath}` : `npx tsc --noEmit ${filePath}`;
104
+ try {
105
+ await execa({
106
+ shell: true,
107
+ stderr: "pipe",
108
+ stdout: "pipe"
109
+ })`${command}`;
110
+ console.log("[FastMCP] \u2713 TypeScript compilation successful");
111
+ } catch (tsError) {
112
+ console.error("[FastMCP] \u2717 TypeScript compilation failed");
113
+ if (tsError instanceof Error && "stderr" in tsError) {
114
+ console.error(tsError.stderr);
115
+ }
116
+ process.exit(1);
117
+ }
118
+ try {
119
+ await execa({
120
+ shell: true,
121
+ stderr: "pipe",
122
+ stdout: "pipe"
123
+ })`node -e "
124
+ (async () => {
125
+ try {
126
+ const { FastMCP } = await import('fastmcp');
127
+ await import('file://${filePath}');
128
+ console.log('[FastMCP] ✓ Server structure validation passed');
129
+ } catch (error) {
130
+ console.error('[FastMCP] ✗ Server structure validation failed:', error.message);
131
+ process.exit(1);
132
+ }
133
+ })();
134
+ "`;
135
+ } catch {
136
+ console.error("[FastMCP] \u2717 Server structure validation failed");
137
+ console.error("Make sure the file properly imports and uses FastMCP");
138
+ process.exit(1);
139
+ }
140
+ console.log(
141
+ "[FastMCP] \u2713 All validations passed! Server file looks good."
142
+ );
143
+ } catch (error) {
144
+ console.error(
145
+ "[FastMCP Error] Validation failed:",
146
+ error instanceof Error ? error.message : String(error)
147
+ );
148
+ process.exit(1);
149
+ }
150
+ }
56
151
  ).help().parseAsync();
57
152
  //# sourceMappingURL=fastmcp.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/bin/fastmcp.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { execa } from \"execa\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nawait yargs(hideBin(process.argv))\n .scriptName(\"fastmcp\")\n .command(\n \"dev <file>\",\n \"Start a development server\",\n (yargs) => {\n return yargs.positional(\"file\", {\n demandOption: true,\n describe: \"The path to the server file\",\n type: \"string\",\n });\n },\n async (argv) => {\n try {\n await execa({\n stderr: \"inherit\",\n stdin: \"inherit\",\n stdout: \"inherit\",\n })`npx @wong2/mcp-cli npx tsx ${argv.file}`;\n } catch (error) {\n console.error(\n \"[FastMCP Error] Failed to start development server:\",\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n },\n )\n .command(\n \"inspect <file>\",\n \"Inspect a server file\",\n (yargs) => {\n return yargs.positional(\"file\", {\n demandOption: true,\n describe: \"The path to the server file\",\n type: \"string\",\n });\n },\n async (argv) => {\n try {\n await execa({\n stderr: \"inherit\",\n stdout: \"inherit\",\n })`npx @modelcontextprotocol/inspector npx tsx ${argv.file}`;\n } catch (error) {\n console.error(\n \"[FastMCP Error] Failed to inspect server:\",\n error instanceof Error ? error.message : String(error),\n );\n process.exit(1);\n }\n },\n )\n .help()\n .parseAsync();\n"],"mappings":";;;AAEA,SAAS,aAAa;AACtB,OAAO,WAAW;AAClB,SAAS,eAAe;AAExB,MAAM,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAC9B,WAAW,SAAS,EACpB;AAAA,EACC;AAAA,EACA;AAAA,EACA,CAACA,WAAU;AACT,WAAOA,OAAM,WAAW,QAAQ;AAAA,MAC9B,cAAc;AAAA,MACd,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EACA,OAAO,SAAS;AACd,QAAI;AACF,YAAM,MAAM;AAAA,QACV,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,QAAQ;AAAA,MACV,CAAC,+BAA+B,KAAK,IAAI;AAAA,IAC3C,SAAS,OAAO;AACd,cAAQ;AAAA,QACN;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACvD;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF,EACC;AAAA,EACC;AAAA,EACA;AAAA,EACA,CAACA,WAAU;AACT,WAAOA,OAAM,WAAW,QAAQ;AAAA,MAC9B,cAAc;AAAA,MACd,UAAU;AAAA,MACV,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AAAA,EACA,OAAO,SAAS;AACd,QAAI;AACF,YAAM,MAAM;AAAA,QACV,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV,CAAC,gDAAgD,KAAK,IAAI;AAAA,IAC5D,SAAS,OAAO;AACd,cAAQ;AAAA,QACN;AAAA,QACA,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,MACvD;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF,EACC,KAAK,EACL,WAAW;","names":["yargs"]}
1
+ {"version":3,"sources":["../../src/bin/fastmcp.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { execa } from \"execa\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\n\nawait yargs(hideBin(process.argv))\n .scriptName(\"fastmcp\")\n .command(\n \"dev <file>\",\n \"Start a development server\",\n (yargs) => {\n return yargs\n .positional(\"file\", {\n demandOption: true,\n describe: \"The path to the server file\",\n type: \"string\",\n })\n\n .option(\"watch\", {\n alias: \"w\",\n default: false,\n describe: \"Watch for file changes and restart server\",\n type: \"boolean\",\n })\n\n .option(\"verbose\", {\n alias: \"v\",\n default: false,\n describe: \"Enable verbose logging\",\n type: \"boolean\",\n });\n },\n\n async (argv) => {\n try {\n const command = argv.watch\n ? `npx @wong2/mcp-cli npx tsx --watch ${argv.file}`\n : `npx @wong2/mcp-cli npx tsx ${argv.file}`;\n\n if (argv.verbose) {\n console.log(`[FastMCP] Starting server: ${command}`);\n console.log(`[FastMCP] File: ${argv.file}`);\n console.log(\n `[FastMCP] Watch mode: ${argv.watch ? \"enabled\" : \"disabled\"}`,\n );\n }\n\n await execa({\n shell: true,\n stderr: \"inherit\",\n stdin: \"inherit\",\n stdout: \"inherit\",\n })`${command}`;\n } catch (error) {\n console.error(\n \"[FastMCP Error] Failed to start development server:\",\n error instanceof Error ? error.message : String(error),\n );\n\n if (argv.verbose && error instanceof Error && error.stack) {\n console.error(\"[FastMCP Debug] Stack trace:\", error.stack);\n }\n\n process.exit(1);\n }\n },\n )\n\n .command(\n \"inspect <file>\",\n \"Inspect a server file\",\n (yargs) => {\n return yargs.positional(\"file\", {\n demandOption: true,\n describe: \"The path to the server file\",\n type: \"string\",\n });\n },\n\n async (argv) => {\n try {\n await execa({\n stderr: \"inherit\",\n stdout: \"inherit\",\n })`npx @modelcontextprotocol/inspector npx tsx ${argv.file}`;\n } catch (error) {\n console.error(\n \"[FastMCP Error] Failed to inspect server:\",\n error instanceof Error ? error.message : String(error),\n );\n\n process.exit(1);\n }\n },\n )\n\n .command(\n \"validate <file>\",\n \"Validate a FastMCP server file for syntax and basic structure\",\n (yargs) => {\n return yargs\n .positional(\"file\", {\n demandOption: true,\n describe: \"The path to the server file\",\n type: \"string\",\n })\n\n .option(\"strict\", {\n alias: \"s\",\n default: false,\n describe: \"Enable strict validation (type checking)\",\n type: \"boolean\",\n });\n },\n\n async (argv) => {\n try {\n const { existsSync } = await import(\"fs\");\n const { resolve } = await import(\"path\");\n const filePath = resolve(argv.file);\n\n if (!existsSync(filePath)) {\n console.error(`[FastMCP Error] File not found: ${filePath}`);\n process.exit(1);\n }\n\n console.log(`[FastMCP] Validating server file: ${filePath}`);\n\n const command = argv.strict\n ? `npx tsc --noEmit --strict ${filePath}`\n : `npx tsc --noEmit ${filePath}`;\n\n try {\n await execa({\n shell: true,\n stderr: \"pipe\",\n stdout: \"pipe\",\n })`${command}`;\n\n console.log(\"[FastMCP] ✓ TypeScript compilation successful\");\n } catch (tsError) {\n console.error(\"[FastMCP] ✗ TypeScript compilation failed\");\n\n if (tsError instanceof Error && \"stderr\" in tsError) {\n console.error(tsError.stderr);\n }\n\n process.exit(1);\n }\n\n try {\n await execa({\n shell: true,\n stderr: \"pipe\",\n stdout: \"pipe\",\n })`node -e \"\n (async () => {\n try {\n const { FastMCP } = await import('fastmcp');\n await import('file://${filePath}');\n console.log('[FastMCP] ✓ Server structure validation passed');\n } catch (error) {\n console.error('[FastMCP] ✗ Server structure validation failed:', error.message);\n process.exit(1);\n }\n })();\n \"`;\n } catch {\n console.error(\"[FastMCP] ✗ Server structure validation failed\");\n console.error(\"Make sure the file properly imports and uses FastMCP\");\n\n process.exit(1);\n }\n\n console.log(\n \"[FastMCP] ✓ All validations passed! Server file looks good.\",\n );\n } catch (error) {\n console.error(\n \"[FastMCP Error] Validation failed:\",\n error instanceof Error ? error.message : String(error),\n );\n\n process.exit(1);\n }\n },\n )\n\n .help()\n .parseAsync();\n"],"mappings":"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","names":["yargs"]}
package/jsr.json CHANGED
@@ -3,5 +3,5 @@
3
3
  "include": ["src/FastMCP.ts", "src/bin/fastmcp.ts"],
4
4
  "license": "MIT",
5
5
  "name": "@punkpeye/fastmcp",
6
- "version": "3.0.1"
6
+ "version": "3.1.1"
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastmcp",
3
- "version": "3.0.1",
3
+ "version": "3.1.1",
4
4
  "main": "dist/FastMCP.js",
5
5
  "scripts": {
6
6
  "build": "tsup",
@@ -1689,7 +1689,7 @@ test("throws ErrorCode.InvalidParams if tool parameters do not match zod schema"
1689
1689
 
1690
1690
  // @ts-expect-error - we know that error is an McpError
1691
1691
  expect(error.message).toBe(
1692
- "MCP error -32602: MCP error -32602: Tool 'add' parameter validation failed: b: Expected number, received string",
1692
+ "MCP error -32602: MCP error -32602: Tool 'add' parameter validation failed: b: Expected number, received string. Please check the parameter types and values according to the tool's schema.",
1693
1693
  );
1694
1694
  }
1695
1695
  },
@@ -1735,7 +1735,7 @@ test("server remains usable after InvalidParams error", async () => {
1735
1735
 
1736
1736
  // @ts-expect-error - we know that error is an McpError
1737
1737
  expect(error.message).toBe(
1738
- "MCP error -32602: MCP error -32602: Tool 'add' parameter validation failed: b: Expected number, received string",
1738
+ "MCP error -32602: MCP error -32602: Tool 'add' parameter validation failed: b: Expected number, received string. Please check the parameter types and values according to the tool's schema.",
1739
1739
  );
1740
1740
  }
1741
1741
 
package/src/FastMCP.ts CHANGED
@@ -773,21 +773,24 @@ export class FastMCPSession<
773
773
  await this.#server.connect(transport);
774
774
 
775
775
  let attempt = 0;
776
+ const maxAttempts = 10;
777
+ const retryDelay = 100;
776
778
 
777
- while (attempt++ < 10) {
779
+ while (attempt++ < maxAttempts) {
778
780
  const capabilities = this.#server.getClientCapabilities();
779
781
 
780
782
  if (capabilities) {
781
783
  this.#clientCapabilities = capabilities;
782
-
783
784
  break;
784
785
  }
785
786
 
786
- await delay(100);
787
+ await delay(retryDelay);
787
788
  }
788
789
 
789
790
  if (!this.#clientCapabilities) {
790
- console.warn("[FastMCP warning] could not infer client capabilities");
791
+ console.warn(
792
+ `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`,
793
+ );
791
794
  }
792
795
 
793
796
  if (
@@ -796,7 +799,7 @@ export class FastMCPSession<
796
799
  ) {
797
800
  try {
798
801
  const roots = await this.#server.listRoots();
799
- this.#roots = roots.roots;
802
+ this.#roots = roots?.roots || [];
800
803
  } catch (e) {
801
804
  if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {
802
805
  console.debug(
@@ -922,6 +925,7 @@ export class FastMCPSession<
922
925
  private addPrompt(inputPrompt: InputPrompt) {
923
926
  const completers: Record<string, ArgumentValueCompleter> = {};
924
927
  const enums: Record<string, string[]> = {};
928
+ const fuseInstances: Record<string, Fuse<string>> = {};
925
929
 
926
930
  for (const argument of inputPrompt.arguments ?? []) {
927
931
  if (argument.complete) {
@@ -930,6 +934,10 @@ export class FastMCPSession<
930
934
 
931
935
  if (argument.enum) {
932
936
  enums[argument.name] = argument.enum;
937
+ fuseInstances[argument.name] = new Fuse(argument.enum, {
938
+ includeScore: true,
939
+ threshold: 0.3, // More flexible matching!
940
+ });
933
941
  }
934
942
  }
935
943
 
@@ -940,12 +948,8 @@ export class FastMCPSession<
940
948
  return await completers[name](value);
941
949
  }
942
950
 
943
- if (enums[name]) {
944
- const fuse = new Fuse(enums[name], {
945
- keys: ["value"],
946
- });
947
-
948
- const result = fuse.search(value);
951
+ if (fuseInstances[name]) {
952
+ const result = fuseInstances[name].search(value);
949
953
 
950
954
  return {
951
955
  total: result.length,
@@ -1354,7 +1358,7 @@ export class FastMCPSession<
1354
1358
 
1355
1359
  throw new McpError(
1356
1360
  ErrorCode.InvalidParams,
1357
- `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}`,
1361
+ `Tool '${request.params.name}' parameter validation failed: ${friendlyErrors}. Please check the parameter types and values according to the tool's schema.`,
1358
1362
  );
1359
1363
  }
1360
1364
 
@@ -1367,16 +1371,25 @@ export class FastMCPSession<
1367
1371
 
1368
1372
  try {
1369
1373
  const reportProgress = async (progress: Progress) => {
1370
- await this.#server.notification({
1371
- method: "notifications/progress",
1372
- params: {
1373
- ...progress,
1374
- progressToken,
1375
- },
1376
- });
1374
+ try {
1375
+ await this.#server.notification({
1376
+ method: "notifications/progress",
1377
+ params: {
1378
+ ...progress,
1379
+ progressToken,
1380
+ },
1381
+ });
1377
1382
 
1378
- if (this.#needsEventLoopFlush) {
1379
- await new Promise((resolve) => setImmediate(resolve));
1383
+ if (this.#needsEventLoopFlush) {
1384
+ await new Promise((resolve) => setImmediate(resolve));
1385
+ }
1386
+ } catch (progressError) {
1387
+ console.warn(
1388
+ `[FastMCP warning] Failed to report progress for tool '${request.params.name}':`,
1389
+ progressError instanceof Error
1390
+ ? progressError.message
1391
+ : String(progressError),
1392
+ );
1380
1393
  }
1381
1394
  };
1382
1395
 
@@ -1425,16 +1438,25 @@ export class FastMCPSession<
1425
1438
  const streamContent = async (content: Content | Content[]) => {
1426
1439
  const contentArray = Array.isArray(content) ? content : [content];
1427
1440
 
1428
- await this.#server.notification({
1429
- method: "notifications/tool/streamContent",
1430
- params: {
1431
- content: contentArray,
1432
- toolName: request.params.name,
1433
- },
1434
- });
1441
+ try {
1442
+ await this.#server.notification({
1443
+ method: "notifications/tool/streamContent",
1444
+ params: {
1445
+ content: contentArray,
1446
+ toolName: request.params.name,
1447
+ },
1448
+ });
1435
1449
 
1436
- if (this.#needsEventLoopFlush) {
1437
- await new Promise((resolve) => setImmediate(resolve));
1450
+ if (this.#needsEventLoopFlush) {
1451
+ await new Promise((resolve) => setImmediate(resolve));
1452
+ }
1453
+ } catch (streamError) {
1454
+ console.warn(
1455
+ `[FastMCP warning] Failed to stream content for tool '${request.params.name}':`,
1456
+ streamError instanceof Error
1457
+ ? streamError.message
1458
+ : String(streamError),
1459
+ );
1438
1460
  }
1439
1461
  };
1440
1462
 
@@ -1450,13 +1472,16 @@ export class FastMCPSession<
1450
1472
  ? Promise.race([
1451
1473
  executeToolPromise,
1452
1474
  new Promise<never>((_, reject) => {
1453
- setTimeout(() => {
1475
+ const timeoutId = setTimeout(() => {
1454
1476
  reject(
1455
1477
  new UserError(
1456
1478
  `Tool '${request.params.name}' timed out after ${tool.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`,
1457
1479
  ),
1458
1480
  );
1459
1481
  }, tool.timeoutMs);
1482
+
1483
+ // If promise resolves first
1484
+ executeToolPromise.finally(() => clearTimeout(timeoutId));
1460
1485
  }),
1461
1486
  ])
1462
1487
  : executeToolPromise)) as
@@ -10,28 +10,63 @@ await yargs(hideBin(process.argv))
10
10
  "dev <file>",
11
11
  "Start a development server",
12
12
  (yargs) => {
13
- return yargs.positional("file", {
14
- demandOption: true,
15
- describe: "The path to the server file",
16
- type: "string",
17
- });
13
+ return yargs
14
+ .positional("file", {
15
+ demandOption: true,
16
+ describe: "The path to the server file",
17
+ type: "string",
18
+ })
19
+
20
+ .option("watch", {
21
+ alias: "w",
22
+ default: false,
23
+ describe: "Watch for file changes and restart server",
24
+ type: "boolean",
25
+ })
26
+
27
+ .option("verbose", {
28
+ alias: "v",
29
+ default: false,
30
+ describe: "Enable verbose logging",
31
+ type: "boolean",
32
+ });
18
33
  },
34
+
19
35
  async (argv) => {
20
36
  try {
37
+ const command = argv.watch
38
+ ? `npx @wong2/mcp-cli npx tsx --watch ${argv.file}`
39
+ : `npx @wong2/mcp-cli npx tsx ${argv.file}`;
40
+
41
+ if (argv.verbose) {
42
+ console.log(`[FastMCP] Starting server: ${command}`);
43
+ console.log(`[FastMCP] File: ${argv.file}`);
44
+ console.log(
45
+ `[FastMCP] Watch mode: ${argv.watch ? "enabled" : "disabled"}`,
46
+ );
47
+ }
48
+
21
49
  await execa({
50
+ shell: true,
22
51
  stderr: "inherit",
23
52
  stdin: "inherit",
24
53
  stdout: "inherit",
25
- })`npx @wong2/mcp-cli npx tsx ${argv.file}`;
54
+ })`${command}`;
26
55
  } catch (error) {
27
56
  console.error(
28
57
  "[FastMCP Error] Failed to start development server:",
29
58
  error instanceof Error ? error.message : String(error),
30
59
  );
60
+
61
+ if (argv.verbose && error instanceof Error && error.stack) {
62
+ console.error("[FastMCP Debug] Stack trace:", error.stack);
63
+ }
64
+
31
65
  process.exit(1);
32
66
  }
33
67
  },
34
68
  )
69
+
35
70
  .command(
36
71
  "inspect <file>",
37
72
  "Inspect a server file",
@@ -42,6 +77,7 @@ await yargs(hideBin(process.argv))
42
77
  type: "string",
43
78
  });
44
79
  },
80
+
45
81
  async (argv) => {
46
82
  try {
47
83
  await execa({
@@ -53,9 +89,103 @@ await yargs(hideBin(process.argv))
53
89
  "[FastMCP Error] Failed to inspect server:",
54
90
  error instanceof Error ? error.message : String(error),
55
91
  );
92
+
93
+ process.exit(1);
94
+ }
95
+ },
96
+ )
97
+
98
+ .command(
99
+ "validate <file>",
100
+ "Validate a FastMCP server file for syntax and basic structure",
101
+ (yargs) => {
102
+ return yargs
103
+ .positional("file", {
104
+ demandOption: true,
105
+ describe: "The path to the server file",
106
+ type: "string",
107
+ })
108
+
109
+ .option("strict", {
110
+ alias: "s",
111
+ default: false,
112
+ describe: "Enable strict validation (type checking)",
113
+ type: "boolean",
114
+ });
115
+ },
116
+
117
+ async (argv) => {
118
+ try {
119
+ const { existsSync } = await import("fs");
120
+ const { resolve } = await import("path");
121
+ const filePath = resolve(argv.file);
122
+
123
+ if (!existsSync(filePath)) {
124
+ console.error(`[FastMCP Error] File not found: ${filePath}`);
125
+ process.exit(1);
126
+ }
127
+
128
+ console.log(`[FastMCP] Validating server file: ${filePath}`);
129
+
130
+ const command = argv.strict
131
+ ? `npx tsc --noEmit --strict ${filePath}`
132
+ : `npx tsc --noEmit ${filePath}`;
133
+
134
+ try {
135
+ await execa({
136
+ shell: true,
137
+ stderr: "pipe",
138
+ stdout: "pipe",
139
+ })`${command}`;
140
+
141
+ console.log("[FastMCP] ✓ TypeScript compilation successful");
142
+ } catch (tsError) {
143
+ console.error("[FastMCP] ✗ TypeScript compilation failed");
144
+
145
+ if (tsError instanceof Error && "stderr" in tsError) {
146
+ console.error(tsError.stderr);
147
+ }
148
+
149
+ process.exit(1);
150
+ }
151
+
152
+ try {
153
+ await execa({
154
+ shell: true,
155
+ stderr: "pipe",
156
+ stdout: "pipe",
157
+ })`node -e "
158
+ (async () => {
159
+ try {
160
+ const { FastMCP } = await import('fastmcp');
161
+ await import('file://${filePath}');
162
+ console.log('[FastMCP] ✓ Server structure validation passed');
163
+ } catch (error) {
164
+ console.error('[FastMCP] ✗ Server structure validation failed:', error.message);
165
+ process.exit(1);
166
+ }
167
+ })();
168
+ "`;
169
+ } catch {
170
+ console.error("[FastMCP] ✗ Server structure validation failed");
171
+ console.error("Make sure the file properly imports and uses FastMCP");
172
+
173
+ process.exit(1);
174
+ }
175
+
176
+ console.log(
177
+ "[FastMCP] ✓ All validations passed! Server file looks good.",
178
+ );
179
+ } catch (error) {
180
+ console.error(
181
+ "[FastMCP Error] Validation failed:",
182
+ error instanceof Error ? error.message : String(error),
183
+ );
184
+
56
185
  process.exit(1);
57
186
  }
58
187
  },
59
188
  )
189
+
60
190
  .help()
61
191
  .parseAsync();