diff options
Diffstat (limited to 'packages/core/src/ide/ide-client.ts')
| -rw-r--r-- | packages/core/src/ide/ide-client.ts | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/packages/core/src/ide/ide-client.ts b/packages/core/src/ide/ide-client.ts new file mode 100644 index 00000000..eeed60b2 --- /dev/null +++ b/packages/core/src/ide/ide-client.ts @@ -0,0 +1,100 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { ideContext, OpenFilesNotificationSchema } from '../ide/ideContext.js'; +import { Client } from '@modelcontextprotocol/sdk/client/index.js'; +import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'; + +const logger = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + debug: (...args: any[]) => + console.debug('[DEBUG] [ImportProcessor]', ...args), +}; + +export type IDEConnectionState = { + status: IDEConnectionStatus; + details?: string; +}; + +export enum IDEConnectionStatus { + Connected = 'connected', + Disconnected = 'disconnected', + Connecting = 'connecting', +} + +/** + * Manages the connection to and interaction with the IDE server. + */ +export class IdeClient { + client: Client | undefined = undefined; + connectionStatus: IDEConnectionStatus = IDEConnectionStatus.Disconnected; + + constructor() { + this.connectToMcpServer().catch((err) => { + logger.debug('Failed to initialize IdeClient:', err); + }); + } + getConnectionStatus(): { + status: IDEConnectionStatus; + details?: string; + } { + let details: string | undefined; + if (this.connectionStatus === IDEConnectionStatus.Disconnected) { + if (!process.env['GEMINI_CLI_IDE_SERVER_PORT']) { + details = 'GEMINI_CLI_IDE_SERVER_PORT environment variable is not set.'; + } + } + return { + status: this.connectionStatus, + details, + }; + } + + async connectToMcpServer(): Promise<void> { + this.connectionStatus = IDEConnectionStatus.Connecting; + const idePort = process.env['GEMINI_CLI_IDE_SERVER_PORT']; + if (!idePort) { + logger.debug( + 'Unable to connect to IDE mode MCP server. GEMINI_CLI_IDE_SERVER_PORT environment variable is not set.', + ); + this.connectionStatus = IDEConnectionStatus.Disconnected; + return; + } + + try { + this.client = new Client({ + name: 'streamable-http-client', + // TODO(#3487): use the CLI version here. + version: '1.0.0', + }); + const transport = new StreamableHTTPClientTransport( + new URL(`http://localhost:${idePort}/mcp`), + ); + await this.client.connect(transport); + this.client.setNotificationHandler( + OpenFilesNotificationSchema, + (notification) => { + ideContext.setOpenFilesContext(notification.params); + }, + ); + this.client.onerror = (error) => { + logger.debug('IDE MCP client error:', error); + this.connectionStatus = IDEConnectionStatus.Disconnected; + ideContext.clearOpenFilesContext(); + }; + this.client.onclose = () => { + logger.debug('IDE MCP client connection closed.'); + this.connectionStatus = IDEConnectionStatus.Disconnected; + ideContext.clearOpenFilesContext(); + }; + + this.connectionStatus = IDEConnectionStatus.Connected; + } catch (error) { + this.connectionStatus = IDEConnectionStatus.Disconnected; + logger.debug('Failed to connect to MCP server:', error); + } + } +} |
