{"version":3,"sources":["../../src/client/client.ts"],"sourcesContent":["/**\n * Copyright 2025 Google LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\nimport type { StdioServerParameters } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport type { StreamableHTTPClientTransportOptions } from '@modelcontextprotocol/sdk/client/streamableHttp.js';\nimport { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {\n  ListRootsRequestSchema,\n  Root,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n  GenkitError,\n  type DynamicActionProviderAction,\n  type DynamicResourceAction,\n  type ExecutablePrompt,\n  type Genkit,\n  type MultipartToolAction,\n  type PromptGenerateOptions,\n  type ToolAction,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport {\n  fetchAllPrompts,\n  fetchDynamicTools,\n  getExecutablePrompt,\n  transportFrom,\n} from '../util/index.mjs';\nimport { fetchDynamicResources } from '../util/resource.mjs';\n\ninterface McpServerRef {\n  client: Client;\n  transport: Transport;\n  error?: string;\n}\n\nexport interface McpServerControls {\n  /** when true, the server will be stopped and its registered components will\n   * not appear in lists/plugins/etc */\n  disabled?: boolean;\n\n  // MCP roots configuration. See: https://modelcontextprotocol.io/docs/concepts/roots\n  roots?: Root[];\n}\n\nexport type McpStdioServerConfig = StdioServerParameters & {\n  url?: never;\n  transport?: never;\n};\n\nexport type McpStreamableHttpConfig = {\n  url: string;\n  command?: never;\n  transport?: never;\n} & Omit<StreamableHTTPClientTransportOptions, 'sessionId'>;\n\nexport type McpTransportServerConfig = {\n  transport: Transport;\n  command?: never;\n  url?: never;\n};\n\n/**\n * Configuration for an individual MCP server. The interface should be familiar\n * and compatible with existing tool configurations e.g. Cursor or Claude\n * Desktop.\n *\n * In addition to stdio servers, remote servers are supported via URL and\n * custom/arbitary transports are supported as well.\n */\nexport type McpServerConfig = (\n  | McpStdioServerConfig\n  | McpStreamableHttpConfig\n  | McpTransportServerConfig\n) &\n  McpServerControls;\n\n/**\n * Configuration options for an individual `GenkitMcpClient` instance.\n * This defines how the client connects to a single MCP server and how it behaves.\n */\nexport type McpClientOptions<M extends boolean = false> = {\n  /** Client name to advertise to the server. */\n  name: string;\n  /** Name for the server, defaults to the server's advertised name. */\n  serverName?: string;\n\n  /**\n   * An optional version number for this client. This is primarily for logging\n   * and identification purposes. Defaults to '1.0.0'.\n   */\n  version?: string;\n  /**\n   * If true, tool responses from the MCP server will be returned in their raw\n   * MCP format. Otherwise (default), they are processed and potentially\n   * simplified for better compatibility with Genkit's typical data structures.\n   */\n  rawToolResponses?: boolean;\n  /** If true, tools will be registered as multipart tool.v2 actions. */\n  multipart?: M;\n  /** The server configuration to connect. */\n  mcpServer: McpServerConfig;\n  /** Manually supply a session id for HTTP streaming clients if desired. */\n  sessionId?: string;\n};\n\nexport type McpClientOptionsWithCache<M extends boolean = false> =\n  McpClientOptions<M> & {\n    cacheTtlMillis?: number;\n  };\n\n/**\n * Represents a client connection to a single MCP (Model Context Protocol) server.\n * It handles the lifecycle of the connection (connect, disconnect, disable, re-enable, reconnect)\n * and provides methods to fetch tools from the connected server.\n *\n * An instance of `GenkitMcpClient` is typically managed by a `GenkitMcpHost`\n * when dealing with multiple MCP server connections.\n */\nexport class GenkitMcpClient<Multipart extends boolean = false> {\n  _server?: McpServerRef;\n  private _dynamicActionProvider: DynamicActionProviderAction | undefined;\n\n  sessionId?: string;\n  readonly name: string;\n  readonly suppliedServerName?: string;\n  private version: string;\n  private serverConfig: McpServerConfig;\n  private rawToolResponses?: boolean;\n  private multipart?: boolean;\n  private disabled: boolean;\n  private roots?: Root[];\n\n  private _readyListeners: {\n    resolve: () => void;\n    reject: (err: Error) => void;\n  }[] = [];\n  private _ready = false;\n\n  constructor(options: McpClientOptions<Multipart>) {\n    this.name = options.name;\n    this.suppliedServerName = options.serverName;\n    this.version = options.version || '1.0.0';\n    this.serverConfig = options.mcpServer;\n    this.rawToolResponses = !!options.rawToolResponses;\n    this.multipart = !!options.multipart;\n    this.disabled = !!options.mcpServer.disabled;\n    this.roots = options.mcpServer.roots;\n    this.sessionId = options.sessionId;\n\n    this._initializeConnection();\n  }\n\n  set dynamicActionProvider(dap: DynamicActionProviderAction) {\n    this._dynamicActionProvider = dap;\n  }\n\n  _invalidateDapCache(): void {\n    if (this._dynamicActionProvider) {\n      this._dynamicActionProvider.invalidateCache();\n    }\n  }\n\n  get serverName(): string {\n    return (\n      this.suppliedServerName ??\n      this._server?.client.getServerVersion()?.name ??\n      'unknown-server'\n    );\n  }\n\n  async updateRoots(roots: Root[]) {\n    this.roots = roots;\n    await this._server?.client.sendRootsListChanged();\n    this._invalidateDapCache();\n  }\n\n  /**\n   * Sets up a connection based on a provided map of server configurations.\n   * - Reconnects existing servers if their configuration appears to have\n   *   changed (implicitly handled by `connectServer`).\n   * - Sets the client's ready state once all connection attempts are complete.\n   * @param mcpServers A record mapping server names to their configurations.\n   */\n  private async _initializeConnection() {\n    this._ready = false;\n    try {\n      await this._connect();\n      this._ready = true;\n      while (this._readyListeners.length) {\n        this._readyListeners.pop()?.resolve();\n      }\n    } catch (err) {\n      while (this._readyListeners.length) {\n        this._readyListeners.pop()?.reject(err as Error);\n      }\n    }\n    if (this.roots) {\n      await this.updateRoots(this.roots);\n    }\n    this._invalidateDapCache();\n  }\n\n  /**\n   * Returns a Promise that resolves when the client has attempted to connect\n   * to all configured servers, or rejects if a critical error occurs during\n   * the initial connection phase.\n   */\n  async ready() {\n    if (this._ready) return;\n    return new Promise<void>((resolve, reject) => {\n      this._readyListeners.push({ resolve, reject });\n    });\n  }\n\n  /**\n   * Connects to a single MCP server defined by the provided configuration.\n   * @param config The configuration object for the server.\n   */\n  private async _connect() {\n    if (this._server) await this._server.transport.close();\n    this._invalidateDapCache();\n    logger.debug(\n      `[MCP Client] Connecting MCP server '${this.serverName}' in client '${this.name}'.`\n    );\n\n    const { transport, type: transportType } = await transportFrom(\n      this.serverConfig,\n      this.sessionId\n    );\n    if (!transport) {\n      throw new GenkitError({\n        status: 'INVALID_ARGUMENT',\n        message: `[MCP Client] Could not determine valid transport config from supplied options.`,\n      });\n    }\n\n    let error: string | undefined;\n\n    const client = new Client(\n      { name: this.name, version: this.version },\n      { capabilities: { roots: { listChanged: true } } }\n    );\n    client.setRequestHandler(ListRootsRequestSchema, () => {\n      logger.debug(`[MCP Client] fetching roots for ${this.name}`);\n      return { roots: this.roots || [] };\n    });\n\n    try {\n      await client.connect(transport);\n    } catch (e) {\n      logger.warn(\n        `[MCP Client] Error connecting server via ${transportType} transport: ${e}`\n      );\n      this.disabled = true;\n      error = (e as Error).toString();\n    }\n\n    this._server = {\n      client,\n      transport,\n      error,\n    } as McpServerRef;\n    this._invalidateDapCache();\n  }\n\n  /**\n   * Disconnects the MCP server and removes its registration\n   * from this client instance.\n   */\n  async _disconnect() {\n    if (this._server) {\n      logger.debug(\n        `[MCP Client] Disconnecting MCP server in client '${this.name}'.`\n      );\n      await this._server.client.close();\n      this._server = undefined;\n      this._invalidateDapCache();\n    }\n  }\n\n  /**\n   * Disables a server. Closes the underlying transport and server's configuration. Does nothing if the server is\n   * already disabled.\n   */\n  async disable() {\n    if (!this.isEnabled()) return;\n    if (this._server) {\n      logger.debug(\n        `[MCP Client] Disabling MCP server in client '${this.name}'`\n      );\n      await this._disconnect();\n      this.disabled = true;\n      this._invalidateDapCache();\n    }\n  }\n\n  /**\n   * Whether this client-server connection is enabled or not.\n   */\n  isEnabled() {\n    return !this.disabled;\n  }\n\n  /**\n   * Enables a server connection, including previously disabled ones. Does nothing if the\n   * server is not disabled.\n   */\n  async enable() {\n    if (this.isEnabled()) return;\n    logger.debug(`[MCP Client] Reenabling MCP server in client '${this.name}'`);\n    await this._initializeConnection();\n    this.disabled = !!this._server!.error;\n    this._invalidateDapCache();\n  }\n\n  /**\n   * Closes and then restarts the transport connection for the specified server.\n   * Useful for attempting to recover from connection issues without full\n   * reconfiguration.\n   */\n  async restart() {\n    if (this._server) {\n      logger.debug(\n        `[MCP Client] Restarting connection to MCP server in client '${this.name}'`\n      );\n      await this._disconnect();\n      await this._initializeConnection();\n      this._invalidateDapCache();\n    }\n  }\n\n  /**\n   * Fetches all tools available through this client, if the server\n   * configuration is not disabled.\n   */\n  async getActiveTools(\n    ai: Genkit\n  ): Promise<(Multipart extends true ? MultipartToolAction : ToolAction)[]> {\n    await this.ready();\n\n    if (this._server) {\n      const capabilities = this._server.client.getServerCapabilities();\n      if (capabilities?.tools) {\n        if (this.multipart) {\n          const tools = await fetchDynamicTools(ai, this._server.client, {\n            rawToolResponses: this.rawToolResponses,\n            multipart: true,\n            serverName: this.serverName,\n            name: this.name,\n          });\n          return tools as unknown as (Multipart extends true\n            ? MultipartToolAction\n            : ToolAction)[];\n        } else {\n          const tools = await fetchDynamicTools(ai, this._server.client, {\n            rawToolResponses: this.rawToolResponses,\n            multipart: false,\n            serverName: this.serverName,\n            name: this.name,\n          });\n          return tools as unknown as (Multipart extends true\n            ? MultipartToolAction\n            : ToolAction)[];\n        }\n      }\n    }\n\n    return [] as unknown as (Multipart extends true\n      ? MultipartToolAction\n      : ToolAction)[];\n  }\n\n  /**\n   * Fetches all resources available through this client, if the server\n   * configuration is not disabled.\n   */\n  async getActiveResources(ai: Genkit): Promise<DynamicResourceAction[]> {\n    await this.ready();\n    let resources: DynamicResourceAction[] = [];\n\n    if (this._server) {\n      const capabilities = this._server.client.getServerCapabilities();\n      if (capabilities?.resources)\n        resources.push(\n          ...(await fetchDynamicResources(ai, this._server.client, {\n            serverName: this.serverName,\n            name: this.name,\n          }))\n        );\n    }\n\n    return resources;\n  }\n\n  /**\n   * Fetches all active prompts available through this client, if the server\n   * configuration supports prompts.\n   * @param ai The Genkit instance.\n   * @param options Optional prompt generation options.\n   * @returns A promise that resolves to an array of ExecutablePrompt.\n   */\n  async getActivePrompts(\n    ai: Genkit,\n    options?: PromptGenerateOptions\n  ): Promise<ExecutablePrompt[]> {\n    if (this._server?.client.getServerCapabilities()?.prompts) {\n      return fetchAllPrompts(this._server.client, {\n        ai,\n        serverName: this.serverName,\n        name: this.name,\n        options,\n      });\n    }\n    return [];\n  }\n\n  /**\n   * Get the specified prompt as an `ExecutablePrompt` available through this\n   * client. If no such prompt is found, return undefined.\n   */\n  async getPrompt(\n    ai: Genkit,\n    promptName: string,\n    opts?: PromptGenerateOptions\n  ): Promise<ExecutablePrompt | undefined> {\n    await this.ready();\n\n    if (this._server) {\n      const capabilities = await this._server.client.getServerCapabilities();\n      if (capabilities?.prompts) {\n        return await getExecutablePrompt(this._server.client, {\n          ai,\n          serverName: this.name,\n          promptName,\n          name: this.name,\n          options: opts,\n        });\n      }\n      logger.debug(`[MCP Client] No prompts are found in this MCP server.`);\n    }\n    return;\n  }\n\n  /** Returns the underlying MCP SDK client if one has been initialized. */\n  get mcpClient(): Client | undefined {\n    return this._server?.client;\n  }\n}\n"],"mappings":"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","names":[]}