@genkit-ai/mcp 1.34.0 → 1.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client/client.js +1 -1
- package/lib/client/client.js.map +1 -1
- package/lib/client/client.mjs +2 -2
- package/lib/client/client.mjs.map +1 -1
- package/lib/client/host.mjs +1 -1
- package/lib/client/host.mjs.map +1 -1
- package/lib/client/index.mjs +2 -2
- package/lib/client/index.mjs.map +1 -1
- package/lib/index.mjs +3 -3
- package/lib/index.mjs.map +1 -1
- package/lib/server.mjs.map +1 -1
- package/lib/util/index.mjs +4 -4
- package/lib/util/index.mjs.map +1 -1
- package/lib/util/prompts.mjs +1 -1
- package/lib/util/prompts.mjs.map +1 -1
- package/lib/util/transport.mjs.map +1 -1
- package/package.json +2 -2
- package/src/client/client.ts +1 -1
package/lib/client/client.js
CHANGED
|
@@ -26,7 +26,7 @@ var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
|
26
26
|
var import_genkit = require("genkit");
|
|
27
27
|
var import_logging = require("genkit/logging");
|
|
28
28
|
var import_util = require("../util");
|
|
29
|
-
var import_resource = require("../util/resource");
|
|
29
|
+
var import_resource = require("../util/resource.js");
|
|
30
30
|
class GenkitMcpClient {
|
|
31
31
|
_server;
|
|
32
32
|
_dynamicActionProvider;
|
package/lib/client/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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';\nimport { fetchDynamicResources } from '../util/resource';\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":[]}
|
|
1
|
+
{"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';\nimport { fetchDynamicResources } from '../util/resource.js';\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":[]}
|
package/lib/client/client.mjs
CHANGED
|
@@ -11,8 +11,8 @@ import {
|
|
|
11
11
|
fetchDynamicTools,
|
|
12
12
|
getExecutablePrompt,
|
|
13
13
|
transportFrom
|
|
14
|
-
} from "../util";
|
|
15
|
-
import { fetchDynamicResources } from "../util/resource";
|
|
14
|
+
} from "../util/index.mjs";
|
|
15
|
+
import { fetchDynamicResources } from "../util/resource.mjs";
|
|
16
16
|
class GenkitMcpClient {
|
|
17
17
|
_server;
|
|
18
18
|
_dynamicActionProvider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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';\nimport { fetchDynamicResources } from '../util/resource';\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":[]}
|
|
1
|
+
{"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":"AAgBA,SAAS,cAAc;AAIvB;AAAA,EACE;AAAA,OAEK;AACP;AAAA,EACE;AAAA,OAQK;AACP,SAAS,cAAc;AACvB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,6BAA6B;AA2F/B,MAAM,gBAAmD;AAAA,EAC9D;AAAA,EACQ;AAAA,EAER;AAAA,EACS;AAAA,EACA;AAAA,EACD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,kBAGF,CAAC;AAAA,EACC,SAAS;AAAA,EAEjB,YAAY,SAAsC;AAChD,SAAK,OAAO,QAAQ;AACpB,SAAK,qBAAqB,QAAQ;AAClC,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,eAAe,QAAQ;AAC5B,SAAK,mBAAmB,CAAC,CAAC,QAAQ;AAClC,SAAK,YAAY,CAAC,CAAC,QAAQ;AAC3B,SAAK,WAAW,CAAC,CAAC,QAAQ,UAAU;AACpC,SAAK,QAAQ,QAAQ,UAAU;AAC/B,SAAK,YAAY,QAAQ;AAEzB,SAAK,sBAAsB;AAAA,EAC7B;AAAA,EAEA,IAAI,sBAAsB,KAAkC;AAC1D,SAAK,yBAAyB;AAAA,EAChC;AAAA,EAEA,sBAA4B;AAC1B,QAAI,KAAK,wBAAwB;AAC/B,WAAK,uBAAuB,gBAAgB;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,IAAI,aAAqB;AACvB,WACE,KAAK,sBACL,KAAK,SAAS,OAAO,iBAAiB,GAAG,QACzC;AAAA,EAEJ;AAAA,EAEA,MAAM,YAAY,OAAe;AAC/B,SAAK,QAAQ;AACb,UAAM,KAAK,SAAS,OAAO,qBAAqB;AAChD,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAc,wBAAwB;AACpC,SAAK,SAAS;AACd,QAAI;AACF,YAAM,KAAK,SAAS;AACpB,WAAK,SAAS;AACd,aAAO,KAAK,gBAAgB,QAAQ;AAClC,aAAK,gBAAgB,IAAI,GAAG,QAAQ;AAAA,MACtC;AAAA,IACF,SAAS,KAAK;AACZ,aAAO,KAAK,gBAAgB,QAAQ;AAClC,aAAK,gBAAgB,IAAI,GAAG,OAAO,GAAY;AAAA,MACjD;AAAA,IACF;AACA,QAAI,KAAK,OAAO;AACd,YAAM,KAAK,YAAY,KAAK,KAAK;AAAA,IACnC;AACA,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,QAAQ;AACZ,QAAI,KAAK,OAAQ;AACjB,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,WAAK,gBAAgB,KAAK,EAAE,SAAS,OAAO,CAAC;AAAA,IAC/C,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAc,WAAW;AACvB,QAAI,KAAK,QAAS,OAAM,KAAK,QAAQ,UAAU,MAAM;AACrD,SAAK,oBAAoB;AACzB,WAAO;AAAA,MACL,uCAAuC,KAAK,UAAU,gBAAgB,KAAK,IAAI;AAAA,IACjF;AAEA,UAAM,EAAE,WAAW,MAAM,cAAc,IAAI,MAAM;AAAA,MAC/C,KAAK;AAAA,MACL,KAAK;AAAA,IACP;AACA,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,YAAY;AAAA,QACpB,QAAQ;AAAA,QACR,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI;AAEJ,UAAM,SAAS,IAAI;AAAA,MACjB,EAAE,MAAM,KAAK,MAAM,SAAS,KAAK,QAAQ;AAAA,MACzC,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,KAAK,EAAE,EAAE;AAAA,IACnD;AACA,WAAO,kBAAkB,wBAAwB,MAAM;AACrD,aAAO,MAAM,mCAAmC,KAAK,IAAI,EAAE;AAC3D,aAAO,EAAE,OAAO,KAAK,SAAS,CAAC,EAAE;AAAA,IACnC,CAAC;AAED,QAAI;AACF,YAAM,OAAO,QAAQ,SAAS;AAAA,IAChC,SAAS,GAAG;AACV,aAAO;AAAA,QACL,4CAA4C,aAAa,eAAe,CAAC;AAAA,MAC3E;AACA,WAAK,WAAW;AAChB,cAAS,EAAY,SAAS;AAAA,IAChC;AAEA,SAAK,UAAU;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc;AAClB,QAAI,KAAK,SAAS;AAChB,aAAO;AAAA,QACL,oDAAoD,KAAK,IAAI;AAAA,MAC/D;AACA,YAAM,KAAK,QAAQ,OAAO,MAAM;AAChC,WAAK,UAAU;AACf,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU;AACd,QAAI,CAAC,KAAK,UAAU,EAAG;AACvB,QAAI,KAAK,SAAS;AAChB,aAAO;AAAA,QACL,gDAAgD,KAAK,IAAI;AAAA,MAC3D;AACA,YAAM,KAAK,YAAY;AACvB,WAAK,WAAW;AAChB,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY;AACV,WAAO,CAAC,KAAK;AAAA,EACf;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,SAAS;AACb,QAAI,KAAK,UAAU,EAAG;AACtB,WAAO,MAAM,iDAAiD,KAAK,IAAI,GAAG;AAC1E,UAAM,KAAK,sBAAsB;AACjC,SAAK,WAAW,CAAC,CAAC,KAAK,QAAS;AAChC,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAU;AACd,QAAI,KAAK,SAAS;AAChB,aAAO;AAAA,QACL,+DAA+D,KAAK,IAAI;AAAA,MAC1E;AACA,YAAM,KAAK,YAAY;AACvB,YAAM,KAAK,sBAAsB;AACjC,WAAK,oBAAoB;AAAA,IAC3B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,eACJ,IACwE;AACxE,UAAM,KAAK,MAAM;AAEjB,QAAI,KAAK,SAAS;AAChB,YAAM,eAAe,KAAK,QAAQ,OAAO,sBAAsB;AAC/D,UAAI,cAAc,OAAO;AACvB,YAAI,KAAK,WAAW;AAClB,gBAAM,QAAQ,MAAM,kBAAkB,IAAI,KAAK,QAAQ,QAAQ;AAAA,YAC7D,kBAAkB,KAAK;AAAA,YACvB,WAAW;AAAA,YACX,YAAY,KAAK;AAAA,YACjB,MAAM,KAAK;AAAA,UACb,CAAC;AACD,iBAAO;AAAA,QAGT,OAAO;AACL,gBAAM,QAAQ,MAAM,kBAAkB,IAAI,KAAK,QAAQ,QAAQ;AAAA,YAC7D,kBAAkB,KAAK;AAAA,YACvB,WAAW;AAAA,YACX,YAAY,KAAK;AAAA,YACjB,MAAM,KAAK;AAAA,UACb,CAAC;AACD,iBAAO;AAAA,QAGT;AAAA,MACF;AAAA,IACF;AAEA,WAAO,CAAC;AAAA,EAGV;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,mBAAmB,IAA8C;AACrE,UAAM,KAAK,MAAM;AACjB,QAAI,YAAqC,CAAC;AAE1C,QAAI,KAAK,SAAS;AAChB,YAAM,eAAe,KAAK,QAAQ,OAAO,sBAAsB;AAC/D,UAAI,cAAc;AAChB,kBAAU;AAAA,UACR,GAAI,MAAM,sBAAsB,IAAI,KAAK,QAAQ,QAAQ;AAAA,YACvD,YAAY,KAAK;AAAA,YACjB,MAAM,KAAK;AAAA,UACb,CAAC;AAAA,QACH;AAAA,IACJ;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,iBACJ,IACA,SAC6B;AAC7B,QAAI,KAAK,SAAS,OAAO,sBAAsB,GAAG,SAAS;AACzD,aAAO,gBAAgB,KAAK,QAAQ,QAAQ;AAAA,QAC1C;AAAA,QACA,YAAY,KAAK;AAAA,QACjB,MAAM,KAAK;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO,CAAC;AAAA,EACV;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UACJ,IACA,YACA,MACuC;AACvC,UAAM,KAAK,MAAM;AAEjB,QAAI,KAAK,SAAS;AAChB,YAAM,eAAe,MAAM,KAAK,QAAQ,OAAO,sBAAsB;AACrE,UAAI,cAAc,SAAS;AACzB,eAAO,MAAM,oBAAoB,KAAK,QAAQ,QAAQ;AAAA,UACpD;AAAA,UACA,YAAY,KAAK;AAAA,UACjB;AAAA,UACA,MAAM,KAAK;AAAA,UACX,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AACA,aAAO,MAAM,uDAAuD;AAAA,IACtE;AACA;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,YAAgC;AAClC,WAAO,KAAK,SAAS;AAAA,EACvB;AACF;","names":[]}
|
package/lib/client/host.mjs
CHANGED
package/lib/client/host.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/host.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 { Root } from '@modelcontextprotocol/sdk/types.js';\nimport {\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 { GenkitMcpClient, McpServerConfig } from './client.js';\n\nexport interface McpHostOptions<M extends boolean = false> {\n /**\n * An optional client name for this MCP host. This name is advertised to MCP Servers\n * as the connecting client name. Defaults to 'genkit-mcp'.\n */\n name?: string;\n /**\n * An optional version for this MCP host. Primarily for\n * logging and identification within Genkit.\n * Defaults to '1.0.0'.\n */\n version?: string;\n /**\n * A record for configuring multiple MCP servers. Each server connection is\n * controlled by a `GenkitMcpClient` instance managed by `GenkitMcpHost`.\n * The key in the record is used as the identifier for the MCP server.\n */\n mcpServers?: Record<string, McpServerConfig>;\n\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\n /** If true, tools will be registered as multipart tool.v2 actions. */\n multipart?: M;\n\n /**\n * When provided, each connected MCP server will be sent the roots specified here. Overridden by any specific roots sent in the `mcpServers` config for a given server.\n */\n roots?: Root[];\n}\n\nexport type McpHostOptionsWithCache<M extends boolean = false> = Omit<\n McpHostOptions<M>,\n 'name'\n> & {\n /**\n * A client name for this MCP host. This name is advertised to MCP Servers\n * as the connecting client name.\n */\n name: string;\n\n /**\n * Cache TTL. The dynamic action provider has a cache for the available actions\n * The default TTL is 3 seconds.\n * The cache will automatically be invalidated if any connections change.\n * Negative = no caching (expect noisy traces and slower resolution)\n * Zero or undefined = use the default 3000 millis (3 seconds)\n * Positive: The number of milliseconds to keep the cache.\n */\n cacheTTLMillis?: number;\n};\n\n/** Internal representation of client state for logging. */\ninterface ClientState {\n error?: {\n message: string;\n detail?: any;\n };\n}\n\n/**\n * Manages connections to multiple MCP (Model Context Protocol) servers.\n * Each server connection is individually configured and managed by an instance of `GenkitMcpClient`.\n * This host provides a centralized way to initialize, update, and interact with these clients.\n *\n * It allows for dynamic registration of tools from all connected and enabled MCP servers\n * into a Genkit instance.\n */\nexport class GenkitMcpHost<Multipart extends boolean = false> {\n name: string;\n private _clients: Record<string, GenkitMcpClient<Multipart>> = {};\n private _clientStates: Record<string, ClientState> = {};\n private _readyListeners: {\n resolve: () => void;\n reject: (err: Error) => void;\n }[] = [];\n private _ready = false;\n private _dynamicActionProvider: DynamicActionProviderAction | undefined;\n private roots: Root[] | undefined;\n rawToolResponses?: boolean;\n multipart?: Multipart;\n\n constructor(options: McpHostOptions<Multipart>) {\n this.name = options.name || 'genkit-mcp';\n this.rawToolResponses = options.rawToolResponses;\n this.multipart = options.multipart;\n this.roots = options.roots;\n\n if (options.mcpServers) {\n this.updateServers(options.mcpServers);\n } else {\n this._ready = true;\n }\n }\n\n set dynamicActionProvider(dap: DynamicActionProviderAction) {\n this._dynamicActionProvider = dap;\n }\n\n _invalidateCache(): void {\n if (this._dynamicActionProvider) {\n this._dynamicActionProvider.invalidateCache();\n }\n }\n\n /**\n * Returns a Promise that resolves when the host has attempted to connect\n * to all configured clients, 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 * If a server with the same name already exists, it will be disconnected first.\n * Stores the client and transport references internally. Handles connection errors\n * by marking the server as disabled.\n * @param serverName The name to assign to this server connection.\n * @param config The configuration object for the server.\n */\n async connect(serverName: string, config: McpServerConfig) {\n const existingEntry = this._clients[serverName];\n if (existingEntry) {\n try {\n await existingEntry._disconnect();\n } catch (e) {\n existingEntry.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error disconnecting from existing connection for ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n }\n\n logger.debug(\n `[MCP Host] Connecting to MCP server '${serverName}' in host '${this.name}'.`\n );\n try {\n const client = new GenkitMcpClient<Multipart>({\n name: this.name,\n serverName: serverName,\n mcpServer: { ...config, roots: config.roots || this.roots },\n rawToolResponses: this.rawToolResponses,\n multipart: this.multipart,\n });\n this._clients[serverName] = client;\n } catch (e) {\n this.setError(serverName, {\n message: `[MCP Host] Error connecting to ${serverName} with config ${config}`,\n detail: `Details: ${e}`,\n });\n }\n this._invalidateCache();\n }\n\n /**\n * Disconnects the specified MCP server and removes its registration\n * from this client instance.\n * @param serverName The name of the server to disconnect.\n */\n async disconnect(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Disconnecting MCP server '${serverName}' in host '${this.name}'.`\n );\n try {\n await client._disconnect();\n } catch (e) {\n client.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error disconnecting from existing connection for ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n delete this._clients[serverName];\n this._invalidateCache();\n }\n\n /**\n * Temporarily disables a server connection. Closes the underlying transport\n * but retains the server's configuration. Does nothing if the server is\n * already disabled.\n * @param serverName The name of the server to disable.\n */\n async disable(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n if (!client.isEnabled()) {\n logger.warn(`[MCP Host] server ${serverName} already disabled`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Disabling MCP server '${serverName}' in host '${this.name}'`\n );\n await client.disable();\n this._invalidateCache();\n }\n\n /**\n * Enables a server connection, including previously disabled ones. Attempts to reconnect\n * using the stored transport. Does nothing if the server is not disabled.\n * @param serverName The name of the server to re-enable.\n */\n async enable(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Reenabling MCP server '${serverName}' in host '${this.name}'`\n );\n try {\n await client.enable();\n } catch (e) {\n client.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error reenabling server ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n this._invalidateCache();\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 * @param serverName The name of the server to reconnect.\n */\n async reconnect(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Restarting connection to MCP server '${serverName}' in host '${this.name}'`\n );\n try {\n await client.restart();\n } catch (e) {\n client.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error restarting to server ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n this._invalidateCache();\n }\n\n /**\n * Updates the connections based on a provided map of server configurations.\n * - Connects any new servers defined in `mcpServers`.\n * - Disconnects any servers currently connected but not present in `mcpServers`.\n * - Reconnects existing servers if their configuration appears to have 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 updateServers(mcpServers: Record<string, McpServerConfig>) {\n this._ready = false;\n const newServerNames = new Set(Object.keys(mcpServers));\n const currentServerNames = new Set(Object.keys(this._clients));\n\n const promises: Promise<void>[] = [];\n for (const serverName in mcpServers) {\n promises.push(this.connect(serverName, mcpServers[serverName]));\n }\n\n // Disconnect servers that are no longer in the config\n for (const serverName of currentServerNames) {\n if (!newServerNames.has(serverName)) {\n this.disconnect(serverName);\n }\n }\n\n Promise.all(promises)\n .then(() => {\n this._ready = true;\n while (this._readyListeners.length) {\n this._readyListeners.pop()?.resolve();\n }\n })\n .catch((err) => {\n while (this._readyListeners.length) {\n this._readyListeners.pop()?.reject(err);\n }\n });\n\n this._invalidateCache();\n }\n\n /**\n * Retrieves all tools from all connected and enabled MCP clients managed by\n * this instance. This method waits for the host to be ready (all initial\n * connection attempts made) before fetching tools.\n *\n * It iterates through each managed `GenkitMcpClient`, and if the client is\n * not disabled, it calls the client's `getTools` method to fetch its\n * available tools. These are then aggregated into a single array.\n *\n * This is useful for dynamically providing a list of all available MCP tools\n * to Genkit, for example, when setting up a Genkit plugin.\n *\n * ```ts\n * const mcpHost = createMcpHost({ ... });\n * // In your Genkit configuration:\n * // const allMcpTools = await McpHost.getActiveTools(ai);\n * // Then, these tools can be used or registered with Genkit.\n * ```\n *\n * @param ai The Genkit instance, used by individual clients to define dynamic\n * tools.\n * @returns A Promise that resolves to an array of `ToolAction` from all\n * active MCP clients.\n */\n async getActiveTools(\n ai: Genkit\n ): Promise<(Multipart extends true ? MultipartToolAction : ToolAction)[]> {\n await this.ready();\n let allTools: (Multipart extends true\n ? MultipartToolAction\n : ToolAction)[] = [];\n\n for (const serverName in this._clients) {\n const client = this._clients[serverName];\n if (client.isEnabled() && !this.hasError(serverName)) {\n try {\n const tools = await client.getActiveTools(ai);\n allTools.push(...tools);\n } catch (e) {\n logger.error(\n `Error fetching active tools from client ${serverName}.`,\n JSON.stringify(e)\n );\n }\n }\n }\n return allTools;\n }\n\n /**\n * Retrieves all resources from all connected and enabled MCP clients managed by\n * this instance. This method waits for the host to be ready (all initial\n * connection attempts made) before fetching resources.\n *\n * It iterates through each managed `GenkitMcpClient`, and if the client is\n * not disabled, it calls the client's `getActiveResources` method to fetch its\n * available resources. These are then aggregated into a single array.\n *\n * This is useful for dynamically providing a list of all available MCP resources\n * to Genkit, for example, when setting up a Genkit plugin.\n *\n * @param ai The Genkit instance, used by individual clients to define dynamic\n * resources.\n * @returns A Promise that resolves to an array of `DynamicResourceAction` from all\n * active MCP clients.\n */\n async getActiveResources(ai: Genkit): Promise<DynamicResourceAction[]> {\n await this.ready();\n let allResources: DynamicResourceAction[] = [];\n\n for (const serverName in this._clients) {\n const client = this._clients[serverName];\n if (client.isEnabled() && !this.hasError(serverName)) {\n try {\n const resources = await client.getActiveResources(ai);\n allResources.push(...resources);\n } catch (e) {\n logger.error(\n `Error fetching active resources from client ${serverName}.`,\n JSON.stringify(e)\n );\n }\n }\n }\n return allResources;\n }\n\n /**\n * Retrieves all prompts from all connected and enabled MCP clients managed by\n * this instance. This method waits for the host to be ready (all initial\n * connection attempts made) before fetching prompts.\n *\n * It iterates through each managed `GenkitMcpClient`, and if the client is\n * not disabled, it calls the client's `getActivePrompts` method to fetch its\n * available prompts. These are then aggregated into a single array.\n *\n * This is useful for dynamically providing a list of all available MCP prompts\n * to Genkit, for example, when setting up a Genkit plugin.\n *\n * @param ai The Genkit instance, used by individual clients to define dynamic\n * prompts.\n * @returns A Promise that resolves to an array of `ExecutablePrompt` from all\n * active MCP clients.\n */\n async getActivePrompts(ai: Genkit): Promise<ExecutablePrompt[]> {\n await this.ready();\n let allPrompts: ExecutablePrompt[] = [];\n\n for (const serverName in this._clients) {\n const client = this._clients[serverName];\n if (client.isEnabled() && !this.hasError(serverName)) {\n allPrompts.push(...(await client.getActivePrompts(ai)));\n }\n }\n return allPrompts;\n }\n\n /**\n * Get the specified prompt as an `ExecutablePrompt` available through the\n * specified server. If no such prompt is found, return undefined.\n */\n async getPrompt(\n ai: Genkit,\n serverName: string,\n promptName: string,\n opts?: PromptGenerateOptions\n ): Promise<ExecutablePrompt<any> | undefined> {\n await this.ready();\n const client = this._clients[serverName];\n if (!client) {\n logger.error(`No client found with name '${serverName}'.`);\n return;\n }\n if (this.hasError(serverName)) {\n const errorStringified = JSON.stringify(\n this._clientStates[serverName].error\n );\n logger.error(\n `Client '${serverName}' is in an error state. ${errorStringified}`\n );\n }\n if (client.isEnabled()) {\n const prompt = await client.getPrompt(ai, promptName, opts);\n if (!prompt) {\n logger.error(\n `[MCP Host] Unable to fetch the specified ${promptName} in server ${serverName}.`\n );\n return;\n }\n return prompt;\n }\n return;\n }\n\n async close() {\n for (const client of Object.values(this._clients)) {\n await client._disconnect();\n }\n this._invalidateCache();\n }\n\n /** Helper method to track and log client errors. */\n private setError(\n serverName: string,\n error: {\n message: string;\n detail?: any;\n }\n ) {\n this._clientStates[serverName] = { error };\n logger.warn(\n `An error has occured while managing your MCP client '${serverName}'. The client may be disabled to avoid further issues. Please resolve the issue and reenable the client '${serverName}' to continue using its resources.`\n );\n logger.warn(error);\n }\n\n private hasError(serverName: string) {\n return (\n this._clientStates[serverName] && !!this._clientStates[serverName].error\n );\n }\n\n /**\n * Returns an array of all active clients.\n */\n get activeClients(): GenkitMcpClient<Multipart>[] {\n return Object.values(this._clients).filter((c) => c.isEnabled());\n }\n\n /**\n * Returns the client by name.\n */\n getClient(name: string) {\n return this._clients[name];\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/client/host.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 { Root } from '@modelcontextprotocol/sdk/types.js';\nimport {\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 { GenkitMcpClient, McpServerConfig } from './client.mjs';\n\nexport interface McpHostOptions<M extends boolean = false> {\n /**\n * An optional client name for this MCP host. This name is advertised to MCP Servers\n * as the connecting client name. Defaults to 'genkit-mcp'.\n */\n name?: string;\n /**\n * An optional version for this MCP host. Primarily for\n * logging and identification within Genkit.\n * Defaults to '1.0.0'.\n */\n version?: string;\n /**\n * A record for configuring multiple MCP servers. Each server connection is\n * controlled by a `GenkitMcpClient` instance managed by `GenkitMcpHost`.\n * The key in the record is used as the identifier for the MCP server.\n */\n mcpServers?: Record<string, McpServerConfig>;\n\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\n /** If true, tools will be registered as multipart tool.v2 actions. */\n multipart?: M;\n\n /**\n * When provided, each connected MCP server will be sent the roots specified here. Overridden by any specific roots sent in the `mcpServers` config for a given server.\n */\n roots?: Root[];\n}\n\nexport type McpHostOptionsWithCache<M extends boolean = false> = Omit<\n McpHostOptions<M>,\n 'name'\n> & {\n /**\n * A client name for this MCP host. This name is advertised to MCP Servers\n * as the connecting client name.\n */\n name: string;\n\n /**\n * Cache TTL. The dynamic action provider has a cache for the available actions\n * The default TTL is 3 seconds.\n * The cache will automatically be invalidated if any connections change.\n * Negative = no caching (expect noisy traces and slower resolution)\n * Zero or undefined = use the default 3000 millis (3 seconds)\n * Positive: The number of milliseconds to keep the cache.\n */\n cacheTTLMillis?: number;\n};\n\n/** Internal representation of client state for logging. */\ninterface ClientState {\n error?: {\n message: string;\n detail?: any;\n };\n}\n\n/**\n * Manages connections to multiple MCP (Model Context Protocol) servers.\n * Each server connection is individually configured and managed by an instance of `GenkitMcpClient`.\n * This host provides a centralized way to initialize, update, and interact with these clients.\n *\n * It allows for dynamic registration of tools from all connected and enabled MCP servers\n * into a Genkit instance.\n */\nexport class GenkitMcpHost<Multipart extends boolean = false> {\n name: string;\n private _clients: Record<string, GenkitMcpClient<Multipart>> = {};\n private _clientStates: Record<string, ClientState> = {};\n private _readyListeners: {\n resolve: () => void;\n reject: (err: Error) => void;\n }[] = [];\n private _ready = false;\n private _dynamicActionProvider: DynamicActionProviderAction | undefined;\n private roots: Root[] | undefined;\n rawToolResponses?: boolean;\n multipart?: Multipart;\n\n constructor(options: McpHostOptions<Multipart>) {\n this.name = options.name || 'genkit-mcp';\n this.rawToolResponses = options.rawToolResponses;\n this.multipart = options.multipart;\n this.roots = options.roots;\n\n if (options.mcpServers) {\n this.updateServers(options.mcpServers);\n } else {\n this._ready = true;\n }\n }\n\n set dynamicActionProvider(dap: DynamicActionProviderAction) {\n this._dynamicActionProvider = dap;\n }\n\n _invalidateCache(): void {\n if (this._dynamicActionProvider) {\n this._dynamicActionProvider.invalidateCache();\n }\n }\n\n /**\n * Returns a Promise that resolves when the host has attempted to connect\n * to all configured clients, 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 * If a server with the same name already exists, it will be disconnected first.\n * Stores the client and transport references internally. Handles connection errors\n * by marking the server as disabled.\n * @param serverName The name to assign to this server connection.\n * @param config The configuration object for the server.\n */\n async connect(serverName: string, config: McpServerConfig) {\n const existingEntry = this._clients[serverName];\n if (existingEntry) {\n try {\n await existingEntry._disconnect();\n } catch (e) {\n existingEntry.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error disconnecting from existing connection for ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n }\n\n logger.debug(\n `[MCP Host] Connecting to MCP server '${serverName}' in host '${this.name}'.`\n );\n try {\n const client = new GenkitMcpClient<Multipart>({\n name: this.name,\n serverName: serverName,\n mcpServer: { ...config, roots: config.roots || this.roots },\n rawToolResponses: this.rawToolResponses,\n multipart: this.multipart,\n });\n this._clients[serverName] = client;\n } catch (e) {\n this.setError(serverName, {\n message: `[MCP Host] Error connecting to ${serverName} with config ${config}`,\n detail: `Details: ${e}`,\n });\n }\n this._invalidateCache();\n }\n\n /**\n * Disconnects the specified MCP server and removes its registration\n * from this client instance.\n * @param serverName The name of the server to disconnect.\n */\n async disconnect(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Disconnecting MCP server '${serverName}' in host '${this.name}'.`\n );\n try {\n await client._disconnect();\n } catch (e) {\n client.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error disconnecting from existing connection for ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n delete this._clients[serverName];\n this._invalidateCache();\n }\n\n /**\n * Temporarily disables a server connection. Closes the underlying transport\n * but retains the server's configuration. Does nothing if the server is\n * already disabled.\n * @param serverName The name of the server to disable.\n */\n async disable(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n if (!client.isEnabled()) {\n logger.warn(`[MCP Host] server ${serverName} already disabled`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Disabling MCP server '${serverName}' in host '${this.name}'`\n );\n await client.disable();\n this._invalidateCache();\n }\n\n /**\n * Enables a server connection, including previously disabled ones. Attempts to reconnect\n * using the stored transport. Does nothing if the server is not disabled.\n * @param serverName The name of the server to re-enable.\n */\n async enable(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Reenabling MCP server '${serverName}' in host '${this.name}'`\n );\n try {\n await client.enable();\n } catch (e) {\n client.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error reenabling server ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n this._invalidateCache();\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 * @param serverName The name of the server to reconnect.\n */\n async reconnect(serverName: string) {\n const client = this._clients[serverName];\n if (!client) {\n logger.warn(`[MCP Host] unable to find server ${serverName}`);\n return;\n }\n\n logger.debug(\n `[MCP Host] Restarting connection to MCP server '${serverName}' in host '${this.name}'`\n );\n try {\n await client.restart();\n } catch (e) {\n client.disable();\n this.setError(serverName, {\n message: `[MCP Host] Error restarting to server ${serverName}`,\n detail: `Details: ${e}`,\n });\n }\n this._invalidateCache();\n }\n\n /**\n * Updates the connections based on a provided map of server configurations.\n * - Connects any new servers defined in `mcpServers`.\n * - Disconnects any servers currently connected but not present in `mcpServers`.\n * - Reconnects existing servers if their configuration appears to have 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 updateServers(mcpServers: Record<string, McpServerConfig>) {\n this._ready = false;\n const newServerNames = new Set(Object.keys(mcpServers));\n const currentServerNames = new Set(Object.keys(this._clients));\n\n const promises: Promise<void>[] = [];\n for (const serverName in mcpServers) {\n promises.push(this.connect(serverName, mcpServers[serverName]));\n }\n\n // Disconnect servers that are no longer in the config\n for (const serverName of currentServerNames) {\n if (!newServerNames.has(serverName)) {\n this.disconnect(serverName);\n }\n }\n\n Promise.all(promises)\n .then(() => {\n this._ready = true;\n while (this._readyListeners.length) {\n this._readyListeners.pop()?.resolve();\n }\n })\n .catch((err) => {\n while (this._readyListeners.length) {\n this._readyListeners.pop()?.reject(err);\n }\n });\n\n this._invalidateCache();\n }\n\n /**\n * Retrieves all tools from all connected and enabled MCP clients managed by\n * this instance. This method waits for the host to be ready (all initial\n * connection attempts made) before fetching tools.\n *\n * It iterates through each managed `GenkitMcpClient`, and if the client is\n * not disabled, it calls the client's `getTools` method to fetch its\n * available tools. These are then aggregated into a single array.\n *\n * This is useful for dynamically providing a list of all available MCP tools\n * to Genkit, for example, when setting up a Genkit plugin.\n *\n * ```ts\n * const mcpHost = createMcpHost({ ... });\n * // In your Genkit configuration:\n * // const allMcpTools = await McpHost.getActiveTools(ai);\n * // Then, these tools can be used or registered with Genkit.\n * ```\n *\n * @param ai The Genkit instance, used by individual clients to define dynamic\n * tools.\n * @returns A Promise that resolves to an array of `ToolAction` from all\n * active MCP clients.\n */\n async getActiveTools(\n ai: Genkit\n ): Promise<(Multipart extends true ? MultipartToolAction : ToolAction)[]> {\n await this.ready();\n let allTools: (Multipart extends true\n ? MultipartToolAction\n : ToolAction)[] = [];\n\n for (const serverName in this._clients) {\n const client = this._clients[serverName];\n if (client.isEnabled() && !this.hasError(serverName)) {\n try {\n const tools = await client.getActiveTools(ai);\n allTools.push(...tools);\n } catch (e) {\n logger.error(\n `Error fetching active tools from client ${serverName}.`,\n JSON.stringify(e)\n );\n }\n }\n }\n return allTools;\n }\n\n /**\n * Retrieves all resources from all connected and enabled MCP clients managed by\n * this instance. This method waits for the host to be ready (all initial\n * connection attempts made) before fetching resources.\n *\n * It iterates through each managed `GenkitMcpClient`, and if the client is\n * not disabled, it calls the client's `getActiveResources` method to fetch its\n * available resources. These are then aggregated into a single array.\n *\n * This is useful for dynamically providing a list of all available MCP resources\n * to Genkit, for example, when setting up a Genkit plugin.\n *\n * @param ai The Genkit instance, used by individual clients to define dynamic\n * resources.\n * @returns A Promise that resolves to an array of `DynamicResourceAction` from all\n * active MCP clients.\n */\n async getActiveResources(ai: Genkit): Promise<DynamicResourceAction[]> {\n await this.ready();\n let allResources: DynamicResourceAction[] = [];\n\n for (const serverName in this._clients) {\n const client = this._clients[serverName];\n if (client.isEnabled() && !this.hasError(serverName)) {\n try {\n const resources = await client.getActiveResources(ai);\n allResources.push(...resources);\n } catch (e) {\n logger.error(\n `Error fetching active resources from client ${serverName}.`,\n JSON.stringify(e)\n );\n }\n }\n }\n return allResources;\n }\n\n /**\n * Retrieves all prompts from all connected and enabled MCP clients managed by\n * this instance. This method waits for the host to be ready (all initial\n * connection attempts made) before fetching prompts.\n *\n * It iterates through each managed `GenkitMcpClient`, and if the client is\n * not disabled, it calls the client's `getActivePrompts` method to fetch its\n * available prompts. These are then aggregated into a single array.\n *\n * This is useful for dynamically providing a list of all available MCP prompts\n * to Genkit, for example, when setting up a Genkit plugin.\n *\n * @param ai The Genkit instance, used by individual clients to define dynamic\n * prompts.\n * @returns A Promise that resolves to an array of `ExecutablePrompt` from all\n * active MCP clients.\n */\n async getActivePrompts(ai: Genkit): Promise<ExecutablePrompt[]> {\n await this.ready();\n let allPrompts: ExecutablePrompt[] = [];\n\n for (const serverName in this._clients) {\n const client = this._clients[serverName];\n if (client.isEnabled() && !this.hasError(serverName)) {\n allPrompts.push(...(await client.getActivePrompts(ai)));\n }\n }\n return allPrompts;\n }\n\n /**\n * Get the specified prompt as an `ExecutablePrompt` available through the\n * specified server. If no such prompt is found, return undefined.\n */\n async getPrompt(\n ai: Genkit,\n serverName: string,\n promptName: string,\n opts?: PromptGenerateOptions\n ): Promise<ExecutablePrompt<any> | undefined> {\n await this.ready();\n const client = this._clients[serverName];\n if (!client) {\n logger.error(`No client found with name '${serverName}'.`);\n return;\n }\n if (this.hasError(serverName)) {\n const errorStringified = JSON.stringify(\n this._clientStates[serverName].error\n );\n logger.error(\n `Client '${serverName}' is in an error state. ${errorStringified}`\n );\n }\n if (client.isEnabled()) {\n const prompt = await client.getPrompt(ai, promptName, opts);\n if (!prompt) {\n logger.error(\n `[MCP Host] Unable to fetch the specified ${promptName} in server ${serverName}.`\n );\n return;\n }\n return prompt;\n }\n return;\n }\n\n async close() {\n for (const client of Object.values(this._clients)) {\n await client._disconnect();\n }\n this._invalidateCache();\n }\n\n /** Helper method to track and log client errors. */\n private setError(\n serverName: string,\n error: {\n message: string;\n detail?: any;\n }\n ) {\n this._clientStates[serverName] = { error };\n logger.warn(\n `An error has occured while managing your MCP client '${serverName}'. The client may be disabled to avoid further issues. Please resolve the issue and reenable the client '${serverName}' to continue using its resources.`\n );\n logger.warn(error);\n }\n\n private hasError(serverName: string) {\n return (\n this._clientStates[serverName] && !!this._clientStates[serverName].error\n );\n }\n\n /**\n * Returns an array of all active clients.\n */\n get activeClients(): GenkitMcpClient<Multipart>[] {\n return Object.values(this._clients).filter((c) => c.isEnabled());\n }\n\n /**\n * Returns the client by name.\n */\n getClient(name: string) {\n return this._clients[name];\n }\n}\n"],"mappings":"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","names":[]}
|
package/lib/client/index.mjs
CHANGED
package/lib/client/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/client/index.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 { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { StdioServerParameters } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport { GenkitMcpClient, McpClientOptions } from './client.
|
|
1
|
+
{"version":3,"sources":["../../src/client/index.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 { SSEClientTransportOptions } from '@modelcontextprotocol/sdk/client/sse.js';\nimport { StdioServerParameters } from '@modelcontextprotocol/sdk/client/stdio.js';\nimport { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport { GenkitMcpClient, McpClientOptions } from './client.mjs';\nimport {\n GenkitMcpHost,\n McpHostOptions,\n McpHostOptionsWithCache,\n} from './host.mjs';\nexport { GenkitMcpClient, GenkitMcpHost };\nexport type {\n McpClientOptions,\n McpHostOptions,\n McpHostOptionsWithCache,\n SSEClientTransportOptions,\n StdioServerParameters,\n Transport,\n};\n"],"mappings":"AAmBA,SAAS,uBAAyC;AAClD;AAAA,EACE;AAAA,OAGK;","names":[]}
|
package/lib/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
GenkitMcpClient
|
|
3
|
-
} from "./client/client.
|
|
3
|
+
} from "./client/client.mjs";
|
|
4
4
|
import {
|
|
5
5
|
GenkitMcpHost
|
|
6
|
-
} from "./client/index.
|
|
7
|
-
import { GenkitMcpServer } from "./server.
|
|
6
|
+
} from "./client/index.mjs";
|
|
7
|
+
import { GenkitMcpServer } from "./server.mjs";
|
|
8
8
|
function createMcpHost(options) {
|
|
9
9
|
return new GenkitMcpHost(options);
|
|
10
10
|
}
|
package/lib/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Copyright 2024 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 type { Genkit } from 'genkit';\nimport {\n GenkitMcpClient,\n McpClientOptions,\n McpClientOptionsWithCache,\n McpServerConfig,\n McpStdioServerConfig,\n} from './client/client.
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * Copyright 2024 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 type { Genkit } from 'genkit';\nimport {\n GenkitMcpClient,\n McpClientOptions,\n McpClientOptionsWithCache,\n McpServerConfig,\n McpStdioServerConfig,\n} from './client/client.mjs';\nimport {\n GenkitMcpHost,\n McpHostOptions,\n McpHostOptionsWithCache,\n} from './client/index.mjs';\nimport { GenkitMcpServer } from './server.mjs';\nexport {\n GenkitMcpClient,\n GenkitMcpHost,\n type McpClientOptions,\n type McpClientOptionsWithCache,\n type McpHostOptions,\n type McpHostOptionsWithCache,\n type McpServerConfig,\n type McpStdioServerConfig,\n};\n\nexport interface McpServerOptions {\n /** The name you want to give your server for MCP inspection. */\n name: string;\n /** The version you want the server to advertise to clients. Defaults to\n * 1.0.0. */\n version?: string;\n}\n\n/**\n * Creates an MCP Client Host that connects to one or more MCP servers.\n * Each server is defined in the `mcpClients` option, where the key is a\n * client-side name for the server and the value is the server's configuration.\n *\n * By default, all servers in the config will be attempted to connect unless\n * their configuration includes `{disabled: true}`.\n *\n * ```ts\n * const clientHost = createMcpHost({\n * name: \"my-mcp-client-host\", // Name for the host itself\n * mcpServers: {\n * // Each key is a name for this client/server configuration\n * // Each value is an McpServerConfig object\n * gitToolServer: { command: \"uvx\", args: [\"mcp-server-git\"] },\n * customApiServer: { url: \"http://localhost:1234/mcp\" }\n * }\n * });\n * ```\n *\n * @param options Configuration for the MCP Client Host, including the definitions of MCP servers to connect to.\n * @returns A new instance of GenkitMcpHost.\n */\nexport function createMcpHost<M extends boolean = false>(\n options: McpHostOptions<M>\n) {\n return new GenkitMcpHost<M>(options);\n}\n\n/**\n * Creates an MCP Client Host that connects to one or more MCP servers.\n * Each server is defined in the `mcpClients` option, where the key is a\n * client-side name for the server and the value is the server's configuration.\n *\n * By default, all servers in the config will be attempted to connect unless\n * their configuration includes `{disabled: true}`.\n *\n * ```ts\n * const clientHost = defineMcpHost(ai, {\n * name: \"my-mcp-client-host\", // Name for the host itself\n * mcpServers: {\n * // Each key is a name for this client/server configuration\n * // Each value is an McpServerConfig object\n * gitToolServer: { command: \"uvx\", args: [\"mcp-server-git\"] },\n * customApiServer: { url: \"http://localhost:1234/mcp\" }\n * }\n * });\n * ```\n *\n * @param options Configuration for the MCP Client Host, including the definitions of MCP servers to connect to.\n * @returns A new instance of GenkitMcpHost.\n */\nexport function defineMcpHost<M extends boolean = false>(\n ai: Genkit,\n options: McpHostOptionsWithCache<M>\n) {\n const mcpHost = new GenkitMcpHost<M>(options);\n const dap = ai.defineDynamicActionProvider(\n {\n name: options.name,\n cacheConfig: {\n ttlMillis: options.cacheTTLMillis,\n },\n },\n async () => ({\n tool: await mcpHost.getActiveTools(ai),\n resource: await mcpHost.getActiveResources(ai),\n })\n );\n mcpHost.dynamicActionProvider = dap;\n return mcpHost;\n}\n\n/**\n * Creates an MCP Client that connects to a single MCP server.\n * This is useful when you only need to interact with one MCP server,\n * or if you want to manage client instances individually.\n *\n * ```ts\n * const client = createMcpClient({\n * name: \"mySingleMcpClient\", // A name for this client instance\n * command: \"npx\", // Example: Launching a local server\n * args: [\"-y\", \"@modelcontextprotocol/server-everything\", \"/path/to/allowed/dir\"],\n * });\n *\n * // To get tools from this client:\n * // const tools = await client.getActiveTools(ai);\n * ```\n *\n * @param options Configuration for the MCP Client, defining how it connects\n * to the MCP server and its behavior.\n * @returns A new instance of GenkitMcpClient.\n */\nexport function createMcpClient<M extends boolean = false>(\n options: McpClientOptions<M>\n) {\n return new GenkitMcpClient<M>(options);\n}\n\n/**\n * Defines an MCP Client that connects to a single MCP server.\n * This is useful when you only need to interact with one MCP server,\n * or if you want to manage client instances individually.\n *\n * ```ts\n * const client = defineMcpClient(ai, {\n * name: \"mySingleMcpClient\", // A name for this client instance\n * command: \"npx\", // Example: Launching a local server\n * args: [\"-y\", \"@modelcontextprotocol/server-everything\", \"/path/to/allowed/dir\"],\n * });\n *\n * // To get tools from this client:\n * // const tools = await client.getActiveTools(ai);\n *\n * // Or in a generate call you can use:\n * ai.generate({\n prompt: `<a prompt requiring tools>`,\n tools: ['mySingleMcpClient:tool/*'],\n });\n * ```\n *\n * @param options Configuration for the MCP Client, defining how it connects\n * to the MCP server and its behavior.\n * @returns A new instance of GenkitMcpClient.\n */\nexport function defineMcpClient<M extends boolean = false>(\n ai: Genkit,\n options: McpClientOptionsWithCache<M>\n) {\n const mcpClient = new GenkitMcpClient<M>(options);\n const dap = ai.defineDynamicActionProvider(\n {\n name: options.name,\n cacheConfig: {\n ttlMillis: options.cacheTtlMillis,\n },\n },\n async () => {\n return {\n tool: await mcpClient.getActiveTools(ai),\n resource: await mcpClient.getActiveResources(ai),\n };\n }\n );\n mcpClient.dynamicActionProvider = dap;\n return mcpClient;\n}\n\n/**\n * Creates an MCP server based on the supplied Genkit instance. All tools and prompts\n * will be automatically converted to MCP compatibility.\n *\n * ```ts\n * const mcpServer = createMcpServer(ai, {name: 'my-mcp-server', version: '0.1.0'});\n *\n * await mcpServer.start(); // starts a stdio transport, OR\n * await mcpServer.start(customMcpTransport); // starts server using supplied transport\n * ```\n *\n * @param ai Your Genkit instance with registered tools and prompts.\n * @param options Configuration metadata for the server.\n * @returns GenkitMcpServer instance.\n */\nexport function createMcpServer(\n ai: Genkit,\n options: McpServerOptions\n): GenkitMcpServer {\n return new GenkitMcpServer(ai, options);\n}\n"],"mappings":"AAiBA;AAAA,EACE;AAAA,OAKK;AACP;AAAA,EACE;AAAA,OAGK;AACP,SAAS,uBAAuB;AA2CzB,SAAS,cACd,SACA;AACA,SAAO,IAAI,cAAiB,OAAO;AACrC;AAyBO,SAAS,cACd,IACA,SACA;AACA,QAAM,UAAU,IAAI,cAAiB,OAAO;AAC5C,QAAM,MAAM,GAAG;AAAA,IACb;AAAA,MACE,MAAM,QAAQ;AAAA,MACd,aAAa;AAAA,QACX,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAAA,IACA,aAAa;AAAA,MACX,MAAM,MAAM,QAAQ,eAAe,EAAE;AAAA,MACrC,UAAU,MAAM,QAAQ,mBAAmB,EAAE;AAAA,IAC/C;AAAA,EACF;AACA,UAAQ,wBAAwB;AAChC,SAAO;AACT;AAsBO,SAAS,gBACd,SACA;AACA,SAAO,IAAI,gBAAmB,OAAO;AACvC;AA4BO,SAAS,gBACd,IACA,SACA;AACA,QAAM,YAAY,IAAI,gBAAmB,OAAO;AAChD,QAAM,MAAM,GAAG;AAAA,IACb;AAAA,MACE,MAAM,QAAQ;AAAA,MACd,aAAa;AAAA,QACX,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AAAA,IACA,YAAY;AACV,aAAO;AAAA,QACL,MAAM,MAAM,UAAU,eAAe,EAAE;AAAA,QACvC,UAAU,MAAM,UAAU,mBAAmB,EAAE;AAAA,MACjD;AAAA,IACF;AAAA,EACF;AACA,YAAU,wBAAwB;AAClC,SAAO;AACT;AAiBO,SAAS,gBACd,IACA,SACiB;AACjB,SAAO,IAAI,gBAAgB,IAAI,OAAO;AACxC;","names":[]}
|
package/lib/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Copyright 2024 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 type { Server } from '@modelcontextprotocol/sdk/server/index.js' with { 'resolution-mode': 'import' };\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js' with { 'resolution-mode': 'import' };\nimport type {\n CallToolRequest,\n CallToolResult,\n GetPromptRequest,\n GetPromptResult,\n ListPromptsRequest,\n ListPromptsResult,\n ListResourceTemplatesResult,\n ListToolsRequest,\n ListToolsResult,\n Prompt,\n PromptMessage,\n Tool,\n} from '@modelcontextprotocol/sdk/types.js' with { 'resolution-mode': 'import' };\nimport {\n ListResourceTemplatesRequest,\n ListResourcesRequest,\n ListResourcesResult,\n ReadResourceRequest,\n ReadResourceResult,\n Resource,\n ResourceTemplate,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n GenkitError,\n Message,\n type Genkit,\n type MessageData,\n type Part,\n type PromptAction,\n type ResourceAction,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { toJsonSchema } from 'genkit/schema';\nimport { toToolDefinition, type ToolAction } from 'genkit/tool';\nimport type { McpServerOptions } from './index.js';\n\n/**\n * Represents an MCP (Model Context Protocol) server that exposes Genkit tools\n * and prompts. This class wraps a Genkit instance and makes its registered\n * actions (tools, prompts) available to MCP clients. It handles the translation\n * between Genkit's action definitions and MCP's expected formats.\n */\nexport class GenkitMcpServer {\n ai: Genkit;\n options: McpServerOptions;\n server?: Server;\n actionsResolved = false;\n toolActions: ToolAction[] = [];\n promptActions: PromptAction[] = [];\n resourceActions: ResourceAction[] = [];\n\n /**\n * Creates an instance of GenkitMcpServer.\n * @param ai The Genkit instance whose actions will be exposed.\n * @param options Configuration options for the MCP server, like its name and version.\n */\n constructor(ai: Genkit, options: McpServerOptions) {\n this.ai = ai;\n this.options = options;\n }\n\n /**\n * Initializes the MCP server instance and registers request handlers. It\n * dynamically imports MCP SDK components and sets up handlers for listing\n * tools, calling tools, listing prompts, and getting prompts. It also\n * resolves and stores all tool and prompt actions from the Genkit instance.\n *\n * This method is called by the constructor and ensures the server is ready\n * before any requests are handled. It's idempotent.\n */\n async setup(): Promise<void> {\n if (this.actionsResolved) return;\n const { Server } = await import(\n '@modelcontextprotocol/sdk/server/index.js'\n );\n\n this.server = new Server(\n { name: this.options.name, version: this.options.version || '1.0.0' },\n {\n capabilities: {\n prompts: {},\n tools: {},\n resources: {},\n },\n }\n );\n\n const {\n CallToolRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ReadResourceRequestSchema,\n } = await import('@modelcontextprotocol/sdk/types.js');\n\n this.server.setRequestHandler(\n ListToolsRequestSchema,\n this.listTools.bind(this)\n );\n this.server.setRequestHandler(\n CallToolRequestSchema,\n this.callTool.bind(this)\n );\n this.server.setRequestHandler(\n ListPromptsRequestSchema,\n this.listPrompts.bind(this)\n );\n this.server.setRequestHandler(\n ListResourcesRequestSchema,\n this.listResources.bind(this)\n );\n this.server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n this.listResourceTemplates.bind(this)\n );\n this.server.setRequestHandler(\n ReadResourceRequestSchema,\n this.readResource.bind(this)\n );\n this.server.setRequestHandler(\n GetPromptRequestSchema,\n this.getPrompt.bind(this)\n );\n\n // TODO -- use listResolvableActions.\n const allActions = await this.ai.registry.listActions();\n const toolList: ToolAction[] = [];\n const promptList: PromptAction[] = [];\n const resourceList: ResourceAction[] = [];\n for (const k in allActions) {\n if (k.startsWith('/tool/')) {\n toolList.push(allActions[k] as ToolAction);\n } else if (k.startsWith('/prompt/')) {\n promptList.push(allActions[k] as PromptAction);\n } else if (k.startsWith('/resource/')) {\n resourceList.push(allActions[k] as ResourceAction);\n }\n }\n this.toolActions = toolList;\n this.promptActions = promptList;\n this.resourceActions = resourceList;\n this.actionsResolved = true;\n }\n\n /**\n * Handles MCP requests to list available tools.\n * It maps the resolved Genkit tool actions to the MCP Tool format.\n * @param req The MCP ListToolsRequest.\n * @returns A Promise resolving to an MCP ListToolsResult.\n */\n async listTools(req: ListToolsRequest): Promise<ListToolsResult> {\n await this.setup();\n return {\n tools: this.toolActions.map((t): Tool => {\n const def = toToolDefinition(t);\n return {\n name: def.name,\n inputSchema: (def.inputSchema as any) || { type: 'object' },\n description: def.description,\n _meta: t.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to call a specific tool. It finds the corresponding\n * Genkit tool action and executes it with the provided arguments. The result\n * is then formatted as an MCP CallToolResult.\n * @param req The MCP CallToolRequest containing the tool name and arguments.\n * @returns A Promise resolving to an MCP CallToolResult.\n * @throws GenkitError if the requested tool is not found.\n */\n async callTool(req: CallToolRequest): Promise<CallToolResult> {\n await this.setup();\n const tool = this.toolActions.find(\n (t) => t.__action.name === req.params.name\n );\n if (!tool)\n throw new GenkitError({\n status: 'NOT_FOUND',\n message: `Tried to call tool '${req.params.name}' but it could not be found.`,\n });\n const result = await tool(req.params.arguments);\n return {\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result),\n },\n ],\n };\n }\n\n /**\n * Handles MCP requests to list available prompts.\n * It maps the resolved Genkit prompt actions to the MCP Prompt format,\n * including converting input schemas to MCP argument definitions.\n * @param req The MCP ListPromptsRequest.\n * @returns A Promise resolving to an MCP ListPromptsResult.\n */\n async listPrompts(req: ListPromptsRequest): Promise<ListPromptsResult> {\n await this.setup();\n return {\n prompts: this.promptActions.map((p): Prompt => {\n return {\n name: p.__action.name,\n description: p.__action.description,\n arguments: toMcpPromptArguments(p),\n _meta: p.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to list available resources.\n * It maps the resolved Genkit resource actions to the MCP Resource format.\n * @param req The MCP ListResourcesRequest.\n * @returns A Promise resolving to an MCP ListResourcesResult.\n */\n async listResources(req: ListResourcesRequest): Promise<ListResourcesResult> {\n await this.setup();\n return {\n resources: this.resourceActions\n .filter((r) => r.__action.metadata?.resource.uri)\n .map((r): Resource => {\n return {\n name: r.__action.name,\n description: r.__action.description,\n uri: r.__action.metadata?.resource.uri,\n _meta: r.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to list available resources.\n * It maps the resolved Genkit resource actions to the MCP Resource format.\n * @param req The MCP ListResourcesRequest.\n * @returns A Promise resolving to an MCP ListResourcesResult.\n */\n async listResourceTemplates(\n req: ListResourceTemplatesRequest\n ): Promise<ListResourceTemplatesResult> {\n await this.setup();\n return {\n resourceTemplates: this.resourceActions\n .filter((r) => r.__action.metadata?.resource.template)\n .map((r): ResourceTemplate => {\n return {\n name: r.__action.name,\n description: r.__action.description,\n uriTemplate: r.__action.metadata?.resource.template,\n _meta: r.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to list available resources.\n * It maps the resolved Genkit resource actions to the MCP Resource format.\n * @param req The MCP ListResourcesRequest.\n * @returns A Promise resolving to an MCP ListResourcesResult.\n */\n async readResource(req: ReadResourceRequest): Promise<ReadResourceResult> {\n await this.setup();\n const resource = this.resourceActions.find((r) =>\n r.matches({ uri: req.params.uri })\n );\n if (!resource) {\n throw new GenkitError({\n status: 'NOT_FOUND',\n message: `Tried to call resource '${req.params.uri}' but it could not be found.`,\n });\n }\n const result = await resource({ uri: req.params.uri });\n return {\n contents: toMcpResourceMessage(req.params.uri, result.content),\n };\n }\n\n /**\n * Handles MCP requests to get (render) a specific prompt. It finds the\n * corresponding Genkit prompt action, executes it with the provided\n * arguments, and then formats the resulting messages into the MCP\n * PromptMessage format.\n * @param req The MCP GetPromptRequest containing the prompt name and\n * arguments.\n * @returns A Promise resolving to an MCP GetPromptResult.\n * @throws GenkitError if the requested prompt is not found.\n */\n async getPrompt(req: GetPromptRequest): Promise<GetPromptResult> {\n await this.setup();\n const prompt = this.promptActions.find(\n (p) => p.__action.name === req.params.name\n );\n if (!prompt)\n throw new GenkitError({\n status: 'NOT_FOUND',\n message: `[MCP Server] Tried to call prompt '${req.params.name}' but it could not be found.`,\n });\n const result = await prompt(req.params.arguments);\n return {\n description: prompt.__action.description,\n messages: result.messages.map(toMcpPromptMessage),\n };\n }\n\n /**\n * Starts the MCP server with the specified transport or a default\n * StdioServerTransport. Ensures the server is set up before connecting the\n * transport.\n * @param transport Optional MCP transport instance. If not provided, a\n * StdioServerTransport will be created and used.\n */\n async start(transport?: Transport) {\n if (!transport) {\n const { StdioServerTransport } = await import(\n '@modelcontextprotocol/sdk/server/stdio.js'\n );\n transport = new StdioServerTransport();\n }\n await this.setup();\n await this.server!.connect(transport);\n logger.debug(\n `[MCP Server] MCP server '${this.options.name}' started successfully.`\n );\n }\n}\n\n/**\n * Converts a Genkit prompt's input schema to an array of MCP prompt arguments.\n * MCP prompts currently only support string arguments.\n * @param p The Genkit PromptAction.\n * @returns An array of MCP prompt arguments, or undefined if the schema is not defined.\n * @throws GenkitError if the input schema is not an object or if any property is not a string.\n */\nfunction toMcpPromptArguments(\n p: PromptAction\n): Prompt['arguments'] | undefined {\n const jsonSchema = toJsonSchema({\n schema: p.__action.inputSchema,\n jsonSchema: p.__action.inputJsonSchema,\n });\n\n if (!jsonSchema) return undefined;\n if (!jsonSchema.properties)\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message: '[MCP Server] MCP prompts must take objects as input schema.',\n });\n\n const args: Prompt['arguments'] = [];\n for (const k in jsonSchema.properties) {\n const { type, description } = jsonSchema.properties[k];\n if (\n type !== 'string' &&\n (!Array.isArray(type) || !type.includes('string'))\n ) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message: `[MCP Server] MCP prompts may only take string arguments, but ${p.__action.name} has property '${k}' of type '${type}'.`,\n });\n }\n args.push({\n name: k,\n description,\n required: jsonSchema.required?.includes(k),\n });\n }\n return args;\n}\n\nconst ROLE_MAP = { model: 'assistant', user: 'user' } as const;\n\n/**\n * Converts a Genkit MessageData object to an MCP PromptMessage.\n * Handles mapping of roles and content types (text, image).\n * MCP only supports 'user' and 'assistant' (model) roles and base64 data images.\n * @param messageData The Genkit MessageData object.\n * @returns An MCP PromptMessage.\n * @throws GenkitError if the role is unsupported or if media is not a data URL.\n */\nfunction toMcpPromptMessage(messageData: MessageData): PromptMessage {\n if (messageData.role !== 'model' && messageData.role !== 'user') {\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP prompt messages do not support role '${messageData.role}'. Only 'user' and 'model' messages are supported.`,\n });\n }\n const message = new Message(messageData);\n const common = { role: ROLE_MAP[messageData.role] };\n if (message.media) {\n const { url, contentType } = message.media;\n if (!url.startsWith('data:'))\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP prompt messages only support base64 data images.`,\n });\n const mimeType =\n contentType || url.substring(url.indexOf(':')! + 1, url.indexOf(';'));\n const data = url.substring(url.indexOf(',') + 1);\n return { ...common, content: { type: 'image', mimeType, data } };\n } else {\n return { ...common, content: { type: 'text', text: message.text } };\n }\n}\n\n/**\n * Converts a Genkit Parts to an MCP resource content.\n * Handles mapping of roles and content types (text, image).\n */\nfunction toMcpResourceMessage(\n uri: string,\n content: Part[]\n): ReadResourceResult['contents'] {\n return content.map((p) => {\n if (p.media) {\n const { url, contentType } = p.media;\n if (!url.startsWith('data:'))\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP resource messages only support base64 data images.`,\n });\n const mimeType =\n contentType || url.substring(url.indexOf(':')! + 1, url.indexOf(';'));\n const data = url.substring(url.indexOf(',') + 1);\n return { uri, mimeType, blob: data };\n } else if (p.text) {\n return { uri, text: p.text };\n } else {\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP resource messages only support media and text parts.`,\n });\n }\n });\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/server.ts"],"sourcesContent":["/**\n * Copyright 2024 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 type { Server } from '@modelcontextprotocol/sdk/server/index.js' with { 'resolution-mode': 'import' };\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js' with { 'resolution-mode': 'import' };\nimport type {\n CallToolRequest,\n CallToolResult,\n GetPromptRequest,\n GetPromptResult,\n ListPromptsRequest,\n ListPromptsResult,\n ListResourceTemplatesResult,\n ListToolsRequest,\n ListToolsResult,\n Prompt,\n PromptMessage,\n Tool,\n} from '@modelcontextprotocol/sdk/types.js' with { 'resolution-mode': 'import' };\nimport {\n ListResourceTemplatesRequest,\n ListResourcesRequest,\n ListResourcesResult,\n ReadResourceRequest,\n ReadResourceResult,\n Resource,\n ResourceTemplate,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n GenkitError,\n Message,\n type Genkit,\n type MessageData,\n type Part,\n type PromptAction,\n type ResourceAction,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { toJsonSchema } from 'genkit/schema';\nimport { toToolDefinition, type ToolAction } from 'genkit/tool';\nimport type { McpServerOptions } from './index.mjs';\n\n/**\n * Represents an MCP (Model Context Protocol) server that exposes Genkit tools\n * and prompts. This class wraps a Genkit instance and makes its registered\n * actions (tools, prompts) available to MCP clients. It handles the translation\n * between Genkit's action definitions and MCP's expected formats.\n */\nexport class GenkitMcpServer {\n ai: Genkit;\n options: McpServerOptions;\n server?: Server;\n actionsResolved = false;\n toolActions: ToolAction[] = [];\n promptActions: PromptAction[] = [];\n resourceActions: ResourceAction[] = [];\n\n /**\n * Creates an instance of GenkitMcpServer.\n * @param ai The Genkit instance whose actions will be exposed.\n * @param options Configuration options for the MCP server, like its name and version.\n */\n constructor(ai: Genkit, options: McpServerOptions) {\n this.ai = ai;\n this.options = options;\n }\n\n /**\n * Initializes the MCP server instance and registers request handlers. It\n * dynamically imports MCP SDK components and sets up handlers for listing\n * tools, calling tools, listing prompts, and getting prompts. It also\n * resolves and stores all tool and prompt actions from the Genkit instance.\n *\n * This method is called by the constructor and ensures the server is ready\n * before any requests are handled. It's idempotent.\n */\n async setup(): Promise<void> {\n if (this.actionsResolved) return;\n const { Server } = await import(\n '@modelcontextprotocol/sdk/server/index.js'\n );\n\n this.server = new Server(\n { name: this.options.name, version: this.options.version || '1.0.0' },\n {\n capabilities: {\n prompts: {},\n tools: {},\n resources: {},\n },\n }\n );\n\n const {\n CallToolRequestSchema,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListToolsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ReadResourceRequestSchema,\n } = await import('@modelcontextprotocol/sdk/types.js');\n\n this.server.setRequestHandler(\n ListToolsRequestSchema,\n this.listTools.bind(this)\n );\n this.server.setRequestHandler(\n CallToolRequestSchema,\n this.callTool.bind(this)\n );\n this.server.setRequestHandler(\n ListPromptsRequestSchema,\n this.listPrompts.bind(this)\n );\n this.server.setRequestHandler(\n ListResourcesRequestSchema,\n this.listResources.bind(this)\n );\n this.server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n this.listResourceTemplates.bind(this)\n );\n this.server.setRequestHandler(\n ReadResourceRequestSchema,\n this.readResource.bind(this)\n );\n this.server.setRequestHandler(\n GetPromptRequestSchema,\n this.getPrompt.bind(this)\n );\n\n // TODO -- use listResolvableActions.\n const allActions = await this.ai.registry.listActions();\n const toolList: ToolAction[] = [];\n const promptList: PromptAction[] = [];\n const resourceList: ResourceAction[] = [];\n for (const k in allActions) {\n if (k.startsWith('/tool/')) {\n toolList.push(allActions[k] as ToolAction);\n } else if (k.startsWith('/prompt/')) {\n promptList.push(allActions[k] as PromptAction);\n } else if (k.startsWith('/resource/')) {\n resourceList.push(allActions[k] as ResourceAction);\n }\n }\n this.toolActions = toolList;\n this.promptActions = promptList;\n this.resourceActions = resourceList;\n this.actionsResolved = true;\n }\n\n /**\n * Handles MCP requests to list available tools.\n * It maps the resolved Genkit tool actions to the MCP Tool format.\n * @param req The MCP ListToolsRequest.\n * @returns A Promise resolving to an MCP ListToolsResult.\n */\n async listTools(req: ListToolsRequest): Promise<ListToolsResult> {\n await this.setup();\n return {\n tools: this.toolActions.map((t): Tool => {\n const def = toToolDefinition(t);\n return {\n name: def.name,\n inputSchema: (def.inputSchema as any) || { type: 'object' },\n description: def.description,\n _meta: t.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to call a specific tool. It finds the corresponding\n * Genkit tool action and executes it with the provided arguments. The result\n * is then formatted as an MCP CallToolResult.\n * @param req The MCP CallToolRequest containing the tool name and arguments.\n * @returns A Promise resolving to an MCP CallToolResult.\n * @throws GenkitError if the requested tool is not found.\n */\n async callTool(req: CallToolRequest): Promise<CallToolResult> {\n await this.setup();\n const tool = this.toolActions.find(\n (t) => t.__action.name === req.params.name\n );\n if (!tool)\n throw new GenkitError({\n status: 'NOT_FOUND',\n message: `Tried to call tool '${req.params.name}' but it could not be found.`,\n });\n const result = await tool(req.params.arguments);\n return {\n content: [\n {\n type: 'text',\n text: typeof result === 'string' ? result : JSON.stringify(result),\n },\n ],\n };\n }\n\n /**\n * Handles MCP requests to list available prompts.\n * It maps the resolved Genkit prompt actions to the MCP Prompt format,\n * including converting input schemas to MCP argument definitions.\n * @param req The MCP ListPromptsRequest.\n * @returns A Promise resolving to an MCP ListPromptsResult.\n */\n async listPrompts(req: ListPromptsRequest): Promise<ListPromptsResult> {\n await this.setup();\n return {\n prompts: this.promptActions.map((p): Prompt => {\n return {\n name: p.__action.name,\n description: p.__action.description,\n arguments: toMcpPromptArguments(p),\n _meta: p.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to list available resources.\n * It maps the resolved Genkit resource actions to the MCP Resource format.\n * @param req The MCP ListResourcesRequest.\n * @returns A Promise resolving to an MCP ListResourcesResult.\n */\n async listResources(req: ListResourcesRequest): Promise<ListResourcesResult> {\n await this.setup();\n return {\n resources: this.resourceActions\n .filter((r) => r.__action.metadata?.resource.uri)\n .map((r): Resource => {\n return {\n name: r.__action.name,\n description: r.__action.description,\n uri: r.__action.metadata?.resource.uri,\n _meta: r.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to list available resources.\n * It maps the resolved Genkit resource actions to the MCP Resource format.\n * @param req The MCP ListResourcesRequest.\n * @returns A Promise resolving to an MCP ListResourcesResult.\n */\n async listResourceTemplates(\n req: ListResourceTemplatesRequest\n ): Promise<ListResourceTemplatesResult> {\n await this.setup();\n return {\n resourceTemplates: this.resourceActions\n .filter((r) => r.__action.metadata?.resource.template)\n .map((r): ResourceTemplate => {\n return {\n name: r.__action.name,\n description: r.__action.description,\n uriTemplate: r.__action.metadata?.resource.template,\n _meta: r.__action.metadata?.mcp?._meta,\n };\n }),\n };\n }\n\n /**\n * Handles MCP requests to list available resources.\n * It maps the resolved Genkit resource actions to the MCP Resource format.\n * @param req The MCP ListResourcesRequest.\n * @returns A Promise resolving to an MCP ListResourcesResult.\n */\n async readResource(req: ReadResourceRequest): Promise<ReadResourceResult> {\n await this.setup();\n const resource = this.resourceActions.find((r) =>\n r.matches({ uri: req.params.uri })\n );\n if (!resource) {\n throw new GenkitError({\n status: 'NOT_FOUND',\n message: `Tried to call resource '${req.params.uri}' but it could not be found.`,\n });\n }\n const result = await resource({ uri: req.params.uri });\n return {\n contents: toMcpResourceMessage(req.params.uri, result.content),\n };\n }\n\n /**\n * Handles MCP requests to get (render) a specific prompt. It finds the\n * corresponding Genkit prompt action, executes it with the provided\n * arguments, and then formats the resulting messages into the MCP\n * PromptMessage format.\n * @param req The MCP GetPromptRequest containing the prompt name and\n * arguments.\n * @returns A Promise resolving to an MCP GetPromptResult.\n * @throws GenkitError if the requested prompt is not found.\n */\n async getPrompt(req: GetPromptRequest): Promise<GetPromptResult> {\n await this.setup();\n const prompt = this.promptActions.find(\n (p) => p.__action.name === req.params.name\n );\n if (!prompt)\n throw new GenkitError({\n status: 'NOT_FOUND',\n message: `[MCP Server] Tried to call prompt '${req.params.name}' but it could not be found.`,\n });\n const result = await prompt(req.params.arguments);\n return {\n description: prompt.__action.description,\n messages: result.messages.map(toMcpPromptMessage),\n };\n }\n\n /**\n * Starts the MCP server with the specified transport or a default\n * StdioServerTransport. Ensures the server is set up before connecting the\n * transport.\n * @param transport Optional MCP transport instance. If not provided, a\n * StdioServerTransport will be created and used.\n */\n async start(transport?: Transport) {\n if (!transport) {\n const { StdioServerTransport } = await import(\n '@modelcontextprotocol/sdk/server/stdio.js'\n );\n transport = new StdioServerTransport();\n }\n await this.setup();\n await this.server!.connect(transport);\n logger.debug(\n `[MCP Server] MCP server '${this.options.name}' started successfully.`\n );\n }\n}\n\n/**\n * Converts a Genkit prompt's input schema to an array of MCP prompt arguments.\n * MCP prompts currently only support string arguments.\n * @param p The Genkit PromptAction.\n * @returns An array of MCP prompt arguments, or undefined if the schema is not defined.\n * @throws GenkitError if the input schema is not an object or if any property is not a string.\n */\nfunction toMcpPromptArguments(\n p: PromptAction\n): Prompt['arguments'] | undefined {\n const jsonSchema = toJsonSchema({\n schema: p.__action.inputSchema,\n jsonSchema: p.__action.inputJsonSchema,\n });\n\n if (!jsonSchema) return undefined;\n if (!jsonSchema.properties)\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message: '[MCP Server] MCP prompts must take objects as input schema.',\n });\n\n const args: Prompt['arguments'] = [];\n for (const k in jsonSchema.properties) {\n const { type, description } = jsonSchema.properties[k];\n if (\n type !== 'string' &&\n (!Array.isArray(type) || !type.includes('string'))\n ) {\n throw new GenkitError({\n status: 'FAILED_PRECONDITION',\n message: `[MCP Server] MCP prompts may only take string arguments, but ${p.__action.name} has property '${k}' of type '${type}'.`,\n });\n }\n args.push({\n name: k,\n description,\n required: jsonSchema.required?.includes(k),\n });\n }\n return args;\n}\n\nconst ROLE_MAP = { model: 'assistant', user: 'user' } as const;\n\n/**\n * Converts a Genkit MessageData object to an MCP PromptMessage.\n * Handles mapping of roles and content types (text, image).\n * MCP only supports 'user' and 'assistant' (model) roles and base64 data images.\n * @param messageData The Genkit MessageData object.\n * @returns An MCP PromptMessage.\n * @throws GenkitError if the role is unsupported or if media is not a data URL.\n */\nfunction toMcpPromptMessage(messageData: MessageData): PromptMessage {\n if (messageData.role !== 'model' && messageData.role !== 'user') {\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP prompt messages do not support role '${messageData.role}'. Only 'user' and 'model' messages are supported.`,\n });\n }\n const message = new Message(messageData);\n const common = { role: ROLE_MAP[messageData.role] };\n if (message.media) {\n const { url, contentType } = message.media;\n if (!url.startsWith('data:'))\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP prompt messages only support base64 data images.`,\n });\n const mimeType =\n contentType || url.substring(url.indexOf(':')! + 1, url.indexOf(';'));\n const data = url.substring(url.indexOf(',') + 1);\n return { ...common, content: { type: 'image', mimeType, data } };\n } else {\n return { ...common, content: { type: 'text', text: message.text } };\n }\n}\n\n/**\n * Converts a Genkit Parts to an MCP resource content.\n * Handles mapping of roles and content types (text, image).\n */\nfunction toMcpResourceMessage(\n uri: string,\n content: Part[]\n): ReadResourceResult['contents'] {\n return content.map((p) => {\n if (p.media) {\n const { url, contentType } = p.media;\n if (!url.startsWith('data:'))\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP resource messages only support base64 data images.`,\n });\n const mimeType =\n contentType || url.substring(url.indexOf(':')! + 1, url.indexOf(';'));\n const data = url.substring(url.indexOf(',') + 1);\n return { uri, mimeType, blob: data };\n } else if (p.text) {\n return { uri, text: p.text };\n } else {\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP Server] MCP resource messages only support media and text parts.`,\n });\n }\n });\n}\n"],"mappings":"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","names":[]}
|
package/lib/util/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from "./message.
|
|
2
|
-
export * from "./prompts.
|
|
3
|
-
export * from "./tools.
|
|
4
|
-
export * from "./transport.
|
|
1
|
+
export * from "./message.mjs";
|
|
2
|
+
export * from "./prompts.mjs";
|
|
3
|
+
export * from "./tools.mjs";
|
|
4
|
+
export * from "./transport.mjs";
|
|
5
5
|
//# sourceMappingURL=index.mjs.map
|
package/lib/util/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/index.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\nexport * from './message.
|
|
1
|
+
{"version":3,"sources":["../../src/util/index.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\nexport * from './message.mjs';\nexport * from './prompts.mjs';\nexport * from './tools.mjs';\nexport * from './transport.mjs';\n"],"mappings":"AAgBA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
|
package/lib/util/prompts.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
GenkitError
|
|
3
3
|
} from "genkit";
|
|
4
4
|
import { logger } from "genkit/logging";
|
|
5
|
-
import { fromMcpPromptMessage } from "./message.
|
|
5
|
+
import { fromMcpPromptMessage } from "./message.mjs";
|
|
6
6
|
function toSchema(args) {
|
|
7
7
|
if (!args) return {};
|
|
8
8
|
const schema = { type: "object", properties: {}, required: [] };
|
package/lib/util/prompts.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/prompts.ts"],"sourcesContent":["/**\n * Copyright 2024 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 { Prompt } from '@modelcontextprotocol/sdk/types.js';\nimport {\n GenkitError,\n z,\n type ExecutablePrompt,\n type GenerateOptions,\n type GenerateResponse,\n type GenerateStreamResponse,\n type Genkit,\n type JSONSchema,\n type PromptGenerateOptions,\n type ToolAction,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { fromMcpPromptMessage } from './message.
|
|
1
|
+
{"version":3,"sources":["../../src/util/prompts.ts"],"sourcesContent":["/**\n * Copyright 2024 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 { Prompt } from '@modelcontextprotocol/sdk/types.js';\nimport {\n GenkitError,\n z,\n type ExecutablePrompt,\n type GenerateOptions,\n type GenerateResponse,\n type GenerateStreamResponse,\n type Genkit,\n type JSONSchema,\n type PromptGenerateOptions,\n type ToolAction,\n} from 'genkit';\nimport { logger } from 'genkit/logging';\nimport { fromMcpPromptMessage } from './message.mjs';\n\nfunction toSchema(args: Prompt['arguments']) {\n if (!args) return {};\n const schema: JSONSchema = { type: 'object', properties: {}, required: [] };\n for (const arg of args) {\n schema.properties[arg.name] = {\n type: 'string',\n description: arg.description,\n };\n if (arg.required) schema.required.push(arg.name);\n }\n return schema;\n}\n\n/**\n * Registers a single MCP prompt as a Genkit prompt.\n * It defines a new Genkit prompt action that, when called, will\n * interact with the MCP client to fetch and render the corresponding MCP prompt.\n *\n * @param ai The Genkit instance to define the prompt on.\n * @param client The MCP client instance used to interact with the MCP server.\n * @param prompt The MCP Prompt object to register.\n * @param params Contains the Genkit client name and the MCP server name for namespacing and logging.\n */\nfunction registerPrompt(\n ai: Genkit,\n client: Client,\n prompt: Prompt,\n params: { name: string; serverName: string }\n) {\n logger.debug(`[MCP] Registering MCP prompt ${params.name}/${prompt.name}`);\n ai.definePrompt({\n name: prompt.name,\n description: prompt.description || '',\n input: { jsonSchema: toSchema(prompt.arguments) },\n output: { format: 'text' },\n metadata: { mcp: { _meta: prompt._meta || {} } },\n messages: async (args, { context }) => {\n logger.debug(\n `[MCP] Calling MCP prompt ${params.name}/${prompt.name} with arguments`,\n JSON.stringify(args)\n );\n const result = await client.getPrompt({\n name: prompt.name,\n arguments: args,\n _meta: context?.mcp?._meta,\n });\n return result.messages.map(fromMcpPromptMessage);\n },\n });\n}\n\nfunction createExecutablePrompt<\n I extends z.ZodTypeAny = z.ZodTypeAny,\n O extends z.ZodTypeAny = z.ZodTypeAny,\n CustomOptions extends z.ZodTypeAny = z.ZodTypeAny,\n>(\n client: Client,\n prompt: Prompt,\n params: {\n ai: Genkit;\n name: string;\n serverName: string;\n promptName: string;\n options?: PromptGenerateOptions<any, any>;\n }\n): ExecutablePrompt<z.infer<I>, O, CustomOptions> {\n const callPrompt = (async (\n input?: z.infer<I>,\n opts?: PromptGenerateOptions<O, CustomOptions>\n ): Promise<GenerateResponse<z.infer<O>>> => {\n logger.debug(`[MCP] Calling MCP prompt ${params.name}/${prompt.name}`);\n return params.ai.generate(callPrompt.render(input, opts));\n }) as ExecutablePrompt<z.infer<I>, O, CustomOptions>;\n\n callPrompt.ref = {\n name: prompt.name,\n metadata: {\n description: prompt.description,\n arguments: prompt.arguments,\n mcp: { _meta: prompt._meta || {} },\n },\n };\n\n callPrompt.stream = (\n input?: z.infer<I>,\n opts?: PromptGenerateOptions<O, CustomOptions>\n ): GenerateStreamResponse<z.infer<O>> => {\n logger.debug(`[MCP] Streaming MCP prompt ${params.name}/${prompt.name}`);\n return params.ai.generateStream(callPrompt.render(input, opts));\n };\n\n callPrompt.render = async (\n input?: I,\n opts?: PromptGenerateOptions<O, CustomOptions>\n ): Promise<GenerateOptions<O, CustomOptions>> => {\n logger.debug(`[MCP] Rendering MCP prompt ${params.name}/${prompt.name}`);\n const result = await client.getPrompt({\n name: prompt.name,\n arguments: input as any,\n _meta: opts?.context?.mcp?._meta,\n });\n const messages = result.messages.map(fromMcpPromptMessage);\n return {\n ...params.options,\n ...opts,\n messages,\n };\n };\n\n callPrompt.asTool = async (): Promise<ToolAction> => {\n throw new GenkitError({\n status: 'UNIMPLEMENTED',\n message: `[MCP] prompt.asTool not supported with MCP`,\n });\n };\n\n return callPrompt;\n}\n\n/**\n * Lookup all prompts available in the server and register each as a Genkit\n * prompt.\n */\nexport async function registerAllPrompts(\n ai: Genkit,\n client: Client,\n params: { name: string; serverName: string }\n): Promise<void> {\n let cursor: string | undefined;\n while (true) {\n const { nextCursor, prompts } = await client.listPrompts({ cursor });\n prompts.forEach((p) => registerPrompt(ai, client, p, params));\n cursor = nextCursor;\n if (!cursor) break;\n }\n}\n\n/**\n * Lookup a specified prompt from the server and return as an ExecutablePrompt.\n */\nexport async function getExecutablePrompt(\n client: Client,\n params: {\n name: string;\n serverName: string;\n promptName: string;\n ai: Genkit;\n options?: PromptGenerateOptions;\n }\n): Promise<ExecutablePrompt | undefined> {\n let cursor: string | undefined;\n\n while (true) {\n const { nextCursor, prompts } = await client.listPrompts({ cursor });\n const maybePrompt = prompts.find(\n (p: Prompt) => p.name === params.promptName\n );\n if (maybePrompt) {\n return createExecutablePrompt(client, maybePrompt, params);\n }\n cursor = nextCursor;\n if (!cursor) break;\n }\n return undefined;\n}\n\nexport async function fetchAllPrompts(\n client: Client,\n params: {\n name: string;\n serverName: string;\n ai: Genkit;\n options?: PromptGenerateOptions;\n }\n): Promise<ExecutablePrompt[]> {\n let cursor: string | undefined;\n const out: ExecutablePrompt[] = [];\n\n while (true) {\n const { nextCursor, prompts } = await client.listPrompts({ cursor });\n for (const p of prompts) {\n out.push(\n createExecutablePrompt(client, p, { ...params, promptName: p.name })\n );\n }\n cursor = nextCursor;\n if (!cursor) break;\n }\n return out;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/util/transport.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 { McpServerConfig } from '../client/client.
|
|
1
|
+
{"version":3,"sources":["../../src/util/transport.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 { McpServerConfig } from '../client/client.mjs';\nimport type { StdioServerParameters, Transport } from '../client/index.mjs';\n\n/**\n * Creates an MCP transport instance based on the provided server configuration.\n * It supports creating SSE, Stdio, or using a pre-configured custom transport.\n *\n * @param config The configuration for the MCP server, determining the type of transport to create.\n * @returns A Promise resolving to an object containing the created `Transport` instance\n * (or `null` if configuration is invalid) and a string indicating the `type` of transport.\n * @throws May throw an error if essential MCP SDK components cannot be imported.\n */\nexport async function transportFrom(\n config: McpServerConfig,\n sessionId?: string\n): Promise<{\n transport: Transport | null;\n type: string;\n}> {\n // Handle pre-configured transport first\n if ('transport' in config && config.transport) {\n return { transport: config.transport, type: 'custom' };\n }\n // Handle SSE config\n if ('url' in config && config.url) {\n const { url, ...httpConfig } = config;\n const { StreamableHTTPClientTransport } = await import(\n '@modelcontextprotocol/sdk/client/streamableHttp.js'\n );\n return {\n transport: new StreamableHTTPClientTransport(new URL(url), {\n ...httpConfig,\n sessionId,\n }),\n type: 'http',\n };\n }\n // Handle Stdio config\n if ('command' in config && config.command) {\n // Create a copy and remove McpServerControls properties\n const stdioConfig = { ...config };\n const { StdioClientTransport } = await import(\n '@modelcontextprotocol/sdk/client/stdio.js'\n );\n return {\n transport: new StdioClientTransport(stdioConfig as StdioServerParameters),\n type: 'stdio',\n };\n }\n return { transport: null, type: 'unknown' };\n}\n"],"mappings":"AA4BA,eAAsB,cACpB,QACA,WAIC;AAED,MAAI,eAAe,UAAU,OAAO,WAAW;AAC7C,WAAO,EAAE,WAAW,OAAO,WAAW,MAAM,SAAS;AAAA,EACvD;AAEA,MAAI,SAAS,UAAU,OAAO,KAAK;AACjC,UAAM,EAAE,KAAK,GAAG,WAAW,IAAI;AAC/B,UAAM,EAAE,8BAA8B,IAAI,MAAM,OAC9C,oDACF;AACA,WAAO;AAAA,MACL,WAAW,IAAI,8BAA8B,IAAI,IAAI,GAAG,GAAG;AAAA,QACzD,GAAG;AAAA,QACH;AAAA,MACF,CAAC;AAAA,MACD,MAAM;AAAA,IACR;AAAA,EACF;AAEA,MAAI,aAAa,UAAU,OAAO,SAAS;AAEzC,UAAM,cAAc,EAAE,GAAG,OAAO;AAChC,UAAM,EAAE,qBAAqB,IAAI,MAAM,OACrC,2CACF;AACA,WAAO;AAAA,MACL,WAAW,IAAI,qBAAqB,WAAoC;AAAA,MACxE,MAAM;AAAA,IACR;AAAA,EACF;AACA,SAAO,EAAE,WAAW,MAAM,MAAM,UAAU;AAC5C;","names":[]}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"genai",
|
|
10
10
|
"generative-ai"
|
|
11
11
|
],
|
|
12
|
-
"version": "1.
|
|
12
|
+
"version": "1.36.0",
|
|
13
13
|
"description": "A Genkit plugin that provides interoperability between Genkit and Model Context Protocol (MCP). Both client and server use cases are supported.",
|
|
14
14
|
"main": "./lib/index.js",
|
|
15
15
|
"types": "./lib/index.d.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"license": "Apache-2.0",
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
34
|
-
"genkit": "^1.
|
|
34
|
+
"genkit": "^1.36.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"get-port": "^5.1.0",
|
package/src/client/client.ts
CHANGED