@langchain/mcp-adapters
Version:
LangChain.js adapters for Model Context Protocol (MCP)
1 lines • 50.5 kB
Source Map (JSON)
{"version":3,"file":"client.cjs","names":["getDebugLog","message: string","serverName?: string","connection: unknown","#config","config: ClientConfig | Record<string, Connection>","parsedServerConfig: ResolvedClientConfig","clientConfigSchema","z","connectionSchema","_resolveAndApplyOverrideHandlingOverrides","#loadToolsOptions","#mcpServers","#clientConnections","ConnectionManager","#onConnectionError","customTransportOptions?: CustomHTTPTransportOptions","#failedServers","#serverNameToTools","servers","level","serverName: string","options?: CustomHTTPTransportOptions","servers: string[]","options: CustomHTTPTransportOptions | undefined","result: Record<string, MCPResource[]>","result: Record<string, MCPResourceTemplate[]>","uri: string","connection: ResolvedConnection","connection: ResolvedStdioConnection","transport: StdioClientTransport","restart: NonNullable<ResolvedStdioConnection[\"restart\"]>","error: unknown","url: string","transport: \"HTTP\" | \"SSE\"","originalError: string","connection: ResolvedStreamableHTTPConnection","transport: SSEClientTransport | StreamableHTTPClientTransport","reconnect: NonNullable<ResolvedStreamableHTTPConnection[\"reconnect\"]>","client: Client","loadMcpTools","#cleanupServerResources","transportOptions: {\n serverName: string;\n authProvider?: OAuthClientProvider;\n headers?: Record<string, string>;\n }","allTools: DynamicStructuredTool[]","serverNames: string[]"],"sources":["../src/client.ts"],"sourcesContent":["import { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport {\n SSEClientTransport,\n type SseError,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport {\n StreamableHTTPClientTransport,\n type StreamableHTTPError,\n} from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type { DynamicStructuredTool } from \"@langchain/core/tools\";\nimport type { LoggingLevel } from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { z } from \"zod/v3\";\nimport { loadMcpTools } from \"./tools.js\";\nimport { ConnectionManager, type Client } from \"./connection.js\";\nimport { getDebugLog } from \"./logging.js\";\nimport {\n type ClientConfig,\n type Connection,\n type ResolvedClientConfig,\n type ResolvedConnection,\n type ResolvedStdioConnection,\n type ResolvedStreamableHTTPConnection,\n type CustomHTTPTransportOptions,\n type MCPResource,\n type MCPResourceTemplate,\n type MCPResourceContent,\n type ConnectionErrorHandler,\n clientConfigSchema,\n connectionSchema,\n type LoadMcpToolsOptions,\n _resolveAndApplyOverrideHandlingOverrides,\n} from \"./types.js\";\n\nconst debugLog = getDebugLog();\n\n/**\n * Error class for MCP client operations\n */\nexport class MCPClientError extends Error {\n constructor(\n message: string,\n public readonly serverName?: string\n ) {\n super(message);\n this.name = \"MCPClientError\";\n }\n}\n\n/**\n * Checks if the connection configuration is for a stdio transport\n * @param connection - The connection configuration\n * @returns True if the connection configuration is for a stdio transport\n */\nfunction isResolvedStdioConnection(\n connection: unknown\n): connection is ResolvedStdioConnection {\n if (\n typeof connection !== \"object\" ||\n connection === null ||\n Array.isArray(connection)\n ) {\n return false;\n }\n\n if (\"transport\" in connection && connection.transport === \"stdio\") {\n return true;\n }\n\n if (\"type\" in connection && connection.type === \"stdio\") {\n return true;\n }\n\n if (\"command\" in connection && typeof connection.command === \"string\") {\n return true;\n }\n\n return false;\n}\n\n/**\n * Checks if the connection configuration is for a streamable HTTP transport\n * @param connection - The connection configuration\n * @returns True if the connection configuration is for a streamable HTTP transport\n */\nfunction isResolvedStreamableHTTPConnection(\n connection: unknown\n): connection is ResolvedStreamableHTTPConnection {\n if (\n typeof connection !== \"object\" ||\n connection === null ||\n Array.isArray(connection)\n ) {\n return false;\n }\n\n if (\n (\"transport\" in connection &&\n typeof connection.transport === \"string\" &&\n [\"http\", \"sse\"].includes(connection.transport)) ||\n (\"type\" in connection &&\n typeof connection.type === \"string\" &&\n [\"http\", \"sse\"].includes(connection.type))\n ) {\n return true;\n }\n\n if (\"url\" in connection && typeof connection.url === \"string\") {\n try {\n new URL(connection.url);\n return true;\n } catch {\n return false;\n }\n }\n\n return false;\n}\n\n/**\n * Client for connecting to multiple MCP servers and loading LangChain-compatible tools.\n */\nexport class MultiServerMCPClient {\n /**\n * Cached map of server names to tools\n */\n #serverNameToTools: Record<string, DynamicStructuredTool[]> = {};\n\n /**\n * Configured MCP servers\n */\n #mcpServers?: Record<string, ResolvedConnection>;\n\n /**\n * Cached map of server names to load tools options\n */\n #loadToolsOptions: Record<string, LoadMcpToolsOptions> = {};\n\n /**\n * Connection manager\n */\n #clientConnections: ConnectionManager;\n\n /**\n * Resolved client config\n */\n #config: ResolvedClientConfig;\n\n /**\n * Behavior when a server fails to connect\n */\n #onConnectionError: \"throw\" | \"ignore\" | ConnectionErrorHandler;\n\n /**\n * Set of server names that have failed to connect (when onConnectionError is \"ignore\")\n */\n #failedServers: Set<string> = new Set();\n\n /**\n * Returns clone of server config for inspection purposes.\n *\n * Client does not support config modifications.\n */\n get config(): ClientConfig {\n // clone config so it can't be mutated\n return JSON.parse(JSON.stringify(this.#config));\n }\n\n /**\n * Create a new MultiServerMCPClient.\n *\n * @param config - Configuration object\n */\n constructor(config: ClientConfig | Record<string, Connection>) {\n let parsedServerConfig: ResolvedClientConfig;\n\n const configSchema = clientConfigSchema;\n\n if (\"mcpServers\" in config) {\n parsedServerConfig = configSchema.parse(config);\n } else {\n // two step parse so parse errors are referencing the correct object paths\n const parsedMcpServers = z.record(connectionSchema).parse(config);\n\n parsedServerConfig = configSchema.parse({ mcpServers: parsedMcpServers });\n }\n\n if (Object.keys(parsedServerConfig.mcpServers).length === 0) {\n throw new MCPClientError(\"No MCP servers provided\");\n }\n\n for (const [serverName, serverConfig] of Object.entries(\n parsedServerConfig.mcpServers\n )) {\n const outputHandling = _resolveAndApplyOverrideHandlingOverrides(\n parsedServerConfig.outputHandling,\n serverConfig.outputHandling\n );\n const defaultToolTimeout =\n parsedServerConfig.defaultToolTimeout ??\n serverConfig.defaultToolTimeout;\n\n this.#loadToolsOptions[serverName] = {\n throwOnLoadError: parsedServerConfig.throwOnLoadError,\n prefixToolNameWithServerName:\n parsedServerConfig.prefixToolNameWithServerName,\n additionalToolNamePrefix: parsedServerConfig.additionalToolNamePrefix,\n useStandardContentBlocks: parsedServerConfig.useStandardContentBlocks,\n ...(Object.keys(outputHandling).length > 0 ? { outputHandling } : {}),\n ...(defaultToolTimeout ? { defaultToolTimeout } : {}),\n onProgress: parsedServerConfig.onProgress,\n /**\n * make sure to place global hooks (e.g. parsedServerConfig) first before\n * server-specific hooks (e.g. serverConfig) so they can override tool call\n * configuration.\n */\n beforeToolCall: parsedServerConfig.beforeToolCall,\n afterToolCall: parsedServerConfig.afterToolCall,\n };\n }\n\n this.#config = parsedServerConfig;\n this.#mcpServers = parsedServerConfig.mcpServers;\n this.#clientConnections = new ConnectionManager(parsedServerConfig);\n this.#onConnectionError = parsedServerConfig.onConnectionError;\n }\n\n /**\n * Proactively initialize connections to all servers. This will be called automatically when\n * methods requiring an active connection (like {@link getTools} or {@link getClient}) are called,\n * but you can call it directly to ensure all connections are established before using the tools.\n *\n * When a server fails to connect, the client will throw an error if `onConnectionError` is \"throw\",\n * otherwise it will skip the server and continue with the remaining servers.\n *\n * @returns A map of server names to arrays of tools\n * @throws {MCPClientError} If initialization fails and `onConnectionError` is \"throw\" (default)\n */\n async initializeConnections(\n customTransportOptions?: CustomHTTPTransportOptions\n ): Promise<Record<string, DynamicStructuredTool[]>> {\n if (!this.#mcpServers || Object.keys(this.#mcpServers).length === 0) {\n throw new MCPClientError(\"No connections to initialize\");\n }\n\n for (const [serverName, connection] of Object.entries(this.#mcpServers)) {\n // Skip servers that have already failed (when onConnectionError is \"ignore\")\n if (\n (this.#onConnectionError === \"ignore\" ||\n typeof this.#onConnectionError === \"function\") &&\n this.#failedServers.has(serverName)\n ) {\n continue;\n }\n\n try {\n await this._initializeConnection(\n serverName,\n connection,\n customTransportOptions\n );\n // If we successfully initialized, remove from failed set (in case it was there before)\n this.#failedServers.delete(serverName);\n } catch (error) {\n if (this.#onConnectionError === \"throw\") {\n throw error;\n }\n\n // Handle custom error handler function\n if (typeof this.#onConnectionError === \"function\") {\n this.#onConnectionError({ serverName, error });\n // If we get here, the handler didn't throw, so treat as ignored\n this.#failedServers.add(serverName);\n debugLog(\n `WARN: Failed to initialize connection to server \"${serverName}\": ${String(error)}`\n );\n continue;\n }\n\n // Default \"ignore\" behavior\n // Mark this server as failed so we don't try again\n this.#failedServers.add(serverName);\n debugLog(\n `WARN: Failed to initialize connection to server \"${serverName}\": ${String(error)}`\n );\n continue;\n }\n }\n\n // Warn if no servers successfully connected when using \"ignore\" mode\n if (\n this.#onConnectionError === \"ignore\" &&\n Object.keys(this.#serverNameToTools).length === 0\n ) {\n debugLog(\n `WARN: No servers successfully connected. All connection attempts failed.`\n );\n }\n\n return this.#serverNameToTools;\n }\n\n /**\n * Get tools from specified servers as a flattened array.\n *\n * @param servers - Optional array of server names to filter tools by.\n * If not provided, returns tools from all servers.\n * @param options - Optional connection options for the tool calls, e.g. custom auth provider or headers.\n * @returns A flattened array of tools from the specified servers (or all servers)\n *\n * @example\n * ```ts\n * // Get tools from all servers\n * const tools = await client.getTools();\n * ```\n *\n * @example\n * ```ts\n * // Get tools from specific servers\n * const tools = await client.getTools(\"server1\", \"server2\");\n * ```\n *\n * @example\n * ```ts\n * // Get tools from specific servers with custom connection options\n * const tools = await client.getTools([\"server1\", \"server2\"], {\n * authProvider: new OAuthClientProvider(),\n * headers: { \"X-Custom-Header\": \"value\" },\n * });\n * ```\n */\n async getTools(...servers: string[]): Promise<DynamicStructuredTool[]>;\n async getTools(\n servers: string[],\n options?: CustomHTTPTransportOptions\n ): Promise<DynamicStructuredTool[]>;\n async getTools(...args: unknown[]): Promise<DynamicStructuredTool[]> {\n if (args.length === 0 || args.every((arg) => typeof arg === \"string\")) {\n await this.initializeConnections();\n\n const servers = args as string[];\n return servers.length === 0\n ? this._getAllToolsAsFlatArray()\n : this._getToolsFromServers(servers);\n }\n\n const [servers, options] = args as [\n string[],\n CustomHTTPTransportOptions | undefined,\n ];\n await this.initializeConnections(options);\n return servers.length === 0\n ? this._getAllToolsAsFlatArray()\n : this._getToolsFromServers(servers);\n }\n\n /**\n * Set the logging level for all servers\n * @param level - The logging level\n *\n * @example\n * ```ts\n * await client.setLoggingLevel(\"debug\");\n * ```\n */\n async setLoggingLevel(level: LoggingLevel): Promise<void>;\n /**\n * Set the logging level for a specific server\n * @param serverName - The name of the server\n * @param level - The logging level\n *\n * @example\n * ```ts\n * await client.setLoggingLevel(\"server1\", \"debug\");\n * ```\n */\n async setLoggingLevel(serverName: string, level: LoggingLevel): Promise<void>;\n async setLoggingLevel(...args: unknown[]): Promise<void> {\n if (args.length === 1 && typeof args[0] === \"string\") {\n const level = args[0] as LoggingLevel;\n await Promise.all(\n this.#clientConnections\n .getAllClients()\n .map((client) => client.setLoggingLevel(level))\n );\n return;\n }\n\n const [serverName, level] = args as [string, LoggingLevel];\n await this.#clientConnections.get(serverName)?.setLoggingLevel(level);\n }\n\n /**\n * Get a the MCP client for a specific server. Useful for fetching prompts or resources from that server.\n *\n * @param serverName - The name of the server\n * @returns The client for the server, or undefined if the server is not connected\n */\n async getClient(\n serverName: string,\n options?: CustomHTTPTransportOptions\n ): Promise<Client | undefined> {\n await this.initializeConnections(options);\n return this.#clientConnections.get({\n serverName,\n headers: options?.headers,\n authProvider: options?.authProvider,\n });\n }\n\n /**\n * List resources from specified servers.\n *\n * @param servers - Optional array of server names to filter resources by.\n * If not provided, returns resources from all servers.\n * @param options - Optional connection options for the resource listing, e.g. custom auth provider or headers.\n * @returns A map of server names to their resources\n *\n * @example\n * ```ts\n * // List resources from all servers\n * const resources = await client.listResources();\n * ```\n *\n * @example\n * ```ts\n * // List resources from specific servers\n * const resources = await client.listResources(\"server1\", \"server2\");\n * ```\n */\n async listResources(\n ...servers: string[]\n ): Promise<Record<string, MCPResource[]>>;\n async listResources(\n servers: string[],\n options?: CustomHTTPTransportOptions\n ): Promise<Record<string, MCPResource[]>>;\n async listResources(\n ...args: unknown[]\n ): Promise<Record<string, MCPResource[]>> {\n let servers: string[];\n let options: CustomHTTPTransportOptions | undefined;\n\n if (args.length === 0 || args.every((arg) => typeof arg === \"string\")) {\n servers = args as string[];\n await this.initializeConnections();\n } else {\n [servers, options] = args as [\n string[],\n CustomHTTPTransportOptions | undefined,\n ];\n await this.initializeConnections(options);\n }\n\n const targetServers =\n servers.length > 0 ? servers : Object.keys(this.#config.mcpServers);\n\n const result: Record<string, MCPResource[]> = {};\n\n for (const serverName of targetServers) {\n const client = await this.getClient(serverName, options);\n if (!client) {\n debugLog(`WARN: Server \"${serverName}\" not found or not connected`);\n continue;\n }\n\n try {\n const resourcesList = await client.listResources();\n result[serverName] = resourcesList.resources.map((resource) => ({\n uri: resource.uri,\n name: resource.title ?? resource.name,\n description: resource.description,\n mimeType: resource.mimeType,\n }));\n debugLog(\n `INFO: Listed ${result[serverName].length} resources from server \"${serverName}\"`\n );\n } catch (error) {\n debugLog(\n `ERROR: Failed to list resources from server \"${serverName}\": ${error}`\n );\n result[serverName] = [];\n }\n }\n\n return result;\n }\n\n /**\n * List resource templates from specified servers.\n *\n * Resource templates are used for dynamic resources with parameterized URIs.\n *\n * @param servers - Optional array of server names to filter resource templates by.\n * If not provided, returns resource templates from all servers.\n * @param options - Optional connection options for the resource template listing, e.g. custom auth provider or headers.\n * @returns A map of server names to their resource templates\n *\n * @example\n * ```ts\n * // List resource templates from all servers\n * const templates = await client.listResourceTemplates();\n * ```\n *\n * @example\n * ```ts\n * // List resource templates from specific servers\n * const templates = await client.listResourceTemplates(\"server1\", \"server2\");\n * ```\n */\n async listResourceTemplates(\n ...servers: string[]\n ): Promise<Record<string, MCPResourceTemplate[]>>;\n async listResourceTemplates(\n servers: string[],\n options?: CustomHTTPTransportOptions\n ): Promise<Record<string, MCPResourceTemplate[]>>;\n async listResourceTemplates(\n ...args: unknown[]\n ): Promise<Record<string, MCPResourceTemplate[]>> {\n let servers: string[];\n let options: CustomHTTPTransportOptions | undefined;\n\n if (args.length === 0 || args.every((arg) => typeof arg === \"string\")) {\n servers = args as string[];\n await this.initializeConnections();\n } else {\n [servers, options] = args as [\n string[],\n CustomHTTPTransportOptions | undefined,\n ];\n await this.initializeConnections(options);\n }\n\n const targetServers =\n servers.length > 0 ? servers : Object.keys(this.#config.mcpServers);\n\n const result: Record<string, MCPResourceTemplate[]> = {};\n\n for (const serverName of targetServers) {\n const client = await this.getClient(serverName, options);\n if (!client) {\n debugLog(`WARN: Server \"${serverName}\" not found or not connected`);\n continue;\n }\n\n try {\n const templatesList = await client.listResourceTemplates();\n result[serverName] = templatesList.resourceTemplates.map(\n (template) => ({\n uriTemplate: template.uriTemplate,\n name: template.title ?? template.name,\n description: template.description,\n mimeType: template.mimeType,\n })\n );\n debugLog(\n `INFO: Listed ${result[serverName].length} resource templates from server \"${serverName}\"`\n );\n } catch (error) {\n debugLog(\n `ERROR: Failed to list resource templates from server \"${serverName}\": ${error}`\n );\n result[serverName] = [];\n }\n }\n\n return result;\n }\n\n /**\n * Read a resource from a specific server.\n *\n * @param serverName - The name of the server to read the resource from\n * @param uri - The URI of the resource to read\n * @param options - Optional connection options for reading the resource, e.g. custom auth provider or headers.\n * @returns The resource contents\n *\n * @example\n * ```ts\n * const content = await client.readResource(\"server1\", \"file://path/to/resource\");\n * ```\n */\n async readResource(\n serverName: string,\n uri: string,\n options?: CustomHTTPTransportOptions\n ): Promise<MCPResourceContent[]> {\n await this.initializeConnections(options);\n\n const client = await this.getClient(serverName, options);\n if (!client) {\n throw new MCPClientError(\n `Server \"${serverName}\" not found or not connected`,\n serverName\n );\n }\n\n try {\n debugLog(`INFO: Reading resource \"${uri}\" from server \"${serverName}\"`);\n const result = await client.readResource({ uri });\n return result.contents.map((content) => ({\n uri: content.uri,\n mimeType: content.mimeType,\n text: \"text\" in content ? content.text : undefined,\n blob: \"blob\" in content ? content.blob : undefined,\n }));\n } catch (error) {\n throw new MCPClientError(\n `Failed to read resource \"${uri}\" from server \"${serverName}\": ${error}`,\n serverName\n );\n }\n }\n\n /**\n * Close all connections.\n */\n async close(): Promise<void> {\n debugLog(`INFO: Closing all MCP connections...`);\n this.#serverNameToTools = {};\n this.#failedServers.clear();\n await this.#clientConnections.delete();\n debugLog(`INFO: All MCP connections closed`);\n }\n\n /**\n * Initialize a connection to a specific server\n */\n private async _initializeConnection(\n serverName: string,\n connection: ResolvedConnection,\n customTransportOptions?: CustomHTTPTransportOptions\n ): Promise<void> {\n if (isResolvedStdioConnection(connection)) {\n debugLog(\n `INFO: Initializing stdio connection to server \"${serverName}\"...`\n );\n\n /**\n * check if we already initialized this stdio connection\n */\n if (this.#clientConnections.has(serverName)) {\n return;\n }\n\n await this._initializeStdioConnection(serverName, connection);\n } else if (isResolvedStreamableHTTPConnection(connection)) {\n /**\n * Users may want to use different connection options for tool calls or tool discovery.\n */\n const { authProvider, headers } = customTransportOptions ?? {};\n const updatedConnection = {\n ...connection,\n authProvider: authProvider ?? connection.authProvider,\n headers: { ...headers, ...connection.headers },\n };\n\n /**\n * check if we already initialized this streamable HTTP connection\n */\n const key = {\n serverName,\n headers: updatedConnection.headers,\n authProvider: updatedConnection.authProvider,\n };\n if (this.#clientConnections.has(key)) {\n return;\n }\n\n if (connection.type === \"sse\" || connection.transport === \"sse\") {\n await this._initializeSSEConnection(serverName, updatedConnection);\n } else {\n await this._initializeStreamableHTTPConnection(\n serverName,\n updatedConnection\n );\n }\n } else {\n // This should never happen due to the validation in the constructor\n throw new MCPClientError(\n `Unsupported transport type for server \"${serverName}\"`,\n serverName\n );\n }\n }\n\n /**\n * Initialize a stdio connection\n */\n private async _initializeStdioConnection(\n serverName: string,\n connection: ResolvedStdioConnection\n ): Promise<void> {\n const { command, args, restart } = connection;\n\n debugLog(\n `DEBUG: Creating stdio transport for server \"${serverName}\" with command: ${command} ${args.join(\n \" \"\n )}`\n );\n\n try {\n const client = await this.#clientConnections.createClient(\n \"stdio\",\n serverName,\n connection\n );\n const transport = this.#clientConnections.getTransport({\n serverName,\n }) as StdioClientTransport;\n\n // Set up auto-restart if configured\n if (restart?.enabled) {\n this._setupStdioRestart(serverName, transport, connection, restart);\n }\n\n // Load tools for this server\n await this._loadToolsForServer(serverName, client);\n } catch (error) {\n throw new MCPClientError(\n `Failed to connect to stdio server \"${serverName}\": ${error}`,\n serverName\n );\n }\n }\n\n /**\n * Set up stdio restart handling\n */\n private _setupStdioRestart(\n serverName: string,\n transport: StdioClientTransport,\n connection: ResolvedStdioConnection,\n restart: NonNullable<ResolvedStdioConnection[\"restart\"]>\n ): void {\n const originalOnClose = transport.onclose;\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n transport.onclose = async () => {\n if (originalOnClose) {\n await originalOnClose();\n }\n\n // Only attempt restart if we haven't cleaned up\n if (this.#clientConnections.get(serverName)) {\n debugLog(\n `INFO: Process for server \"${serverName}\" exited, attempting to restart...`\n );\n await this._attemptReconnect(\n serverName,\n connection,\n restart.maxAttempts,\n restart.delayMs\n );\n }\n };\n }\n\n private _getHttpErrorCode(error: unknown): number | undefined {\n const streamableError = error as StreamableHTTPError | SseError;\n let { code } = streamableError;\n // try parsing from error message if code is not set\n if (code == null) {\n const m = streamableError.message.match(/\\(HTTP (\\d\\d\\d)\\)/);\n if (m && m.length > 1) {\n code = parseInt(m[1], 10);\n }\n }\n return code;\n }\n\n private _createAuthenticationErrorMessage(\n serverName: string,\n url: string,\n transport: \"HTTP\" | \"SSE\",\n originalError: string\n ): string {\n return (\n `Authentication failed for ${transport} server \"${serverName}\" at ${url}. ` +\n `Please check your credentials, authorization headers, or OAuth configuration. ` +\n `Original error: ${originalError}`\n );\n }\n\n private _toSSEConnectionURL(url: string): string {\n const urlObj = new URL(url);\n const pathnameParts = urlObj.pathname.split(\"/\");\n const lastPart = pathnameParts.at(-1);\n if (lastPart && lastPart === \"mcp\") {\n pathnameParts[pathnameParts.length - 1] = \"sse\";\n }\n urlObj.pathname = pathnameParts.join(\"/\");\n return urlObj.toString();\n }\n\n /**\n * Initialize a streamable HTTP connection\n */\n private async _initializeStreamableHTTPConnection(\n serverName: string,\n connection: ResolvedStreamableHTTPConnection\n ): Promise<void> {\n const { url, type: typeField, transport: transportField } = connection;\n const automaticSSEFallback = connection.automaticSSEFallback ?? true;\n const transportType = typeField || transportField;\n\n debugLog(\n `DEBUG: Creating Streamable HTTP transport for server \"${serverName}\" with URL: ${url}`\n );\n\n if (transportType === \"http\" || transportType == null) {\n try {\n const client = await this.#clientConnections.createClient(\n \"http\",\n serverName,\n connection\n );\n\n await this._loadToolsForServer(serverName, client);\n } catch (error) {\n const code = this._getHttpErrorCode(error);\n if (automaticSSEFallback && code != null && code >= 400 && code < 500) {\n // Streamable HTTP error is a 4xx, so fall back to SSE\n try {\n await this._initializeSSEConnection(serverName, connection);\n } catch (firstSSEError) {\n // try one more time, but modify the URL to end with `/sse`\n const sseUrl = this._toSSEConnectionURL(url);\n\n if (sseUrl !== url) {\n try {\n await this._initializeSSEConnection(serverName, {\n ...connection,\n url: sseUrl,\n });\n } catch (secondSSEError) {\n // Provide specific error message for authentication failures\n if (code === 401) {\n throw new MCPClientError(\n this._createAuthenticationErrorMessage(\n serverName,\n url,\n \"HTTP\",\n `${error}. Also tried SSE fallback at ${url} and ${sseUrl}, but both failed with authentication errors.`\n ),\n serverName\n );\n }\n throw new MCPClientError(\n `Failed to connect to streamable HTTP server \"${serverName}, url: ${url}\": ${error}. Additionally, tried falling back to SSE at ${url} and ${sseUrl}, but this also failed: ${secondSSEError}`,\n serverName\n );\n }\n } else {\n // Provide specific error message for authentication failures\n if (code === 401) {\n throw new MCPClientError(\n this._createAuthenticationErrorMessage(\n serverName,\n url,\n \"HTTP\",\n `${error}. Also tried SSE fallback at ${url}, but it failed with authentication error: ${firstSSEError}`\n ),\n serverName\n );\n }\n throw new MCPClientError(\n `Failed to connect to streamable HTTP server after trying to fall back to SSE: \"${serverName}, url: ${url}\": ${error} (SSE fallback failed with error ${firstSSEError})`,\n serverName\n );\n }\n }\n } else {\n // Provide specific error message for authentication failures\n if (code === 401) {\n throw new MCPClientError(\n this._createAuthenticationErrorMessage(\n serverName,\n url,\n \"HTTP\",\n `${error}`\n ),\n serverName\n );\n }\n throw new MCPClientError(\n `Failed to connect to streamable HTTP server \"${serverName}, url: ${url}\": ${error}`,\n serverName\n );\n }\n }\n }\n }\n\n /**\n * Initialize an SSE connection\n *\n * Don't call this directly unless SSE transport is explicitly requested. Otherwise,\n * use _initializeStreamableHTTPConnection and it'll fall back to SSE if needed for\n * backwards compatibility.\n *\n * @param serverName - The name of the server\n * @param connection - The connection configuration\n */\n private async _initializeSSEConnection(\n serverName: string,\n connection: ResolvedStreamableHTTPConnection // used for both SSE and streamable HTTP\n ): Promise<void> {\n const { url, headers, reconnect, authProvider } = connection;\n\n try {\n const client = await this.#clientConnections.createClient(\n \"sse\",\n serverName,\n connection\n );\n const transport = this.#clientConnections.getTransport({\n serverName,\n headers,\n authProvider,\n }) as SSEClientTransport;\n\n // Set up auto-reconnect if configured\n if (reconnect?.enabled) {\n this._setupSSEReconnect(serverName, transport, connection, reconnect);\n }\n\n // Load tools for this server\n await this._loadToolsForServer(serverName, client);\n } catch (error) {\n // Check if this is already a wrapped error that should be re-thrown\n if (error && (error as Error).name === \"MCPClientError\") {\n throw error;\n }\n\n // Check if this is an authentication error that needs better messaging\n const isAuthError = error && this._getHttpErrorCode(error) === 401;\n\n if (isAuthError) {\n throw new MCPClientError(\n this._createAuthenticationErrorMessage(\n serverName,\n url,\n \"SSE\",\n `${error}`\n ),\n serverName\n );\n }\n\n throw new MCPClientError(\n `Failed to create SSE transport for server \"${serverName}, url: ${url}\": ${error}`,\n serverName\n );\n }\n }\n\n /**\n * Set up reconnect handling for SSE (Streamable HTTP reconnects are more complex and are handled internally by the SDK)\n */\n private _setupSSEReconnect(\n serverName: string,\n transport: SSEClientTransport | StreamableHTTPClientTransport,\n connection: ResolvedStreamableHTTPConnection,\n reconnect: NonNullable<ResolvedStreamableHTTPConnection[\"reconnect\"]>\n ): void {\n const originalOnClose = transport.onclose;\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n transport.onclose = async () => {\n if (originalOnClose) {\n await originalOnClose();\n }\n\n // Only attempt reconnect if we haven't cleaned up\n if (\n this.#clientConnections.get({\n serverName,\n headers: connection.headers,\n authProvider: connection.authProvider,\n })\n ) {\n debugLog(\n `INFO: HTTP connection for server \"${serverName}\" closed, attempting to reconnect...`\n );\n await this._attemptReconnect(\n serverName,\n connection,\n reconnect.maxAttempts,\n reconnect.delayMs\n );\n }\n };\n }\n\n /**\n * Load tools for a specific server\n */\n private async _loadToolsForServer(\n serverName: string,\n client: Client\n ): Promise<void> {\n try {\n debugLog(`DEBUG: Loading tools for server \"${serverName}\"...`);\n const tools = await loadMcpTools(\n serverName,\n client,\n this.#loadToolsOptions[serverName]\n );\n this.#serverNameToTools[serverName] = tools;\n debugLog(\n `INFO: Successfully loaded ${tools.length} tools from server \"${serverName}\"`\n );\n } catch (error) {\n throw new MCPClientError(\n `Failed to load tools from server \"${serverName}\": ${error}`\n );\n }\n }\n\n /**\n * Attempt to reconnect to a server after a connection failure.\n *\n * @param serverName - The name of the server to reconnect to\n * @param connection - The connection configuration\n * @param maxAttempts - Maximum number of reconnection attempts\n * @param delayMs - Delay in milliseconds between reconnection attempts\n * @private\n */\n private async _attemptReconnect(\n serverName: string,\n connection: ResolvedConnection,\n maxAttempts = 3,\n delayMs = 1000\n ): Promise<void> {\n let connected = false;\n let attempts = 0;\n\n // Clean up previous connection resources\n if (\"headers\" in connection || \"authProvider\" in connection) {\n const { headers, authProvider } = connection;\n await this.#cleanupServerResources({ serverName, authProvider, headers });\n } else {\n await this.#cleanupServerResources({ serverName });\n }\n\n while (\n !connected &&\n (maxAttempts === undefined || attempts < maxAttempts)\n ) {\n attempts += 1;\n debugLog(\n `INFO: Reconnection attempt ${attempts}${\n maxAttempts ? `/${maxAttempts}` : \"\"\n } for server \"${serverName}\"`\n );\n\n try {\n // Wait before attempting to reconnect\n if (delayMs) {\n await new Promise((resolve) => {\n setTimeout(resolve, delayMs);\n });\n }\n\n // Initialize just this connection based on its type\n if (isResolvedStdioConnection(connection)) {\n await this._initializeStdioConnection(serverName, connection);\n } else if (isResolvedStreamableHTTPConnection(connection)) {\n if (connection.type === \"sse\" || connection.transport === \"sse\") {\n await this._initializeSSEConnection(serverName, connection);\n } else {\n await this._initializeStreamableHTTPConnection(\n serverName,\n connection\n );\n }\n }\n\n // Check if connected\n const key =\n \"headers\" in connection\n ? {\n serverName,\n headers: connection.headers,\n authProvider: connection.authProvider,\n }\n : { serverName };\n if (this.#clientConnections.has(key)) {\n connected = true;\n debugLog(`INFO: Successfully reconnected to server \"${serverName}\"`);\n }\n } catch (error) {\n debugLog(\n `ERROR: Failed to reconnect to server \"${serverName}\" (attempt ${attempts}): ${error}`\n );\n }\n }\n\n if (!connected) {\n debugLog(\n `ERROR: Failed to reconnect to server \"${serverName}\" after ${attempts} attempts`\n );\n }\n }\n\n /**\n * Clean up resources for a specific server\n */\n async #cleanupServerResources(transportOptions: {\n serverName: string;\n authProvider?: OAuthClientProvider;\n headers?: Record<string, string>;\n }): Promise<void> {\n const { serverName, authProvider, headers } = transportOptions;\n delete this.#serverNameToTools[serverName];\n await this.#clientConnections.delete({ serverName, authProvider, headers });\n }\n\n /**\n * Get all tools from all servers as a flat array.\n *\n * @returns A flattened array of all tools\n */\n private _getAllToolsAsFlatArray(): DynamicStructuredTool[] {\n const allTools: DynamicStructuredTool[] = [];\n for (const tools of Object.values(this.#serverNameToTools)) {\n allTools.push(...tools);\n }\n return allTools;\n }\n\n /**\n * Get tools from specific servers as a flat array.\n *\n * @param serverNames - Names of servers to get tools from\n * @returns A flattened array of tools from the specified servers\n */\n private _getToolsFromServers(serverNames: string[]): DynamicStructuredTool[] {\n const allTools: DynamicStructuredTool[] = [];\n for (const serverName of serverNames) {\n const tools = this.#serverNameToTools[serverName];\n if (tools) {\n allTools.push(...tools);\n }\n }\n return allTools;\n }\n}\n"],"mappings":"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