fastmcp 4.20.0 → 4.20.2

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/FastMCP.ts","../src/DiscoveryDocumentCache.ts","../src/jsonSchemaAdapter.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { RequestHandlerExtra } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n CreateMessageRequestSchema,\n ElicitRequestFormParams,\n ElicitRequestURLParams,\n ElicitResult,\n ErrorCode,\n GetPromptRequestSchema,\n GetPromptResult,\n Icon,\n ListPromptsRequestSchema,\n ListPromptsResult,\n ListResourcesRequestSchema,\n ListResourcesResult,\n ListResourceTemplatesRequestSchema,\n ListResourceTemplatesResult,\n ListToolsRequestSchema,\n ListToolsResult,\n McpError,\n ReadResourceRequestSchema,\n ResourceLink,\n Root,\n RootsListChangedNotificationSchema,\n Tool as SDKTool,\n ServerCapabilities,\n ServerNotification,\n ServerRequest,\n SetLevelRequestSchema,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { EventEmitter } from \"events\";\nimport { readFile } from \"fs/promises\";\nimport Fuse from \"fuse.js\";\nimport { Hono } from \"hono\";\nimport http from \"http\";\nimport { type CorsOptions, startHTTPServer } from \"mcp-proxy\";\nimport { StrictEventEmitter } from \"strict-event-emitter-types\";\nimport { setTimeout as delay } from \"timers/promises\";\nimport parseURITemplate from \"uri-templates\";\nimport { strictJsonSchema, toJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\n\nimport type { OAuthProxy } from \"./auth/OAuthProxy.js\";\nimport type {\n AuthProvider,\n OAuthSession,\n} from \"./auth/providers/AuthProvider.js\";\n\nimport { cancelResponseBody } from \"./cancelResponseBody.js\";\n\nexport interface Logger {\n debug(...args: unknown[]): void;\n\n error(...args: unknown[]): void;\n\n info(...args: unknown[]): void;\n\n log(...args: unknown[]): void;\n\n warn(...args: unknown[]): void;\n}\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype FastMCPEvents<T extends FastMCPSessionAuth> = {\n connect: (event: { session: FastMCPSession<T> }) => void;\n disconnect: (event: { session: FastMCPSession<T> }) => void;\n};\n\ntype FastMCPSessionEvents = {\n error: (event: { error: Error }) => void;\n ready: () => void;\n rootsChanged: (event: { roots: Root[] }) => void;\n};\n\n/**\n * Timeout for image/audio URL fetches (in milliseconds). The OAuth upstream\n * fetches (#304) use 10s because they are short interactive exchanges; media\n * downloads can be larger and slower, so 30s is the balance between hanging\n * forever on an unresponsive server and false positives on slow connections.\n */\nexport const MEDIA_FETCH_TIMEOUT_MS = 30000;\n\ntype MediaContentInput =\n | { buffer: Buffer }\n | { path: string }\n | { timeoutMs?: number; url: string };\n\nexport const imageContent = async (\n input: MediaContentInput,\n): Promise<ImageContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n const timeoutMs = input.timeoutMs ?? MEDIA_FETCH_TIMEOUT_MS;\n\n try {\n const response = await fetch(input.url, {\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (!response.ok) {\n await cancelResponseBody(response);\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 // \"AbortError\" is unreachable today (no caller signal); kept as insurance.\n if (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ) {\n throw new Error(\n `Failed to fetch image from URL (${input.url}): timed out after ${timeoutMs}ms`,\n );\n }\n\n throw new Error(\n `Failed to fetch image from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read image from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"image/\")) {\n console.warn(\n `Warning: Content may not be a valid image. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"image/png\",\n type: \"image\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing image: ${String(error)}`);\n }\n }\n};\n\nexport const audioContent = async (\n input: MediaContentInput,\n): Promise<AudioContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n const timeoutMs = input.timeoutMs ?? MEDIA_FETCH_TIMEOUT_MS;\n\n try {\n const response = await fetch(input.url, {\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (!response.ok) {\n await cancelResponseBody(response);\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 // \"AbortError\" is unreachable today (no caller signal); kept as insurance.\n if (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ) {\n throw new Error(\n `Failed to fetch audio from URL (${input.url}): timed out after ${timeoutMs}ms`,\n );\n }\n\n throw new Error(\n `Failed to fetch audio from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read audio from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"audio/\")) {\n console.warn(\n `Warning: Content may not be a valid audio file. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"audio/mpeg\",\n type: \"audio\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing audio: ${String(error)}`);\n }\n }\n};\n\ntype Context<T extends FastMCPSessionAuth> = {\n client: {\n version: ReturnType<Server[\"getClientVersion\"]>;\n };\n /**\n * Requests additional information from the user via the client\n * (see https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation).\n * The client must advertise the matching `elicitation` capability mode —\n * `elicitation: { form: {} }` for form requests (the default) and/or\n * `elicitation: { url: {} }` for url requests.\n */\n elicit: (\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ) => Promise<ElicitResult>;\n log: {\n debug: (message: string, data?: SerializableValue) => void;\n error: (message: string, data?: SerializableValue) => void;\n info: (message: string, data?: SerializableValue) => void;\n warn: (message: string, data?: SerializableValue) => void;\n };\n reportProgress: (progress: Progress) => Promise<void>;\n /**\n * Request ID from the current MCP request.\n * Available for all transports when the client provides it.\n */\n requestId?: string;\n session: T | undefined;\n /**\n * Session ID from the Mcp-Session-Id header.\n * Only available for HTTP-based transports (SSE, HTTP Stream).\n * Can be used to track per-session state, implement session-specific\n * counters, or maintain user-specific data across multiple requests.\n */\n sessionId?: string;\n /**\n * Aborted once the tool's result can no longer reach anyone: the client\n * cancelled the call, the session went away, or `timeoutMs` elapsed.\n *\n * Nothing is killed on your behalf — FastMCP stops waiting, but the promise\n * `execute` returned keeps running until it settles. Forward this signal to\n * whatever does the real work (`fetch`, a database driver, a subprocess) so\n * the work stops with the call instead of outliving it.\n *\n * It is never aborted after a call completes normally, so it is safe to\n * attach cleanup to it.\n */\n signal: AbortSignal;\n /**\n * Streams incremental content while the tool is still executing, by emitting\n * a `notifications/tool/streamContent` notification.\n *\n * NOTE: this is a FastMCP extension, not part of the MCP specification. As of\n * revision 2025-11-25 the spec has no streaming tool output primitive (see\n * SEP-2998 for the in-progress proposal). A client only receives these\n * notifications if it registers a handler for the method or sets a\n * `fallbackNotificationHandler`; otherwise the SDK drops them silently. No\n * client is known to render them as tool output.\n *\n * Always return a final result from `execute` rather than relying on streamed\n * content alone, otherwise clients that ignore the notification see an empty\n * tool result. For incremental status that works everywhere, prefer\n * {@link Context.reportProgress} with a `message`.\n */\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\n/**\n * Context passed to `load` for resources, resource templates, and prompts.\n *\n * This is a subset of the tool execution {@link Context}. `reportProgress`\n * and `streamContent` are tied to a tool call's progress token / streaming\n * notification and are not available outside of `tool.execute`. `signal` is\n * omitted too: its timeout leg comes from `tool.timeoutMs`, which `load` has\n * no equivalent of.\n */\ntype LoadContext<T extends FastMCPSessionAuth> = Omit<\n Context<T>,\n \"reportProgress\" | \"signal\" | \"streamContent\"\n>;\n\ntype Progress = {\n /**\n * An optional human-readable message describing the current progress.\n *\n * Part of `notifications/progress` since MCP revision 2025-03-26, so unlike\n * `streamContent` this reaches any spec-compliant client.\n */\n message?: string;\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\nexport abstract class FastMCPError extends Error {\n public constructor(message?: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/**\n * An error raised when a session encounters a problem (e.g. connection\n * failures, protocol violations). Consumers can use this class to\n * distinguish fastmcp session errors from unrelated runtime errors:\n *\n * ```ts\n * server.on(\"error\", ({ error }) => {\n * if (error instanceof SessionError) { ... }\n * });\n * ```\n */\nexport class SessionError extends FastMCPError {}\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\nfunction assertStandardSchema(\n toolName: string,\n schemaName: \"outputSchema\" | \"parameters\",\n schema: ToolParameters,\n): void {\n const standard = (schema as { \"~standard\"?: { validate?: unknown } })[\n \"~standard\"\n ];\n\n if (typeof standard?.validate === \"function\") {\n return;\n }\n\n throw new UserError(\n `Tool '${toolName}' ${schemaName} must implement Standard Schema. If you are using Zod, upgrade to version 3.24 or later.`,\n );\n}\n\nfunction assertToolSchemas(tool: {\n name: string;\n outputSchema?: ToolParameters;\n parameters?: ToolParameters;\n}): void {\n if (tool.parameters) {\n assertStandardSchema(tool.name, \"parameters\", tool.parameters);\n }\n\n if (tool.outputSchema) {\n assertStandardSchema(tool.name, \"outputSchema\", tool.outputSchema);\n }\n}\n\nconst STREAM_KEEPALIVE_LOGGER = \"fastmcp-keepalive\";\n\nconst STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS = 20_000;\n\nconst TextContentZodSchema = z\n .object({\n /**\n * The text content of the message.\n */\n text: z.string(),\n type: z.literal(\"text\"),\n })\n .strict() satisfies z.ZodType<TextContent>;\n\ntype ImageContent = {\n data: string;\n mimeType: string;\n type: \"image\";\n};\n\nconst ImageContentZodSchema = z\n .object({\n /**\n * The base64-encoded image data.\n */\n data: z.string().base64(),\n /**\n * The MIME type of the image. Different providers may support different image types.\n */\n mimeType: z.string(),\n type: z.literal(\"image\"),\n })\n .strict() satisfies z.ZodType<ImageContent>;\n\ntype AudioContent = {\n data: string;\n mimeType: string;\n type: \"audio\";\n};\n\nconst AudioContentZodSchema = z\n .object({\n /**\n * The base64-encoded audio data.\n */\n data: z.string().base64(),\n mimeType: z.string(),\n type: z.literal(\"audio\"),\n })\n .strict() satisfies z.ZodType<AudioContent>;\n\ntype ResourceContent = {\n resource: {\n blob?: string;\n mimeType?: string;\n text?: string;\n uri: string;\n };\n type: \"resource\";\n};\n\nconst ResourceContentZodSchema = z\n .object({\n resource: z.object({\n blob: z.string().optional(),\n mimeType: z.string().optional(),\n text: z.string().optional(),\n uri: z.string(),\n }),\n type: z.literal(\"resource\"),\n })\n .strict() satisfies z.ZodType<ResourceContent>;\n\nconst ResourceLinkZodSchema = z.object({\n description: z.string().optional(),\n mimeType: z.string().optional(),\n name: z.string(),\n title: z.string().optional(),\n type: z.literal(\"resource_link\"),\n uri: z.string(),\n}) satisfies z.ZodType<ResourceLink>;\n\ntype Content =\n | AudioContent\n | ImageContent\n | ResourceContent\n | ResourceLink\n | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n AudioContentZodSchema,\n ResourceContentZodSchema,\n ResourceLinkZodSchema,\n]) satisfies z.ZodType<Content>;\n\ntype ContentResult = {\n _meta?: Record<string, unknown>;\n content: Content[];\n isError?: boolean;\n structuredContent?: Record<string, unknown>;\n};\n\nconst ContentResultZodSchema = z\n .object({\n _meta: z.record(z.string(), z.unknown()).optional(),\n content: ContentZodSchema.array(),\n isError: z.boolean().optional(),\n structuredContent: z.record(z.string(), z.unknown()).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. The MCP spec caps this at 100 items; values\n * beyond the cap are trimmed by `capCompletionValues` (which sets `hasMore`)\n * rather than rejected, so the schema itself does not enforce the limit.\n */\n values: z.array(z.string()),\n}) satisfies z.ZodType<Completion>;\n\n/**\n * The MCP completion result must not exceed 100 values. Rather than failing when\n * a user-supplied completer returns more, trim to the cap and flag `hasMore` so\n * the client knows the list was truncated.\n */\nconst COMPLETION_VALUES_LIMIT = 100;\n\nconst capCompletionValues = (completion: Completion): Completion => {\n if (completion.values.length <= COMPLETION_VALUES_LIMIT) {\n return completion;\n }\n\n return {\n ...completion,\n hasMore: true,\n values: completion.values.slice(0, COMPLETION_VALUES_LIMIT),\n };\n};\n\ntype ArgumentValueCompleter<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n (value: string, auth?: T) => Promise<Completion>;\n\ntype InputPrompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends InputPromptArgument<T>[] = InputPromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: InputPromptArgument<T>[];\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: Args,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<PromptResult>;\n name: string;\n};\n\ntype InputPromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype InputResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends InputResourceTemplateArgument<T>[] =\n InputResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype InputResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype LoggingLevel =\n | \"alert\"\n | \"critical\"\n | \"debug\"\n | \"emergency\"\n | \"error\"\n | \"info\"\n | \"notice\"\n | \"warning\";\n\ntype Prompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends PromptArgument<T>[] = PromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument<T>[];\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: Args,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<PromptResult>;\n name: string;\n};\n\ntype PromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =\n {\n [K in T[number][\"name\"]]: Extract<\n T[number],\n { name: K }\n >[\"required\"] extends true\n ? string\n : string | undefined;\n };\n\ntype PromptResult = Pick<GetPromptResult, \"messages\"> | string;\n\ntype Resource<T extends FastMCPSessionAuth> = {\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uri: string;\n};\n\ntype ResourceResult =\n | {\n blob: string;\n mimeType?: string;\n uri?: string;\n }\n | {\n mimeType?: string;\n text: string;\n uri?: string;\n };\n\ntype ResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends ResourceTemplateArgument<T>[] =\n ResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype ResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype SamplingResponse = {\n content: AudioContent | ImageContent | TextContent;\n model: string;\n role: \"assistant\" | \"user\";\n stopReason?: \"endTurn\" | \"maxTokens\" | \"stopSequence\" | string;\n};\n\ntype ServerOptions<T extends FastMCPSessionAuth> = {\n /**\n * Authentication provider for OAuth flows.\n * When provided, automatically configures the `authenticate` function\n * and `oauth` settings.\n *\n * For custom authentication logic, use the `authenticate` option instead.\n * If both are provided, `authenticate` takes precedence.\n *\n * @example\n * ```typescript\n * import { FastMCP, GitHubProvider } from \"fastmcp\";\n *\n * const server = new FastMCP({\n * auth: new GitHubProvider({\n * baseUrl: \"http://localhost:8000\",\n * clientId: process.env.GITHUB_CLIENT_ID!,\n * clientSecret: process.env.GITHUB_CLIENT_SECRET!,\n * }),\n * name: \"My Server\",\n * version: \"1.0.0\",\n * });\n * ```\n */\n auth?: AuthProvider<T extends OAuthSession ? T : OAuthSession>;\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 /**\n * Optional icons for this server.\n * Advertised to clients via MCP `initialize` (`serverInfo.icons`) so UIs can\n * show a logo next to the server name.\n */\n icons?: Icon[];\n instructions?: string;\n /**\n * Custom logger instance. If not provided, defaults to console.\n * Use this to integrate with your own logging system.\n */\n logger?: Logger;\n name: string;\n\n /**\n * Configuration for OAuth well-known discovery endpoints that can be exposed\n * when the server is running using HTTP-based transports (SSE or HTTP Stream).\n * When enabled, the server will respond to requests for OAuth discovery endpoints\n * with the configured metadata.\n *\n * The endpoints are only added when the server is started with\n * `transportType: \"httpStream\"` – they are ignored for the stdio transport.\n * Both SSE and HTTP Stream transports support OAuth endpoints.\n */\n oauth?: {\n /**\n * OAuth Authorization Server metadata for /.well-known/oauth-authorization-server\n *\n * This endpoint follows RFC 8414 (OAuth 2.0 Authorization Server Metadata)\n * and provides metadata about the OAuth 2.0 authorization server.\n *\n * Required by MCP Specification 2025-03-26\n */\n authorizationServer?: {\n authorizationEndpoint: string;\n // Client ID Metadata Documents (SEP-991) accepted in place of DCR\n clientIdMetadataDocumentSupported?: boolean;\n codeChallengeMethodsSupported?: string[];\n // DPoP support\n dpopSigningAlgValuesSupported?: string[];\n grantTypesSupported?: string[];\n\n introspectionEndpoint?: string;\n // Required\n issuer: string;\n // Common optional\n jwksUri?: string;\n opPolicyUri?: string;\n opTosUri?: string;\n registrationEndpoint?: string;\n responseModesSupported?: string[];\n responseTypesSupported: string[];\n revocationEndpoint?: string;\n scopesSupported?: string[];\n serviceDocumentation?: string;\n tokenEndpoint: string;\n tokenEndpointAuthMethodsSupported?: string[];\n tokenEndpointAuthSigningAlgValuesSupported?: string[];\n\n uiLocalesSupported?: string[];\n };\n\n /**\n * Whether OAuth discovery endpoints should be enabled.\n */\n enabled: boolean;\n\n /**\n * OAuth Protected Resource metadata for `/.well-known/oauth-protected-resource`\n *\n * This endpoint follows {@link https://www.rfc-editor.org/rfc/rfc9728.html | RFC 9728}\n * and provides metadata describing how an OAuth 2.0 protected resource (in this case,\n * an MCP server) expects to be accessed.\n *\n * When configured, FastMCP will automatically serve this metadata at the\n * `/.well-known/oauth-protected-resource` endpoint. The `authorizationServers` and `resource`\n * fields are required. All others are optional and will be omitted from the published\n * metadata if not specified.\n *\n * This satisfies the requirements of the MCP Authorization specification's\n * {@link https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#authorization-server-location | Authorization Server Location section}.\n *\n * Clients consuming this metadata MUST validate that any presented values comply with\n * RFC 9728, including strict validation of the `resource` identifier and intended audience\n * when access tokens are issued and presented (per RFC 8707 §2).\n *\n * @remarks Required by MCP Specification version 2025-06-18\n */\n protectedResource?: {\n /**\n * Allows for additional metadata fields beyond those defined in RFC 9728.\n *\n * @remarks This supports vendor-specific or experimental extensions.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2.3 | RFC 9728 §2.3}\n */\n [key: string]: unknown;\n\n /**\n * Supported values for the `authorization_details` parameter (RFC 9396).\n *\n * @remarks Used when fine-grained access control is in play.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.23 | RFC 9728 §2.2.23}\n */\n authorizationDetailsTypesSupported?: string[];\n\n /**\n * List of OAuth 2.0 authorization server issuer identifiers.\n *\n * These correspond to ASes that can issue access tokens for this protected resource.\n * MCP clients use these values to locate the relevant `/.well-known/oauth-authorization-server`\n * metadata for initiating the OAuth flow.\n *\n * @remarks Required by the MCP spec. MCP servers MUST provide at least one issuer.\n * Clients are responsible for choosing among them (see RFC 9728 §7.6).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.3 | RFC 9728 §2.2.3}\n */\n authorizationServers: string[];\n\n /**\n * List of supported methods for presenting OAuth 2.0 bearer tokens.\n *\n * @remarks Valid values are `header`, `body`, and `query`.\n * If omitted, clients MAY assume only `header` is supported, per RFC 6750.\n * This is a client-side interpretation and not a serialization default.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.9 | RFC 9728 §2.2.9}\n */\n bearerMethodsSupported?: string[];\n\n /**\n * Whether this resource requires all access tokens to be DPoP-bound.\n *\n * @remarks If omitted, clients SHOULD assume this is `false`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.27 | RFC 9728 §2.2.27}\n */\n dpopBoundAccessTokensRequired?: boolean;\n\n /**\n * Supported algorithms for verifying DPoP proofs (RFC 9449).\n *\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.25 | RFC 9728 §2.2.25}\n */\n dpopSigningAlgValuesSupported?: string[];\n\n /**\n * JWKS URI of this resource. Used to validate access tokens or sign responses.\n *\n * @remarks When present, this MUST be an `https:` URI pointing to a valid JWK Set (RFC 7517).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.5 | RFC 9728 §2.2.5}\n */\n jwksUri?: string;\n\n /**\n * Canonical OAuth resource identifier for this protected resource (the MCP server).\n *\n * @remarks Typically the base URL of the MCP server. Clients MUST use this as the\n * `resource` parameter in authorization and token requests (per RFC 8707).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.1 | RFC 9728 §2.2.1}\n */\n resource: string;\n\n /**\n * URL to developer-accessible documentation for this resource.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n resourceDocumentation?: string;\n\n /**\n * Human-readable name for display purposes (e.g., in UIs).\n *\n * @remarks This field MAY be localized using language tags (`resource_name#en`, etc.).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.13 | RFC 9728 §2.2.13}\n */\n resourceName?: string;\n\n /**\n * URL to a human-readable policy page describing acceptable use.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.17 | RFC 9728 §2.2.17}\n */\n resourcePolicyUri?: string;\n\n /**\n * Supported JWS algorithms for signed responses from this resource (e.g., response signing).\n *\n * @remarks MUST NOT include `none`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.11 | RFC 9728 §2.2.11}\n */\n resourceSigningAlgValuesSupported?: string[];\n\n /**\n * URL to the protected resource’s Terms of Service.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.19 | RFC 9728 §2.2.19}\n */\n resourceTosUri?: string;\n\n /**\n * Supported OAuth scopes for requesting access to this resource.\n *\n * @remarks Useful for discovery, but clients SHOULD still request the minimal scope required.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.7 | RFC 9728 §2.2.7}\n */\n scopesSupported?: string[];\n\n /**\n * Developer-accessible documentation for how to use the service (not end-user docs).\n *\n * @remarks Semantically equivalent to `resourceDocumentation`, but included under its\n * alternate name for compatibility with tools or schemas expecting either.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n serviceDocumentation?: string;\n\n /**\n * Whether mutual-TLS-bound access tokens are required.\n *\n * @remarks If omitted, clients SHOULD assume this is `false` (client-side behavior).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.21 | RFC 9728 §2.2.21}\n */\n tlsClientCertificateBoundAccessTokens?: boolean;\n };\n\n /**\n * OAuth Proxy instance for automatic OAuth flow handling.\n * When provided, FastMCP will automatically register OAuth endpoints:\n * - /oauth/register (DCR)\n * - /oauth/authorize\n * - /oauth/token\n * - /oauth/callback\n * - /oauth/consent\n */\n proxy?: OAuthProxy;\n };\n /**\n * Callback invoked when a tool is called.\n * Use this to log, audit, or track tool usage.\n */\n onToolCall?: (context: {\n arguments: Record<string, unknown>;\n toolName: string;\n }) => Promise<void> | void;\n\n ping?: {\n /**\n * Whether ping should be enabled by default.\n * - true for SSE or HTTP Stream\n * - false for stdio\n */\n enabled?: boolean;\n /**\n * Interval\n * @default 5000 (5s)\n */\n intervalMs?: number;\n /**\n * Logging level for ping-related messages.\n * @default 'debug'\n */\n logLevel?: LoggingLevel;\n };\n /**\n * Configuration for roots capability\n */\n roots?: {\n /**\n * Whether roots capability should be enabled\n * Set to false to completely disable roots support\n * @default true\n */\n enabled?: boolean;\n };\n /**\n * Writes periodically to an in-flight tool call's own response stream, so a\n * proxy or load balancer does not close the connection as idle while a\n * long-running tool produces no output.\n *\n * Unlike {@link ServerOptions.ping}, these messages are related to the\n * request being served, so they travel on that request's stream instead of\n * the standalone server-to-client stream. That makes them the only option\n * that works with `httpStream.stateless`, where no standing server-to-client\n * stream exists.\n */\n streamKeepalive?: {\n /**\n * Whether to write keepalives. Opt-in.\n * @default false\n */\n enabled?: boolean;\n /**\n * Interval between keepalives. Keep it comfortably below the shortest idle\n * timeout on the path (AWS ALB defaults to 60s). Values below 1ms fall back\n * to the default.\n * @default 20000 (20s)\n */\n intervalMs?: number;\n /**\n * Level reported on the keepalive notification.\n * @default 'debug'\n */\n logLevel?: LoggingLevel;\n };\n /**\n * Optional human-readable title for display in client UIs.\n * Advertised via MCP `initialize` (`serverInfo.title`).\n */\n title?: string;\n /**\n * General utilities\n */\n utils?: {\n formatInvalidParamsErrorMessage?: (\n issues: readonly StandardSchemaV1.Issue[],\n ) => string;\n };\n version: `${number}.${number}.${number}`;\n /**\n * Optional URL of the website for this server.\n * Advertised via MCP `initialize` (`serverInfo.websiteUrl`).\n */\n websiteUrl?: string;\n};\n\ntype Tool<\n T extends FastMCPSessionAuth,\n Params extends ToolParameters = ToolParameters,\n OutputParams extends ToolParameters = ToolParameters,\n> = {\n /**\n * MCP ext-apps metadata for linking interactive UI components.\n * This field is passed through to the tool listing response.\n * @see https://modelcontextprotocol.github.io/ext-apps/\n */\n _meta?: {\n /** Additional metadata fields */\n [key: string]: unknown;\n /** UI component configuration */\n ui?: {\n /** URI of the resource serving the UI (e.g., \"ui://my-tool/app.html\") */\n resourceUri?: string;\n };\n };\n annotations?: {\n /**\n * Advisory metadata signalling that the tool streams incremental content\n * via {@link Context.streamContent}. Forwarded verbatim in `tools/list`.\n *\n * This has no effect on FastMCP's behavior: it neither enables nor is\n * required by `streamContent`. No known client interprets it today.\n */\n streamingHint?: boolean;\n } & ToolAnnotations;\n canAccess?: (auth: T) => boolean;\n\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 | ResourceLink\n | StandardSchemaV1.InferOutput<OutputParams>\n | string\n | TextContent\n | void\n >;\n name: string;\n outputSchema?: OutputParams;\n parameters?: Params;\n timeoutMs?: number;\n};\n\n/**\n * Tool annotations as defined in MCP Specification (2025-03-26)\n * These provide hints about a tool's behavior.\n */\ntype ToolAnnotations = {\n /**\n * If true, the tool may perform destructive updates\n * Only meaningful when readOnlyHint is false\n * @default true\n */\n destructiveHint?: boolean;\n\n /**\n * If true, calling the tool repeatedly with the same arguments has no additional effect\n * Only meaningful when readOnlyHint is false\n * @default false\n */\n idempotentHint?: boolean;\n\n /**\n * If true, the tool may interact with an \"open world\" of external entities\n * @default true\n */\n openWorldHint?: boolean;\n\n /**\n * If true, indicates the tool does not modify its environment\n * @default false\n */\n readOnlyHint?: boolean;\n\n /**\n * A human-readable title for the tool, useful for UI display\n */\n title?: string;\n};\n\nconst FastMCPSessionEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;\n} = EventEmitter;\n\nexport enum ServerState {\n Error = \"error\",\n Running = \"running\",\n Stopped = \"stopped\",\n}\n\n/**\n * Enhanced request object for custom routes\n */\nexport interface FastMCPRequest<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> {\n auth?: T;\n body?: unknown;\n headers: http.IncomingHttpHeaders;\n\n json(): Promise<unknown>;\n\n method: string;\n params: Record<string, string>;\n query: Record<string, string | string[]>;\n\n text(): Promise<string>;\n\n url: string;\n}\n\n/**\n * Enhanced response object for custom routes\n */\nexport interface FastMCPResponse {\n end(data?: Buffer | string): void;\n\n json(data: unknown): void;\n\n send(data: Buffer | string): void;\n\n setHeader(name: string, value: number | string | string[]): FastMCPResponse;\n\n status(code: number): FastMCPResponse;\n}\n\n/**\n * HTTP method types for custom routes\n */\nexport type HTTPMethod =\n | \"DELETE\"\n | \"GET\"\n | \"OPTIONS\"\n | \"PATCH\"\n | \"POST\"\n | \"PUT\";\n\n/**\n * Route handler function type\n */\nexport type RouteHandler<T extends FastMCPSessionAuth = FastMCPSessionAuth> = (\n req: FastMCPRequest<T>,\n res: FastMCPResponse,\n) => Promise<void> | void;\n\n/**\n * Options for configuring custom routes\n */\nexport interface RouteOptions {\n /**\n * Whether this route should bypass authentication.\n * When true, the route handler will be called without authentication,\n * and req.auth will be undefined.\n * @default false\n */\n public?: boolean;\n}\n\n/**\n * Returning a nullish value signals that authentication failed; FastMCP turns\n * it into a 401 rather than creating a session. This is what the built-in\n * OAuth `AuthProvider` does for a missing or invalid bearer token.\n */\ntype Authenticate<T> = (\n request: http.IncomingMessage,\n) => Promise<null | T | undefined>;\n\ntype FastMCPSessionAuth = Record<string, unknown> | undefined;\n\nclass FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}\n\nexport class FastMCPSession<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPSessionEventEmitter {\n public get clientCapabilities(): ClientCapabilities | null {\n return this.#clientCapabilities ?? null;\n }\n\n public get isReady(): boolean {\n return this.#connectionState === \"ready\";\n }\n\n public get loggingLevel(): LoggingLevel {\n return this.#loggingLevel;\n }\n\n public get roots(): Root[] {\n return this.#roots;\n }\n\n public get server(): Server {\n return this.#server;\n }\n\n /**\n * The HTTP session ID, or `undefined` for transports that do not have one.\n *\n * Resolved from the transport rather than captured when the session\n * connects: `StreamableHTTPServerTransport` assigns its `sessionId` while it\n * handles `initialize`, which happens after `connect()` resolves. A value\n * read at connect time is therefore still `undefined`.\n *\n * The first ID seen is latched, so the session keeps reporting it once the\n * transport detaches — `Protocol` drops its transport reference on close,\n * which would otherwise make the ID vanish mid-teardown. Latching is safe\n * because {@link connect} refuses a second transport, so a session never\n * sees two IDs.\n */\n public get sessionId(): string | undefined {\n if (this.#sessionId === undefined) {\n const transportSessionId = this.#server.transport?.sessionId;\n\n if (typeof transportSessionId === \"string\") {\n this.#sessionId = transportSessionId;\n }\n }\n\n return this.#sessionId;\n }\n\n public set sessionId(value: string | undefined) {\n this.#sessionId = value;\n }\n\n /**\n * Aborted once the session ends, and folded into the `signal` every tool\n * call receives. The MCP SDK only aborts a request's own signal for an\n * explicit `notifications/cancelled`, and neither `Protocol` nor\n * `StreamableHTTPServerTransport` touches it when the transport simply goes\n * away — so without this a tool keeps running after the client that asked\n * for it has hung up.\n */\n #abortController = new AbortController();\n\n #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #connectionState: \"closed\" | \"connecting\" | \"error\" | \"ready\" = \"connecting\";\n #logger: Logger;\n #loggingLevel: LoggingLevel = \"info\";\n #needsEventLoopFlush: boolean = false;\n #onToolCall?: ServerOptions<T>[\"onToolCall\"];\n #pingConfig?: ServerOptions<T>[\"ping\"];\n\n #pingInFlight = false;\n #pingInterval: null | ReturnType<typeof setInterval> = null;\n\n #prompts: Map<string, Prompt<T>> = new Map();\n\n #resources: Map<string, Resource<T>> = new Map();\n\n #resourceTemplates: Map<string, ResourceTemplate<T>> = new Map();\n\n #roots: Root[] = [];\n\n #rootsConfig?: ServerOptions<T>[\"roots\"];\n\n #server: Server;\n\n /**\n * Session ID from the Mcp-Session-Id header (HTTP transports only).\n * Used to track per-session state across multiple requests.\n */\n #sessionId?: string;\n\n /**\n * Whether this session serves a single stateless HTTP request. The client\n * handshake belongs to a different session — potentially on a different\n * instance — so capabilities can never be inferred here.\n */\n #stateless: boolean;\n\n #streamKeepaliveConfig: ServerOptions<T>[\"streamKeepalive\"];\n\n /**\n * Resource URIs the connected client has subscribed to via\n * `resources/subscribe`. Used to scope `notifications/resources/updated`\n * to interested clients only.\n */\n #subscriptions: Set<string> = new Set();\n\n #utils?: ServerOptions<T>[\"utils\"];\n\n constructor({\n auth,\n icons,\n instructions,\n logger,\n name,\n onToolCall,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n roots,\n sessionId,\n stateless = false,\n streamKeepalive,\n title,\n tools,\n transportType,\n utils,\n version,\n websiteUrl,\n }: {\n auth?: T;\n icons?: Icon[];\n instructions?: string;\n logger: Logger;\n name: string;\n onToolCall?: ServerOptions<T>[\"onToolCall\"];\n ping?: ServerOptions<T>[\"ping\"];\n prompts: Prompt<T>[];\n resources: Resource<T>[];\n resourcesTemplates: InputResourceTemplate<T>[];\n roots?: ServerOptions<T>[\"roots\"];\n sessionId?: string;\n stateless?: boolean;\n streamKeepalive?: ServerOptions<T>[\"streamKeepalive\"];\n title?: string;\n tools: Tool<T>[];\n transportType?: \"httpStream\" | \"stdio\";\n utils?: ServerOptions<T>[\"utils\"];\n version: string;\n websiteUrl?: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#logger = logger;\n this.#onToolCall = onToolCall;\n this.#pingConfig = ping;\n this.#rootsConfig = roots;\n this.#sessionId = sessionId;\n this.#stateless = stateless;\n this.#streamKeepaliveConfig = streamKeepalive;\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 = { listChanged: true, subscribe: true };\n }\n\n if (prompts.length) {\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n\n this.#capabilities.prompts = { listChanged: true };\n }\n\n this.#capabilities.logging = {};\n\n this.#capabilities.completions = {};\n\n this.#server = new Server(\n {\n ...(icons !== undefined ? { icons } : {}),\n name,\n ...(title !== undefined ? { title } : {}),\n version,\n ...(websiteUrl !== undefined ? { websiteUrl } : {}),\n },\n { capabilities: this.#capabilities, instructions: instructions },\n );\n\n this.#utils = utils;\n\n this.setupErrorHandling();\n this.setupLoggingHandlers();\n this.setupRootsHandlers();\n this.setupCompleteHandlers();\n\n if (tools.length) {\n this.setupToolHandlers(tools);\n }\n\n if (resources.length || resourcesTemplates.length) {\n for (const resource of resources) {\n this.addResource(resource);\n }\n\n for (const resourceTemplate of resourcesTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n\n this.setupResourceHandlers();\n this.setupResourceSubscriptionHandlers();\n // `resources/templates/list` belongs to the `resources` capability that\n // was just advertised, so the handler has to answer even when there is\n // nothing to list - the reference SDK returns an empty array. Gating it\n // on having templates made a resources-only server reply -32601 Method\n // not found to any client that lists templates.\n this.setupResourceTemplateHandlers();\n }\n\n if (prompts.length) {\n this.setupPromptHandlers();\n }\n }\n\n public async close() {\n this.#connectionState = \"closed\";\n\n if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n this.#abortSession();\n\n try {\n await this.#server.close();\n } catch (error) {\n this.#logger.error(\"[FastMCP error]\", \"could not close server\", error);\n }\n }\n\n public async connect(transport: Transport) {\n if (this.#server.transport) {\n throw new UnexpectedStateError(\"Server is already connected\");\n }\n\n this.#connectionState = \"connecting\";\n\n try {\n await this.#server.connect(transport);\n\n // Skipped in stateless mode: a session there serves one request, and the\n // initialize that carried the client's capabilities was handled by a\n // different session, so polling can only ever time out and warn — once\n // per request.\n if (!this.#stateless) {\n let attempt = 0;\n const maxAttempts = 10;\n const retryDelay = 100;\n\n while (attempt++ < maxAttempts) {\n const capabilities = this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n break;\n }\n\n await delay(retryDelay);\n }\n\n if (!this.#clientCapabilities) {\n this.#logger.warn(\n `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`,\n );\n }\n }\n\n if (\n this.#rootsConfig?.enabled !== false &&\n this.#clientCapabilities?.roots?.listChanged &&\n typeof this.#server.listRoots === \"function\"\n ) {\n try {\n const roots = await this.#server.listRoots();\n this.#roots = roots?.roots || [];\n } catch (e) {\n if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n e instanceof Error ? e.stack : JSON.stringify(e)\n }`,\n );\n }\n }\n }\n\n if (this.#clientCapabilities) {\n const pingConfig = this.#getPingConfig(transport);\n\n if (pingConfig.enabled) {\n this.#pingInterval = setInterval(async () => {\n if (this.#pingInFlight) {\n return;\n }\n\n this.#pingInFlight = true;\n\n try {\n await this.#server.ping();\n } catch {\n // The reason we are not emitting an error here is because some clients\n // seem to not respond to the ping request, and we don't want to crash the server,\n // e.g., https://github.com/punkpeye/fastmcp/issues/38.\n const logLevel = pingConfig.logLevel;\n\n if (logLevel === \"debug\") {\n this.#logger.debug(\"[FastMCP debug] server ping failed\");\n } else if (logLevel === \"warning\") {\n this.#logger.warn(\n \"[FastMCP warning] server is not responding to ping\",\n );\n } else if (logLevel === \"error\") {\n this.#logger.error(\n \"[FastMCP error] server is not responding to ping\",\n );\n } else {\n this.#logger.info(\"[FastMCP info] server ping failed\");\n }\n } finally {\n this.#pingInFlight = false;\n }\n }, pingConfig.intervalMs);\n }\n }\n\n // Mark connection as ready and emit event\n this.#connectionState = \"ready\";\n this.emit(\"ready\");\n } catch (error) {\n this.#connectionState = \"error\";\n const errorEvent = {\n error: error instanceof Error ? error : new Error(String(error)),\n };\n this.emit(\"error\", errorEvent);\n throw error;\n }\n }\n\n promptsListChanged(prompts: Prompt<T>[]) {\n this.#prompts.clear();\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n this.setupPromptHandlers();\n this.triggerListChangedNotification(\"notifications/prompts/list_changed\");\n }\n\n public async requestElicitation(\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ): Promise<ElicitResult> {\n return this.#server.elicitInput(params, options);\n }\n\n public async requestSampling(\n message: z.infer<typeof CreateMessageRequestSchema>[\"params\"],\n options?: RequestOptions,\n ): Promise<SamplingResponse> {\n return this.#server.createMessage(message, options);\n }\n\n resourcesListChanged(resources: Resource<T>[]) {\n this.#resources.clear();\n for (const resource of resources) {\n this.addResource(resource);\n }\n this.setupResourceHandlers();\n this.triggerListChangedNotification(\"notifications/resources/list_changed\");\n }\n\n resourceTemplatesListChanged(resourceTemplates: ResourceTemplate<T>[]) {\n this.#resourceTemplates.clear();\n for (const resourceTemplate of resourceTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n this.setupResourceTemplateHandlers();\n this.triggerListChangedNotification(\"notifications/resources/list_changed\");\n }\n\n /**\n * Notifies the connected client that the contents of a resource have changed.\n *\n * The `notifications/resources/updated` notification is only sent when the\n * client has subscribed to the URI via `resources/subscribe`; otherwise this\n * is a no-op.\n */\n async sendResourceUpdated(uri: string) {\n if (!this.#subscriptions.has(uri)) {\n return;\n }\n\n try {\n await this.#server.sendResourceUpdated({ uri });\n } catch (error) {\n this.#logger.error(\n `[FastMCP error] failed to send resources/updated notification for '${uri}'.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n }\n\n toolsListChanged(tools: Tool<T>[]) {\n const allowedTools = tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(this.#auth as T) : true,\n );\n this.setupToolHandlers(allowedTools);\n this.triggerListChangedNotification(\"notifications/tools/list_changed\");\n }\n\n async triggerListChangedNotification(method: string) {\n try {\n await this.#server.notification({\n method,\n });\n } catch (error) {\n this.#logger.error(\n `[FastMCP error] failed to send ${method} notification.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n }\n\n /**\n * Update the session's authentication context.\n * Called by mcp-proxy when a new token is validated on subsequent requests.\n */\n public updateAuth(auth: T): void {\n this.#auth = auth;\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 /**\n * Cancels the `signal` held by every tool still executing on this session.\n * Idempotent, so the close path and the transport's own close handler can\n * both call it.\n */\n #abortSession() {\n if (!this.#abortController.signal.aborted) {\n this.#abortController.abort(new SessionError(\"Session closed\"));\n }\n }\n\n /**\n * Builds the context object passed as the third argument to\n * `resource.load` / `resourceTemplate.load` / `prompt.load`.\n *\n * This mirrors the `client`, `elicit`, `log`, `requestId`, `session`,\n * and `sessionId` fields available to `tool.execute` via {@link Context}.\n * `reportProgress` and `streamContent` are intentionally omitted: they\n * are tied to a tool call's progress token / streaming notification,\n * which resource and prompt reads do not have.\n */\n #createLoadContext(meta?: Record<string, unknown>): LoadContext<T> {\n return {\n client: {\n version: this.#server.getClientVersion(),\n },\n elicit: (\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ) => this.#server.elicitInput(params, options),\n log: this.#createLog(),\n requestId:\n typeof meta?.requestId === \"string\" ? meta.requestId : undefined,\n session: this.#auth,\n sessionId: this.sessionId,\n };\n }\n\n #createLog(): Context<T>[\"log\"] {\n return {\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\n #formatSchemaIssues(issues: readonly StandardSchemaV1.Issue[]): string {\n return this.#utils?.formatInvalidParamsErrorMessage\n ? this.#utils.formatInvalidParamsErrorMessage(issues)\n : issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\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 /**\n * Periodically writes to the response stream of an in-flight tool call, so an\n * idle-connection timeout (proxy, load balancer) does not close it while a\n * long-running tool produces no output of its own.\n *\n * The notification is related to the tool call, so it travels on that\n * request's own stream, which is the only server-to-client route that exists\n * when running stateless.\n *\n * @returns a function that stops the keepalive.\n */\n #startStreamKeepalive(\n extra: Pick<\n RequestHandlerExtra<ServerRequest, ServerNotification>,\n \"sendNotification\" | \"signal\"\n >,\n toolName: string,\n ): () => void {\n const config = this.#streamKeepaliveConfig;\n\n if (!config?.enabled) {\n return () => {};\n }\n\n // A non-positive interval would fire on every tick and flood the stream.\n const intervalMs =\n config.intervalMs && config.intervalMs > 0\n ? config.intervalMs\n : STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS;\n\n const timer = setInterval(() => {\n extra\n .sendNotification({\n method: \"notifications/message\",\n params: {\n data: { message: `keepalive while '${toolName}' is running` },\n level: config.logLevel ?? \"debug\",\n logger: STREAM_KEEPALIVE_LOGGER,\n },\n })\n .catch((error: unknown) => {\n // Left running: the caller stops it when the request finishes, and a\n // transient write failure should not silence the connection.\n this.#logger.debug(\n `[FastMCP debug] stream keepalive for '${toolName}' failed:`,\n error instanceof Error ? error.message : String(error),\n );\n });\n }, intervalMs);\n\n timer.unref?.();\n\n const stop = () => clearInterval(timer);\n\n // A cancelled or disconnected request stops waiting for the tool, so the\n // keepalive must not outlive the abort.\n extra.signal?.addEventListener(\"abort\", stop, { once: true });\n\n return stop;\n }\n\n async #validateStructuredContent(\n tool: Tool<T>,\n value: Record<string, unknown>,\n toolName: string,\n ): Promise<Record<string, unknown>> {\n if (!tool.outputSchema) {\n return value;\n }\n\n const parsed = await tool.outputSchema[\"~standard\"].validate(value);\n\n if (parsed.issues) {\n throw new UserError(\n `Tool '${toolName}' structured output validation failed: ${this.#formatSchemaIssues(parsed.issues)}. Please check the result matches the tool's outputSchema.`,\n );\n }\n\n return parsed.value as Record<string, unknown>;\n }\n\n private addPrompt(inputPrompt: InputPrompt<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n const enums: Record<string, string[]> = {};\n const fuseInstances: Record<string, Fuse<string>> = {};\n\n for (const argument of inputPrompt.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n\n if (argument.enum) {\n enums[argument.name] = argument.enum;\n fuseInstances[argument.name] = new Fuse(argument.enum, {\n includeScore: true,\n threshold: 0.3, // More flexible matching!\n });\n }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n if (inputPrompt.complete) {\n return await inputPrompt.complete(name, value, auth);\n }\n\n if (fuseInstances[name]) {\n // An empty query yields no fuzzy matches, so a client asking for\n // completions before the user has typed anything would see nothing.\n // Offer the full enum instead — it is the set of valid values, and\n // the central cap trims it to the MCP limit if it is large.\n if (value === \"\") {\n const values = enums[name];\n\n return {\n total: values.length,\n values,\n };\n }\n\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.set(prompt.name, prompt);\n }\n\n private addResource(inputResource: Resource<T>) {\n this.#resources.set(inputResource.uri, inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n\n for (const argument of inputResourceTemplate.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n }\n\n const resourceTemplate = {\n ...inputResourceTemplate,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n if (inputResourceTemplate.complete) {\n return await inputResourceTemplate.complete(name, value, auth);\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#resourceTemplates.set(resourceTemplate.name, resourceTemplate);\n }\n\n private setupCompleteHandlers() {\n this.#server.setRequestHandler(CompleteRequestSchema, async (request) => {\n if (request.params.ref.type === \"ref/prompt\") {\n const ref = request.params.ref;\n\n const prompt = \"name\" in ref && this.#prompts.get(ref.name);\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 = capCompletionValues(\n CompletionZodSchema.parse(\n await prompt.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n ),\n );\n\n return {\n completion,\n };\n }\n\n if (request.params.ref.type === \"ref/resource\") {\n const ref = request.params.ref;\n\n const resource =\n \"uri\" in ref &&\n Array.from(this.#resourceTemplates.values()).find(\n (resource) => resource.uriTemplate === 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 = capCompletionValues(\n CompletionZodSchema.parse(\n await resource.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n ),\n );\n\n return {\n completion,\n };\n }\n\n throw new UnexpectedStateError(\"Unexpected completion request\", {\n request,\n });\n });\n }\n\n private setupErrorHandling() {\n this.#server.onerror = (error) => {\n this.#logger.error(\"[FastMCP error]\", error);\n };\n\n // Covers the client that hangs up rather than closing politely: `close()`\n // never runs in that case, but the transport still reports the loss.\n this.#server.onclose = () => {\n this.#abortSession();\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() {\n let cachedPromptsList: ListPromptsResult[\"prompts\"] | null = null;\n\n this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {\n if (cachedPromptsList) {\n return {\n prompts: cachedPromptsList,\n };\n }\n\n cachedPromptsList = Array.from(this.#prompts.values()).map((prompt) => {\n return {\n arguments: prompt.arguments,\n complete: prompt.complete,\n description: prompt.description,\n name: prompt.name,\n };\n });\n\n return {\n prompts: cachedPromptsList,\n };\n });\n\n this.#server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = this.#prompts.get(request.params.name);\n\n if (!prompt) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown prompt: ${request.params.name}`,\n );\n }\n\n const args = request.params.arguments;\n\n for (const arg of prompt.arguments ?? []) {\n if (arg.required && !(args && arg.name in args)) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Prompt '${request.params.name}' requires argument '${arg.name}': ${\n arg.description || \"No description provided\"\n }`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt<T>[\"load\"]>>;\n\n try {\n result = await prompt.load(\n args as Record<string, string | undefined>,\n this.#auth,\n this.#createLoadContext(request.params?._meta),\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load prompt '${request.params.name}': ${errorMessage}`,\n );\n }\n\n if (typeof result === \"string\") {\n return {\n description: prompt.description,\n messages: [\n {\n content: { text: result, type: \"text\" },\n role: \"user\",\n },\n ],\n };\n } else {\n return {\n description: prompt.description,\n messages: result.messages,\n };\n }\n });\n }\n\n private setupResourceHandlers() {\n let cachedResourcesList: ListResourcesResult[\"resources\"] | null = null;\n\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n if (cachedResourcesList) {\n return {\n resources: cachedResourcesList,\n };\n }\n\n cachedResourcesList = Array.from(this.#resources.values()).map(\n (resource) => ({\n description: resource.description,\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n }),\n );\n\n return {\n resources: cachedResourcesList,\n };\n });\n\n this.#server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n if (\"uri\" in request.params) {\n const resource = this.#resources.get(request.params.uri);\n\n if (!resource) {\n for (const resourceTemplate of this.#resourceTemplates.values()) {\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(\n match,\n this.#auth,\n this.#createLoadContext(request.params?._meta),\n );\n\n const resources = Array.isArray(result) ? result : [result];\n return {\n contents: resources.map((resource) => ({\n ...resource,\n description: resourceTemplate.description,\n mimeType: resource.mimeType ?? resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uri: resource.uri ?? uri,\n })),\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Resource not found: '${request.params.uri}'. Available resources: ${\n Array.from(this.#resources.values())\n .map((r) => r.uri)\n .join(\", \") || \"none\"\n }`,\n );\n }\n\n if (!(\"uri\" in resource)) {\n throw new UnexpectedStateError(\"Resource does not support reading\");\n }\n\n let maybeArrayResult: Awaited<ReturnType<Resource<T>[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load(\n this.#auth,\n this.#createLoadContext(request.params?._meta),\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load resource '${resource.name}' (${resource.uri}): ${errorMessage}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n const resourceResults = Array.isArray(maybeArrayResult)\n ? maybeArrayResult\n : [maybeArrayResult];\n\n return {\n contents: resourceResults.map((result) => ({\n ...result,\n mimeType: result.mimeType ?? resource.mimeType,\n name: resource.name,\n uri: result.uri ?? resource.uri,\n })),\n };\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n\n private setupResourceSubscriptionHandlers() {\n this.#server.setRequestHandler(SubscribeRequestSchema, (request) => {\n this.#subscriptions.add(request.params.uri);\n\n return {};\n });\n\n this.#server.setRequestHandler(UnsubscribeRequestSchema, (request) => {\n this.#subscriptions.delete(request.params.uri);\n\n return {};\n });\n }\n\n private setupResourceTemplateHandlers() {\n let cachedResourceTemplatesList:\n | ListResourceTemplatesResult[\"resourceTemplates\"]\n | null = null;\n\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n if (cachedResourceTemplatesList) {\n return {\n resourceTemplates: cachedResourceTemplatesList,\n };\n }\n\n cachedResourceTemplatesList = Array.from(\n this.#resourceTemplates.values(),\n ).map((resourceTemplate) => ({\n description: resourceTemplate.description,\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n }));\n\n return {\n resourceTemplates: cachedResourceTemplatesList,\n };\n },\n );\n }\n\n private setupRootsHandlers() {\n if (this.#rootsConfig?.enabled === false) {\n this.#logger.debug(\n \"[FastMCP debug] roots capability explicitly disabled via config\",\n );\n return;\n }\n\n // Only set up roots notification handling if the server supports it\n if (typeof this.#server.listRoots === \"function\") {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server\n .listRoots()\n .then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n })\n .catch((error) => {\n if (\n error instanceof McpError &&\n error.code === ErrorCode.MethodNotFound\n ) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n });\n },\n );\n } else {\n this.#logger.debug(\n \"[FastMCP debug] roots capability not available, not setting up notification handler\",\n );\n }\n }\n\n private setupToolHandlers(tools: Tool<T>[]) {\n const toolsMap = new Map(tools.map((tool) => [tool.name, tool]));\n let cachedToolsList: ListToolsResult[\"tools\"] | null = null;\n\n this.#server.setRequestHandler(ListToolsRequestSchema, async () => {\n if (cachedToolsList) {\n return {\n tools: cachedToolsList,\n };\n }\n cachedToolsList = await Promise.all(\n tools.map(async (tool) => {\n return {\n annotations: tool.annotations,\n description: tool.description,\n inputSchema: (tool.parameters\n ? strictJsonSchema(await toJsonSchema(tool.parameters))\n : {\n additionalProperties: false,\n properties: {},\n type: \"object\",\n }) as SDKTool[\"inputSchema\"],\n name: tool.name,\n ...(tool.outputSchema && {\n outputSchema: strictJsonSchema(\n await toJsonSchema(tool.outputSchema),\n ) as SDKTool[\"inputSchema\"],\n }),\n // Pass through _meta for MCP ext-apps UI support (issue #229)\n ...(tool._meta && { _meta: tool._meta }),\n };\n }),\n );\n\n return {\n tools: cachedToolsList,\n };\n });\n\n this.#server.setRequestHandler(\n CallToolRequestSchema,\n async (request, extra) => {\n const tool = toolsMap.get(request.params.name);\n\n if (!tool) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n\n let args: unknown = undefined;\n\n if (tool.parameters) {\n const parsed = await tool.parameters[\"~standard\"].validate(\n request.params.arguments,\n );\n\n if (parsed.issues) {\n const friendlyErrors = this.#formatSchemaIssues(parsed.issues);\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 // Progress notifications must reference the progressToken supplied by\n // the client in the initiating request. If the client did not request\n // progress, there is nothing to associate the update with, and sending\n // a notification without a token produces an invalid message.\n if (progressToken === undefined) {\n return;\n }\n\n try {\n await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (progressError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to report progress for tool '${request.params.name}':`,\n progressError instanceof Error\n ? progressError.message\n : String(progressError),\n );\n }\n };\n\n const log = this.#createLog();\n\n // Create a promise for tool execution\n // Streams partial results while a tool is still executing\n // Enables progressive rendering and real-time feedback\n const streamContent = async (content: Content | Content[]) => {\n const contentArray = Array.isArray(content) ? content : [content];\n\n try {\n await this.#server.notification({\n method: \"notifications/tool/streamContent\",\n params: {\n content: contentArray,\n toolName: request.params.name,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (streamError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to stream content for tool '${request.params.name}':`,\n streamError instanceof Error\n ? streamError.message\n : String(streamError),\n );\n }\n };\n\n if (this.#onToolCall) {\n await this.#onToolCall({\n arguments: (args ?? {}) as Record<string, unknown>,\n toolName: request.params.name,\n });\n }\n\n // Aborted when this call times out. Kept separate from the sources\n // below so the timer that drives it can still be cleared the moment\n // the tool settles — a fired-and-forgotten timeout would abort the\n // signal after a successful call and run the tool's cleanup for it.\n const timeoutAbort = new AbortController();\n\n // Composed rather than forwarded by hand: `AbortSignal.any()` needs\n // no listener bookkeeping, so nothing leaks when `execute` throws\n // synchronously, and Node holds the composite through a WeakRef, so\n // a per-call signal cannot pin the session-scoped one.\n const signal = AbortSignal.any([\n timeoutAbort.signal,\n this.#abortController.signal,\n // Only ever aborted for an explicit `notifications/cancelled`; the\n // session signal above is what covers a client that simply left.\n ...(extra.signal ? [extra.signal] : []),\n ]);\n\n const executeToolPromise = Promise.resolve(\n tool.execute(args, {\n client: {\n version: this.#server.getClientVersion(),\n },\n elicit: (\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ) => this.#server.elicitInput(params, options),\n log,\n reportProgress,\n requestId:\n typeof request.params?._meta?.requestId === \"string\"\n ? request.params._meta.requestId\n : undefined,\n session: this.#auth,\n sessionId: this.sessionId,\n signal,\n streamContent,\n }),\n );\n\n // Started only once execute has returned a promise, so a tool that\n // throws synchronously cannot leave a timer behind.\n const stopStreamKeepalive = this.#startStreamKeepalive(\n extra,\n request.params.name,\n );\n\n // Handle timeout if specified\n const maybeStringResult = (await (\n tool.timeoutMs\n ? Promise.race([\n executeToolPromise,\n new Promise<never>((_, reject) => {\n const timeoutId = setTimeout(() => {\n const timedOut = new UserError(\n `Tool '${request.params.name}' timed out after ${tool.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`,\n );\n\n // Abort before rejecting: the tool learns it lost the\n // race while its own frame is still the reason, rather\n // than after the error has already gone back out.\n timeoutAbort.abort(timedOut);\n reject(timedOut);\n }, tool.timeoutMs);\n\n // If promise resolves first\n executeToolPromise.then(\n () => clearTimeout(timeoutId),\n () => clearTimeout(timeoutId),\n );\n }),\n ])\n : executeToolPromise\n ).finally(stopStreamKeepalive)) as\n | AudioContent\n | ContentResult\n | ImageContent\n | null\n | Record<string, unknown>\n | ResourceContent\n | ResourceLink\n | string\n | TextContent\n | undefined;\n\n // Without this test, we are running into situations where the last progress update is not reported.\n // See the 'reports multiple progress updates without buffering' test in FastMCP.test.ts before refactoring.\n await delay(1);\n\n if (maybeStringResult === undefined || maybeStringResult === null) {\n result = ContentResultZodSchema.parse({\n content: [],\n });\n } else if (typeof maybeStringResult === \"string\") {\n result = ContentResultZodSchema.parse({\n content: [{ text: maybeStringResult, type: \"text\" }],\n });\n } else if (\n \"content\" in maybeStringResult &&\n Array.isArray(maybeStringResult.content) &&\n (!tool.outputSchema ||\n ContentResultZodSchema.safeParse(maybeStringResult).success)\n ) {\n // Explicit ContentResult: the tool returned MCP content directly\n // (`{ content: [...], structuredContent? }`), so it takes precedence\n // over outputSchema and a tool can ship custom content blocks\n // alongside its structured payload. When an outputSchema is\n // declared, only claim the value if it really parses as a\n // ContentResult — otherwise an array-valued `content` field in the\n // structured payload itself would be misread as content blocks.\n result = ContentResultZodSchema.parse(maybeStringResult);\n if (result.structuredContent !== undefined && tool.outputSchema) {\n result.structuredContent = await this.#validateStructuredContent(\n tool,\n result.structuredContent,\n request.params.name,\n );\n }\n } else if (tool.outputSchema) {\n // A tool that declares an outputSchema returns its structured\n // payload directly, so outputSchema wins over the `type`/`content`\n // shorthands below. Without this precedence a payload whose\n // top-level shape happens to carry a `type` key (the common\n // discriminated-union case) or a `content` key would be misrouted\n // as MCP content and never surface as structuredContent.\n const structuredContent = await this.#validateStructuredContent(\n tool,\n maybeStringResult,\n request.params.name,\n );\n result = ContentResultZodSchema.parse({\n content: [\n {\n text: JSON.stringify(structuredContent),\n type: \"text\",\n },\n ],\n structuredContent,\n });\n } else if (\"type\" in maybeStringResult) {\n result = ContentResultZodSchema.parse({\n content: [maybeStringResult],\n });\n } else {\n result = ContentResultZodSchema.parse(maybeStringResult);\n }\n } catch (error) {\n if (error instanceof UserError) {\n return {\n content: [{ text: error.message, type: \"text\" }],\n isError: true,\n ...(error.extras ? { structuredContent: error.extras } : {}),\n };\n }\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n text: `Tool '${request.params.name}' execution failed: ${errorMessage}`,\n type: \"text\",\n },\n ],\n isError: true,\n };\n }\n\n return result;\n },\n );\n }\n}\n\n/**\n * Converts camelCase to snake_case for OAuth endpoint responses\n */\nfunction camelToSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Converts an object with camelCase keys to snake_case keys\n */\nfunction convertObjectToSnakeCase(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = camelToSnakeCase(key);\n result[snakeKey] = value;\n }\n\n return result;\n}\n\nfunction joinPaths(basePath: \"\" | `/${string}`, path: string): `/${string}` {\n return `${basePath}${normalizePath(path)}` as `/${string}`;\n}\n\nfunction normalizeBasePath(path: string | undefined): \"\" | `/${string}` {\n if (!path || path === \"/\") {\n return \"\";\n }\n\n const withLeadingSlash = path.startsWith(\"/\") ? path : `/${path}`;\n const withoutTrailingSlash = withLeadingSlash.replace(/\\/+$/, \"\");\n\n return withoutTrailingSlash ? (withoutTrailingSlash as `/${string}`) : \"\";\n}\n\nfunction normalizePath(path: string): `/${string}` {\n return (path.startsWith(\"/\") ? path : `/${path}`) as `/${string}`;\n}\n\n/**\n * Parses Basic auth header (RFC 6749 Section 2.3.1)\n */\nfunction parseBasicAuthHeader(\n authHeader: string | undefined,\n): { clientId: string; clientSecret: string } | null {\n const basicMatch = authHeader?.match(/^Basic\\s+(.+)$/);\n if (!basicMatch) return null;\n\n try {\n const credentials = Buffer.from(basicMatch[1], \"base64\").toString(\"utf-8\");\n const credMatch = credentials.match(/^([^:]+):(.*)$/);\n if (!credMatch) return null;\n\n return { clientId: credMatch[1], clientSecret: credMatch[2] };\n } catch {\n return null;\n }\n}\n\n/**\n * Maximum request body size (in bytes) accepted by the OAuth proxy endpoints\n * (registration, consent and token). These endpoints receive small JSON or\n * form-urlencoded payloads, so 1 MiB is a generous bound that prevents\n * unbounded memory growth from slow or malicious clients.\n */\nconst OAUTH_PROXY_MAX_BODY_SIZE = 1024 * 1024; // 1 MiB\n\n/**\n * RFC 6749 §5.1 requires `Cache-Control: no-store` and `Pragma: no-cache` on\n * token endpoint responses, and RFC 7591 §3.2.1 requires the same for a\n * registration response carrying `client_secret`. Without them an intermediary\n * proxy or the browser may retain the credential.\n */\nconst OAUTH_CREDENTIAL_RESPONSE_HEADERS = {\n \"Cache-Control\": \"no-store\",\n \"Content-Type\": \"application/json\",\n Pragma: \"no-cache\",\n} as const;\n\nfunction stripBasePath(\n path: string,\n basePath: \"\" | `/${string}`,\n): null | string {\n if (!basePath) {\n return path;\n }\n\n if (path === basePath) {\n return \"/\";\n }\n\n if (path.startsWith(`${basePath}/`)) {\n return path.slice(basePath.length);\n }\n\n return null;\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;\n} = EventEmitter;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPEventEmitter {\n public get serverState(): ServerState {\n return this.#serverState;\n }\n\n public get sessions(): FastMCPSession<T>[] {\n return this.#sessions;\n }\n\n #authenticate: Authenticate<T> | undefined;\n #honoApp = new Hono();\n #httpStreamServer: null | SSEServer = null;\n #logger: Logger;\n #options: ServerOptions<T>;\n #prompts: InputPrompt<T>[] = [];\n #resources: Resource<T>[] = [];\n #resourcesTemplates: InputResourceTemplate<T>[] = [];\n #serverState: ServerState = ServerState.Stopped;\n #sessions: FastMCPSession<T>[] = [];\n\n #tools: Tool<T>[] = [];\n\n constructor(public options: ServerOptions<T>) {\n super();\n\n this.#options = options;\n this.#logger = options.logger || console;\n\n // If auth provider is specified, use it to configure authenticate and oauth\n if (options.auth) {\n // Use auth provider's authenticate if not explicitly overridden\n if (!options.authenticate) {\n this.#authenticate = ((request: http.IncomingMessage | undefined) =>\n options.auth!.authenticate(request)) as Authenticate<T>;\n } else {\n this.#authenticate = options.authenticate;\n }\n\n // Use auth provider's oauth config if not explicitly overridden\n if (!options.oauth) {\n this.#options = {\n ...options,\n oauth: options.auth.getOAuthConfig(),\n };\n }\n } else {\n this.#authenticate = options.authenticate;\n }\n }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument<T>[]>(\n prompt: InputPrompt<T, Args>,\n ) {\n this.#prompts = this.#prompts.filter((p) => p.name !== prompt.name);\n this.#prompts.push(prompt);\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Adds prompts to the server.\n */\n public addPrompts<const Args extends InputPromptArgument<T>[]>(\n prompts: InputPrompt<T, Args>[],\n ) {\n const newPromptNames = new Set(prompts.map((prompt) => prompt.name));\n this.#prompts = this.#prompts.filter((p) => !newPromptNames.has(p.name));\n this.#prompts.push(...prompts);\n\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource<T>) {\n this.#resources = this.#resources.filter((r) => r.name !== resource.name);\n\n this.#resources.push(resource);\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Adds resources to the server.\n */\n public addResources(resources: Resource<T>[]) {\n const newResourceNames = new Set(\n resources.map((resource) => resource.name),\n );\n this.#resources = this.#resources.filter(\n (r) => !newResourceNames.has(r.name),\n );\n this.#resources.push(...resources);\n\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Adds a resource template to the server.\n */\n public addResourceTemplate<\n const Args extends InputResourceTemplateArgument[],\n >(resource: InputResourceTemplate<T, Args>) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== resource.name,\n );\n\n this.#resourcesTemplates.push(resource);\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Adds resource templates to the server.\n */\n public addResourceTemplates<\n const Args extends InputResourceTemplateArgument[],\n >(resources: InputResourceTemplate<T, Args>[]) {\n const newResourceTemplateNames = new Set(\n resources.map((resource) => resource.name),\n );\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => !newResourceTemplateNames.has(t.name),\n );\n this.#resourcesTemplates.push(...resources);\n\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Adds a tool to the server.\n */\n public addTool<Params extends ToolParameters>(tool: Tool<T, Params>) {\n assertToolSchemas(tool);\n\n // Remove existing tool with the same name\n this.#tools = this.#tools.filter((t) => t.name !== tool.name);\n this.#tools.push(tool as unknown as Tool<T>);\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Adds tools to the server.\n */\n public addTools<Params extends ToolParameters>(tools: Tool<T, Params>[]) {\n tools.forEach(assertToolSchemas);\n\n const newToolNames = new Set(tools.map((tool) => tool.name));\n this.#tools = this.#tools.filter((t) => !newToolNames.has(t.name));\n this.#tools.push(...(tools as unknown as Tool<T>[]));\n\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Connects the server to a transport you constructed yourself, instead of\n * letting {@link FastMCP.start} create one.\n *\n * The session is built from the tools, resources and prompts registered on\n * this instance — exactly as `start()` does — so tests exercise the same\n * wiring the real server uses. The main use case is driving a server\n * in-process over `InMemoryTransport` without binding a port:\n *\n * ```ts\n * const [clientTransport, serverTransport] =\n * InMemoryTransport.createLinkedPair();\n *\n * await Promise.all([\n * server.connect(serverTransport),\n * client.connect(clientTransport),\n * ]);\n * ```\n *\n * The transport's lifecycle belongs to the caller: `stop()` does not close\n * transports passed here. Close the returned session (or the transport) when\n * you are done with it.\n *\n * @param transport - An already-constructed MCP server transport.\n * @param auth - Session auth, equivalent to what `authenticate` would return.\n * @returns The session bound to the transport.\n */\n public async connect(\n transport: Transport,\n auth?: T,\n ): Promise<FastMCPSession<T>> {\n const session = this.#createSession(auth);\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n session.once(\"error\", () => {\n this.#removeSession(session);\n });\n\n const originalOnClose = transport.onclose;\n\n transport.onclose = () => {\n this.#removeSession(session);\n\n if (originalOnClose) {\n originalOnClose();\n }\n };\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n\n this.#serverState = ServerState.Running;\n\n return session;\n }\n\n /**\n * Embeds a resource by URI, making it easy to include resources in tool responses.\n *\n * @param uri - The URI of the resource to embed\n * @returns Promise<ResourceContent> - The embedded resource content\n */\n public async embedded(uri: string): Promise<ResourceContent[\"resource\"]> {\n // First, try to find a direct resource match\n const directResource = this.#resources.find(\n (resource) => resource.uri === uri,\n );\n\n if (directResource) {\n const result = await directResource.load();\n const results = Array.isArray(result) ? result : [result];\n const firstResult = results[0];\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: directResource.mimeType,\n uri,\n };\n\n if (\"text\" in firstResult) {\n resourceData.text = firstResult.text;\n }\n\n if (\"blob\" in firstResult) {\n resourceData.blob = firstResult.blob;\n }\n\n return resourceData;\n }\n\n // Try to match against resource templates\n for (const template of this.#resourcesTemplates) {\n const parsedTemplate = parseURITemplate(template.uriTemplate);\n const params = parsedTemplate.fromUri(uri);\n if (!params) {\n continue;\n }\n\n const result = await template.load(\n params as ResourceTemplateArgumentsToObject<typeof template.arguments>,\n );\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: template.mimeType,\n uri,\n };\n\n if (\"text\" in result) {\n resourceData.text = result.text;\n }\n\n if (\"blob\" in result) {\n resourceData.blob = result.blob;\n }\n\n return resourceData; // The resource we're looking for\n }\n\n throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });\n }\n\n /**\n * Returns the underlying Hono app instance for direct access to Hono's native API.\n * This allows you to add custom routes, middleware, and handlers using Hono's standard methods.\n *\n * @returns The Hono app instance\n *\n * @example\n * ```typescript\n * const app = server.getApp();\n *\n * // Add routes using native Hono API\n * app.get('/api/users', async (c) => {\n * return c.json({ users: [] });\n * });\n *\n * app.post('/api/users/:id', async (c) => {\n * const id = c.req.param('id');\n * return c.json({ id });\n * });\n * ```\n */\n public getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Removes a prompt from the server.\n */\n public removePrompt(name: string) {\n this.#prompts = this.#prompts.filter((p) => p.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Removes prompts from the server.\n */\n public removePrompts(names: string[]) {\n for (const name of names) {\n this.#prompts = this.#prompts.filter((p) => p.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Removes a resource from the server.\n */\n public removeResource(name: string) {\n this.#resources = this.#resources.filter((r) => r.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Removes resources from the server.\n */\n public removeResources(names: string[]) {\n for (const name of names) {\n this.#resources = this.#resources.filter((r) => r.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Removes a resource template from the server.\n */\n public removeResourceTemplate(name: string) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== name,\n );\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Removes resource templates from the server.\n */\n public removeResourceTemplates(names: string[]) {\n for (const name of names) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== name,\n );\n }\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Removes a tool from the server.\n */\n public removeTool(name: string) {\n // Remove existing tool with the same name\n this.#tools = this.#tools.filter((t) => t.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Removes tools from the server.\n */\n public removeTools(names: string[]) {\n for (const name of names) {\n this.#tools = this.#tools.filter((t) => t.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Notifies subscribed clients that a resource's contents have changed.\n *\n * Sends a `notifications/resources/updated` notification to every connected\n * session that has subscribed to `uri` via `resources/subscribe`. Sessions\n * that have not subscribed to the URI are skipped, so it is safe to call this\n * whenever the underlying data changes.\n *\n * @param uri - The URI of the resource whose contents changed.\n */\n public async sendResourceUpdated(uri: string): Promise<void> {\n await Promise.all(\n this.#sessions.map((session) => session.sendResourceUpdated(uri)),\n );\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options?: Partial<{\n httpStream: {\n basePath?: `/${string}`;\n cors?: boolean | CorsOptions;\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n eventStore?: EventStore;\n host?: string;\n port: number;\n sslCa?: string;\n sslCert?: string;\n sslKey?: string;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ) {\n const config = this.#parseRuntimeConfig(options);\n\n if (config.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n // For stdio transport, if authenticate function is provided, call it\n // with undefined request (since stdio doesn't have HTTP request context)\n let auth: T | undefined;\n\n if (this.#authenticate) {\n try {\n auth =\n (await this.#authenticate(\n undefined as unknown as http.IncomingMessage,\n )) ?? undefined;\n } catch (error) {\n this.#logger.error(\n \"[FastMCP error] Authentication failed for stdio transport:\",\n error instanceof Error ? error.message : String(error),\n );\n // Continue without auth if authentication fails\n }\n }\n\n const session = new FastMCPSession<T>({\n auth,\n icons: this.#options.icons,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n onToolCall: this.#options.onToolCall,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n streamKeepalive: this.#options.streamKeepalive,\n title: this.#options.title,\n tools: this.#tools,\n transportType: \"stdio\",\n utils: this.#options.utils,\n version: this.#options.version,\n websiteUrl: this.#options.websiteUrl,\n });\n\n await session.connect(transport);\n\n // Belt-and-suspenders: detect when the MCP client closes its end of\n // the stdin pipe and shut down the transport so the process doesn't\n // linger as a zombie/orphan. The upstream SDK fix (PR #2003) handles\n // this inside StdioServerTransport itself, but adding the listener here\n // means older SDK versions are also protected.\n let stdinClosed = false;\n const onStdinClose = () => {\n if (stdinClosed) return;\n stdinClosed = true;\n process.stdin.off(\"close\", onStdinClose);\n process.stdin.off(\"end\", onStdinClose);\n transport.close().catch(() => {});\n };\n process.stdin.on(\"close\", onStdinClose);\n process.stdin.on(\"end\", onStdinClose);\n\n this.#sessions.push(session);\n\n session.once(\"error\", () => {\n this.#removeSession(session);\n });\n\n // Monitor the underlying transport for close events\n if (transport.onclose) {\n const originalOnClose = transport.onclose;\n\n transport.onclose = () => {\n process.stdin.off(\"close\", onStdinClose);\n process.stdin.off(\"end\", onStdinClose);\n this.#removeSession(session);\n\n if (originalOnClose) {\n originalOnClose();\n }\n };\n } else {\n transport.onclose = () => {\n process.stdin.off(\"close\", onStdinClose);\n process.stdin.off(\"end\", onStdinClose);\n this.#removeSession(session);\n };\n }\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n this.#serverState = ServerState.Running;\n } else if (config.transportType === \"httpStream\") {\n const httpConfig = config.httpStream;\n const protocol =\n httpConfig.sslCert || httpConfig.sslKey ? \"https\" : \"http\";\n const streamEndpoint = joinPaths(\n httpConfig.basePath,\n httpConfig.endpoint,\n );\n\n if (httpConfig.stateless) {\n // Stateless mode - create new server instance for each request\n this.#logger.info(\n `[FastMCP info] Starting server in stateless mode on HTTP Stream at ${protocol}://${httpConfig.host}:${httpConfig.port}${streamEndpoint}`,\n );\n\n // Shared per-request memo: mcp-proxy's gating call and the\n // `createServer` call below collapse into one real `authenticate`\n // invocation per request (see `#memoizedAuthenticate`).\n const authenticate = this.#authenticate\n ? this.#memoizedAuthenticate()\n : undefined;\n\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(authenticate ? { authenticate } : {}),\n cors: httpConfig.cors,\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (authenticate) {\n auth = this.#requireAuthenticated(await authenticate(request));\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n // In stateless mode, create a new session for each request\n // without persisting it in the sessions array\n return this.#createSession(auth, sessionId, true);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n ...(this.#options.oauth?.enabled &&\n this.#options.oauth.protectedResource?.resource\n ? {\n oauth: {\n protectedResource: {\n resource: this.#options.oauth.protectedResource.resource,\n },\n },\n }\n : {}),\n // In stateless mode, we don't track sessions\n onClose: async () => {\n // No session tracking in stateless mode\n },\n onConnect: async () => {\n // No persistent session tracking in stateless mode\n this.#logger.debug(\n `[FastMCP debug] Stateless HTTP Stream request handled`,\n );\n },\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(\n req,\n res,\n true,\n httpConfig.host,\n streamEndpoint,\n httpConfig.basePath,\n );\n },\n port: httpConfig.port,\n sslCa: httpConfig.sslCa,\n sslCert: httpConfig.sslCert,\n sslKey: httpConfig.sslKey,\n stateless: true,\n streamEndpoint,\n });\n } else {\n // Regular mode with session management\n // Shared per-request memo: mcp-proxy's gating call and the\n // `createServer` call below collapse into one real `authenticate`\n // invocation per request (see `#memoizedAuthenticate`).\n const authenticate = this.#authenticate\n ? this.#memoizedAuthenticate()\n : undefined;\n\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(authenticate ? { authenticate } : {}),\n cors: httpConfig.cors,\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (authenticate) {\n auth = this.#requireAuthenticated(await authenticate(request));\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n return this.#createSession(auth, sessionId);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n ...(this.#options.oauth?.enabled &&\n this.#options.oauth.protectedResource?.resource\n ? {\n oauth: {\n protectedResource: {\n resource: this.#options.oauth.protectedResource.resource,\n },\n },\n }\n : {}),\n onClose: async (session) => {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) this.#sessions.splice(sessionIndex, 1);\n\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.#logger.info(`[FastMCP info] HTTP Stream session established`);\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(\n req,\n res,\n false,\n httpConfig.host,\n streamEndpoint,\n httpConfig.basePath,\n );\n },\n port: httpConfig.port,\n sslCa: httpConfig.sslCa,\n sslCert: httpConfig.sslCert,\n sslKey: httpConfig.sslKey,\n stateless: httpConfig.stateless,\n streamEndpoint,\n });\n\n this.#logger.info(\n `[FastMCP info] server is running on HTTP Stream at ${protocol}://${httpConfig.host}:${httpConfig.port}${streamEndpoint}`,\n );\n }\n this.#serverState = ServerState.Running;\n } else {\n throw new Error(\"Invalid transport type\");\n }\n }\n\n /**\n * Stops the server.\n */\n public async stop() {\n if (this.#httpStreamServer) {\n await this.#httpStreamServer.close();\n }\n this.#serverState = ServerState.Stopped;\n }\n\n /**\n * Creates a new FastMCPSession instance with the current configuration.\n * Used both for regular sessions and stateless requests.\n */\n #createSession(\n auth?: T,\n sessionId?: string,\n stateless = false,\n ): FastMCPSession<T> {\n // Check if authentication failed\n if (\n auth &&\n typeof auth === \"object\" &&\n \"authenticated\" in auth &&\n !(auth as { authenticated: unknown }).authenticated\n ) {\n const errorMessage =\n \"error\" in auth &&\n typeof (auth as { error: unknown }).error === \"string\"\n ? (auth as { error: string }).error\n : \"Authentication failed\";\n throw this.#createUnauthorizedResponse(errorMessage);\n }\n\n const allowedTools = auth\n ? this.#tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(auth) : true,\n )\n : this.#tools;\n return new FastMCPSession<T>({\n auth,\n icons: this.#options.icons,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n onToolCall: this.#options.onToolCall,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n sessionId,\n stateless,\n streamKeepalive: this.#options.streamKeepalive,\n title: this.#options.title,\n tools: allowedTools,\n transportType: \"httpStream\",\n utils: this.#options.utils,\n version: this.#options.version,\n websiteUrl: this.#options.websiteUrl,\n });\n }\n\n /**\n * Builds a 401 Unauthorized HTTP Response for authentication failures.\n *\n * Throwing a `Response` (rather than a plain `Error`) guarantees that the\n * transport (e.g. mcp-proxy) surfaces the correct status code directly,\n * instead of relying on heuristics that infer the status code from the\n * error message's text (see https://github.com/punkpeye/fastmcp/issues/180).\n *\n * The response body matches the JSON-RPC error envelope FastMCP otherwise\n * produces, and a `WWW-Authenticate` header is included per RFC 7235 (and\n * RFC 9728 when protected-resource metadata is configured), so HTTP-aware\n * clients can distinguish \"unauthenticated\" from a malformed request.\n */\n #createUnauthorizedResponse(message: string): Response {\n // Only advertise resource_metadata when OAuth is enabled: the\n // `/.well-known/oauth-protected-resource` endpoint is served only under\n // `oauth.enabled` (and this matches how the oauth config is forwarded to\n // mcp-proxy at the httpStream call sites), so gating here avoids pointing\n // clients at an endpoint that would 404.\n const oauth = this.#options.oauth;\n const resource = oauth?.enabled\n ? oauth.protectedResource?.resource\n : undefined;\n const wwwAuthenticateParts = [\n 'error=\"invalid_token\"',\n `error_description=\"${message.replace(/\"/g, '\\\\\"')}\"`,\n ];\n\n if (resource) {\n wwwAuthenticateParts.push(\n `resource_metadata=\"${resource}/.well-known/oauth-protected-resource\"`,\n );\n }\n\n return new Response(\n JSON.stringify({\n error: { code: -32000, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: {\n \"Content-Type\": \"application/json\",\n \"WWW-Authenticate\": `Bearer ${wwwAuthenticateParts.join(\", \")}`,\n },\n status: 401,\n },\n );\n }\n\n /**\n * Handles unhandled HTTP requests with health, readiness, OAuth endpoints, and custom routes\n */\n #handleUnhandledRequest = async (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n isStateless = false,\n host: string,\n streamEndpoint?: string,\n basePath: \"\" | `/${string}` = \"\",\n ) => {\n const url = new URL(req.url || \"\", `http://${host}`);\n const basePathRelativePath = stripBasePath(url.pathname, basePath);\n\n // Try Hono routes first - users may have added routes via getApp()\n try {\n // Convert Node.js IncomingMessage to Web Request\n const webRequest = this.#nodeRequestToWebRequest(req, url);\n\n // Call Hono's fetch handler\n const honoResponse = await this.#honoApp.fetch(webRequest, {\n incoming: req,\n outgoing: res,\n });\n\n // If Hono handled it (not 404), write response and return\n if (honoResponse.status !== 404) {\n // Write Hono response to Node.js response\n if (!res.headersSent) {\n res.statusCode = honoResponse.status;\n honoResponse.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n\n if (honoResponse.body) {\n const reader = honoResponse.body.getReader();\n\n // A custom route is free to return a stream that never ends on its\n // own (SSE, a proxied upstream). The client going away is then the\n // only thing that ends it, and such a stream may well be quiet at\n // that moment, so waiting on `read()` alone would keep pumping\n // until a chunk that may never arrive. Race every read against the\n // response closing instead.\n let resolveClosed!: () => void;\n const closed = new Promise<undefined>((resolve) => {\n resolveClosed = () => resolve(undefined);\n });\n res.once(\"close\", resolveClosed);\n if (res.writableEnded || res.destroyed) {\n resolveClosed();\n }\n\n try {\n while (!res.writableEnded && !res.destroyed) {\n const read = reader.read();\n // `closed` may win the race, leaving this promise to settle\n // with nobody observing it.\n read.catch(() => {});\n const result = await Promise.race([read, closed]);\n if (!result || result.done) break;\n res.write(result.value);\n }\n } finally {\n res.off(\"close\", resolveClosed);\n // `releaseLock` detaches this reader but leaves the body itself\n // unread and its source running; only `cancel` tells the route\n // to stop producing and release what it holds.\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n }\n res.end();\n }\n return;\n }\n } catch (error) {\n // If Hono throws, log and continue to other endpoints\n this.#logger.debug(\"[FastMCP debug] Hono route not matched\", error);\n }\n\n const healthConfig = this.#options.health ?? {};\n\n const enabled =\n healthConfig.enabled === undefined ? true : healthConfig.enabled;\n\n if (enabled) {\n const path = healthConfig.path ?? \"/health\";\n\n try {\n if (\n (req.method === \"GET\" || req.method === \"HEAD\") &&\n url.pathname === joinPaths(basePath, path)\n ) {\n res\n .writeHead(healthConfig.status ?? 200, {\n \"Content-Type\": \"text/plain\",\n })\n .end(\n req.method === \"HEAD\"\n ? undefined\n : (healthConfig.message ?? \"✓ Ok\"),\n );\n\n return;\n }\n\n // Enhanced readiness check endpoint\n if (\n (req.method === \"GET\" || req.method === \"HEAD\") &&\n url.pathname === joinPaths(basePath, \"/ready\")\n ) {\n if (isStateless) {\n // In stateless mode, we're always ready if the server is running\n const response = {\n mode: \"stateless\",\n ready: 1,\n status: \"ready\",\n total: 1,\n };\n\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(\n req.method === \"HEAD\" ? undefined : JSON.stringify(response),\n );\n } else {\n const readySessions = this.#sessions.filter(\n (s) => s.isReady,\n ).length;\n const totalSessions = this.#sessions.length;\n const allReady =\n readySessions === totalSessions && totalSessions > 0;\n\n const response = {\n ready: readySessions,\n status: allReady\n ? \"ready\"\n : totalSessions === 0\n ? \"no_sessions\"\n : \"initializing\",\n total: totalSessions,\n };\n\n res\n .writeHead(allReady ? 200 : 503, {\n \"Content-Type\": \"application/json\",\n })\n .end(\n req.method === \"HEAD\" ? undefined : JSON.stringify(response),\n );\n }\n\n return;\n }\n } catch (error) {\n this.#logger.error(\"[FastMCP error] health endpoint error\", error);\n }\n }\n\n // Handle OAuth well-known endpoints\n const oauthConfig = this.#options.oauth;\n if (oauthConfig?.enabled && req.method === \"GET\") {\n const url = new URL(req.url || \"\", `http://${host}`);\n const authorizationServerMetadataPath = joinPaths(\n \"\",\n `/.well-known/oauth-authorization-server${basePath}`,\n );\n\n if (\n url.pathname === authorizationServerMetadataPath &&\n oauthConfig.authorizationServer\n ) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.authorizationServer,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n\n // Handle Protected Resource Metadata with MCP 2025-11-25 compliant discovery\n // Per spec, clients should search in order:\n // 1. WWW-Authenticate header (handled by mcp-proxy)\n // 2. /.well-known/oauth-protected-resource<sub-path> (e.g., /mcp)\n // 3. /.well-known/oauth-protected-resource (root)\n if (oauthConfig.protectedResource) {\n const wellKnownBase = \"/.well-known/oauth-protected-resource\";\n let shouldServeMetadata = false;\n\n // Check for sub-path variant first (higher priority per MCP spec)\n if (\n streamEndpoint &&\n url.pathname === `${wellKnownBase}${streamEndpoint}`\n ) {\n shouldServeMetadata = true;\n }\n // Fall back to root path\n else if (url.pathname === wellKnownBase) {\n shouldServeMetadata = true;\n }\n\n if (shouldServeMetadata) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.protectedResource,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n }\n }\n\n // Handle OAuth Proxy endpoints\n const oauthProxy = oauthConfig?.proxy;\n if (oauthProxy && oauthConfig?.enabled) {\n const url = new URL(req.url || \"\", `http://${host}`);\n const oauthPath = basePathRelativePath;\n\n try {\n // DCR endpoint - POST /oauth/register\n if (req.method === \"POST\" && oauthPath === \"/oauth/register\") {\n await new Promise<void>((resolve) => {\n const bodyChunks: Buffer[] = [];\n let bodySize = 0;\n let failed = false;\n const fail = () => {\n if (failed || res.headersSent) {\n resolve();\n return;\n }\n failed = true;\n res\n .writeHead(400, {\n Connection: \"close\",\n \"Content-Type\": \"application/json\",\n })\n .end(\n JSON.stringify({\n error: \"invalid_request\",\n error_description: \"Request body exceeds 1 MiB\",\n }),\n );\n resolve();\n };\n req.on(\"data\", (chunk) => {\n if (failed) {\n return;\n }\n bodySize += chunk.length;\n if (bodySize > OAUTH_PROXY_MAX_BODY_SIZE) {\n fail();\n return;\n }\n bodyChunks.push(chunk);\n });\n // An aborted/errored request never emits \"end\"; settle the promise\n // instead of leaving the handler pending forever.\n req.on(\"aborted\", fail);\n req.on(\"error\", fail);\n req.on(\"end\", async () => {\n if (failed) {\n return;\n }\n try {\n const request = JSON.parse(\n Buffer.concat(bodyChunks).toString(\"utf8\"),\n );\n const response = await oauthProxy.registerClient(request);\n res\n .writeHead(201, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(JSON.stringify(response));\n } catch (error) {\n const statusCode =\n (error as { statusCode?: number }).statusCode || 400;\n res\n .writeHead(statusCode, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"invalid_request\",\n },\n ),\n );\n }\n resolve();\n });\n });\n return;\n }\n\n // Authorization endpoint - GET /oauth/authorize\n if (req.method === \"GET\" && oauthPath === \"/oauth/authorize\") {\n try {\n const params = Object.fromEntries(url.searchParams.entries());\n const response = await oauthProxy.authorize(\n params as {\n [key: string]: unknown;\n client_id: string;\n redirect_uri: string;\n response_type: string;\n },\n );\n\n // Response is a redirect\n const location = response.headers.get(\"Location\");\n if (location) {\n res.writeHead(response.status, { Location: location }).end();\n } else {\n // HTML consent screen\n const html = await response.text();\n res\n .writeHead(response.status, { \"Content-Type\": \"text/html\" })\n .end(html);\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"invalid_request\",\n },\n ),\n );\n }\n return;\n }\n\n // Callback endpoint - GET /oauth/callback\n if (req.method === \"GET\" && oauthPath === \"/oauth/callback\") {\n try {\n const mockRequest = new Request(`http://${host}${req.url}`);\n const response = await oauthProxy.handleCallback(mockRequest);\n\n const location = response.headers.get(\"Location\");\n if (location) {\n res.writeHead(response.status, { Location: location }).end();\n } else {\n const text = await response.text();\n res.writeHead(response.status).end(text);\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"server_error\",\n },\n ),\n );\n }\n return;\n }\n\n // Consent endpoint - POST /oauth/consent\n if (req.method === \"POST\" && oauthPath === \"/oauth/consent\") {\n await new Promise<void>((resolve) => {\n const bodyChunks: Buffer[] = [];\n let bodySize = 0;\n let failed = false;\n const fail = () => {\n if (failed || res.headersSent) {\n resolve();\n return;\n }\n failed = true;\n res\n .writeHead(400, {\n Connection: \"close\",\n \"Content-Type\": \"application/json\",\n })\n .end(\n JSON.stringify({\n error: \"invalid_request\",\n error_description: \"Request body exceeds 1 MiB\",\n }),\n );\n resolve();\n };\n req.on(\"data\", (chunk) => {\n if (failed) {\n return;\n }\n bodySize += chunk.length;\n if (bodySize > OAUTH_PROXY_MAX_BODY_SIZE) {\n fail();\n return;\n }\n bodyChunks.push(chunk);\n });\n // An aborted/errored request never emits \"end\"; settle the promise\n // instead of leaving the handler pending forever.\n req.on(\"aborted\", fail);\n req.on(\"error\", fail);\n req.on(\"end\", async () => {\n if (failed) {\n return;\n }\n try {\n const mockRequest = new Request(\n `http://${host}${url.pathname}${url.search}`,\n {\n body: Buffer.concat(bodyChunks).toString(\"utf8\"),\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n method: \"POST\",\n },\n );\n const response = await oauthProxy.handleConsent(mockRequest);\n\n const location = response.headers.get(\"Location\");\n if (location) {\n res.writeHead(response.status, { Location: location }).end();\n } else {\n const text = await response.text();\n res.writeHead(response.status).end(text);\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"server_error\",\n },\n ),\n );\n }\n resolve();\n });\n });\n return;\n }\n\n // Token endpoint - POST /oauth/token\n if (req.method === \"POST\" && oauthPath === \"/oauth/token\") {\n await new Promise<void>((resolve) => {\n const bodyChunks: Buffer[] = [];\n let bodySize = 0;\n let failed = false;\n const fail = () => {\n if (failed || res.headersSent) {\n resolve();\n return;\n }\n failed = true;\n res\n .writeHead(400, {\n Connection: \"close\",\n \"Content-Type\": \"application/json\",\n })\n .end(\n JSON.stringify({\n error: \"invalid_request\",\n error_description: \"Request body exceeds 1 MiB\",\n }),\n );\n resolve();\n };\n req.on(\"data\", (chunk) => {\n if (failed) {\n return;\n }\n bodySize += chunk.length;\n if (bodySize > OAUTH_PROXY_MAX_BODY_SIZE) {\n fail();\n return;\n }\n bodyChunks.push(chunk);\n });\n // An aborted/errored request never emits \"end\"; settle the promise\n // instead of leaving the handler pending forever.\n req.on(\"aborted\", fail);\n req.on(\"error\", fail);\n req.on(\"end\", async () => {\n if (failed) {\n return;\n }\n try {\n const params = new URLSearchParams(\n Buffer.concat(bodyChunks).toString(\"utf8\"),\n );\n const grantType = params.get(\"grant_type\");\n\n // Parse Basic auth header (RFC 6749 Section 2.3.1)\n const basicAuth = parseBasicAuthHeader(\n req.headers.authorization,\n );\n\n // Use Basic auth credentials if present, otherwise fall back to POST body\n const clientId =\n basicAuth?.clientId || params.get(\"client_id\") || \"\";\n const clientSecret =\n basicAuth?.clientSecret ??\n params.get(\"client_secret\") ??\n undefined;\n\n let response;\n if (grantType === \"authorization_code\") {\n response = await oauthProxy.exchangeAuthorizationCode({\n client_id: clientId,\n client_secret: clientSecret,\n code: params.get(\"code\") || \"\",\n code_verifier: params.get(\"code_verifier\") || undefined,\n grant_type: \"authorization_code\",\n redirect_uri: params.get(\"redirect_uri\") || \"\",\n });\n } else if (grantType === \"refresh_token\") {\n response = await oauthProxy.exchangeRefreshToken({\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: \"refresh_token\",\n refresh_token: params.get(\"refresh_token\") || \"\",\n scope: params.get(\"scope\") || undefined,\n });\n } else {\n throw {\n statusCode: 400,\n toJSON: () => ({ error: \"unsupported_grant_type\" }),\n };\n }\n\n res\n .writeHead(200, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(JSON.stringify(response));\n } catch (error) {\n const statusCode =\n (error as { statusCode?: number }).statusCode || 400;\n res\n .writeHead(statusCode, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"invalid_request\",\n },\n ),\n );\n }\n resolve();\n });\n });\n return;\n }\n } catch (error) {\n this.#logger.error(\"[FastMCP error] OAuth Proxy endpoint error\", error);\n res.writeHead(500).end();\n return;\n }\n }\n };\n\n /**\n * On `httpStream`, `authenticate` is handed to both mcp-proxy (which calls it\n * once per request to gate the 401) and this server's own `createServer`\n * callback (which calls it again to obtain the session auth). Both receive\n * the identical `IncomingMessage`, so a single request would otherwise be\n * authenticated twice — halving the effective budget of any non-idempotent\n * `authenticate` (see #352).\n *\n * This wraps `#authenticate` in a per-request memo keyed on the request\n * object, collapsing the two calls into one real invocation. The *promise* is\n * cached (not the resolved value) so a second call that arrives before the\n * first settles joins it rather than starting a competing attempt. Keys are\n * the request objects themselves, so each request is authenticated exactly\n * once, a distinct request is authenticated afresh, and entries are collected\n * with their requests — nothing leaks across requests. A rejected or nullish\n * result is cached as-is, so a failed authentication is never seen as a\n * success by the second caller.\n */\n #memoizedAuthenticate(): Authenticate<T> {\n const authenticate = this.#authenticate!;\n const cache = new WeakMap<\n http.IncomingMessage,\n Promise<null | T | undefined>\n >();\n\n return (request: http.IncomingMessage) => {\n // stdio passes `undefined`; there is nothing to key a memo on, and this\n // path is httpStream-only anyway, so fall straight through.\n if (!request) {\n return authenticate(request);\n }\n\n const cached = cache.get(request);\n\n if (cached) {\n return cached;\n }\n\n const result = Promise.resolve(authenticate(request));\n\n cache.set(request, result);\n\n return result;\n };\n }\n\n /**\n * Converts Node.js IncomingMessage to Web Request for Hono\n */\n #nodeRequestToWebRequest(req: http.IncomingMessage, url: URL): Request {\n const method = req.method || \"GET\";\n\n // Build headers\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n if (Array.isArray(value)) {\n for (const v of value) {\n headers.append(key, v);\n }\n } else {\n headers.set(key, value);\n }\n }\n }\n\n // Create Web Request\n // For methods that can have a body, we need to pass the body\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n\n if (hasBody) {\n return new Request(url.toString(), {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n body: req as any, // Node.js IncomingMessage is readable stream\n duplex: \"half\", // Required for streaming bodies\n headers,\n method,\n } as RequestInit);\n } else {\n return new Request(url.toString(), {\n headers,\n method,\n });\n }\n }\n\n #parseRuntimeConfig(\n overrides?: Partial<{\n httpStream: {\n basePath?: `/${string}`;\n cors?: boolean | CorsOptions;\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n eventStore?: EventStore;\n host?: string;\n port: number;\n sslCa?: string;\n sslCert?: string;\n sslKey?: string;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ):\n | {\n httpStream: {\n basePath: \"\" | `/${string}`;\n cors?: boolean | CorsOptions;\n enableJsonResponse?: boolean;\n endpoint: `/${string}`;\n eventStore?: EventStore;\n host: string;\n port: number;\n sslCa?: string;\n sslCert?: string;\n sslKey?: string;\n stateless?: boolean;\n };\n transportType: \"httpStream\";\n }\n | { transportType: \"stdio\" } {\n const args = process.argv.slice(2);\n const getArg = (name: string) => {\n const index = args.findIndex((arg) => arg === `--${name}`);\n\n return index !== -1 && index + 1 < args.length\n ? args[index + 1]\n : undefined;\n };\n\n const transportArg = getArg(\"transport\");\n const portArg = getArg(\"port\");\n const endpointArg = getArg(\"endpoint\");\n const basePathArg = getArg(\"base-path\");\n const statelessArg = getArg(\"stateless\");\n const hostArg = getArg(\"host\");\n\n const envTransport = process.env.FASTMCP_TRANSPORT;\n const envPort = process.env.FASTMCP_PORT;\n const envEndpoint = process.env.FASTMCP_ENDPOINT;\n const envBasePath = process.env.FASTMCP_BASE_PATH;\n const envStateless = process.env.FASTMCP_STATELESS;\n const envHost = process.env.FASTMCP_HOST;\n // Overrides > CLI > env > defaults\n const transportType =\n overrides?.transportType ||\n (transportArg === \"http-stream\" ? \"httpStream\" : transportArg) ||\n envTransport ||\n \"stdio\";\n\n if (transportType === \"httpStream\") {\n const port = parseInt(\n overrides?.httpStream?.port?.toString() || portArg || envPort || \"8080\",\n );\n const host =\n overrides?.httpStream?.host || hostArg || envHost || \"localhost\";\n const endpoint =\n overrides?.httpStream?.endpoint || endpointArg || envEndpoint || \"/mcp\";\n const basePath = normalizeBasePath(\n overrides?.httpStream?.basePath || basePathArg || envBasePath,\n );\n const enableJsonResponse =\n overrides?.httpStream?.enableJsonResponse || false;\n const stateless =\n overrides?.httpStream?.stateless ||\n statelessArg === \"true\" ||\n envStateless === \"true\" ||\n false;\n const cors = overrides?.httpStream?.cors;\n const eventStore = overrides?.httpStream?.eventStore;\n const sslCa = overrides?.httpStream?.sslCa;\n const sslCert = overrides?.httpStream?.sslCert;\n const sslKey = overrides?.httpStream?.sslKey;\n\n return {\n httpStream: {\n basePath,\n cors,\n enableJsonResponse,\n endpoint: endpoint as `/${string}`,\n eventStore,\n host,\n port,\n sslCa,\n sslCert,\n sslKey,\n stateless,\n },\n transportType: \"httpStream\" as const,\n };\n }\n\n return { transportType: \"stdio\" as const };\n }\n\n /**\n * Notifies all sessions that the prompts list has changed.\n */\n #promptsListChanged(prompts: Prompt<T>[]) {\n for (const session of this.#sessions) {\n session.promptsListChanged(prompts);\n }\n }\n\n #removeSession(session: FastMCPSession<T>): void {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) {\n this.#sessions.splice(sessionIndex, 1);\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n }\n }\n\n /**\n * Rejects a failed authentication result before it can become a session.\n *\n * Authentication is REQUIRED whenever an `authenticate` function is\n * configured. mcp-proxy gates the HTTP Stream endpoint before `createServer`\n * runs, but it does not gate the SSE endpoint it serves at `/sse` by default:\n * `handleSSERequest` never receives `authenticate`. Throwing here is what\n * stops `/sse` from handing out a session — with access to every tool, since\n * `#createSession` skips `canAccess` filtering when `auth` is falsy — to a\n * client that `/mcp` would have answered with a 401.\n *\n * The falsy test matches mcp-proxy's own check so that both endpoints agree\n * on what counts as a failed authentication. Returning a nullish value is the\n * idiomatic way to signal failure, and is what the built-in OAuth\n * `AuthProvider` does for a missing or invalid bearer token.\n */\n #requireAuthenticated<TAuth>(auth: TAuth): NonNullable<TAuth> {\n if (!auth) {\n throw this.#createUnauthorizedResponse(\"Authentication required\");\n }\n\n return auth as NonNullable<TAuth>;\n }\n\n /**\n * Notifies all sessions that the resources list has changed.\n */\n #resourcesListChanged(resources: Resource<T>[]) {\n for (const session of this.#sessions) {\n session.resourcesListChanged(resources);\n }\n }\n\n /**\n * Notifies all sessions that the resource templates list has changed.\n */\n #resourceTemplatesListChanged(templates: InputResourceTemplate<T>[]) {\n for (const session of this.#sessions) {\n session.resourceTemplatesListChanged(templates);\n }\n }\n\n /**\n * Notifies all sessions that the tools list has changed.\n */\n #toolsListChanged(tools: Tool<T>[]) {\n for (const session of this.#sessions) {\n session.toolsListChanged(tools);\n }\n }\n}\n\n// Re-export commonly used auth utilities for convenience\n// Users can also import from \"fastmcp/auth\" for the full auth module\nexport {\n // Auth providers\n AuthProvider,\n AzureProvider,\n // Auth helpers for canAccess\n getAuthSession,\n GitHubProvider,\n GoogleProvider,\n OAuthProvider,\n requireAll,\n requireAny,\n requireAuth,\n requireRole,\n requireScopes,\n} from \"./auth/index.js\";\n\nexport type {\n AuthProviderConfig,\n AzureProviderConfig,\n AzureSession,\n GenericOAuthProviderConfig,\n GitHubSession,\n GoogleSession,\n OAuthSession,\n} from \"./auth/index.js\";\n\nexport { DiscoveryDocumentCache } from \"./DiscoveryDocumentCache.js\";\n\nexport {\n jsonSchemaAdapter,\n type JsonSchemaObject,\n type JsonSchemaStandardSchema,\n} from \"./jsonSchemaAdapter.js\";\n\nexport type {\n AudioContent,\n Content,\n ContentResult,\n Context,\n CorsOptions,\n FastMCPEvents,\n FastMCPSessionAuth,\n FastMCPSessionEvents,\n Icon,\n ImageContent,\n InputPrompt,\n InputPromptArgument,\n LoadContext,\n LoggingLevel,\n Progress,\n Prompt,\n PromptArgument,\n Resource,\n ResourceContent,\n ResourceLink,\n ResourceResult,\n ResourceTemplate,\n ResourceTemplateArgument,\n SerializableValue,\n ServerOptions,\n TextContent,\n Tool,\n ToolParameters,\n};\n","import { cancelResponseBody } from \"./cancelResponseBody.js\";\n\nexport class DiscoveryDocumentCache {\n public get size(): number {\n return this.#cache.size;\n }\n\n #cache: Map<\n string,\n {\n data: unknown;\n expiresAt: number;\n }\n > = new Map();\n\n #generation = 0;\n\n #inFlight: Map<string, Promise<unknown>> = new Map();\n\n #timeoutMs: number;\n\n #ttl: number;\n\n #urlGenerations: Map<string, number> = new Map();\n\n /**\n * @param options - configuration options\n * @param options.timeoutMs - timeout in miliseconds for the upstream fetch\n * @param options.ttl - time-to-live in miliseconds\n */\n public constructor(options: { timeoutMs?: number; ttl?: number } = {}) {\n this.#timeoutMs = options.timeoutMs ?? 10000; // default 10 seconds\n this.#ttl = options.ttl ?? 3600000; // default 1 hour\n }\n\n /**\n * @param url - optional URL to clear. if omitted, clears all cached documents.\n */\n public clear(url?: string): void {\n if (url) {\n this.#cache.delete(url);\n this.#inFlight.delete(url);\n this.#urlGenerations.set(url, (this.#urlGenerations.get(url) ?? 0) + 1);\n } else {\n this.#cache.clear();\n this.#inFlight.clear();\n this.#urlGenerations.clear();\n this.#generation++;\n }\n }\n\n /**\n * fetches a discovery document from the given URL.\n * uses cached value if available and not expired.\n * coalesces concurrent requests for the same URL to prevent duplicate fetches.\n *\n * @param url - the discovery document URL (e.g., /.well-known/openid-configuration)\n * @returns the discovery document as a JSON object\n * @throws Error if the fetch fails or returns non-OK status\n */\n public async get(url: string): Promise<unknown> {\n const now = Date.now();\n const cached = this.#cache.get(url);\n\n // return cached value if still valid\n if (cached && cached.expiresAt > now) {\n return cached.data;\n }\n\n // check if there’s already an in-flight request for this URL\n const inFlight = this.#inFlight.get(url);\n\n if (inFlight) {\n return inFlight;\n }\n\n // create a new fetch promise and store it\n const fetchPromise = this.#fetchAndCache(\n url,\n this.#generation,\n this.#urlGenerations.get(url) ?? 0,\n );\n\n this.#inFlight.set(url, fetchPromise);\n\n try {\n const data = await fetchPromise;\n return data;\n } finally {\n // clean up in-flight promise after completion\n // (success or failure)\n if (this.#inFlight.get(url) === fetchPromise) {\n this.#inFlight.delete(url);\n }\n }\n }\n\n /**\n * @param url - the URL to check\n * @returns true if the URL is cached and nott expired\n */\n public has(url: string): boolean {\n const cached = this.#cache.get(url);\n\n if (!cached) {\n return false;\n }\n\n const now = Date.now();\n\n if (cached.expiresAt <= now) {\n // expired, remove from cache\n this.#cache.delete(url);\n return false;\n }\n\n return true;\n }\n\n async #fetchAndCache(\n url: string,\n generation: number,\n urlGeneration: number,\n ): Promise<unknown> {\n // fetch fresh document, bounded by the configured timeout\n let res: Response;\n try {\n res = await fetch(url, {\n signal: AbortSignal.timeout(this.#timeoutMs),\n });\n } catch (error) {\n if (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ) {\n throw new Error(\n `Failed to fetch discovery document from ${url}: timed out after ${this.#timeoutMs}ms`,\n );\n }\n throw error;\n }\n\n if (!res.ok) {\n await cancelResponseBody(res);\n throw new Error(\n `Failed to fetch discovery document from ${url}: ${res.status} ${res.statusText}`,\n );\n }\n\n const data = await res.json();\n // calculate expiration time AFTER fetch completes\n const expiresAt = Date.now() + this.#ttl;\n\n // A clear that occurred while the fetch was pending invalidates its result.\n if (\n this.#generation === generation &&\n (this.#urlGenerations.get(url) ?? 0) === urlGeneration\n ) {\n this.#cache.set(url, {\n data,\n expiresAt,\n });\n }\n\n return data;\n }\n}\n","import { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * A plain JSON Schema object descriptor.\n */\nexport type JsonSchemaObject = {\n [key: string]: unknown;\n $schema?: string;\n additionalProperties?: boolean;\n properties?: Record<string, unknown>;\n required?: string[];\n type: string;\n};\n\n/**\n * A Standard Schema that also carries the JSON Schema it was built from.\n *\n * `~standard.jsonSchema` is the Standard JSON Schema extension. Anything that\n * knows about it — including the `xsschema` conversion FastMCP uses to build\n * `tools/list` — reads the schema straight off the object instead of trying to\n * derive one from a validation library it does not recognise.\n */\nexport interface JsonSchemaStandardSchema extends StandardSchemaV1 {\n readonly \"~standard\": {\n readonly jsonSchema: {\n readonly input: () => JsonSchemaObject;\n readonly output: () => JsonSchemaObject;\n };\n } & StandardSchemaV1.Props;\n}\n\ninterface AjvErrorObject {\n instancePath: string;\n keyword: string;\n message?: string;\n params?: Record<string, unknown>;\n}\n\ntype AjvValidateFunction = {\n errors?: AjvErrorObject[] | null;\n (data: unknown): boolean;\n};\n\n/**\n * Wraps a plain JSON Schema object so it can be used as a tool's `parameters`\n * or `outputSchema`, without pulling in Zod, Valibot, or another validation\n * library.\n *\n * Validation uses AJV, which is an optional peer dependency — install `ajv`\n * (and `ajv-formats` if you use `format` keywords) to use this. It is imported\n * on first validation, so servers that never call this pay nothing for it.\n *\n * Note that FastMCP applies the same strictness to every tool schema: objects\n * are advertised with `additionalProperties: false`, whatever the input schema\n * said.\n *\n * @example\n * ```ts\n * import { FastMCP, jsonSchemaAdapter } from \"fastmcp\";\n *\n * const server = new FastMCP({ name: \"Example\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"greet\",\n * description: \"Greet a user\",\n * parameters: jsonSchemaAdapter({\n * type: \"object\",\n * properties: {\n * name: { type: \"string\" },\n * },\n * required: [\"name\"],\n * }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n * ```\n *\n * @param schema - A plain JSON Schema object\n * @returns A Standard Schema that validates against `schema`\n */\nexport function jsonSchemaAdapter(\n schema: JsonSchemaObject,\n): JsonSchemaStandardSchema {\n // Compiling a schema makes AJV generate and evaluate JavaScript, so it has\n // to happen once rather than per call. The promise is memoised, not just the\n // result, so concurrent first calls share a single compilation.\n let compiled: Promise<AjvValidateFunction> | undefined;\n\n const getValidator = (): Promise<AjvValidateFunction> => {\n compiled ??= compileSchema(schema).catch((error: unknown) => {\n // Do not memoise a failure: a missing dependency should be reported on\n // every call, not swallowed after the first.\n compiled = undefined;\n throw error;\n });\n\n return compiled;\n };\n\n return {\n \"~standard\": {\n jsonSchema: {\n input: () => schema,\n output: () => schema,\n },\n validate: async (\n data: unknown,\n ): Promise<StandardSchemaV1.Result<unknown>> => {\n const validate = await getValidator();\n\n if (validate(data)) {\n return { value: data };\n }\n\n return { issues: (validate.errors ?? []).map(toIssue) };\n },\n vendor: \"json-schema\",\n version: 1,\n },\n };\n}\n\nasync function compileSchema(\n schema: JsonSchemaObject,\n): Promise<AjvValidateFunction> {\n let ajvModule;\n\n try {\n ajvModule = await import(\"ajv\");\n } catch {\n throw new Error(\n 'The \"ajv\" package is required to validate JSON Schema tool parameters. ' +\n \"Install it with: npm install ajv\",\n );\n }\n\n // ajv ships CommonJS, so depending on the loader the class arrives as the\n // module namespace, as `.default`, or as `.default.default`.\n const Ajv = unwrapDefault(unwrapDefault(ajvModule)) as unknown as new (\n options: Record<string, unknown>,\n ) => {\n compile: (schema: unknown) => AjvValidateFunction;\n };\n\n const ajv = new Ajv({ allErrors: true, strict: false });\n\n try {\n const formatsModule = await import(\"ajv-formats\");\n const addFormats = unwrapDefault(\n unwrapDefault(formatsModule),\n ) as unknown as (ajv: unknown) => void;\n\n addFormats(ajv);\n } catch {\n // ajv-formats is optional; `format` keywords are simply not enforced.\n }\n\n return ajv.compile(schema);\n}\n\nfunction toIssue(error: AjvErrorObject): StandardSchemaV1.Issue {\n const path = error.instancePath\n .split(\"/\")\n .filter(Boolean)\n // JSON Pointer escapes, per RFC 6901.\n .map((segment) => segment.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\"))\n .map((segment): number | string => {\n const index = Number(segment);\n return /^(?:0|[1-9]\\d*)$/.test(segment) && Number.isSafeInteger(index)\n ? index\n : segment;\n });\n\n // AJV reports a missing property against its parent object, with the name in\n // `params`. Appending it points the issue at the field the user has to fix.\n const missingProperty = error.params?.missingProperty;\n\n if (error.keyword === \"required\" && typeof missingProperty === \"string\") {\n path.push(missingProperty);\n }\n\n return {\n message: error.message || \"Validation error\",\n path,\n };\n}\n\nfunction unwrapDefault(value: unknown): unknown {\n return typeof value === \"object\" && value !== null && \"default\" in value\n ? (value as { default: unknown }).default\n : value;\n}\n"],"mappings":"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","names":["ServerState","resource","url"]}
1
+ {"version":3,"sources":["../src/FastMCP.ts","../src/DiscoveryDocumentCache.ts","../src/jsonSchemaAdapter.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { EventStore } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport { RequestOptions } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { RequestHandlerExtra } from \"@modelcontextprotocol/sdk/shared/protocol.js\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport {\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n CreateMessageRequestSchema,\n ElicitRequestFormParams,\n ElicitRequestURLParams,\n ElicitResult,\n ErrorCode,\n GetPromptRequestSchema,\n GetPromptResult,\n Icon,\n ListPromptsRequestSchema,\n ListPromptsResult,\n ListResourcesRequestSchema,\n ListResourcesResult,\n ListResourceTemplatesRequestSchema,\n ListResourceTemplatesResult,\n ListToolsRequestSchema,\n ListToolsResult,\n McpError,\n ReadResourceRequestSchema,\n ResourceLink,\n Root,\n RootsListChangedNotificationSchema,\n Tool as SDKTool,\n ServerCapabilities,\n ServerNotification,\n ServerRequest,\n SetLevelRequestSchema,\n SubscribeRequestSchema,\n UnsubscribeRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { EventEmitter } from \"events\";\nimport { readFile } from \"fs/promises\";\nimport Fuse from \"fuse.js\";\nimport { Hono } from \"hono\";\nimport http from \"http\";\nimport { type CorsOptions, startHTTPServer } from \"mcp-proxy\";\nimport { StrictEventEmitter } from \"strict-event-emitter-types\";\nimport { setTimeout as delay } from \"timers/promises\";\nimport parseURITemplate from \"uri-templates\";\nimport { strictJsonSchema, toJsonSchema } from \"xsschema\";\nimport { z } from \"zod\";\n\nimport type { OAuthProxy } from \"./auth/OAuthProxy.js\";\nimport type {\n AuthProvider,\n OAuthSession,\n} from \"./auth/providers/AuthProvider.js\";\n\nimport { cancelResponseBody } from \"./cancelResponseBody.js\";\n\nexport interface Logger {\n debug(...args: unknown[]): void;\n\n error(...args: unknown[]): void;\n\n info(...args: unknown[]): void;\n\n log(...args: unknown[]): void;\n\n warn(...args: unknown[]): void;\n}\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype FastMCPEvents<T extends FastMCPSessionAuth> = {\n connect: (event: { session: FastMCPSession<T> }) => void;\n disconnect: (event: { session: FastMCPSession<T> }) => void;\n};\n\ntype FastMCPSessionEvents = {\n error: (event: { error: Error }) => void;\n ready: () => void;\n rootsChanged: (event: { roots: Root[] }) => void;\n};\n\n/**\n * Timeout for image/audio URL fetches (in milliseconds). The OAuth upstream\n * fetches (#304) use 10s because they are short interactive exchanges; media\n * downloads can be larger and slower, so 30s is the balance between hanging\n * forever on an unresponsive server and false positives on slow connections.\n */\nexport const MEDIA_FETCH_TIMEOUT_MS = 30000;\n\ntype MediaContentInput =\n | { buffer: Buffer }\n | { path: string }\n | { timeoutMs?: number; url: string };\n\nexport const imageContent = async (\n input: MediaContentInput,\n): Promise<ImageContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n const timeoutMs = input.timeoutMs ?? MEDIA_FETCH_TIMEOUT_MS;\n\n try {\n const response = await fetch(input.url, {\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (!response.ok) {\n await cancelResponseBody(response);\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 // \"AbortError\" is unreachable today (no caller signal); kept as insurance.\n if (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ) {\n throw new Error(\n `Failed to fetch image from URL (${input.url}): timed out after ${timeoutMs}ms`,\n );\n }\n\n throw new Error(\n `Failed to fetch image from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read image from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"image/\")) {\n console.warn(\n `Warning: Content may not be a valid image. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"image/png\",\n type: \"image\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing image: ${String(error)}`);\n }\n }\n};\n\nexport const audioContent = async (\n input: MediaContentInput,\n): Promise<AudioContent> => {\n let rawData: Buffer;\n\n try {\n if (\"url\" in input) {\n const timeoutMs = input.timeoutMs ?? MEDIA_FETCH_TIMEOUT_MS;\n\n try {\n const response = await fetch(input.url, {\n signal: AbortSignal.timeout(timeoutMs),\n });\n\n if (!response.ok) {\n await cancelResponseBody(response);\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 // \"AbortError\" is unreachable today (no caller signal); kept as insurance.\n if (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ) {\n throw new Error(\n `Failed to fetch audio from URL (${input.url}): timed out after ${timeoutMs}ms`,\n );\n }\n\n throw new Error(\n `Failed to fetch audio from URL (${input.url}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"path\" in input) {\n try {\n rawData = await readFile(input.path);\n } catch (error) {\n throw new Error(\n `Failed to read audio from path (${input.path}): ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const { fileTypeFromBuffer } = await import(\"file-type\");\n const mimeType = await fileTypeFromBuffer(rawData);\n\n if (!mimeType || !mimeType.mime.startsWith(\"audio/\")) {\n console.warn(\n `Warning: Content may not be a valid audio file. Detected MIME: ${\n mimeType?.mime || \"unknown\"\n }`,\n );\n }\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n data: base64Data,\n mimeType: mimeType?.mime ?? \"audio/mpeg\",\n type: \"audio\",\n } as const;\n } catch (error) {\n if (error instanceof Error) {\n throw error;\n } else {\n throw new Error(`Unexpected error processing audio: ${String(error)}`);\n }\n }\n};\n\ntype Context<T extends FastMCPSessionAuth> = {\n client: {\n version: ReturnType<Server[\"getClientVersion\"]>;\n };\n /**\n * Requests additional information from the user via the client\n * (see https://modelcontextprotocol.io/specification/2025-06-18/client/elicitation).\n * The client must advertise the matching `elicitation` capability mode —\n * `elicitation: { form: {} }` for form requests (the default) and/or\n * `elicitation: { url: {} }` for url requests.\n */\n elicit: (\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ) => Promise<ElicitResult>;\n log: {\n debug: (message: string, data?: SerializableValue) => void;\n error: (message: string, data?: SerializableValue) => void;\n info: (message: string, data?: SerializableValue) => void;\n warn: (message: string, data?: SerializableValue) => void;\n };\n reportProgress: (progress: Progress) => Promise<void>;\n /**\n * Request ID from the current MCP request.\n * Available for all transports when the client provides it.\n */\n requestId?: string;\n session: T | undefined;\n /**\n * Session ID from the Mcp-Session-Id header.\n * Only available for HTTP-based transports (SSE, HTTP Stream).\n * Can be used to track per-session state, implement session-specific\n * counters, or maintain user-specific data across multiple requests.\n */\n sessionId?: string;\n /**\n * Aborted once the tool's result can no longer reach anyone: the client\n * cancelled the call, the session went away, or `timeoutMs` elapsed.\n *\n * Nothing is killed on your behalf — FastMCP stops waiting, but the promise\n * `execute` returned keeps running until it settles. Forward this signal to\n * whatever does the real work (`fetch`, a database driver, a subprocess) so\n * the work stops with the call instead of outliving it.\n *\n * It is never aborted after a call completes normally, so it is safe to\n * attach cleanup to it.\n */\n signal: AbortSignal;\n /**\n * Streams incremental content while the tool is still executing, by emitting\n * a `notifications/tool/streamContent` notification.\n *\n * NOTE: this is a FastMCP extension, not part of the MCP specification. As of\n * revision 2025-11-25 the spec has no streaming tool output primitive (see\n * SEP-2998 for the in-progress proposal). A client only receives these\n * notifications if it registers a handler for the method or sets a\n * `fallbackNotificationHandler`; otherwise the SDK drops them silently. No\n * client is known to render them as tool output.\n *\n * Always return a final result from `execute` rather than relying on streamed\n * content alone, otherwise clients that ignore the notification see an empty\n * tool result. For incremental status that works everywhere, prefer\n * {@link Context.reportProgress} with a `message`.\n */\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\n/**\n * Context passed to `load` for resources, resource templates, and prompts.\n *\n * This is a subset of the tool execution {@link Context}. `reportProgress`\n * and `streamContent` are tied to a tool call's progress token / streaming\n * notification and are not available outside of `tool.execute`. `signal` is\n * omitted too: its timeout leg comes from `tool.timeoutMs`, which `load` has\n * no equivalent of.\n */\ntype LoadContext<T extends FastMCPSessionAuth> = Omit<\n Context<T>,\n \"reportProgress\" | \"signal\" | \"streamContent\"\n>;\n\ntype Progress = {\n /**\n * An optional human-readable message describing the current progress.\n *\n * Part of `notifications/progress` since MCP revision 2025-03-26, so unlike\n * `streamContent` this reaches any spec-compliant client.\n */\n message?: string;\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\nexport abstract class FastMCPError extends Error {\n public constructor(message?: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\n/**\n * An error raised when a session encounters a problem (e.g. connection\n * failures, protocol violations). Consumers can use this class to\n * distinguish fastmcp session errors from unrelated runtime errors:\n *\n * ```ts\n * server.on(\"error\", ({ error }) => {\n * if (error instanceof SessionError) { ... }\n * });\n * ```\n */\nexport class SessionError extends FastMCPError {}\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\nfunction assertStandardSchema(\n toolName: string,\n schemaName: \"outputSchema\" | \"parameters\",\n schema: ToolParameters,\n): void {\n const standard = (schema as { \"~standard\"?: { validate?: unknown } })[\n \"~standard\"\n ];\n\n if (typeof standard?.validate === \"function\") {\n return;\n }\n\n throw new UserError(\n `Tool '${toolName}' ${schemaName} must implement Standard Schema. If you are using Zod, upgrade to version 3.24 or later.`,\n );\n}\n\nfunction assertToolSchemas(tool: {\n name: string;\n outputSchema?: ToolParameters;\n parameters?: ToolParameters;\n}): void {\n if (tool.parameters) {\n assertStandardSchema(tool.name, \"parameters\", tool.parameters);\n }\n\n if (tool.outputSchema) {\n assertStandardSchema(tool.name, \"outputSchema\", tool.outputSchema);\n }\n}\n\nconst STREAM_KEEPALIVE_LOGGER = \"fastmcp-keepalive\";\n\nconst STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS = 20_000;\n\nconst TextContentZodSchema = z\n .object({\n /**\n * The text content of the message.\n */\n text: z.string(),\n type: z.literal(\"text\"),\n })\n .strict() satisfies z.ZodType<TextContent>;\n\ntype ImageContent = {\n data: string;\n mimeType: string;\n type: \"image\";\n};\n\nconst ImageContentZodSchema = z\n .object({\n /**\n * The base64-encoded image data.\n */\n data: z.string().base64(),\n /**\n * The MIME type of the image. Different providers may support different image types.\n */\n mimeType: z.string(),\n type: z.literal(\"image\"),\n })\n .strict() satisfies z.ZodType<ImageContent>;\n\ntype AudioContent = {\n data: string;\n mimeType: string;\n type: \"audio\";\n};\n\nconst AudioContentZodSchema = z\n .object({\n /**\n * The base64-encoded audio data.\n */\n data: z.string().base64(),\n mimeType: z.string(),\n type: z.literal(\"audio\"),\n })\n .strict() satisfies z.ZodType<AudioContent>;\n\ntype ResourceContent = {\n resource: {\n blob?: string;\n mimeType?: string;\n text?: string;\n uri: string;\n };\n type: \"resource\";\n};\n\nconst ResourceContentZodSchema = z\n .object({\n resource: z.object({\n blob: z.string().optional(),\n mimeType: z.string().optional(),\n text: z.string().optional(),\n uri: z.string(),\n }),\n type: z.literal(\"resource\"),\n })\n .strict() satisfies z.ZodType<ResourceContent>;\n\nconst ResourceLinkZodSchema = z.object({\n description: z.string().optional(),\n mimeType: z.string().optional(),\n name: z.string(),\n title: z.string().optional(),\n type: z.literal(\"resource_link\"),\n uri: z.string(),\n}) satisfies z.ZodType<ResourceLink>;\n\ntype Content =\n | AudioContent\n | ImageContent\n | ResourceContent\n | ResourceLink\n | TextContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n AudioContentZodSchema,\n ResourceContentZodSchema,\n ResourceLinkZodSchema,\n]) satisfies z.ZodType<Content>;\n\ntype ContentResult = {\n _meta?: Record<string, unknown>;\n content: Content[];\n isError?: boolean;\n structuredContent?: Record<string, unknown>;\n};\n\nconst ContentResultZodSchema = z\n .object({\n _meta: z.record(z.string(), z.unknown()).optional(),\n content: ContentZodSchema.array(),\n isError: z.boolean().optional(),\n structuredContent: z.record(z.string(), z.unknown()).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. The MCP spec caps this at 100 items; values\n * beyond the cap are trimmed by `capCompletionValues` (which sets `hasMore`)\n * rather than rejected, so the schema itself does not enforce the limit.\n */\n values: z.array(z.string()),\n}) satisfies z.ZodType<Completion>;\n\n/**\n * The MCP completion result must not exceed 100 values. Rather than failing when\n * a user-supplied completer returns more, trim to the cap and flag `hasMore` so\n * the client knows the list was truncated.\n */\nconst COMPLETION_VALUES_LIMIT = 100;\n\nconst capCompletionValues = (completion: Completion): Completion => {\n if (completion.values.length <= COMPLETION_VALUES_LIMIT) {\n return completion;\n }\n\n return {\n ...completion,\n hasMore: true,\n values: completion.values.slice(0, COMPLETION_VALUES_LIMIT),\n };\n};\n\ntype ArgumentValueCompleter<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n (value: string, auth?: T) => Promise<Completion>;\n\ntype InputPrompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends InputPromptArgument<T>[] = InputPromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: InputPromptArgument<T>[];\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: Args,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<PromptResult>;\n name: string;\n};\n\ntype InputPromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype InputResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends InputResourceTemplateArgument<T>[] =\n InputResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype InputResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype LoggingLevel =\n | \"alert\"\n | \"critical\"\n | \"debug\"\n | \"emergency\"\n | \"error\"\n | \"info\"\n | \"notice\"\n | \"warning\";\n\ntype Prompt<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n Arguments extends PromptArgument<T>[] = PromptArgument<T>[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument<T>[];\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: Args,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<PromptResult>;\n name: string;\n};\n\ntype PromptArgument<T extends FastMCPSessionAuth = FastMCPSessionAuth> =\n Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n enum?: string[];\n name: string;\n required?: boolean;\n }>;\n\ntype PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =\n {\n [K in T[number][\"name\"]]: Extract<\n T[number],\n { name: K }\n >[\"required\"] extends true\n ? string\n : string | undefined;\n };\n\ntype PromptResult = Pick<GetPromptResult, \"messages\"> | string;\n\ntype Resource<T extends FastMCPSessionAuth> = {\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uri: string;\n};\n\ntype ResourceResult =\n | {\n blob: string;\n mimeType?: string;\n uri?: string;\n }\n | {\n mimeType?: string;\n text: string;\n uri?: string;\n };\n\ntype ResourceTemplate<\n T extends FastMCPSessionAuth,\n Arguments extends ResourceTemplateArgument<T>[] =\n ResourceTemplateArgument<T>[],\n> = {\n arguments: Arguments;\n complete?: (name: string, value: string, auth?: T) => Promise<Completion>;\n description?: string;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n auth?: T,\n context?: LoadContext<T>,\n ) => Promise<ResourceResult | ResourceResult[]>;\n mimeType?: string;\n name: string;\n uriTemplate: string;\n};\n\ntype ResourceTemplateArgument<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> = Readonly<{\n complete?: ArgumentValueCompleter<T>;\n description?: string;\n name: string;\n required?: boolean;\n}>;\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype SamplingResponse = {\n content: AudioContent | ImageContent | TextContent;\n model: string;\n role: \"assistant\" | \"user\";\n stopReason?: \"endTurn\" | \"maxTokens\" | \"stopSequence\" | string;\n};\n\ntype ServerOptions<T extends FastMCPSessionAuth> = {\n /**\n * Authentication provider for OAuth flows.\n * When provided, automatically configures the `authenticate` function\n * and `oauth` settings.\n *\n * For custom authentication logic, use the `authenticate` option instead.\n * If both are provided, `authenticate` takes precedence.\n *\n * @example\n * ```typescript\n * import { FastMCP, GitHubProvider } from \"fastmcp\";\n *\n * const server = new FastMCP({\n * auth: new GitHubProvider({\n * baseUrl: \"http://localhost:8000\",\n * clientId: process.env.GITHUB_CLIENT_ID!,\n * clientSecret: process.env.GITHUB_CLIENT_SECRET!,\n * }),\n * name: \"My Server\",\n * version: \"1.0.0\",\n * });\n * ```\n */\n auth?: AuthProvider<T extends OAuthSession ? T : OAuthSession>;\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 /**\n * Optional icons for this server.\n * Advertised to clients via MCP `initialize` (`serverInfo.icons`) so UIs can\n * show a logo next to the server name.\n */\n icons?: Icon[];\n instructions?: string;\n /**\n * Custom logger instance. If not provided, defaults to console.\n * Use this to integrate with your own logging system.\n */\n logger?: Logger;\n name: string;\n\n /**\n * Configuration for OAuth well-known discovery endpoints that can be exposed\n * when the server is running using HTTP-based transports (SSE or HTTP Stream).\n * When enabled, the server will respond to requests for OAuth discovery endpoints\n * with the configured metadata.\n *\n * The endpoints are only added when the server is started with\n * `transportType: \"httpStream\"` – they are ignored for the stdio transport.\n * Both SSE and HTTP Stream transports support OAuth endpoints.\n */\n oauth?: {\n /**\n * OAuth Authorization Server metadata for /.well-known/oauth-authorization-server\n *\n * This endpoint follows RFC 8414 (OAuth 2.0 Authorization Server Metadata)\n * and provides metadata about the OAuth 2.0 authorization server.\n *\n * Required by MCP Specification 2025-03-26\n */\n authorizationServer?: {\n authorizationEndpoint: string;\n // Client ID Metadata Documents (SEP-991) accepted in place of DCR\n clientIdMetadataDocumentSupported?: boolean;\n codeChallengeMethodsSupported?: string[];\n // DPoP support\n dpopSigningAlgValuesSupported?: string[];\n grantTypesSupported?: string[];\n\n introspectionEndpoint?: string;\n // Required\n issuer: string;\n // Common optional\n jwksUri?: string;\n opPolicyUri?: string;\n opTosUri?: string;\n registrationEndpoint?: string;\n responseModesSupported?: string[];\n responseTypesSupported: string[];\n revocationEndpoint?: string;\n scopesSupported?: string[];\n serviceDocumentation?: string;\n tokenEndpoint: string;\n tokenEndpointAuthMethodsSupported?: string[];\n tokenEndpointAuthSigningAlgValuesSupported?: string[];\n\n uiLocalesSupported?: string[];\n };\n\n /**\n * Whether OAuth discovery endpoints should be enabled.\n */\n enabled: boolean;\n\n /**\n * OAuth Protected Resource metadata for `/.well-known/oauth-protected-resource`\n *\n * This endpoint follows {@link https://www.rfc-editor.org/rfc/rfc9728.html | RFC 9728}\n * and provides metadata describing how an OAuth 2.0 protected resource (in this case,\n * an MCP server) expects to be accessed.\n *\n * When configured, FastMCP will automatically serve this metadata at the\n * `/.well-known/oauth-protected-resource` endpoint. The `authorizationServers` and `resource`\n * fields are required. All others are optional and will be omitted from the published\n * metadata if not specified.\n *\n * This satisfies the requirements of the MCP Authorization specification's\n * {@link https://modelcontextprotocol.io/specification/2025-06-18/basic/authorization#authorization-server-location | Authorization Server Location section}.\n *\n * Clients consuming this metadata MUST validate that any presented values comply with\n * RFC 9728, including strict validation of the `resource` identifier and intended audience\n * when access tokens are issued and presented (per RFC 8707 §2).\n *\n * @remarks Required by MCP Specification version 2025-06-18\n */\n protectedResource?: {\n /**\n * Allows for additional metadata fields beyond those defined in RFC 9728.\n *\n * @remarks This supports vendor-specific or experimental extensions.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2.3 | RFC 9728 §2.3}\n */\n [key: string]: unknown;\n\n /**\n * Supported values for the `authorization_details` parameter (RFC 9396).\n *\n * @remarks Used when fine-grained access control is in play.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.23 | RFC 9728 §2.2.23}\n */\n authorizationDetailsTypesSupported?: string[];\n\n /**\n * List of OAuth 2.0 authorization server issuer identifiers.\n *\n * These correspond to ASes that can issue access tokens for this protected resource.\n * MCP clients use these values to locate the relevant `/.well-known/oauth-authorization-server`\n * metadata for initiating the OAuth flow.\n *\n * @remarks Required by the MCP spec. MCP servers MUST provide at least one issuer.\n * Clients are responsible for choosing among them (see RFC 9728 §7.6).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.3 | RFC 9728 §2.2.3}\n */\n authorizationServers: string[];\n\n /**\n * List of supported methods for presenting OAuth 2.0 bearer tokens.\n *\n * @remarks Valid values are `header`, `body`, and `query`.\n * If omitted, clients MAY assume only `header` is supported, per RFC 6750.\n * This is a client-side interpretation and not a serialization default.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.9 | RFC 9728 §2.2.9}\n */\n bearerMethodsSupported?: string[];\n\n /**\n * Whether this resource requires all access tokens to be DPoP-bound.\n *\n * @remarks If omitted, clients SHOULD assume this is `false`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.27 | RFC 9728 §2.2.27}\n */\n dpopBoundAccessTokensRequired?: boolean;\n\n /**\n * Supported algorithms for verifying DPoP proofs (RFC 9449).\n *\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.25 | RFC 9728 §2.2.25}\n */\n dpopSigningAlgValuesSupported?: string[];\n\n /**\n * JWKS URI of this resource. Used to validate access tokens or sign responses.\n *\n * @remarks When present, this MUST be an `https:` URI pointing to a valid JWK Set (RFC 7517).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.5 | RFC 9728 §2.2.5}\n */\n jwksUri?: string;\n\n /**\n * Canonical OAuth resource identifier for this protected resource (the MCP server).\n *\n * @remarks Typically the base URL of the MCP server. Clients MUST use this as the\n * `resource` parameter in authorization and token requests (per RFC 8707).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.1 | RFC 9728 §2.2.1}\n */\n resource: string;\n\n /**\n * URL to developer-accessible documentation for this resource.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n resourceDocumentation?: string;\n\n /**\n * Human-readable name for display purposes (e.g., in UIs).\n *\n * @remarks This field MAY be localized using language tags (`resource_name#en`, etc.).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.13 | RFC 9728 §2.2.13}\n */\n resourceName?: string;\n\n /**\n * URL to a human-readable policy page describing acceptable use.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.17 | RFC 9728 §2.2.17}\n */\n resourcePolicyUri?: string;\n\n /**\n * Supported JWS algorithms for signed responses from this resource (e.g., response signing).\n *\n * @remarks MUST NOT include `none`.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.11 | RFC 9728 §2.2.11}\n */\n resourceSigningAlgValuesSupported?: string[];\n\n /**\n * URL to the protected resource’s Terms of Service.\n *\n * @remarks This field MAY be localized.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.19 | RFC 9728 §2.2.19}\n */\n resourceTosUri?: string;\n\n /**\n * Supported OAuth scopes for requesting access to this resource.\n *\n * @remarks Useful for discovery, but clients SHOULD still request the minimal scope required.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.7 | RFC 9728 §2.2.7}\n */\n scopesSupported?: string[];\n\n /**\n * Developer-accessible documentation for how to use the service (not end-user docs).\n *\n * @remarks Semantically equivalent to `resourceDocumentation`, but included under its\n * alternate name for compatibility with tools or schemas expecting either.\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.15 | RFC 9728 §2.2.15}\n */\n serviceDocumentation?: string;\n\n /**\n * Whether mutual-TLS-bound access tokens are required.\n *\n * @remarks If omitted, clients SHOULD assume this is `false` (client-side behavior).\n * @see {@link https://www.rfc-editor.org/rfc/rfc9728.html#section-2-2.21 | RFC 9728 §2.2.21}\n */\n tlsClientCertificateBoundAccessTokens?: boolean;\n };\n\n /**\n * OAuth Proxy instance for automatic OAuth flow handling.\n * When provided, FastMCP will automatically register OAuth endpoints:\n * - /oauth/register (DCR)\n * - /oauth/authorize\n * - /oauth/token\n * - /oauth/callback\n * - /oauth/consent\n */\n proxy?: OAuthProxy;\n };\n /**\n * Callback invoked when a tool is called.\n * Use this to log, audit, or track tool usage.\n */\n onToolCall?: (context: {\n arguments: Record<string, unknown>;\n toolName: string;\n }) => Promise<void> | void;\n\n ping?: {\n /**\n * Whether ping should be enabled by default.\n * - true for SSE or HTTP Stream\n * - false for stdio\n */\n enabled?: boolean;\n /**\n * Interval\n * @default 5000 (5s)\n */\n intervalMs?: number;\n /**\n * Logging level for ping-related messages.\n * @default 'debug'\n */\n logLevel?: LoggingLevel;\n };\n /**\n * Configuration for roots capability\n */\n roots?: {\n /**\n * Whether roots capability should be enabled\n * Set to false to completely disable roots support\n * @default true\n */\n enabled?: boolean;\n };\n /**\n * Writes periodically to an in-flight tool call's own response stream, so a\n * proxy or load balancer does not close the connection as idle while a\n * long-running tool produces no output.\n *\n * Unlike {@link ServerOptions.ping}, these messages are related to the\n * request being served, so they travel on that request's stream instead of\n * the standalone server-to-client stream. That makes them the only option\n * that works with `httpStream.stateless`, where no standing server-to-client\n * stream exists.\n */\n streamKeepalive?: {\n /**\n * Whether to write keepalives. Opt-in.\n * @default false\n */\n enabled?: boolean;\n /**\n * Interval between keepalives. Keep it comfortably below the shortest idle\n * timeout on the path (AWS ALB defaults to 60s). Values below 1ms fall back\n * to the default.\n * @default 20000 (20s)\n */\n intervalMs?: number;\n /**\n * Level reported on the keepalive notification.\n * @default 'debug'\n */\n logLevel?: LoggingLevel;\n };\n /**\n * Optional human-readable title for display in client UIs.\n * Advertised via MCP `initialize` (`serverInfo.title`).\n */\n title?: string;\n /**\n * General utilities\n */\n utils?: {\n formatInvalidParamsErrorMessage?: (\n issues: readonly StandardSchemaV1.Issue[],\n ) => string;\n };\n version: `${number}.${number}.${number}`;\n /**\n * Optional URL of the website for this server.\n * Advertised via MCP `initialize` (`serverInfo.websiteUrl`).\n */\n websiteUrl?: string;\n};\n\ntype Tool<\n T extends FastMCPSessionAuth,\n Params extends ToolParameters = ToolParameters,\n OutputParams extends ToolParameters = ToolParameters,\n> = {\n /**\n * MCP ext-apps metadata for linking interactive UI components.\n * This field is passed through to the tool listing response.\n * @see https://modelcontextprotocol.github.io/ext-apps/\n */\n _meta?: {\n /** Additional metadata fields */\n [key: string]: unknown;\n /** UI component configuration */\n ui?: {\n /** URI of the resource serving the UI (e.g., \"ui://my-tool/app.html\") */\n resourceUri?: string;\n };\n };\n annotations?: {\n /**\n * Advisory metadata signalling that the tool streams incremental content\n * via {@link Context.streamContent}. Forwarded verbatim in `tools/list`.\n *\n * This has no effect on FastMCP's behavior: it neither enables nor is\n * required by `streamContent`. No known client interprets it today.\n */\n streamingHint?: boolean;\n } & ToolAnnotations;\n canAccess?: (auth: T) => boolean;\n\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 | ResourceLink\n | StandardSchemaV1.InferOutput<OutputParams>\n | string\n | TextContent\n | void\n >;\n name: string;\n outputSchema?: OutputParams;\n parameters?: Params;\n timeoutMs?: number;\n};\n\n/**\n * Tool annotations as defined in MCP Specification (2025-03-26)\n * These provide hints about a tool's behavior.\n */\ntype ToolAnnotations = {\n /**\n * If true, the tool may perform destructive updates\n * Only meaningful when readOnlyHint is false\n * @default true\n */\n destructiveHint?: boolean;\n\n /**\n * If true, calling the tool repeatedly with the same arguments has no additional effect\n * Only meaningful when readOnlyHint is false\n * @default false\n */\n idempotentHint?: boolean;\n\n /**\n * If true, the tool may interact with an \"open world\" of external entities\n * @default true\n */\n openWorldHint?: boolean;\n\n /**\n * If true, indicates the tool does not modify its environment\n * @default false\n */\n readOnlyHint?: boolean;\n\n /**\n * A human-readable title for the tool, useful for UI display\n */\n title?: string;\n};\n\nconst FastMCPSessionEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;\n} = EventEmitter;\n\nexport enum ServerState {\n Error = \"error\",\n Running = \"running\",\n Stopped = \"stopped\",\n}\n\n/**\n * Enhanced request object for custom routes\n */\nexport interface FastMCPRequest<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> {\n auth?: T;\n body?: unknown;\n headers: http.IncomingHttpHeaders;\n\n json(): Promise<unknown>;\n\n method: string;\n params: Record<string, string>;\n query: Record<string, string | string[]>;\n\n text(): Promise<string>;\n\n url: string;\n}\n\n/**\n * Enhanced response object for custom routes\n */\nexport interface FastMCPResponse {\n end(data?: Buffer | string): void;\n\n json(data: unknown): void;\n\n send(data: Buffer | string): void;\n\n setHeader(name: string, value: number | string | string[]): FastMCPResponse;\n\n status(code: number): FastMCPResponse;\n}\n\n/**\n * HTTP method types for custom routes\n */\nexport type HTTPMethod =\n | \"DELETE\"\n | \"GET\"\n | \"OPTIONS\"\n | \"PATCH\"\n | \"POST\"\n | \"PUT\";\n\n/**\n * Route handler function type\n */\nexport type RouteHandler<T extends FastMCPSessionAuth = FastMCPSessionAuth> = (\n req: FastMCPRequest<T>,\n res: FastMCPResponse,\n) => Promise<void> | void;\n\n/**\n * Options for configuring custom routes\n */\nexport interface RouteOptions {\n /**\n * Whether this route should bypass authentication.\n * When true, the route handler will be called without authentication,\n * and req.auth will be undefined.\n * @default false\n */\n public?: boolean;\n}\n\n/**\n * Returning a nullish value signals that authentication failed; FastMCP turns\n * it into a 401 rather than creating a session. This is what the built-in\n * OAuth `AuthProvider` does for a missing or invalid bearer token.\n */\ntype Authenticate<T> = (\n request: http.IncomingMessage,\n) => Promise<null | T | undefined>;\n\ntype FastMCPSessionAuth = Record<string, unknown> | undefined;\n\nclass FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}\n\nexport class FastMCPSession<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPSessionEventEmitter {\n public get clientCapabilities(): ClientCapabilities | null {\n return this.#clientCapabilities ?? null;\n }\n\n public get isReady(): boolean {\n return this.#connectionState === \"ready\";\n }\n\n public get loggingLevel(): LoggingLevel {\n return this.#loggingLevel;\n }\n\n public get roots(): Root[] {\n return this.#roots;\n }\n\n public get server(): Server {\n return this.#server;\n }\n\n /**\n * The HTTP session ID, or `undefined` for transports that do not have one.\n *\n * Resolved from the transport rather than captured when the session\n * connects: `StreamableHTTPServerTransport` assigns its `sessionId` while it\n * handles `initialize`, which happens after `connect()` resolves. A value\n * read at connect time is therefore still `undefined`.\n *\n * The first ID seen is latched, so the session keeps reporting it once the\n * transport detaches — `Protocol` drops its transport reference on close,\n * which would otherwise make the ID vanish mid-teardown. Latching is safe\n * because {@link connect} refuses a second transport, so a session never\n * sees two IDs.\n */\n public get sessionId(): string | undefined {\n if (this.#sessionId === undefined) {\n const transportSessionId = this.#server.transport?.sessionId;\n\n if (typeof transportSessionId === \"string\") {\n this.#sessionId = transportSessionId;\n }\n }\n\n return this.#sessionId;\n }\n\n public set sessionId(value: string | undefined) {\n this.#sessionId = value;\n }\n\n /**\n * Aborted once the session ends, and folded into the `signal` every tool\n * call receives. The MCP SDK only aborts a request's own signal for an\n * explicit `notifications/cancelled`, and neither `Protocol` nor\n * `StreamableHTTPServerTransport` touches it when the transport simply goes\n * away — so without this a tool keeps running after the client that asked\n * for it has hung up.\n */\n #abortController = new AbortController();\n\n #auth: T | undefined;\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #connectionState: \"closed\" | \"connecting\" | \"error\" | \"ready\" = \"connecting\";\n #logger: Logger;\n #loggingLevel: LoggingLevel = \"info\";\n #needsEventLoopFlush: boolean = false;\n #onToolCall?: ServerOptions<T>[\"onToolCall\"];\n #pingConfig?: ServerOptions<T>[\"ping\"];\n\n #pingInFlight = false;\n #pingInterval: null | ReturnType<typeof setInterval> = null;\n\n #prompts: Map<string, Prompt<T>> = new Map();\n\n #resources: Map<string, Resource<T>> = new Map();\n\n #resourceTemplates: Map<string, ResourceTemplate<T>> = new Map();\n\n #roots: Root[] = [];\n\n #rootsConfig?: ServerOptions<T>[\"roots\"];\n\n #server: Server;\n\n /**\n * Session ID from the Mcp-Session-Id header (HTTP transports only).\n * Used to track per-session state across multiple requests.\n */\n #sessionId?: string;\n\n /**\n * Whether this session serves a single stateless HTTP request. The client\n * handshake belongs to a different session — potentially on a different\n * instance — so capabilities can never be inferred here.\n */\n #stateless: boolean;\n\n #streamKeepaliveConfig: ServerOptions<T>[\"streamKeepalive\"];\n\n /**\n * Resource URIs the connected client has subscribed to via\n * `resources/subscribe`. Used to scope `notifications/resources/updated`\n * to interested clients only.\n */\n #subscriptions: Set<string> = new Set();\n\n #utils?: ServerOptions<T>[\"utils\"];\n\n constructor({\n auth,\n icons,\n instructions,\n logger,\n name,\n onToolCall,\n ping,\n prompts,\n resources,\n resourcesTemplates,\n roots,\n sessionId,\n stateless = false,\n streamKeepalive,\n title,\n tools,\n transportType,\n utils,\n version,\n websiteUrl,\n }: {\n auth?: T;\n icons?: Icon[];\n instructions?: string;\n logger: Logger;\n name: string;\n onToolCall?: ServerOptions<T>[\"onToolCall\"];\n ping?: ServerOptions<T>[\"ping\"];\n prompts: Prompt<T>[];\n resources: Resource<T>[];\n resourcesTemplates: InputResourceTemplate<T>[];\n roots?: ServerOptions<T>[\"roots\"];\n sessionId?: string;\n stateless?: boolean;\n streamKeepalive?: ServerOptions<T>[\"streamKeepalive\"];\n title?: string;\n tools: Tool<T>[];\n transportType?: \"httpStream\" | \"stdio\";\n utils?: ServerOptions<T>[\"utils\"];\n version: string;\n websiteUrl?: string;\n }) {\n super();\n\n this.#auth = auth;\n this.#logger = logger;\n this.#onToolCall = onToolCall;\n this.#pingConfig = ping;\n this.#rootsConfig = roots;\n this.#sessionId = sessionId;\n this.#stateless = stateless;\n this.#streamKeepaliveConfig = streamKeepalive;\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 = { listChanged: true, subscribe: true };\n }\n\n if (prompts.length) {\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n\n this.#capabilities.prompts = { listChanged: true };\n }\n\n this.#capabilities.logging = {};\n\n this.#capabilities.completions = {};\n\n this.#server = new Server(\n {\n ...(icons !== undefined ? { icons } : {}),\n name,\n ...(title !== undefined ? { title } : {}),\n version,\n ...(websiteUrl !== undefined ? { websiteUrl } : {}),\n },\n { capabilities: this.#capabilities, instructions: instructions },\n );\n\n this.#utils = utils;\n\n this.setupErrorHandling();\n this.setupLoggingHandlers();\n this.setupRootsHandlers();\n this.setupCompleteHandlers();\n\n if (tools.length) {\n this.setupToolHandlers(tools);\n }\n\n if (resources.length || resourcesTemplates.length) {\n for (const resource of resources) {\n this.addResource(resource);\n }\n\n for (const resourceTemplate of resourcesTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n\n this.setupResourceHandlers();\n this.setupResourceSubscriptionHandlers();\n // `resources/templates/list` belongs to the `resources` capability that\n // was just advertised, so the handler has to answer even when there is\n // nothing to list - the reference SDK returns an empty array. Gating it\n // on having templates made a resources-only server reply -32601 Method\n // not found to any client that lists templates.\n this.setupResourceTemplateHandlers();\n }\n\n if (prompts.length) {\n this.setupPromptHandlers();\n }\n }\n\n public async close() {\n this.#connectionState = \"closed\";\n\n if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n this.#abortSession();\n\n try {\n await this.#server.close();\n } catch (error) {\n this.#logger.error(\"[FastMCP error]\", \"could not close server\", error);\n }\n }\n\n public async connect(transport: Transport) {\n if (this.#server.transport) {\n throw new UnexpectedStateError(\"Server is already connected\");\n }\n\n this.#connectionState = \"connecting\";\n\n try {\n await this.#server.connect(transport);\n\n // Skipped in stateless mode: a session there serves one request, and the\n // initialize that carried the client's capabilities was handled by a\n // different session, so polling can only ever time out and warn — once\n // per request.\n if (!this.#stateless) {\n let attempt = 0;\n const maxAttempts = 10;\n const retryDelay = 100;\n\n while (attempt++ < maxAttempts) {\n const capabilities = this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n break;\n }\n\n await delay(retryDelay);\n }\n\n if (!this.#clientCapabilities) {\n this.#logger.warn(\n `[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`,\n );\n }\n }\n\n if (\n this.#rootsConfig?.enabled !== false &&\n this.#clientCapabilities?.roots?.listChanged &&\n typeof this.#server.listRoots === \"function\"\n ) {\n try {\n const roots = await this.#server.listRoots();\n this.#roots = roots?.roots || [];\n } catch (e) {\n if (e instanceof McpError && e.code === ErrorCode.MethodNotFound) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n e instanceof Error ? e.stack : JSON.stringify(e)\n }`,\n );\n }\n }\n }\n\n if (this.#clientCapabilities) {\n const pingConfig = this.#getPingConfig(transport);\n\n if (pingConfig.enabled) {\n this.#pingInterval = setInterval(async () => {\n if (this.#pingInFlight) {\n return;\n }\n\n this.#pingInFlight = true;\n\n try {\n await this.#server.ping();\n } catch {\n // The reason we are not emitting an error here is because some clients\n // seem to not respond to the ping request, and we don't want to crash the server,\n // e.g., https://github.com/punkpeye/fastmcp/issues/38.\n const logLevel = pingConfig.logLevel;\n\n if (logLevel === \"debug\") {\n this.#logger.debug(\"[FastMCP debug] server ping failed\");\n } else if (logLevel === \"warning\") {\n this.#logger.warn(\n \"[FastMCP warning] server is not responding to ping\",\n );\n } else if (logLevel === \"error\") {\n this.#logger.error(\n \"[FastMCP error] server is not responding to ping\",\n );\n } else {\n this.#logger.info(\"[FastMCP info] server ping failed\");\n }\n } finally {\n this.#pingInFlight = false;\n }\n }, pingConfig.intervalMs);\n }\n }\n\n // Mark connection as ready and emit event\n this.#connectionState = \"ready\";\n this.emit(\"ready\");\n } catch (error) {\n this.#connectionState = \"error\";\n const errorEvent = {\n error: error instanceof Error ? error : new Error(String(error)),\n };\n this.emit(\"error\", errorEvent);\n throw error;\n }\n }\n\n promptsListChanged(prompts: Prompt<T>[]) {\n this.#prompts.clear();\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n this.setupPromptHandlers();\n this.triggerListChangedNotification(\"notifications/prompts/list_changed\");\n }\n\n public async requestElicitation(\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ): Promise<ElicitResult> {\n return this.#server.elicitInput(params, options);\n }\n\n public async requestSampling(\n message: z.infer<typeof CreateMessageRequestSchema>[\"params\"],\n options?: RequestOptions,\n ): Promise<SamplingResponse> {\n return this.#server.createMessage(message, options);\n }\n\n resourcesListChanged(resources: Resource<T>[]) {\n this.#resources.clear();\n for (const resource of resources) {\n this.addResource(resource);\n }\n this.setupResourceHandlers();\n this.triggerListChangedNotification(\"notifications/resources/list_changed\");\n }\n\n resourceTemplatesListChanged(resourceTemplates: ResourceTemplate<T>[]) {\n this.#resourceTemplates.clear();\n for (const resourceTemplate of resourceTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n this.setupResourceTemplateHandlers();\n this.triggerListChangedNotification(\"notifications/resources/list_changed\");\n }\n\n /**\n * Notifies the connected client that the contents of a resource have changed.\n *\n * The `notifications/resources/updated` notification is only sent when the\n * client has subscribed to the URI via `resources/subscribe`; otherwise this\n * is a no-op.\n */\n async sendResourceUpdated(uri: string) {\n if (!this.#subscriptions.has(uri)) {\n return;\n }\n\n try {\n await this.#server.sendResourceUpdated({ uri });\n } catch (error) {\n this.#logger.error(\n `[FastMCP error] failed to send resources/updated notification for '${uri}'.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n }\n\n toolsListChanged(tools: Tool<T>[]) {\n const allowedTools = tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(this.#auth as T) : true,\n );\n this.setupToolHandlers(allowedTools);\n this.triggerListChangedNotification(\"notifications/tools/list_changed\");\n }\n\n async triggerListChangedNotification(method: string) {\n try {\n await this.#server.notification({\n method,\n });\n } catch (error) {\n this.#logger.error(\n `[FastMCP error] failed to send ${method} notification.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n }\n\n /**\n * Update the session's authentication context.\n * Called by mcp-proxy when a new token is validated on subsequent requests.\n */\n public updateAuth(auth: T): void {\n this.#auth = auth;\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 /**\n * Cancels the `signal` held by every tool still executing on this session.\n * Idempotent, so the close path and the transport's own close handler can\n * both call it.\n */\n #abortSession() {\n if (!this.#abortController.signal.aborted) {\n this.#abortController.abort(new SessionError(\"Session closed\"));\n }\n }\n\n /**\n * Builds the context object passed as the third argument to\n * `resource.load` / `resourceTemplate.load` / `prompt.load`.\n *\n * This mirrors the `client`, `elicit`, `log`, `requestId`, `session`,\n * and `sessionId` fields available to `tool.execute` via {@link Context}.\n * `reportProgress` and `streamContent` are intentionally omitted: they\n * are tied to a tool call's progress token / streaming notification,\n * which resource and prompt reads do not have.\n */\n #createLoadContext(meta?: Record<string, unknown>): LoadContext<T> {\n return {\n client: {\n version: this.#server.getClientVersion(),\n },\n elicit: (\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ) => this.#server.elicitInput(params, options),\n log: this.#createLog(),\n requestId:\n typeof meta?.requestId === \"string\" ? meta.requestId : undefined,\n session: this.#auth,\n sessionId: this.sessionId,\n };\n }\n\n #createLog(): Context<T>[\"log\"] {\n return {\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\n #formatSchemaIssues(issues: readonly StandardSchemaV1.Issue[]): string {\n return this.#utils?.formatInvalidParamsErrorMessage\n ? this.#utils.formatInvalidParamsErrorMessage(issues)\n : issues\n .map((issue) => {\n const path = issue.path?.join(\".\") || \"root\";\n return `${path}: ${issue.message}`;\n })\n .join(\", \");\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 /**\n * Periodically writes to the response stream of an in-flight tool call, so an\n * idle-connection timeout (proxy, load balancer) does not close it while a\n * long-running tool produces no output of its own.\n *\n * The notification is related to the tool call, so it travels on that\n * request's own stream, which is the only server-to-client route that exists\n * when running stateless.\n *\n * @returns a function that stops the keepalive.\n */\n #startStreamKeepalive(\n extra: Pick<\n RequestHandlerExtra<ServerRequest, ServerNotification>,\n \"sendNotification\" | \"signal\"\n >,\n toolName: string,\n ): () => void {\n const config = this.#streamKeepaliveConfig;\n\n if (!config?.enabled) {\n return () => {};\n }\n\n // A non-positive interval would fire on every tick and flood the stream.\n const intervalMs =\n config.intervalMs && config.intervalMs > 0\n ? config.intervalMs\n : STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS;\n\n const timer = setInterval(() => {\n extra\n .sendNotification({\n method: \"notifications/message\",\n params: {\n data: { message: `keepalive while '${toolName}' is running` },\n level: config.logLevel ?? \"debug\",\n logger: STREAM_KEEPALIVE_LOGGER,\n },\n })\n .catch((error: unknown) => {\n // Left running: the caller stops it when the request finishes, and a\n // transient write failure should not silence the connection.\n this.#logger.debug(\n `[FastMCP debug] stream keepalive for '${toolName}' failed:`,\n error instanceof Error ? error.message : String(error),\n );\n });\n }, intervalMs);\n\n timer.unref?.();\n\n const stop = () => clearInterval(timer);\n\n // A cancelled or disconnected request stops waiting for the tool, so the\n // keepalive must not outlive the abort.\n extra.signal?.addEventListener(\"abort\", stop, { once: true });\n\n return stop;\n }\n\n async #validateStructuredContent(\n tool: Tool<T>,\n value: Record<string, unknown>,\n toolName: string,\n ): Promise<Record<string, unknown>> {\n if (!tool.outputSchema) {\n return value;\n }\n\n const parsed = await tool.outputSchema[\"~standard\"].validate(value);\n\n if (parsed.issues) {\n throw new UserError(\n `Tool '${toolName}' structured output validation failed: ${this.#formatSchemaIssues(parsed.issues)}. Please check the result matches the tool's outputSchema.`,\n );\n }\n\n return parsed.value as Record<string, unknown>;\n }\n\n private addPrompt(inputPrompt: InputPrompt<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n const enums: Record<string, string[]> = {};\n const fuseInstances: Record<string, Fuse<string>> = {};\n\n for (const argument of inputPrompt.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n\n if (argument.enum) {\n enums[argument.name] = argument.enum;\n fuseInstances[argument.name] = new Fuse(argument.enum, {\n includeScore: true,\n threshold: 0.3, // More flexible matching!\n });\n }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n if (inputPrompt.complete) {\n return await inputPrompt.complete(name, value, auth);\n }\n\n if (fuseInstances[name]) {\n // An empty query yields no fuzzy matches, so a client asking for\n // completions before the user has typed anything would see nothing.\n // Offer the full enum instead — it is the set of valid values, and\n // the central cap trims it to the MCP limit if it is large.\n if (value === \"\") {\n const values = enums[name];\n\n return {\n total: values.length,\n values,\n };\n }\n\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.set(prompt.name, prompt);\n }\n\n private addResource(inputResource: Resource<T>) {\n this.#resources.set(inputResource.uri, inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate<T>) {\n const completers: Record<string, ArgumentValueCompleter<T>> = {};\n\n for (const argument of inputResourceTemplate.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n }\n\n const resourceTemplate = {\n ...inputResourceTemplate,\n complete: async (name: string, value: string, auth?: T) => {\n if (completers[name]) {\n return await completers[name](value, auth);\n }\n\n if (inputResourceTemplate.complete) {\n return await inputResourceTemplate.complete(name, value, auth);\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#resourceTemplates.set(resourceTemplate.name, resourceTemplate);\n }\n\n private setupCompleteHandlers() {\n this.#server.setRequestHandler(CompleteRequestSchema, async (request) => {\n if (request.params.ref.type === \"ref/prompt\") {\n const ref = request.params.ref;\n\n const prompt = \"name\" in ref && this.#prompts.get(ref.name);\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 = capCompletionValues(\n CompletionZodSchema.parse(\n await prompt.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n ),\n );\n\n return {\n completion,\n };\n }\n\n if (request.params.ref.type === \"ref/resource\") {\n const ref = request.params.ref;\n\n const resource =\n \"uri\" in ref &&\n Array.from(this.#resourceTemplates.values()).find(\n (resource) => resource.uriTemplate === 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 = capCompletionValues(\n CompletionZodSchema.parse(\n await resource.complete(\n request.params.argument.name,\n request.params.argument.value,\n this.#auth,\n ),\n ),\n );\n\n return {\n completion,\n };\n }\n\n throw new UnexpectedStateError(\"Unexpected completion request\", {\n request,\n });\n });\n }\n\n private setupErrorHandling() {\n this.#server.onerror = (error) => {\n this.#logger.error(\"[FastMCP error]\", error);\n };\n\n // Covers the client that hangs up rather than closing politely: `close()`\n // never runs in that case, but the transport still reports the loss.\n this.#server.onclose = () => {\n this.#abortSession();\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() {\n let cachedPromptsList: ListPromptsResult[\"prompts\"] | null = null;\n\n this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {\n if (cachedPromptsList) {\n return {\n prompts: cachedPromptsList,\n };\n }\n\n cachedPromptsList = Array.from(this.#prompts.values()).map((prompt) => {\n return {\n arguments: prompt.arguments,\n complete: prompt.complete,\n description: prompt.description,\n name: prompt.name,\n };\n });\n\n return {\n prompts: cachedPromptsList,\n };\n });\n\n this.#server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = this.#prompts.get(request.params.name);\n\n if (!prompt) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown prompt: ${request.params.name}`,\n );\n }\n\n const args = request.params.arguments;\n\n for (const arg of prompt.arguments ?? []) {\n if (arg.required && !(args && arg.name in args)) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Prompt '${request.params.name}' requires argument '${arg.name}': ${\n arg.description || \"No description provided\"\n }`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt<T>[\"load\"]>>;\n\n try {\n result = await prompt.load(\n args as Record<string, string | undefined>,\n this.#auth,\n this.#createLoadContext(request.params?._meta),\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load prompt '${request.params.name}': ${errorMessage}`,\n );\n }\n\n if (typeof result === \"string\") {\n return {\n description: prompt.description,\n messages: [\n {\n content: { text: result, type: \"text\" },\n role: \"user\",\n },\n ],\n };\n } else {\n return {\n description: prompt.description,\n messages: result.messages,\n };\n }\n });\n }\n\n private setupResourceHandlers() {\n let cachedResourcesList: ListResourcesResult[\"resources\"] | null = null;\n\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n if (cachedResourcesList) {\n return {\n resources: cachedResourcesList,\n };\n }\n\n cachedResourcesList = Array.from(this.#resources.values()).map(\n (resource) => ({\n description: resource.description,\n mimeType: resource.mimeType,\n name: resource.name,\n uri: resource.uri,\n }),\n );\n\n return {\n resources: cachedResourcesList,\n };\n });\n\n this.#server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n if (\"uri\" in request.params) {\n const resource = this.#resources.get(request.params.uri);\n\n if (!resource) {\n for (const resourceTemplate of this.#resourceTemplates.values()) {\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(\n match,\n this.#auth,\n this.#createLoadContext(request.params?._meta),\n );\n\n const resources = Array.isArray(result) ? result : [result];\n return {\n contents: resources.map((resource) => ({\n ...resource,\n description: resourceTemplate.description,\n mimeType: resource.mimeType ?? resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uri: resource.uri ?? uri,\n })),\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Resource not found: '${request.params.uri}'. Available resources: ${\n Array.from(this.#resources.values())\n .map((r) => r.uri)\n .join(\", \") || \"none\"\n }`,\n );\n }\n\n if (!(\"uri\" in resource)) {\n throw new UnexpectedStateError(\"Resource does not support reading\");\n }\n\n let maybeArrayResult: Awaited<ReturnType<Resource<T>[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load(\n this.#auth,\n this.#createLoadContext(request.params?._meta),\n );\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n throw new McpError(\n ErrorCode.InternalError,\n `Failed to load resource '${resource.name}' (${resource.uri}): ${errorMessage}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n const resourceResults = Array.isArray(maybeArrayResult)\n ? maybeArrayResult\n : [maybeArrayResult];\n\n return {\n contents: resourceResults.map((result) => ({\n ...result,\n mimeType: result.mimeType ?? resource.mimeType,\n name: resource.name,\n uri: result.uri ?? resource.uri,\n })),\n };\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n\n private setupResourceSubscriptionHandlers() {\n this.#server.setRequestHandler(SubscribeRequestSchema, (request) => {\n this.#subscriptions.add(request.params.uri);\n\n return {};\n });\n\n this.#server.setRequestHandler(UnsubscribeRequestSchema, (request) => {\n this.#subscriptions.delete(request.params.uri);\n\n return {};\n });\n }\n\n private setupResourceTemplateHandlers() {\n let cachedResourceTemplatesList:\n | ListResourceTemplatesResult[\"resourceTemplates\"]\n | null = null;\n\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n if (cachedResourceTemplatesList) {\n return {\n resourceTemplates: cachedResourceTemplatesList,\n };\n }\n\n cachedResourceTemplatesList = Array.from(\n this.#resourceTemplates.values(),\n ).map((resourceTemplate) => ({\n description: resourceTemplate.description,\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n }));\n\n return {\n resourceTemplates: cachedResourceTemplatesList,\n };\n },\n );\n }\n\n private setupRootsHandlers() {\n if (this.#rootsConfig?.enabled === false) {\n this.#logger.debug(\n \"[FastMCP debug] roots capability explicitly disabled via config\",\n );\n return;\n }\n\n // Only set up roots notification handling if the server supports it\n if (typeof this.#server.listRoots === \"function\") {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server\n .listRoots()\n .then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n })\n .catch((error) => {\n if (\n error instanceof McpError &&\n error.code === ErrorCode.MethodNotFound\n ) {\n this.#logger.debug(\n \"[FastMCP debug] listRoots method not supported by client\",\n );\n } else {\n this.#logger.error(\n `[FastMCP error] received error listing roots.\\n\\n${\n error instanceof Error ? error.stack : JSON.stringify(error)\n }`,\n );\n }\n });\n },\n );\n } else {\n this.#logger.debug(\n \"[FastMCP debug] roots capability not available, not setting up notification handler\",\n );\n }\n }\n\n private setupToolHandlers(tools: Tool<T>[]) {\n const toolsMap = new Map(tools.map((tool) => [tool.name, tool]));\n let cachedToolsList: ListToolsResult[\"tools\"] | null = null;\n\n this.#server.setRequestHandler(ListToolsRequestSchema, async () => {\n if (cachedToolsList) {\n return {\n tools: cachedToolsList,\n };\n }\n cachedToolsList = await Promise.all(\n tools.map(async (tool) => {\n return {\n annotations: tool.annotations,\n description: tool.description,\n inputSchema: (tool.parameters\n ? strictJsonSchema(await toJsonSchema(tool.parameters))\n : {\n additionalProperties: false,\n properties: {},\n type: \"object\",\n }) as SDKTool[\"inputSchema\"],\n name: tool.name,\n ...(tool.outputSchema && {\n outputSchema: strictJsonSchema(\n await toJsonSchema(tool.outputSchema),\n ) as SDKTool[\"inputSchema\"],\n }),\n // Pass through _meta for MCP ext-apps UI support (issue #229)\n ...(tool._meta && { _meta: tool._meta }),\n };\n }),\n );\n\n return {\n tools: cachedToolsList,\n };\n });\n\n this.#server.setRequestHandler(\n CallToolRequestSchema,\n async (request, extra) => {\n const tool = toolsMap.get(request.params.name);\n\n if (!tool) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n\n let args: unknown = undefined;\n\n if (tool.parameters) {\n const parsed = await tool.parameters[\"~standard\"].validate(\n request.params.arguments,\n );\n\n if (parsed.issues) {\n const friendlyErrors = this.#formatSchemaIssues(parsed.issues);\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 // Progress notifications must reference the progressToken supplied by\n // the client in the initiating request. If the client did not request\n // progress, there is nothing to associate the update with, and sending\n // a notification without a token produces an invalid message.\n if (progressToken === undefined) {\n return;\n }\n\n try {\n await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (progressError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to report progress for tool '${request.params.name}':`,\n progressError instanceof Error\n ? progressError.message\n : String(progressError),\n );\n }\n };\n\n const log = this.#createLog();\n\n // Create a promise for tool execution\n // Streams partial results while a tool is still executing\n // Enables progressive rendering and real-time feedback\n const streamContent = async (content: Content | Content[]) => {\n const contentArray = Array.isArray(content) ? content : [content];\n\n try {\n await this.#server.notification({\n method: \"notifications/tool/streamContent\",\n params: {\n content: contentArray,\n toolName: request.params.name,\n },\n });\n\n if (this.#needsEventLoopFlush) {\n await new Promise((resolve) => setImmediate(resolve));\n }\n } catch (streamError) {\n this.#logger.warn(\n `[FastMCP warning] Failed to stream content for tool '${request.params.name}':`,\n streamError instanceof Error\n ? streamError.message\n : String(streamError),\n );\n }\n };\n\n if (this.#onToolCall) {\n await this.#onToolCall({\n arguments: (args ?? {}) as Record<string, unknown>,\n toolName: request.params.name,\n });\n }\n\n // Aborted when this call times out. Kept separate from the sources\n // below so the timer that drives it can still be cleared the moment\n // the tool settles — a fired-and-forgotten timeout would abort the\n // signal after a successful call and run the tool's cleanup for it.\n const timeoutAbort = new AbortController();\n\n // Composed rather than forwarded by hand: `AbortSignal.any()` needs\n // no listener bookkeeping, so nothing leaks when `execute` throws\n // synchronously, and Node holds the composite through a WeakRef, so\n // a per-call signal cannot pin the session-scoped one.\n const signal = AbortSignal.any([\n timeoutAbort.signal,\n this.#abortController.signal,\n // Only ever aborted for an explicit `notifications/cancelled`; the\n // session signal above is what covers a client that simply left.\n ...(extra.signal ? [extra.signal] : []),\n ]);\n\n const executeToolPromise = Promise.resolve(\n tool.execute(args, {\n client: {\n version: this.#server.getClientVersion(),\n },\n elicit: (\n params: ElicitRequestFormParams | ElicitRequestURLParams,\n options?: RequestOptions,\n ) => this.#server.elicitInput(params, options),\n log,\n reportProgress,\n requestId:\n typeof request.params?._meta?.requestId === \"string\"\n ? request.params._meta.requestId\n : undefined,\n session: this.#auth,\n sessionId: this.sessionId,\n signal,\n streamContent,\n }),\n );\n\n // Started only once execute has returned a promise, so a tool that\n // throws synchronously cannot leave a timer behind.\n const stopStreamKeepalive = this.#startStreamKeepalive(\n extra,\n request.params.name,\n );\n\n // Handle timeout if specified\n const maybeStringResult = (await (\n tool.timeoutMs\n ? Promise.race([\n executeToolPromise,\n new Promise<never>((_, reject) => {\n const timeoutId = setTimeout(() => {\n const timedOut = new UserError(\n `Tool '${request.params.name}' timed out after ${tool.timeoutMs}ms. Consider increasing timeoutMs or optimizing the tool implementation.`,\n );\n\n // Abort before rejecting: the tool learns it lost the\n // race while its own frame is still the reason, rather\n // than after the error has already gone back out.\n timeoutAbort.abort(timedOut);\n reject(timedOut);\n }, tool.timeoutMs);\n\n // If promise resolves first\n executeToolPromise.then(\n () => clearTimeout(timeoutId),\n () => clearTimeout(timeoutId),\n );\n }),\n ])\n : executeToolPromise\n ).finally(stopStreamKeepalive)) as\n | AudioContent\n | ContentResult\n | ImageContent\n | null\n | Record<string, unknown>\n | ResourceContent\n | ResourceLink\n | string\n | TextContent\n | undefined;\n\n // Without this test, we are running into situations where the last progress update is not reported.\n // See the 'reports multiple progress updates without buffering' test in FastMCP.test.ts before refactoring.\n await delay(1);\n\n if (maybeStringResult === undefined || maybeStringResult === null) {\n result = ContentResultZodSchema.parse({\n content: [],\n });\n } else if (typeof maybeStringResult === \"string\") {\n result = ContentResultZodSchema.parse({\n content: [{ text: maybeStringResult, type: \"text\" }],\n });\n } else if (\n \"content\" in maybeStringResult &&\n Array.isArray(maybeStringResult.content) &&\n (!tool.outputSchema ||\n ContentResultZodSchema.safeParse(maybeStringResult).success)\n ) {\n // Explicit ContentResult: the tool returned MCP content directly\n // (`{ content: [...], structuredContent? }`), so it takes precedence\n // over outputSchema and a tool can ship custom content blocks\n // alongside its structured payload. When an outputSchema is\n // declared, only claim the value if it really parses as a\n // ContentResult — otherwise an array-valued `content` field in the\n // structured payload itself would be misread as content blocks.\n result = ContentResultZodSchema.parse(maybeStringResult);\n if (result.structuredContent !== undefined && tool.outputSchema) {\n result.structuredContent = await this.#validateStructuredContent(\n tool,\n result.structuredContent,\n request.params.name,\n );\n }\n } else if (tool.outputSchema) {\n // A tool that declares an outputSchema returns its structured\n // payload directly, so outputSchema wins over the `type`/`content`\n // shorthands below. Without this precedence a payload whose\n // top-level shape happens to carry a `type` key (the common\n // discriminated-union case) or a `content` key would be misrouted\n // as MCP content and never surface as structuredContent.\n const structuredContent = await this.#validateStructuredContent(\n tool,\n maybeStringResult,\n request.params.name,\n );\n result = ContentResultZodSchema.parse({\n content: [\n {\n text: JSON.stringify(structuredContent),\n type: \"text\",\n },\n ],\n structuredContent,\n });\n } else if (\"type\" in maybeStringResult) {\n result = ContentResultZodSchema.parse({\n content: [maybeStringResult],\n });\n } else {\n result = ContentResultZodSchema.parse(maybeStringResult);\n }\n } catch (error) {\n if (error instanceof UserError) {\n return {\n content: [{ text: error.message, type: \"text\" }],\n isError: true,\n ...(error.extras ? { structuredContent: error.extras } : {}),\n };\n }\n\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n return {\n content: [\n {\n text: `Tool '${request.params.name}' execution failed: ${errorMessage}`,\n type: \"text\",\n },\n ],\n isError: true,\n };\n }\n\n return result;\n },\n );\n }\n}\n\n/**\n * Converts camelCase to snake_case for OAuth endpoint responses\n */\nfunction camelToSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Converts an object with camelCase keys to snake_case keys\n */\nfunction convertObjectToSnakeCase(\n obj: Record<string, unknown>,\n): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(obj)) {\n const snakeKey = camelToSnakeCase(key);\n result[snakeKey] = value;\n }\n\n return result;\n}\n\nfunction joinPaths(basePath: \"\" | `/${string}`, path: string): `/${string}` {\n return `${basePath}${normalizePath(path)}` as `/${string}`;\n}\n\nfunction normalizeBasePath(path: string | undefined): \"\" | `/${string}` {\n if (!path || path === \"/\") {\n return \"\";\n }\n\n const withLeadingSlash = path.startsWith(\"/\") ? path : `/${path}`;\n const withoutTrailingSlash = withLeadingSlash.replace(/\\/+$/, \"\");\n\n return withoutTrailingSlash ? (withoutTrailingSlash as `/${string}`) : \"\";\n}\n\nfunction normalizePath(path: string): `/${string}` {\n return (path.startsWith(\"/\") ? path : `/${path}`) as `/${string}`;\n}\n\n/**\n * Parses Basic auth header (RFC 6749 Section 2.3.1)\n */\nfunction parseBasicAuthHeader(\n authHeader: string | undefined,\n): { clientId: string; clientSecret: string } | null {\n const basicMatch = authHeader?.match(/^Basic\\s+(.+)$/);\n if (!basicMatch) return null;\n\n try {\n const credentials = Buffer.from(basicMatch[1], \"base64\").toString(\"utf-8\");\n const credMatch = credentials.match(/^([^:]+):(.*)$/);\n if (!credMatch) return null;\n\n return { clientId: credMatch[1], clientSecret: credMatch[2] };\n } catch {\n return null;\n }\n}\n\n/**\n * Maximum request body size (in bytes) accepted by the OAuth proxy endpoints\n * (registration, consent and token). These endpoints receive small JSON or\n * form-urlencoded payloads, so 1 MiB is a generous bound that prevents\n * unbounded memory growth from slow or malicious clients.\n */\nconst OAUTH_PROXY_MAX_BODY_SIZE = 1024 * 1024; // 1 MiB\n\n/**\n * RFC 6749 §5.1 requires `Cache-Control: no-store` and `Pragma: no-cache` on\n * token endpoint responses, and RFC 7591 §3.2.1 requires the same for a\n * registration response carrying `client_secret`. Without them an intermediary\n * proxy or the browser may retain the credential.\n */\nconst OAUTH_CREDENTIAL_RESPONSE_HEADERS = {\n \"Cache-Control\": \"no-store\",\n \"Content-Type\": \"application/json\",\n Pragma: \"no-cache\",\n} as const;\n\nfunction stripBasePath(\n path: string,\n basePath: \"\" | `/${string}`,\n): null | string {\n if (!basePath) {\n return path;\n }\n\n if (path === basePath) {\n return \"/\";\n }\n\n if (path.startsWith(`${basePath}/`)) {\n return path.slice(basePath.length);\n }\n\n return null;\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;\n} = EventEmitter;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP<\n T extends FastMCPSessionAuth = FastMCPSessionAuth,\n> extends FastMCPEventEmitter {\n public get serverState(): ServerState {\n return this.#serverState;\n }\n\n public get sessions(): FastMCPSession<T>[] {\n return this.#sessions;\n }\n\n #authenticate: Authenticate<T> | undefined;\n #honoApp = new Hono();\n #httpStreamServer: null | SSEServer = null;\n #logger: Logger;\n #options: ServerOptions<T>;\n #prompts: InputPrompt<T>[] = [];\n #resources: Resource<T>[] = [];\n #resourcesTemplates: InputResourceTemplate<T>[] = [];\n #serverState: ServerState = ServerState.Stopped;\n #sessions: FastMCPSession<T>[] = [];\n\n #tools: Tool<T>[] = [];\n\n constructor(public options: ServerOptions<T>) {\n super();\n\n this.#options = options;\n this.#logger = options.logger || console;\n\n // If auth provider is specified, use it to configure authenticate and oauth\n if (options.auth) {\n // Use auth provider's authenticate if not explicitly overridden\n if (!options.authenticate) {\n this.#authenticate = ((request: http.IncomingMessage | undefined) =>\n options.auth!.authenticate(request)) as Authenticate<T>;\n } else {\n this.#authenticate = options.authenticate;\n }\n\n // Use auth provider's oauth config if not explicitly overridden\n if (!options.oauth) {\n this.#options = {\n ...options,\n oauth: options.auth.getOAuthConfig(),\n };\n }\n } else {\n this.#authenticate = options.authenticate;\n }\n }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument<T>[]>(\n prompt: InputPrompt<T, Args>,\n ) {\n this.#prompts = this.#prompts.filter((p) => p.name !== prompt.name);\n this.#prompts.push(prompt);\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Adds prompts to the server.\n */\n public addPrompts<const Args extends InputPromptArgument<T>[]>(\n prompts: InputPrompt<T, Args>[],\n ) {\n const newPromptNames = new Set(prompts.map((prompt) => prompt.name));\n this.#prompts = this.#prompts.filter((p) => !newPromptNames.has(p.name));\n this.#prompts.push(...prompts);\n\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource<T>) {\n this.#resources = this.#resources.filter((r) => r.name !== resource.name);\n\n this.#resources.push(resource);\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Adds resources to the server.\n */\n public addResources(resources: Resource<T>[]) {\n const newResourceNames = new Set(\n resources.map((resource) => resource.name),\n );\n this.#resources = this.#resources.filter(\n (r) => !newResourceNames.has(r.name),\n );\n this.#resources.push(...resources);\n\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Adds a resource template to the server.\n */\n public addResourceTemplate<\n const Args extends InputResourceTemplateArgument[],\n >(resource: InputResourceTemplate<T, Args>) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== resource.name,\n );\n\n this.#resourcesTemplates.push(resource);\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Adds resource templates to the server.\n */\n public addResourceTemplates<\n const Args extends InputResourceTemplateArgument[],\n >(resources: InputResourceTemplate<T, Args>[]) {\n const newResourceTemplateNames = new Set(\n resources.map((resource) => resource.name),\n );\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => !newResourceTemplateNames.has(t.name),\n );\n this.#resourcesTemplates.push(...resources);\n\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Adds a tool to the server.\n */\n public addTool<Params extends ToolParameters>(tool: Tool<T, Params>) {\n assertToolSchemas(tool);\n\n // Remove existing tool with the same name\n this.#tools = this.#tools.filter((t) => t.name !== tool.name);\n this.#tools.push(tool as unknown as Tool<T>);\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Adds tools to the server.\n */\n public addTools<Params extends ToolParameters>(tools: Tool<T, Params>[]) {\n tools.forEach(assertToolSchemas);\n\n const newToolNames = new Set(tools.map((tool) => tool.name));\n this.#tools = this.#tools.filter((t) => !newToolNames.has(t.name));\n this.#tools.push(...(tools as unknown as Tool<T>[]));\n\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Connects the server to a transport you constructed yourself, instead of\n * letting {@link FastMCP.start} create one.\n *\n * The session is built from the tools, resources and prompts registered on\n * this instance — exactly as `start()` does — so tests exercise the same\n * wiring the real server uses. The main use case is driving a server\n * in-process over `InMemoryTransport` without binding a port:\n *\n * ```ts\n * const [clientTransport, serverTransport] =\n * InMemoryTransport.createLinkedPair();\n *\n * await Promise.all([\n * server.connect(serverTransport),\n * client.connect(clientTransport),\n * ]);\n * ```\n *\n * The transport's lifecycle belongs to the caller: `stop()` does not close\n * transports passed here. Close the returned session (or the transport) when\n * you are done with it.\n *\n * @param transport - An already-constructed MCP server transport.\n * @param auth - Session auth, equivalent to what `authenticate` would return.\n * @returns The session bound to the transport.\n */\n public async connect(\n transport: Transport,\n auth?: T,\n ): Promise<FastMCPSession<T>> {\n const session = this.#createSession(auth);\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n session.once(\"error\", () => {\n this.#removeSession(session);\n });\n\n const originalOnClose = transport.onclose;\n\n transport.onclose = () => {\n this.#removeSession(session);\n\n if (originalOnClose) {\n originalOnClose();\n }\n };\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n\n this.#serverState = ServerState.Running;\n\n return session;\n }\n\n /**\n * Embeds a resource by URI, making it easy to include resources in tool responses.\n *\n * @param uri - The URI of the resource to embed\n * @returns Promise<ResourceContent> - The embedded resource content\n */\n public async embedded(uri: string): Promise<ResourceContent[\"resource\"]> {\n // First, try to find a direct resource match\n const directResource = this.#resources.find(\n (resource) => resource.uri === uri,\n );\n\n if (directResource) {\n const result = await directResource.load();\n const results = Array.isArray(result) ? result : [result];\n const firstResult = results[0];\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: directResource.mimeType,\n uri,\n };\n\n if (\"text\" in firstResult) {\n resourceData.text = firstResult.text;\n }\n\n if (\"blob\" in firstResult) {\n resourceData.blob = firstResult.blob;\n }\n\n return resourceData;\n }\n\n // Try to match against resource templates\n for (const template of this.#resourcesTemplates) {\n const parsedTemplate = parseURITemplate(template.uriTemplate);\n const params = parsedTemplate.fromUri(uri);\n if (!params) {\n continue;\n }\n\n const result = await template.load(\n params as ResourceTemplateArgumentsToObject<typeof template.arguments>,\n );\n\n const resourceData: ResourceContent[\"resource\"] = {\n mimeType: template.mimeType,\n uri,\n };\n\n if (\"text\" in result) {\n resourceData.text = result.text;\n }\n\n if (\"blob\" in result) {\n resourceData.blob = result.blob;\n }\n\n return resourceData; // The resource we're looking for\n }\n\n throw new UnexpectedStateError(`Resource not found: ${uri}`, { uri });\n }\n\n /**\n * Returns the underlying Hono app instance for direct access to Hono's native API.\n * This allows you to add custom routes, middleware, and handlers using Hono's standard methods.\n *\n * @returns The Hono app instance\n *\n * @example\n * ```typescript\n * const app = server.getApp();\n *\n * // Add routes using native Hono API\n * app.get('/api/users', async (c) => {\n * return c.json({ users: [] });\n * });\n *\n * app.post('/api/users/:id', async (c) => {\n * const id = c.req.param('id');\n * return c.json({ id });\n * });\n * ```\n */\n public getApp(): Hono {\n return this.#honoApp;\n }\n\n /**\n * Removes a prompt from the server.\n */\n public removePrompt(name: string) {\n this.#prompts = this.#prompts.filter((p) => p.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Removes prompts from the server.\n */\n public removePrompts(names: string[]) {\n for (const name of names) {\n this.#prompts = this.#prompts.filter((p) => p.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#promptsListChanged(this.#prompts);\n }\n }\n\n /**\n * Removes a resource from the server.\n */\n public removeResource(name: string) {\n this.#resources = this.#resources.filter((r) => r.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Removes resources from the server.\n */\n public removeResources(names: string[]) {\n for (const name of names) {\n this.#resources = this.#resources.filter((r) => r.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#resourcesListChanged(this.#resources);\n }\n }\n\n /**\n * Removes a resource template from the server.\n */\n public removeResourceTemplate(name: string) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== name,\n );\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Removes resource templates from the server.\n */\n public removeResourceTemplates(names: string[]) {\n for (const name of names) {\n this.#resourcesTemplates = this.#resourcesTemplates.filter(\n (t) => t.name !== name,\n );\n }\n if (this.#serverState === ServerState.Running) {\n this.#resourceTemplatesListChanged(this.#resourcesTemplates);\n }\n }\n\n /**\n * Removes a tool from the server.\n */\n public removeTool(name: string) {\n // Remove existing tool with the same name\n this.#tools = this.#tools.filter((t) => t.name !== name);\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Removes tools from the server.\n */\n public removeTools(names: string[]) {\n for (const name of names) {\n this.#tools = this.#tools.filter((t) => t.name !== name);\n }\n if (this.#serverState === ServerState.Running) {\n this.#toolsListChanged(this.#tools);\n }\n }\n\n /**\n * Notifies subscribed clients that a resource's contents have changed.\n *\n * Sends a `notifications/resources/updated` notification to every connected\n * session that has subscribed to `uri` via `resources/subscribe`. Sessions\n * that have not subscribed to the URI are skipped, so it is safe to call this\n * whenever the underlying data changes.\n *\n * @param uri - The URI of the resource whose contents changed.\n */\n public async sendResourceUpdated(uri: string): Promise<void> {\n await Promise.all(\n this.#sessions.map((session) => session.sendResourceUpdated(uri)),\n );\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options?: Partial<{\n httpStream: {\n basePath?: `/${string}`;\n cors?: boolean | CorsOptions;\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n eventStore?: EventStore;\n host?: string;\n port: number;\n sslCa?: string;\n sslCert?: string;\n sslKey?: string;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ) {\n const config = this.#parseRuntimeConfig(options);\n\n if (config.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n // For stdio transport, if authenticate function is provided, call it\n // with undefined request (since stdio doesn't have HTTP request context)\n let auth: T | undefined;\n\n if (this.#authenticate) {\n try {\n auth =\n (await this.#authenticate(\n undefined as unknown as http.IncomingMessage,\n )) ?? undefined;\n } catch (error) {\n this.#logger.error(\n \"[FastMCP error] Authentication failed for stdio transport:\",\n error instanceof Error ? error.message : String(error),\n );\n // Continue without auth if authentication fails\n }\n }\n\n const session = new FastMCPSession<T>({\n auth,\n icons: this.#options.icons,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n onToolCall: this.#options.onToolCall,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n streamKeepalive: this.#options.streamKeepalive,\n title: this.#options.title,\n tools: this.#tools,\n transportType: \"stdio\",\n utils: this.#options.utils,\n version: this.#options.version,\n websiteUrl: this.#options.websiteUrl,\n });\n\n await session.connect(transport);\n\n // Belt-and-suspenders: detect when the MCP client closes its end of\n // the stdin pipe and shut down the transport so the process doesn't\n // linger as a zombie/orphan. The upstream SDK fix (PR #2003) handles\n // this inside StdioServerTransport itself, but adding the listener here\n // means older SDK versions are also protected.\n let stdinClosed = false;\n const onStdinClose = () => {\n if (stdinClosed) return;\n stdinClosed = true;\n process.stdin.off(\"close\", onStdinClose);\n process.stdin.off(\"end\", onStdinClose);\n transport.close().catch(() => {});\n };\n process.stdin.on(\"close\", onStdinClose);\n process.stdin.on(\"end\", onStdinClose);\n\n this.#sessions.push(session);\n\n session.once(\"error\", () => {\n this.#removeSession(session);\n });\n\n // Monitor the underlying transport for close events\n if (transport.onclose) {\n const originalOnClose = transport.onclose;\n\n transport.onclose = () => {\n process.stdin.off(\"close\", onStdinClose);\n process.stdin.off(\"end\", onStdinClose);\n this.#removeSession(session);\n\n if (originalOnClose) {\n originalOnClose();\n }\n };\n } else {\n transport.onclose = () => {\n process.stdin.off(\"close\", onStdinClose);\n process.stdin.off(\"end\", onStdinClose);\n this.#removeSession(session);\n };\n }\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n this.#serverState = ServerState.Running;\n } else if (config.transportType === \"httpStream\") {\n const httpConfig = config.httpStream;\n const protocol =\n httpConfig.sslCert || httpConfig.sslKey ? \"https\" : \"http\";\n const streamEndpoint = joinPaths(\n httpConfig.basePath,\n httpConfig.endpoint,\n );\n\n if (httpConfig.stateless) {\n // Stateless mode - create new server instance for each request\n this.#logger.info(\n `[FastMCP info] Starting server in stateless mode on HTTP Stream at ${protocol}://${httpConfig.host}:${httpConfig.port}${streamEndpoint}`,\n );\n\n // Shared per-request memo: mcp-proxy's gating call and the\n // `createServer` call below collapse into one real `authenticate`\n // invocation per request (see `#memoizedAuthenticate`).\n const authenticate = this.#authenticate\n ? this.#memoizedAuthenticate()\n : undefined;\n\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(authenticate ? { authenticate } : {}),\n cors: httpConfig.cors,\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (authenticate) {\n auth = this.#requireAuthenticated(await authenticate(request));\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n // In stateless mode, create a new session for each request\n // without persisting it in the sessions array\n return this.#createSession(auth, sessionId, true);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n ...this.#httpStreamOAuthConfig(),\n // In stateless mode, we don't track sessions\n onClose: async () => {\n // No session tracking in stateless mode\n },\n onConnect: async () => {\n // No persistent session tracking in stateless mode\n this.#logger.debug(\n `[FastMCP debug] Stateless HTTP Stream request handled`,\n );\n },\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(\n req,\n res,\n true,\n httpConfig.host,\n streamEndpoint,\n httpConfig.basePath,\n );\n },\n port: httpConfig.port,\n sslCa: httpConfig.sslCa,\n sslCert: httpConfig.sslCert,\n sslKey: httpConfig.sslKey,\n stateless: true,\n streamEndpoint,\n });\n } else {\n // Regular mode with session management\n // Shared per-request memo: mcp-proxy's gating call and the\n // `createServer` call below collapse into one real `authenticate`\n // invocation per request (see `#memoizedAuthenticate`).\n const authenticate = this.#authenticate\n ? this.#memoizedAuthenticate()\n : undefined;\n\n this.#httpStreamServer = await startHTTPServer<FastMCPSession<T>>({\n ...(authenticate ? { authenticate } : {}),\n cors: httpConfig.cors,\n createServer: async (request) => {\n let auth: T | undefined;\n\n if (authenticate) {\n auth = this.#requireAuthenticated(await authenticate(request));\n }\n\n // Extract session ID from headers\n const sessionId = Array.isArray(request.headers[\"mcp-session-id\"])\n ? request.headers[\"mcp-session-id\"][0]\n : request.headers[\"mcp-session-id\"];\n\n return this.#createSession(auth, sessionId);\n },\n enableJsonResponse: httpConfig.enableJsonResponse,\n eventStore: httpConfig.eventStore,\n host: httpConfig.host,\n ...this.#httpStreamOAuthConfig(),\n onClose: async (session) => {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) this.#sessions.splice(sessionIndex, 1);\n\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.#logger.info(`[FastMCP info] HTTP Stream session established`);\n\n this.emit(\"connect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n },\n\n onUnhandledRequest: async (req, res) => {\n await this.#handleUnhandledRequest(\n req,\n res,\n false,\n httpConfig.host,\n streamEndpoint,\n httpConfig.basePath,\n );\n },\n port: httpConfig.port,\n sslCa: httpConfig.sslCa,\n sslCert: httpConfig.sslCert,\n sslKey: httpConfig.sslKey,\n stateless: httpConfig.stateless,\n streamEndpoint,\n });\n\n this.#logger.info(\n `[FastMCP info] server is running on HTTP Stream at ${protocol}://${httpConfig.host}:${httpConfig.port}${streamEndpoint}`,\n );\n }\n this.#serverState = ServerState.Running;\n } else {\n throw new Error(\"Invalid transport type\");\n }\n }\n\n /**\n * Stops the server.\n */\n public async stop() {\n if (this.#httpStreamServer) {\n await this.#httpStreamServer.close();\n }\n this.#serverState = ServerState.Stopped;\n }\n\n /**\n * Creates a new FastMCPSession instance with the current configuration.\n * Used both for regular sessions and stateless requests.\n */\n #createSession(\n auth?: T,\n sessionId?: string,\n stateless = false,\n ): FastMCPSession<T> {\n // Check if authentication failed\n if (\n auth &&\n typeof auth === \"object\" &&\n \"authenticated\" in auth &&\n !(auth as { authenticated: unknown }).authenticated\n ) {\n const errorMessage =\n \"error\" in auth &&\n typeof (auth as { error: unknown }).error === \"string\"\n ? (auth as { error: string }).error\n : \"Authentication failed\";\n throw this.#createUnauthorizedResponse(errorMessage);\n }\n\n const allowedTools = auth\n ? this.#tools.filter((tool) =>\n tool.canAccess ? tool.canAccess(auth) : true,\n )\n : this.#tools;\n return new FastMCPSession<T>({\n auth,\n icons: this.#options.icons,\n instructions: this.#options.instructions,\n logger: this.#logger,\n name: this.#options.name,\n onToolCall: this.#options.onToolCall,\n ping: this.#options.ping,\n prompts: this.#prompts,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n roots: this.#options.roots,\n sessionId,\n stateless,\n streamKeepalive: this.#options.streamKeepalive,\n title: this.#options.title,\n tools: allowedTools,\n transportType: \"httpStream\",\n utils: this.#options.utils,\n version: this.#options.version,\n websiteUrl: this.#options.websiteUrl,\n });\n }\n\n /**\n * Builds a 401 Unauthorized HTTP Response for authentication failures.\n *\n * Throwing a `Response` (rather than a plain `Error`) guarantees that the\n * transport (e.g. mcp-proxy) surfaces the correct status code directly,\n * instead of relying on heuristics that infer the status code from the\n * error message's text (see https://github.com/punkpeye/fastmcp/issues/180).\n *\n * The response body matches the JSON-RPC error envelope FastMCP otherwise\n * produces, and a `WWW-Authenticate` header is included per RFC 7235 (and\n * RFC 9728 when protected-resource metadata is configured), so HTTP-aware\n * clients can distinguish \"unauthenticated\" from a malformed request.\n */\n #createUnauthorizedResponse(message: string): Response {\n // Only advertise resource_metadata when OAuth is enabled: the\n // `/.well-known/oauth-protected-resource` endpoint is served only under\n // `oauth.enabled` (and this matches how the oauth config is forwarded to\n // mcp-proxy at the httpStream call sites), so gating here avoids pointing\n // clients at an endpoint that would 404.\n const oauth = this.#options.oauth;\n const resource = oauth?.enabled\n ? oauth.protectedResource?.resource\n : undefined;\n const wwwAuthenticateParts = [\n 'error=\"invalid_token\"',\n `error_description=\"${message.replace(/\"/g, '\\\\\"')}\"`,\n ];\n\n if (resource) {\n wwwAuthenticateParts.push(\n `resource_metadata=\"${resource}/.well-known/oauth-protected-resource\"`,\n );\n }\n\n return new Response(\n JSON.stringify({\n error: { code: -32000, message },\n id: null,\n jsonrpc: \"2.0\",\n }),\n {\n headers: {\n \"Content-Type\": \"application/json\",\n \"WWW-Authenticate\": `Bearer ${wwwAuthenticateParts.join(\", \")}`,\n },\n status: 401,\n },\n );\n }\n\n /**\n * Handles unhandled HTTP requests with health, readiness, OAuth endpoints, and custom routes\n */\n #handleUnhandledRequest = async (\n req: http.IncomingMessage,\n res: http.ServerResponse,\n isStateless = false,\n host: string,\n streamEndpoint?: string,\n basePath: \"\" | `/${string}` = \"\",\n ) => {\n const url = new URL(req.url || \"\", `http://${host}`);\n const basePathRelativePath = stripBasePath(url.pathname, basePath);\n\n // Try Hono routes first - users may have added routes via getApp()\n try {\n // Convert Node.js IncomingMessage to Web Request\n const webRequest = this.#nodeRequestToWebRequest(req, url);\n\n // Call Hono's fetch handler\n const honoResponse = await this.#honoApp.fetch(webRequest, {\n incoming: req,\n outgoing: res,\n });\n\n // If Hono handled it (not 404), write response and return\n if (honoResponse.status !== 404) {\n // Write Hono response to Node.js response\n if (!res.headersSent) {\n res.statusCode = honoResponse.status;\n honoResponse.headers.forEach((value, key) => {\n res.setHeader(key, value);\n });\n\n if (honoResponse.body) {\n const reader = honoResponse.body.getReader();\n\n // A custom route is free to return a stream that never ends on its\n // own (SSE, a proxied upstream). The client going away is then the\n // only thing that ends it, and such a stream may well be quiet at\n // that moment, so waiting on `read()` alone would keep pumping\n // until a chunk that may never arrive. Race every read against the\n // response closing instead.\n let resolveClosed!: () => void;\n const closed = new Promise<undefined>((resolve) => {\n resolveClosed = () => resolve(undefined);\n });\n res.once(\"close\", resolveClosed);\n if (res.writableEnded || res.destroyed) {\n resolveClosed();\n }\n\n try {\n while (!res.writableEnded && !res.destroyed) {\n const read = reader.read();\n // `closed` may win the race, leaving this promise to settle\n // with nobody observing it.\n read.catch(() => {});\n const result = await Promise.race([read, closed]);\n if (!result || result.done) break;\n res.write(result.value);\n }\n } finally {\n res.off(\"close\", resolveClosed);\n // `releaseLock` detaches this reader but leaves the body itself\n // unread and its source running; only `cancel` tells the route\n // to stop producing and release what it holds.\n await reader.cancel().catch(() => {});\n reader.releaseLock();\n }\n }\n res.end();\n }\n return;\n }\n } catch (error) {\n // If Hono throws, log and continue to other endpoints\n this.#logger.debug(\"[FastMCP debug] Hono route not matched\", error);\n }\n\n const healthConfig = this.#options.health ?? {};\n\n const enabled =\n healthConfig.enabled === undefined ? true : healthConfig.enabled;\n\n if (enabled) {\n const path = healthConfig.path ?? \"/health\";\n\n try {\n if (\n (req.method === \"GET\" || req.method === \"HEAD\") &&\n url.pathname === joinPaths(basePath, path)\n ) {\n res\n .writeHead(healthConfig.status ?? 200, {\n \"Content-Type\": \"text/plain\",\n })\n .end(\n req.method === \"HEAD\"\n ? undefined\n : (healthConfig.message ?? \"✓ Ok\"),\n );\n\n return;\n }\n\n // Enhanced readiness check endpoint\n if (\n (req.method === \"GET\" || req.method === \"HEAD\") &&\n url.pathname === joinPaths(basePath, \"/ready\")\n ) {\n if (isStateless) {\n // In stateless mode, we're always ready if the server is running\n const response = {\n mode: \"stateless\",\n ready: 1,\n status: \"ready\",\n total: 1,\n };\n\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(\n req.method === \"HEAD\" ? undefined : JSON.stringify(response),\n );\n } else {\n const readySessions = this.#sessions.filter(\n (s) => s.isReady,\n ).length;\n const totalSessions = this.#sessions.length;\n const allReady =\n readySessions === totalSessions && totalSessions > 0;\n\n const response = {\n ready: readySessions,\n status: allReady\n ? \"ready\"\n : totalSessions === 0\n ? \"no_sessions\"\n : \"initializing\",\n total: totalSessions,\n };\n\n res\n .writeHead(allReady ? 200 : 503, {\n \"Content-Type\": \"application/json\",\n })\n .end(\n req.method === \"HEAD\" ? undefined : JSON.stringify(response),\n );\n }\n\n return;\n }\n } catch (error) {\n this.#logger.error(\"[FastMCP error] health endpoint error\", error);\n }\n }\n\n // Handle OAuth well-known endpoints\n const oauthConfig = this.#options.oauth;\n if (oauthConfig?.enabled && req.method === \"GET\") {\n const url = new URL(req.url || \"\", `http://${host}`);\n const authorizationServerMetadataPath = joinPaths(\n \"\",\n `/.well-known/oauth-authorization-server${basePath}`,\n );\n\n if (\n url.pathname === authorizationServerMetadataPath &&\n oauthConfig.authorizationServer\n ) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.authorizationServer,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n\n // Handle Protected Resource Metadata with MCP 2025-11-25 compliant discovery\n // Per spec, clients should search in order:\n // 1. WWW-Authenticate header (handled by mcp-proxy)\n // 2. /.well-known/oauth-protected-resource<sub-path> (e.g., /mcp)\n // 3. /.well-known/oauth-protected-resource (root)\n if (oauthConfig.protectedResource) {\n const wellKnownBase = \"/.well-known/oauth-protected-resource\";\n let shouldServeMetadata = false;\n\n // Check for sub-path variant first (higher priority per MCP spec)\n if (\n streamEndpoint &&\n url.pathname === `${wellKnownBase}${streamEndpoint}`\n ) {\n shouldServeMetadata = true;\n }\n // Fall back to root path\n else if (url.pathname === wellKnownBase) {\n shouldServeMetadata = true;\n }\n\n if (shouldServeMetadata) {\n const metadata = convertObjectToSnakeCase(\n oauthConfig.protectedResource,\n );\n res\n .writeHead(200, {\n \"Content-Type\": \"application/json\",\n })\n .end(JSON.stringify(metadata));\n return;\n }\n }\n }\n\n // Handle OAuth Proxy endpoints\n const oauthProxy = oauthConfig?.proxy;\n if (oauthProxy && oauthConfig?.enabled) {\n const url = new URL(req.url || \"\", `http://${host}`);\n const oauthPath = basePathRelativePath;\n\n try {\n // DCR endpoint - POST /oauth/register\n if (req.method === \"POST\" && oauthPath === \"/oauth/register\") {\n await new Promise<void>((resolve) => {\n const bodyChunks: Buffer[] = [];\n let bodySize = 0;\n let failed = false;\n const fail = () => {\n if (failed || res.headersSent) {\n resolve();\n return;\n }\n failed = true;\n res\n .writeHead(400, {\n Connection: \"close\",\n \"Content-Type\": \"application/json\",\n })\n .end(\n JSON.stringify({\n error: \"invalid_request\",\n error_description: \"Request body exceeds 1 MiB\",\n }),\n );\n resolve();\n };\n req.on(\"data\", (chunk) => {\n if (failed) {\n return;\n }\n bodySize += chunk.length;\n if (bodySize > OAUTH_PROXY_MAX_BODY_SIZE) {\n fail();\n return;\n }\n bodyChunks.push(chunk);\n });\n // An aborted/errored request never emits \"end\"; settle the promise\n // instead of leaving the handler pending forever.\n req.on(\"aborted\", fail);\n req.on(\"error\", fail);\n req.on(\"end\", async () => {\n if (failed) {\n return;\n }\n try {\n const request = JSON.parse(\n Buffer.concat(bodyChunks).toString(\"utf8\"),\n );\n const response = await oauthProxy.registerClient(request);\n res\n .writeHead(201, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(JSON.stringify(response));\n } catch (error) {\n const statusCode =\n (error as { statusCode?: number }).statusCode || 400;\n res\n .writeHead(statusCode, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"invalid_request\",\n },\n ),\n );\n }\n resolve();\n });\n });\n return;\n }\n\n // Authorization endpoint - GET /oauth/authorize\n if (req.method === \"GET\" && oauthPath === \"/oauth/authorize\") {\n try {\n const params = Object.fromEntries(url.searchParams.entries());\n const response = await oauthProxy.authorize(\n params as {\n [key: string]: unknown;\n client_id: string;\n redirect_uri: string;\n response_type: string;\n },\n );\n\n // Response is a redirect\n const location = response.headers.get(\"Location\");\n if (location) {\n res.writeHead(response.status, { Location: location }).end();\n } else {\n // HTML consent screen\n const html = await response.text();\n res\n .writeHead(response.status, { \"Content-Type\": \"text/html\" })\n .end(html);\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"invalid_request\",\n },\n ),\n );\n }\n return;\n }\n\n // Callback endpoint - GET /oauth/callback\n if (req.method === \"GET\" && oauthPath === \"/oauth/callback\") {\n try {\n const mockRequest = new Request(`http://${host}${req.url}`);\n const response = await oauthProxy.handleCallback(mockRequest);\n\n const location = response.headers.get(\"Location\");\n if (location) {\n res.writeHead(response.status, { Location: location }).end();\n } else {\n const text = await response.text();\n res.writeHead(response.status).end(text);\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"server_error\",\n },\n ),\n );\n }\n return;\n }\n\n // Consent endpoint - POST /oauth/consent\n if (req.method === \"POST\" && oauthPath === \"/oauth/consent\") {\n await new Promise<void>((resolve) => {\n const bodyChunks: Buffer[] = [];\n let bodySize = 0;\n let failed = false;\n const fail = () => {\n if (failed || res.headersSent) {\n resolve();\n return;\n }\n failed = true;\n res\n .writeHead(400, {\n Connection: \"close\",\n \"Content-Type\": \"application/json\",\n })\n .end(\n JSON.stringify({\n error: \"invalid_request\",\n error_description: \"Request body exceeds 1 MiB\",\n }),\n );\n resolve();\n };\n req.on(\"data\", (chunk) => {\n if (failed) {\n return;\n }\n bodySize += chunk.length;\n if (bodySize > OAUTH_PROXY_MAX_BODY_SIZE) {\n fail();\n return;\n }\n bodyChunks.push(chunk);\n });\n // An aborted/errored request never emits \"end\"; settle the promise\n // instead of leaving the handler pending forever.\n req.on(\"aborted\", fail);\n req.on(\"error\", fail);\n req.on(\"end\", async () => {\n if (failed) {\n return;\n }\n try {\n const mockRequest = new Request(\n `http://${host}${url.pathname}${url.search}`,\n {\n body: Buffer.concat(bodyChunks).toString(\"utf8\"),\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n method: \"POST\",\n },\n );\n const response = await oauthProxy.handleConsent(mockRequest);\n\n const location = response.headers.get(\"Location\");\n if (location) {\n res.writeHead(response.status, { Location: location }).end();\n } else {\n const text = await response.text();\n res.writeHead(response.status).end(text);\n }\n } catch (error) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" }).end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"server_error\",\n },\n ),\n );\n }\n resolve();\n });\n });\n return;\n }\n\n // Token endpoint - POST /oauth/token\n if (req.method === \"POST\" && oauthPath === \"/oauth/token\") {\n await new Promise<void>((resolve) => {\n const bodyChunks: Buffer[] = [];\n let bodySize = 0;\n let failed = false;\n const fail = () => {\n if (failed || res.headersSent) {\n resolve();\n return;\n }\n failed = true;\n res\n .writeHead(400, {\n Connection: \"close\",\n \"Content-Type\": \"application/json\",\n })\n .end(\n JSON.stringify({\n error: \"invalid_request\",\n error_description: \"Request body exceeds 1 MiB\",\n }),\n );\n resolve();\n };\n req.on(\"data\", (chunk) => {\n if (failed) {\n return;\n }\n bodySize += chunk.length;\n if (bodySize > OAUTH_PROXY_MAX_BODY_SIZE) {\n fail();\n return;\n }\n bodyChunks.push(chunk);\n });\n // An aborted/errored request never emits \"end\"; settle the promise\n // instead of leaving the handler pending forever.\n req.on(\"aborted\", fail);\n req.on(\"error\", fail);\n req.on(\"end\", async () => {\n if (failed) {\n return;\n }\n try {\n const params = new URLSearchParams(\n Buffer.concat(bodyChunks).toString(\"utf8\"),\n );\n const grantType = params.get(\"grant_type\");\n\n // Parse Basic auth header (RFC 6749 Section 2.3.1)\n const basicAuth = parseBasicAuthHeader(\n req.headers.authorization,\n );\n\n // Use Basic auth credentials if present, otherwise fall back to POST body\n const clientId =\n basicAuth?.clientId || params.get(\"client_id\") || \"\";\n const clientSecret =\n basicAuth?.clientSecret ??\n params.get(\"client_secret\") ??\n undefined;\n\n let response;\n if (grantType === \"authorization_code\") {\n response = await oauthProxy.exchangeAuthorizationCode({\n client_id: clientId,\n client_secret: clientSecret,\n code: params.get(\"code\") || \"\",\n code_verifier: params.get(\"code_verifier\") || undefined,\n grant_type: \"authorization_code\",\n redirect_uri: params.get(\"redirect_uri\") || \"\",\n });\n } else if (grantType === \"refresh_token\") {\n response = await oauthProxy.exchangeRefreshToken({\n client_id: clientId,\n client_secret: clientSecret,\n grant_type: \"refresh_token\",\n refresh_token: params.get(\"refresh_token\") || \"\",\n scope: params.get(\"scope\") || undefined,\n });\n } else {\n throw {\n statusCode: 400,\n toJSON: () => ({ error: \"unsupported_grant_type\" }),\n };\n }\n\n res\n .writeHead(200, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(JSON.stringify(response));\n } catch (error) {\n const statusCode =\n (error as { statusCode?: number }).statusCode || 400;\n res\n .writeHead(statusCode, OAUTH_CREDENTIAL_RESPONSE_HEADERS)\n .end(\n JSON.stringify(\n (error as { toJSON?: () => unknown }).toJSON?.() || {\n error: \"invalid_request\",\n },\n ),\n );\n }\n resolve();\n });\n });\n return;\n }\n } catch (error) {\n this.#logger.error(\"[FastMCP error] OAuth Proxy endpoint error\", error);\n res.writeHead(500).end();\n return;\n }\n }\n };\n\n /**\n * Only advertise `resource_metadata` when OAuth is enabled: the\n * `/.well-known/oauth-protected-resource` endpoint is served only under\n * `oauth.enabled`, so gating here avoids pointing clients at a URL that\n * would 404. mcp-proxy emits the `WWW-Authenticate` challenge on every 401\n * regardless (RFC 7235), so no config is needed just to get the header.\n */\n #httpStreamOAuthConfig(): {\n oauth?: {\n protectedResource?: { resource: string };\n };\n } {\n const resource = this.#options.oauth?.enabled\n ? this.#options.oauth.protectedResource?.resource\n : undefined;\n if (!resource) {\n return {};\n }\n return {\n oauth: {\n protectedResource: {\n resource,\n },\n },\n };\n }\n\n /**\n * On `httpStream`, `authenticate` is handed to both mcp-proxy (which calls it\n * once per request to gate the 401) and this server's own `createServer`\n * callback (which calls it again to obtain the session auth). Both receive\n * the identical `IncomingMessage`, so a single request would otherwise be\n * authenticated twice — halving the effective budget of any non-idempotent\n * `authenticate` (see #352).\n *\n * This wraps `#authenticate` in a per-request memo keyed on the request\n * object, collapsing the two calls into one real invocation. The *promise* is\n * cached (not the resolved value) so a second call that arrives before the\n * first settles joins it rather than starting a competing attempt. Keys are\n * the request objects themselves, so each request is authenticated exactly\n * once, a distinct request is authenticated afresh, and entries are collected\n * with their requests — nothing leaks across requests. A rejected or nullish\n * result is cached as-is, so a failed authentication is never seen as a\n * success by the second caller.\n */\n #memoizedAuthenticate(): Authenticate<T> {\n const authenticate = this.#authenticate!;\n const cache = new WeakMap<\n http.IncomingMessage,\n Promise<null | T | undefined>\n >();\n\n return (request: http.IncomingMessage) => {\n // stdio passes `undefined`; there is nothing to key a memo on, and this\n // path is httpStream-only anyway, so fall straight through.\n if (!request) {\n return authenticate(request);\n }\n\n const cached = cache.get(request);\n\n if (cached) {\n return cached;\n }\n\n const result = Promise.resolve(authenticate(request));\n\n cache.set(request, result);\n\n return result;\n };\n }\n\n /**\n * Converts Node.js IncomingMessage to Web Request for Hono\n */\n #nodeRequestToWebRequest(req: http.IncomingMessage, url: URL): Request {\n const method = req.method || \"GET\";\n\n // Build headers\n const headers = new Headers();\n for (const [key, value] of Object.entries(req.headers)) {\n if (value) {\n if (Array.isArray(value)) {\n for (const v of value) {\n headers.append(key, v);\n }\n } else {\n headers.set(key, value);\n }\n }\n }\n\n // Create Web Request\n // For methods that can have a body, we need to pass the body\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n\n if (hasBody) {\n return new Request(url.toString(), {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n body: req as any, // Node.js IncomingMessage is readable stream\n duplex: \"half\", // Required for streaming bodies\n headers,\n method,\n } as RequestInit);\n } else {\n return new Request(url.toString(), {\n headers,\n method,\n });\n }\n }\n\n #parseRuntimeConfig(\n overrides?: Partial<{\n httpStream: {\n basePath?: `/${string}`;\n cors?: boolean | CorsOptions;\n enableJsonResponse?: boolean;\n endpoint?: `/${string}`;\n eventStore?: EventStore;\n host?: string;\n port: number;\n sslCa?: string;\n sslCert?: string;\n sslKey?: string;\n stateless?: boolean;\n };\n transportType: \"httpStream\" | \"stdio\";\n }>,\n ):\n | {\n httpStream: {\n basePath: \"\" | `/${string}`;\n cors?: boolean | CorsOptions;\n enableJsonResponse?: boolean;\n endpoint: `/${string}`;\n eventStore?: EventStore;\n host: string;\n port: number;\n sslCa?: string;\n sslCert?: string;\n sslKey?: string;\n stateless?: boolean;\n };\n transportType: \"httpStream\";\n }\n | { transportType: \"stdio\" } {\n const args = process.argv.slice(2);\n const getArg = (name: string) => {\n const index = args.findIndex((arg) => arg === `--${name}`);\n\n return index !== -1 && index + 1 < args.length\n ? args[index + 1]\n : undefined;\n };\n\n const transportArg = getArg(\"transport\");\n const portArg = getArg(\"port\");\n const endpointArg = getArg(\"endpoint\");\n const basePathArg = getArg(\"base-path\");\n const statelessArg = getArg(\"stateless\");\n const hostArg = getArg(\"host\");\n\n const envTransport = process.env.FASTMCP_TRANSPORT;\n const envPort = process.env.FASTMCP_PORT;\n const envEndpoint = process.env.FASTMCP_ENDPOINT;\n const envBasePath = process.env.FASTMCP_BASE_PATH;\n const envStateless = process.env.FASTMCP_STATELESS;\n const envHost = process.env.FASTMCP_HOST;\n // Overrides > CLI > env > defaults\n const transportType =\n overrides?.transportType ||\n (transportArg === \"http-stream\" ? \"httpStream\" : transportArg) ||\n envTransport ||\n \"stdio\";\n\n if (transportType === \"httpStream\") {\n const port = parseInt(\n overrides?.httpStream?.port?.toString() || portArg || envPort || \"8080\",\n );\n const host =\n overrides?.httpStream?.host || hostArg || envHost || \"localhost\";\n const endpoint =\n overrides?.httpStream?.endpoint || endpointArg || envEndpoint || \"/mcp\";\n const basePath = normalizeBasePath(\n overrides?.httpStream?.basePath || basePathArg || envBasePath,\n );\n const enableJsonResponse =\n overrides?.httpStream?.enableJsonResponse || false;\n const stateless =\n overrides?.httpStream?.stateless ||\n statelessArg === \"true\" ||\n envStateless === \"true\" ||\n false;\n const cors = overrides?.httpStream?.cors;\n const eventStore = overrides?.httpStream?.eventStore;\n const sslCa = overrides?.httpStream?.sslCa;\n const sslCert = overrides?.httpStream?.sslCert;\n const sslKey = overrides?.httpStream?.sslKey;\n\n return {\n httpStream: {\n basePath,\n cors,\n enableJsonResponse,\n endpoint: endpoint as `/${string}`,\n eventStore,\n host,\n port,\n sslCa,\n sslCert,\n sslKey,\n stateless,\n },\n transportType: \"httpStream\" as const,\n };\n }\n\n return { transportType: \"stdio\" as const };\n }\n\n /**\n * Notifies all sessions that the prompts list has changed.\n */\n #promptsListChanged(prompts: Prompt<T>[]) {\n for (const session of this.#sessions) {\n session.promptsListChanged(prompts);\n }\n }\n\n #removeSession(session: FastMCPSession<T>): void {\n const sessionIndex = this.#sessions.indexOf(session);\n\n if (sessionIndex !== -1) {\n this.#sessions.splice(sessionIndex, 1);\n this.emit(\"disconnect\", {\n session: session as FastMCPSession<FastMCPSessionAuth>,\n });\n }\n }\n\n /**\n * Rejects a failed authentication result before it can become a session.\n *\n * Authentication is REQUIRED whenever an `authenticate` function is\n * configured. mcp-proxy gates the HTTP Stream endpoint before `createServer`\n * runs, but it does not gate the SSE endpoint it serves at `/sse` by default:\n * `handleSSERequest` never receives `authenticate`. Throwing here is what\n * stops `/sse` from handing out a session — with access to every tool, since\n * `#createSession` skips `canAccess` filtering when `auth` is falsy — to a\n * client that `/mcp` would have answered with a 401.\n *\n * The falsy test matches mcp-proxy's own check so that both endpoints agree\n * on what counts as a failed authentication. Returning a nullish value is the\n * idiomatic way to signal failure, and is what the built-in OAuth\n * `AuthProvider` does for a missing or invalid bearer token.\n */\n #requireAuthenticated<TAuth>(auth: TAuth): NonNullable<TAuth> {\n if (!auth) {\n throw this.#createUnauthorizedResponse(\"Authentication required\");\n }\n\n return auth as NonNullable<TAuth>;\n }\n\n /**\n * Notifies all sessions that the resources list has changed.\n */\n #resourcesListChanged(resources: Resource<T>[]) {\n for (const session of this.#sessions) {\n session.resourcesListChanged(resources);\n }\n }\n\n /**\n * Notifies all sessions that the resource templates list has changed.\n */\n #resourceTemplatesListChanged(templates: InputResourceTemplate<T>[]) {\n for (const session of this.#sessions) {\n session.resourceTemplatesListChanged(templates);\n }\n }\n\n /**\n * Notifies all sessions that the tools list has changed.\n */\n #toolsListChanged(tools: Tool<T>[]) {\n for (const session of this.#sessions) {\n session.toolsListChanged(tools);\n }\n }\n}\n\n// Re-export commonly used auth utilities for convenience\n// Users can also import from \"fastmcp/auth\" for the full auth module\nexport {\n // Auth providers\n AuthProvider,\n AzureProvider,\n // Auth helpers for canAccess\n getAuthSession,\n GitHubProvider,\n GoogleProvider,\n OAuthProvider,\n requireAll,\n requireAny,\n requireAuth,\n requireRole,\n requireScopes,\n} from \"./auth/index.js\";\n\nexport type {\n AuthProviderConfig,\n AzureProviderConfig,\n AzureSession,\n GenericOAuthProviderConfig,\n GitHubSession,\n GoogleSession,\n OAuthSession,\n} from \"./auth/index.js\";\n\nexport { DiscoveryDocumentCache } from \"./DiscoveryDocumentCache.js\";\n\nexport {\n jsonSchemaAdapter,\n type JsonSchemaObject,\n type JsonSchemaStandardSchema,\n} from \"./jsonSchemaAdapter.js\";\n\nexport type {\n AudioContent,\n Content,\n ContentResult,\n Context,\n CorsOptions,\n FastMCPEvents,\n FastMCPSessionAuth,\n FastMCPSessionEvents,\n Icon,\n ImageContent,\n InputPrompt,\n InputPromptArgument,\n LoadContext,\n LoggingLevel,\n Progress,\n Prompt,\n PromptArgument,\n Resource,\n ResourceContent,\n ResourceLink,\n ResourceResult,\n ResourceTemplate,\n ResourceTemplateArgument,\n SerializableValue,\n ServerOptions,\n TextContent,\n Tool,\n ToolParameters,\n};\n","import { cancelResponseBody } from \"./cancelResponseBody.js\";\n\nexport class DiscoveryDocumentCache {\n public get size(): number {\n return this.#cache.size;\n }\n\n #cache: Map<\n string,\n {\n data: unknown;\n expiresAt: number;\n }\n > = new Map();\n\n #generation = 0;\n\n #inFlight: Map<string, Promise<unknown>> = new Map();\n\n #timeoutMs: number;\n\n #ttl: number;\n\n #urlGenerations: Map<string, number> = new Map();\n\n /**\n * @param options - configuration options\n * @param options.timeoutMs - timeout in miliseconds for the upstream fetch\n * @param options.ttl - time-to-live in miliseconds\n */\n public constructor(options: { timeoutMs?: number; ttl?: number } = {}) {\n this.#timeoutMs = options.timeoutMs ?? 10000; // default 10 seconds\n this.#ttl = options.ttl ?? 3600000; // default 1 hour\n }\n\n /**\n * @param url - optional URL to clear. if omitted, clears all cached documents.\n */\n public clear(url?: string): void {\n if (url) {\n this.#cache.delete(url);\n this.#inFlight.delete(url);\n this.#urlGenerations.set(url, (this.#urlGenerations.get(url) ?? 0) + 1);\n } else {\n this.#cache.clear();\n this.#inFlight.clear();\n this.#urlGenerations.clear();\n this.#generation++;\n }\n }\n\n /**\n * fetches a discovery document from the given URL.\n * uses cached value if available and not expired.\n * coalesces concurrent requests for the same URL to prevent duplicate fetches.\n *\n * @param url - the discovery document URL (e.g., /.well-known/openid-configuration)\n * @returns the discovery document as a JSON object\n * @throws Error if the fetch fails or returns non-OK status\n */\n public async get(url: string): Promise<unknown> {\n const now = Date.now();\n const cached = this.#cache.get(url);\n\n // return cached value if still valid\n if (cached && cached.expiresAt > now) {\n return cached.data;\n }\n\n // check if there’s already an in-flight request for this URL\n const inFlight = this.#inFlight.get(url);\n\n if (inFlight) {\n return inFlight;\n }\n\n // create a new fetch promise and store it\n const fetchPromise = this.#fetchAndCache(\n url,\n this.#generation,\n this.#urlGenerations.get(url) ?? 0,\n );\n\n this.#inFlight.set(url, fetchPromise);\n\n try {\n const data = await fetchPromise;\n return data;\n } finally {\n // clean up in-flight promise after completion\n // (success or failure)\n if (this.#inFlight.get(url) === fetchPromise) {\n this.#inFlight.delete(url);\n }\n }\n }\n\n /**\n * @param url - the URL to check\n * @returns true if the URL is cached and nott expired\n */\n public has(url: string): boolean {\n const cached = this.#cache.get(url);\n\n if (!cached) {\n return false;\n }\n\n const now = Date.now();\n\n if (cached.expiresAt <= now) {\n // expired, remove from cache\n this.#cache.delete(url);\n return false;\n }\n\n return true;\n }\n\n async #fetchAndCache(\n url: string,\n generation: number,\n urlGeneration: number,\n ): Promise<unknown> {\n // fetch fresh document, bounded by the configured timeout\n let res: Response;\n try {\n res = await fetch(url, {\n signal: AbortSignal.timeout(this.#timeoutMs),\n });\n } catch (error) {\n if (\n error instanceof Error &&\n (error.name === \"AbortError\" || error.name === \"TimeoutError\")\n ) {\n throw new Error(\n `Failed to fetch discovery document from ${url}: timed out after ${this.#timeoutMs}ms`,\n );\n }\n throw error;\n }\n\n if (!res.ok) {\n await cancelResponseBody(res);\n throw new Error(\n `Failed to fetch discovery document from ${url}: ${res.status} ${res.statusText}`,\n );\n }\n\n const data = await res.json();\n // calculate expiration time AFTER fetch completes\n const expiresAt = Date.now() + this.#ttl;\n\n // A clear that occurred while the fetch was pending invalidates its result.\n if (\n this.#generation === generation &&\n (this.#urlGenerations.get(url) ?? 0) === urlGeneration\n ) {\n this.#cache.set(url, {\n data,\n expiresAt,\n });\n }\n\n return data;\n }\n}\n","import { StandardSchemaV1 } from \"@standard-schema/spec\";\n\n/**\n * A plain JSON Schema object descriptor.\n */\nexport type JsonSchemaObject = {\n [key: string]: unknown;\n $schema?: string;\n additionalProperties?: boolean;\n properties?: Record<string, unknown>;\n required?: string[];\n type: string;\n};\n\n/**\n * A Standard Schema that also carries the JSON Schema it was built from.\n *\n * `~standard.jsonSchema` is the Standard JSON Schema extension. Anything that\n * knows about it — including the `xsschema` conversion FastMCP uses to build\n * `tools/list` — reads the schema straight off the object instead of trying to\n * derive one from a validation library it does not recognise.\n */\nexport interface JsonSchemaStandardSchema extends StandardSchemaV1 {\n readonly \"~standard\": {\n readonly jsonSchema: {\n readonly input: () => JsonSchemaObject;\n readonly output: () => JsonSchemaObject;\n };\n } & StandardSchemaV1.Props;\n}\n\ninterface AjvErrorObject {\n instancePath: string;\n keyword: string;\n message?: string;\n params?: Record<string, unknown>;\n}\n\ntype AjvValidateFunction = {\n errors?: AjvErrorObject[] | null;\n (data: unknown): boolean;\n};\n\n/**\n * Wraps a plain JSON Schema object so it can be used as a tool's `parameters`\n * or `outputSchema`, without pulling in Zod, Valibot, or another validation\n * library.\n *\n * Validation uses AJV, which is an optional peer dependency — install `ajv`\n * (and `ajv-formats` if you use `format` keywords) to use this. It is imported\n * on first validation, so servers that never call this pay nothing for it.\n *\n * Note that FastMCP applies the same strictness to every tool schema: objects\n * are advertised with `additionalProperties: false`, whatever the input schema\n * said.\n *\n * @example\n * ```ts\n * import { FastMCP, jsonSchemaAdapter } from \"fastmcp\";\n *\n * const server = new FastMCP({ name: \"Example\", version: \"1.0.0\" });\n *\n * server.addTool({\n * name: \"greet\",\n * description: \"Greet a user\",\n * parameters: jsonSchemaAdapter({\n * type: \"object\",\n * properties: {\n * name: { type: \"string\" },\n * },\n * required: [\"name\"],\n * }),\n * execute: async ({ name }) => `Hello, ${name}!`,\n * });\n * ```\n *\n * @param schema - A plain JSON Schema object\n * @returns A Standard Schema that validates against `schema`\n */\nexport function jsonSchemaAdapter(\n schema: JsonSchemaObject,\n): JsonSchemaStandardSchema {\n // Compiling a schema makes AJV generate and evaluate JavaScript, so it has\n // to happen once rather than per call. The promise is memoised, not just the\n // result, so concurrent first calls share a single compilation.\n let compiled: Promise<AjvValidateFunction> | undefined;\n\n const getValidator = (): Promise<AjvValidateFunction> => {\n compiled ??= compileSchema(schema).catch((error: unknown) => {\n // Do not memoise a failure: a missing dependency should be reported on\n // every call, not swallowed after the first.\n compiled = undefined;\n throw error;\n });\n\n return compiled;\n };\n\n return {\n \"~standard\": {\n jsonSchema: {\n input: () => schema,\n output: () => schema,\n },\n validate: async (\n data: unknown,\n ): Promise<StandardSchemaV1.Result<unknown>> => {\n const validate = await getValidator();\n\n if (validate(data)) {\n return { value: data };\n }\n\n return { issues: (validate.errors ?? []).map(toIssue) };\n },\n vendor: \"json-schema\",\n version: 1,\n },\n };\n}\n\nasync function compileSchema(\n schema: JsonSchemaObject,\n): Promise<AjvValidateFunction> {\n let ajvModule;\n\n try {\n ajvModule = await import(\"ajv\");\n } catch {\n throw new Error(\n 'The \"ajv\" package is required to validate JSON Schema tool parameters. ' +\n \"Install it with: npm install ajv\",\n );\n }\n\n // ajv ships CommonJS, so depending on the loader the class arrives as the\n // module namespace, as `.default`, or as `.default.default`.\n const Ajv = unwrapDefault(unwrapDefault(ajvModule)) as unknown as new (\n options: Record<string, unknown>,\n ) => {\n compile: (schema: unknown) => AjvValidateFunction;\n };\n\n const ajv = new Ajv({ allErrors: true, strict: false });\n\n try {\n const formatsModule = await import(\"ajv-formats\");\n const addFormats = unwrapDefault(\n unwrapDefault(formatsModule),\n ) as unknown as (ajv: unknown) => void;\n\n addFormats(ajv);\n } catch {\n // ajv-formats is optional; `format` keywords are simply not enforced.\n }\n\n return ajv.compile(schema);\n}\n\nfunction toIssue(error: AjvErrorObject): StandardSchemaV1.Issue {\n const path = error.instancePath\n .split(\"/\")\n .filter(Boolean)\n // JSON Pointer escapes, per RFC 6901.\n .map((segment) => segment.replaceAll(\"~1\", \"/\").replaceAll(\"~0\", \"~\"))\n .map((segment): number | string => {\n const index = Number(segment);\n return /^(?:0|[1-9]\\d*)$/.test(segment) && Number.isSafeInteger(index)\n ? index\n : segment;\n });\n\n // AJV reports a missing property against its parent object, with the name in\n // `params`. Appending it points the issue at the field the user has to fix.\n const missingProperty = error.params?.missingProperty;\n\n if (error.keyword === \"required\" && typeof missingProperty === \"string\") {\n path.push(missingProperty);\n }\n\n return {\n message: error.message || \"Validation error\",\n path,\n };\n}\n\nfunction unwrapDefault(value: unknown): unknown {\n return typeof value === \"object\" && value !== null && \"default\" in value\n ? (value as { default: unknown }).default\n : value;\n}\n"],"mappings":"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","names":["ServerState","resource","url"]}