mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-18 18:11:02 -07:00
Add MCP loading indicator when initializing Gemini CLI (#6923)
This commit is contained in:
@@ -54,6 +54,7 @@ import type { AnyToolInvocation } from '../tools/tools.js';
|
||||
import { WorkspaceContext } from '../utils/workspaceContext.js';
|
||||
import { Storage } from './storage.js';
|
||||
import { FileExclusions } from '../utils/ignorePatterns.js';
|
||||
import type { EventEmitter } from 'node:events';
|
||||
|
||||
export enum ApprovalMode {
|
||||
DEFAULT = 'default',
|
||||
@@ -207,6 +208,7 @@ export interface ConfigParameters {
|
||||
skipNextSpeakerCheck?: boolean;
|
||||
extensionManagement?: boolean;
|
||||
enablePromptCompletion?: boolean;
|
||||
eventEmitter?: EventEmitter;
|
||||
}
|
||||
|
||||
export class Config {
|
||||
@@ -282,6 +284,7 @@ export class Config {
|
||||
private initialized: boolean = false;
|
||||
readonly storage: Storage;
|
||||
private readonly fileExclusions: FileExclusions;
|
||||
private readonly eventEmitter?: EventEmitter;
|
||||
|
||||
constructor(params: ConfigParameters) {
|
||||
this.sessionId = params.sessionId;
|
||||
@@ -356,6 +359,7 @@ export class Config {
|
||||
this.storage = new Storage(this.targetDir);
|
||||
this.enablePromptCompletion = params.enablePromptCompletion ?? false;
|
||||
this.fileExclusions = new FileExclusions(this);
|
||||
this.eventEmitter = params.eventEmitter;
|
||||
|
||||
if (params.contextFileName) {
|
||||
setGeminiMdFilename(params.contextFileName);
|
||||
@@ -803,7 +807,7 @@ export class Config {
|
||||
}
|
||||
|
||||
async createToolRegistry(): Promise<ToolRegistry> {
|
||||
const registry = new ToolRegistry(this);
|
||||
const registry = new ToolRegistry(this, this.eventEmitter);
|
||||
|
||||
// helper to create & register core tools that are enabled
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
populateMcpServerCommand,
|
||||
} from './mcp-client.js';
|
||||
import { getErrorMessage } from '../utils/errors.js';
|
||||
import type { EventEmitter } from 'node:events';
|
||||
import type { WorkspaceContext } from '../utils/workspaceContext.js';
|
||||
|
||||
/**
|
||||
@@ -29,6 +30,7 @@ export class McpClientManager {
|
||||
private readonly debugMode: boolean;
|
||||
private readonly workspaceContext: WorkspaceContext;
|
||||
private discoveryState: MCPDiscoveryState = MCPDiscoveryState.NOT_STARTED;
|
||||
private readonly eventEmitter?: EventEmitter;
|
||||
|
||||
constructor(
|
||||
mcpServers: Record<string, MCPServerConfig>,
|
||||
@@ -37,6 +39,7 @@ export class McpClientManager {
|
||||
promptRegistry: PromptRegistry,
|
||||
debugMode: boolean,
|
||||
workspaceContext: WorkspaceContext,
|
||||
eventEmitter?: EventEmitter,
|
||||
) {
|
||||
this.mcpServers = mcpServers;
|
||||
this.mcpServerCommand = mcpServerCommand;
|
||||
@@ -44,6 +47,7 @@ export class McpClientManager {
|
||||
this.promptRegistry = promptRegistry;
|
||||
this.debugMode = debugMode;
|
||||
this.workspaceContext = workspaceContext;
|
||||
this.eventEmitter = eventEmitter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,14 +57,28 @@ export class McpClientManager {
|
||||
*/
|
||||
async discoverAllMcpTools(): Promise<void> {
|
||||
await this.stop();
|
||||
this.discoveryState = MCPDiscoveryState.IN_PROGRESS;
|
||||
|
||||
const servers = populateMcpServerCommand(
|
||||
this.mcpServers,
|
||||
this.mcpServerCommand,
|
||||
);
|
||||
|
||||
const discoveryPromises = Object.entries(servers).map(
|
||||
async ([name, config]) => {
|
||||
const serverEntries = Object.entries(servers);
|
||||
const total = serverEntries.length;
|
||||
|
||||
this.eventEmitter?.emit('mcp-servers-discovery-start', { count: total });
|
||||
|
||||
this.discoveryState = MCPDiscoveryState.IN_PROGRESS;
|
||||
|
||||
const discoveryPromises = serverEntries.map(
|
||||
async ([name, config], index) => {
|
||||
const current = index + 1;
|
||||
this.eventEmitter?.emit('mcp-server-connecting', {
|
||||
name,
|
||||
current,
|
||||
total,
|
||||
});
|
||||
|
||||
const client = new McpClient(
|
||||
name,
|
||||
config,
|
||||
@@ -70,10 +88,22 @@ export class McpClientManager {
|
||||
this.debugMode,
|
||||
);
|
||||
this.clients.set(name, client);
|
||||
|
||||
try {
|
||||
await client.connect();
|
||||
await client.discover();
|
||||
this.eventEmitter?.emit('mcp-server-connected', {
|
||||
name,
|
||||
current,
|
||||
total,
|
||||
});
|
||||
} catch (error) {
|
||||
this.eventEmitter?.emit('mcp-server-error', {
|
||||
name,
|
||||
current,
|
||||
total,
|
||||
error,
|
||||
});
|
||||
// Log the error but don't let a single failed server stop the others
|
||||
console.error(
|
||||
`Error during discovery for server '${name}': ${getErrorMessage(
|
||||
|
||||
@@ -20,6 +20,7 @@ import { DiscoveredMCPTool } from './mcp-tool.js';
|
||||
import { parse } from 'shell-quote';
|
||||
import { ToolErrorType } from './tool-error.js';
|
||||
import { safeJsonStringify } from '../utils/safeJsonStringify.js';
|
||||
import type { EventEmitter } from 'node:events';
|
||||
|
||||
type ToolParams = Record<string, unknown>;
|
||||
|
||||
@@ -170,7 +171,7 @@ export class ToolRegistry {
|
||||
private config: Config;
|
||||
private mcpClientManager: McpClientManager;
|
||||
|
||||
constructor(config: Config) {
|
||||
constructor(config: Config, eventEmitter?: EventEmitter) {
|
||||
this.config = config;
|
||||
this.mcpClientManager = new McpClientManager(
|
||||
this.config.getMcpServers() ?? {},
|
||||
@@ -179,6 +180,7 @@ export class ToolRegistry {
|
||||
this.config.getPromptRegistry(),
|
||||
this.config.getDebugMode(),
|
||||
this.config.getWorkspaceContext(),
|
||||
eventEmitter,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user