{"version":3,"file":"connection.cjs","names":["getDebugLog","#hooks","#createStreamableHTTPTransport","#createSSETransport","#createStdioTransport","MCPClient","LoggingMessageNotificationSchema","InitializedNotificationSchema","CancelledNotificationSchema","PromptListChangedNotificationSchema","ResourceListChangedNotificationSchema","ResourceUpdatedNotificationSchema","RootsListChangedNotificationSchema","ToolListChangedNotificationSchema","#forkClient","#connections","#queryConnection","StreamableHTTPClientTransport","SSEClientTransport","StdioClientTransport"],"sources":["../src/connection.ts"],"sourcesContent":["import {\n  SSEClientTransport,\n  SSEClientTransportOptions,\n} from \"@modelcontextprotocol/sdk/client/sse.js\";\n\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport type { OAuthClientProvider } from \"@modelcontextprotocol/sdk/client/auth.js\";\nimport type {\n  StreamableHTTPClientTransportOptions,\n  StreamableHTTPReconnectionOptions,\n} from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { Client as MCPClient } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StdioClientTransport } from \"@modelcontextprotocol/sdk/client/stdio.js\";\nimport {\n  LoggingMessageNotificationSchema,\n  CancelledNotificationSchema,\n  InitializedNotificationSchema,\n  PromptListChangedNotificationSchema,\n  ResourceListChangedNotificationSchema,\n  ResourceUpdatedNotificationSchema,\n  RootsListChangedNotificationSchema,\n  ToolListChangedNotificationSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\nimport { getDebugLog } from \"./logging.js\";\nimport type {\n  ResolvedStreamableHTTPConnection,\n  ResolvedStdioConnection,\n  ResolvedClientConfig,\n} from \"./types.js\";\n\n/**\n * TSDown automatically creates a JS file that allows us to consume the package.json file\n * within ESM and CJS modules.\n */\nimport packageJson from \"../package.json\" with { type: \"json\" };\n\nconst debugLog = getDebugLog(\"connection\");\n\nexport interface Client extends MCPClient {\n  /**\n   * Fork the client with a new set of headers, it either returns a new client or the same client if the headers are the same\n   * @param headers - The headers to fork the client with\n   * @returns The forked client\n   */\n  fork: (headers: Record<string, string>) => Promise<Client>;\n}\n\nexport interface TransportOptions {\n  serverName: string;\n  headers?: Record<string, string>;\n  authProvider?: OAuthClientProvider;\n}\n\ntype ClientKeyObject = Omit<TransportOptions, \"headers\"> & {\n  headers?: string;\n};\n\nexport interface Connection {\n  transport:\n    | StreamableHTTPClientTransport\n    | SSEClientTransport\n    | StdioClientTransport;\n  client: Client;\n  transportOptions: ResolvedStdioConnection | ResolvedStreamableHTTPConnection;\n  closeCallback: () => Promise<void>;\n}\n\nconst transportTypes = [\"http\", \"sse\", \"stdio\"] as const;\n\ntype ConnectionManagerConfig = Pick<\n  ResolvedClientConfig,\n  | \"onCancelled\"\n  | \"onInitialized\"\n  | \"onMessage\"\n  | \"onPromptsListChanged\"\n  | \"onResourcesListChanged\"\n  | \"onResourcesUpdated\"\n  | \"onRootsListChanged\"\n  | \"onToolsListChanged\"\n>;\n\n/**\n * Manages a pool of MCP clients with different transport, server name and connection configurations.\n * This ensures we don't create multiple connections for the same server with the same configuration.\n */\nexport class ConnectionManager {\n  #connections: Map<ClientKeyObject, Connection> = new Map();\n  #hooks: ConnectionManagerConfig;\n\n  constructor(hooks: ConnectionManagerConfig = {}) {\n    this.#hooks = hooks;\n  }\n\n  async createClient(\n    type: \"stdio\",\n    serverName: string,\n    options: ResolvedStdioConnection\n  ): Promise<Client>;\n  async createClient(\n    type: \"http\",\n    serverName: string,\n    options: ResolvedStreamableHTTPConnection\n  ): Promise<Client>;\n  async createClient(\n    type: \"sse\",\n    serverName: string,\n    options: ResolvedStreamableHTTPConnection\n  ): Promise<Client>;\n  async createClient(\n    ...args:\n      | [\"stdio\", string, ResolvedStdioConnection]\n      | [\"sse\", string, ResolvedStreamableHTTPConnection]\n      | [\"http\", string, ResolvedStreamableHTTPConnection]\n  ): Promise<Client> {\n    const [type, serverName, options] = args;\n    if (!transportTypes.includes(type)) {\n      throw new Error(`Invalid transport type: ${type}`);\n    }\n\n    const transport =\n      type === \"http\"\n        ? await this.#createStreamableHTTPTransport(serverName, options)\n        : type === \"sse\"\n          ? await this.#createSSETransport(serverName, options)\n          : await this.#createStdioTransport(options);\n    const mcpClient = new MCPClient({\n      name: packageJson.name,\n      version: packageJson.version,\n    });\n    await mcpClient.connect(transport);\n\n    if (this.#hooks.onMessage) {\n      mcpClient.setNotificationHandler(\n        LoggingMessageNotificationSchema,\n        (notification) =>\n          this.#hooks.onMessage?.(notification.params, {\n            server: serverName,\n            options,\n          })\n      );\n    }\n\n    if (this.#hooks.onInitialized) {\n      mcpClient.setNotificationHandler(InitializedNotificationSchema, () =>\n        this.#hooks.onInitialized?.({\n          server: serverName,\n          options,\n        })\n      );\n    }\n\n    if (this.#hooks.onCancelled) {\n      mcpClient.setNotificationHandler(\n        CancelledNotificationSchema,\n        (notification) => {\n          const { requestId, reason } = notification.params;\n\n          if (requestId == null) {\n            return;\n          }\n\n          const result = this.#hooks.onCancelled?.(\n            { requestId, reason },\n            {\n              server: serverName,\n              options,\n            }\n          );\n\n          if (result && typeof result.catch === \"function\") {\n            result.catch(() => {\n              /* ignore hook errors */\n            });\n          }\n        }\n      );\n    }\n\n    if (this.#hooks.onPromptsListChanged) {\n      mcpClient.setNotificationHandler(\n        PromptListChangedNotificationSchema,\n        () =>\n          this.#hooks.onPromptsListChanged?.({\n            server: serverName,\n            options,\n          })\n      );\n    }\n\n    if (this.#hooks.onResourcesListChanged) {\n      mcpClient.setNotificationHandler(\n        ResourceListChangedNotificationSchema,\n        () =>\n          this.#hooks.onResourcesListChanged?.({\n            server: serverName,\n            options,\n          })\n      );\n    }\n\n    if (this.#hooks.onResourcesUpdated) {\n      mcpClient.setNotificationHandler(\n        ResourceUpdatedNotificationSchema,\n        (notification) =>\n          this.#hooks.onResourcesUpdated?.(notification.params, {\n            server: serverName,\n            options,\n          })\n      );\n    }\n\n    if (this.#hooks.onRootsListChanged) {\n      mcpClient.setNotificationHandler(RootsListChangedNotificationSchema, () =>\n        this.#hooks.onRootsListChanged?.({\n          server: serverName,\n          options,\n        })\n      );\n    }\n\n    if (this.#hooks.onToolsListChanged) {\n      mcpClient.setNotificationHandler(ToolListChangedNotificationSchema, () =>\n        this.#hooks.onToolsListChanged?.({\n          server: serverName,\n          options,\n        })\n      );\n    }\n\n    const key: ClientKeyObject =\n      type === \"stdio\"\n        ? { serverName }\n        : {\n            serverName,\n            headers: serializeHeaders(options.headers),\n            authProvider: options.authProvider,\n          };\n\n    const forkClient = (headers: Record<string, string>): Promise<Client> => {\n      return this.#forkClient(key, headers);\n    };\n\n    const client = new Proxy(mcpClient, {\n      get(target, prop) {\n        if (prop === \"fork\") {\n          return forkClient.bind(this);\n        }\n\n        return target[prop as keyof MCPClient];\n      },\n    }) as Client;\n\n    this.#connections.set(key, {\n      transport,\n      client,\n      transportOptions: options,\n      closeCallback: async () => client.close(),\n    });\n\n    return client;\n  }\n\n  /**\n   * Allows to fork a client with a new set of headers\n   */\n  #forkClient(\n    key: ClientKeyObject,\n    headers: Record<string, string>\n  ): Promise<Client> {\n    const [, connection] =\n      [...this.#connections.entries()].find(([k]) => key === k) ?? [];\n\n    if (!connection) {\n      throw new Error(\"Transport not found\");\n    }\n\n    const type =\n      connection.transportOptions.type ?? connection.transportOptions.transport;\n    if (type === \"stdio\") {\n      throw new Error(\"Forking stdio transport is not supported\");\n    }\n\n    return this.createClient(type as \"http\", key.serverName, {\n      ...connection.transportOptions,\n      headers,\n    } as ResolvedStreamableHTTPConnection);\n  }\n\n  /**\n   * Get the transport based on server name and connection configuration.\n   * @param options - The options for the transport\n   * @returns The transport\n   */\n  get(serverName: string): Client | undefined;\n  get(options: TransportOptions): Client | undefined;\n  get(options: TransportOptions | string): Client | undefined {\n    if (typeof options === \"string\") {\n      return this.#queryConnection({ serverName: options })?.connection.client;\n    }\n\n    return this.#queryConnection(options)?.connection.client;\n  }\n\n  /**\n   * Get all clients\n   * @returns All clients\n   */\n  getAllClients(): Client[] {\n    return Array.from(this.#connections.values()).map(\n      (connection) => connection.client\n    );\n  }\n\n  /**\n   * Find the connection based on the parameter provided. This approach makes sure\n   * that `this.get({ serverName })` and `this.get({ serverName, headers: undefined, authProvider: undefined })`\n   * will return the same connection.\n   *\n   * @param options - The options for the transport\n   * @returns The connection and the key\n   */\n  #queryConnection(\n    options: TransportOptions\n  ): { key: ClientKeyObject; connection: Connection } | undefined {\n    const headers = serializeHeaders(options.headers);\n    const [key, connection] =\n      [...this.#connections.entries()].find(([key]) => {\n        if (options.headers && options.authProvider) {\n          return (\n            key.serverName === options.serverName &&\n            key.headers === headers &&\n            key.authProvider === options.authProvider\n          );\n        }\n        if (options.headers && !options.authProvider) {\n          return (\n            key.serverName === options.serverName && key.headers === headers\n          );\n        }\n        if (options.authProvider && !options.headers) {\n          return (\n            key.serverName === options.serverName &&\n            key.authProvider === options.authProvider\n          );\n        }\n        return key.serverName === options.serverName;\n      }) ?? [];\n\n    if (key && connection) {\n      return { key, connection };\n    }\n\n    return undefined;\n  }\n\n  /**\n   * Check if a client exists based on server name and connection configuration.\n   * @param options - The options for the transport\n   * @returns True if the client exists, false otherwise\n   */\n  has(serverName: string): boolean;\n  has(options: TransportOptions): boolean;\n  has(options: TransportOptions | string): boolean {\n    return Boolean(\n      typeof options === \"string\" ? this.get(options) : this.get(options)\n    );\n  }\n\n  /**\n   * Delete the transport based on server name and connection configuration.\n   * @param options - The options for the transport, if not provided, all transports are deleted\n   */\n  async delete(options?: TransportOptions) {\n    if (!options) {\n      await Promise.all(\n        Array.from(this.#connections.values()).map((connection) =>\n          connection.closeCallback()\n        )\n      );\n      this.#connections.clear();\n      return;\n    }\n\n    const result = this.#queryConnection(options);\n    if (result) {\n      await result.connection.closeCallback();\n      this.#connections.delete(result.key);\n    }\n  }\n\n  /**\n   * Get the transport for a specific client\n   * @param client - The client to get the transport for\n   */\n  getTransport(\n    client: Client\n  ):\n    | StreamableHTTPClientTransport\n    | SSEClientTransport\n    | StdioClientTransport\n    | undefined;\n  /**\n   * Get the transport for a specific connection combination\n   * @param options - The options to get the transport for\n   */\n  getTransport(\n    options: TransportOptions\n  ):\n    | StreamableHTTPClientTransport\n    | SSEClientTransport\n    | StdioClientTransport\n    | undefined;\n  getTransport(\n    opts: Client | TransportOptions\n  ):\n    | StreamableHTTPClientTransport\n    | SSEClientTransport\n    | StdioClientTransport\n    | undefined {\n    /**\n     * if a client instance is passed in\n     */\n    if (\"listTools\" in opts) {\n      const connection = [...this.#connections.values()].find(\n        (connection) => connection.client === opts\n      );\n      return connection?.transport;\n    }\n\n    const result = this.#queryConnection(opts);\n    if (result) {\n      return result.connection.transport;\n    }\n    return undefined;\n  }\n\n  async #createStreamableHTTPTransport(\n    serverName: string,\n    args: ResolvedStreamableHTTPConnection\n  ): Promise<StreamableHTTPClientTransport> {\n    const { url, headers, reconnect, authProvider } = args;\n\n    const options: StreamableHTTPClientTransportOptions = {\n      ...(authProvider ? { authProvider } : {}),\n      ...(headers ? { requestInit: { headers } } : {}),\n    };\n\n    if (reconnect != null) {\n      const reconnectionOptions: StreamableHTTPReconnectionOptions = {\n        initialReconnectionDelay: reconnect?.delayMs ?? 1000, // MCP default\n        maxReconnectionDelay: reconnect?.delayMs ?? 30000, // MCP default\n        maxRetries: reconnect?.maxAttempts ?? 2, // MCP default\n        reconnectionDelayGrowFactor: 1.5, // MCP default\n      };\n\n      if (reconnect.enabled === false) {\n        reconnectionOptions.maxRetries = 0;\n      }\n\n      options.reconnectionOptions = reconnectionOptions;\n    }\n\n    if (options.requestInit?.headers) {\n      debugLog(\n        `DEBUG: Using custom headers for SSE transport to server \"${serverName}\"`\n      );\n    }\n\n    if (options.authProvider) {\n      debugLog(\n        `DEBUG: Using OAuth authentication for Streamable HTTP transport to server \"${serverName}\"`\n      );\n    }\n\n    if (options.reconnectionOptions) {\n      if (options.reconnectionOptions.maxRetries === 0) {\n        debugLog(\n          `DEBUG: Disabling reconnection for Streamable HTTP transport to server \"${serverName}\"`\n        );\n      } else {\n        debugLog(\n          `DEBUG: Using custom reconnection options for Streamable HTTP transport to server \"${serverName}\"`\n        );\n      }\n    }\n\n    // Only pass options if there are any, otherwise use default constructor\n    return Object.keys(options).length > 0\n      ? new StreamableHTTPClientTransport(new URL(url), options)\n      : new StreamableHTTPClientTransport(new URL(url));\n  }\n\n  /**\n   * Create an SSE transport with appropriate EventSource implementation\n   *\n   * @param serverName - The name of the server\n   * @param url - The URL of the server\n   * @param headers - The headers to send with the request\n   * @param authProvider - The OAuth client provider to use for authentication\n   * @returns The SSE transport\n   */\n  async #createSSETransport(\n    serverName: string,\n    args: ResolvedStreamableHTTPConnection\n  ): Promise<SSEClientTransport> {\n    const { url, headers, authProvider } = args;\n    const options: SSEClientTransportOptions = {};\n\n    if (authProvider) {\n      options.authProvider = authProvider;\n      debugLog(\n        `DEBUG: Using OAuth authentication for SSE transport to server \"${serverName}\"`\n      );\n    }\n\n    if (headers) {\n      // For SSE, we need to pass headers via eventSourceInit.fetch for the initial connection\n      // and also via requestInit.headers for subsequent POST requests\n      options.eventSourceInit = {\n        fetch: async (url, init) => {\n          const requestHeaders = new Headers(init?.headers);\n\n          // Add OAuth token if authProvider is available\n          // This is necessary because setting eventSourceInit.fetch prevents automatic Authorization header\n          if (authProvider) {\n            const tokens = await authProvider.tokens();\n            if (tokens) {\n              requestHeaders.set(\n                \"Authorization\",\n                `Bearer ${tokens.access_token}`\n              );\n            }\n          }\n\n          // Add our custom headers\n          Object.entries(headers).forEach(([key, value]) => {\n            requestHeaders.set(key, value);\n          });\n          // Always include Accept header for SSE\n          requestHeaders.set(\"Accept\", \"text/event-stream\");\n\n          return fetch(url, {\n            ...init,\n            headers: requestHeaders,\n          });\n        },\n      };\n\n      // Also include headers for POST requests\n      options.requestInit = { headers };\n\n      debugLog(\n        `DEBUG: Using custom headers for SSE transport to server \"${serverName}\"`\n      );\n    }\n\n    return new SSEClientTransport(new URL(url), options);\n  }\n\n  #createStdioTransport(\n    options: ResolvedStdioConnection\n  ): StdioClientTransport {\n    const { command, args, env, stderr, cwd } = options;\n    return new StdioClientTransport({\n      command,\n      args,\n      stderr,\n      cwd,\n      // oxlint-disable-next-line no-process-env\n      ...(env ? { env: { PATH: process.env.PATH!, ...env } } : {}),\n    });\n  }\n}\n\n/**\n * A utility function that serializes the headers object to a string\n * and orders the keys alphabetically so that the same headers object\n * will always produce the same string.\n * @param headers - The headers object to serialize\n * @returns The serialized headers object\n */\nfunction serializeHeaders(\n  headers?: Record<string, string>\n): string | undefined {\n  if (!headers) {\n    return;\n  }\n  return Object.entries(headers)\n    .sort(([a], [b]) => a.localeCompare(b))\n    .map(([key, value]) => `${key}: ${value}`)\n    .join(\"\\n\");\n}\n"],"mappings":"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"}