From 87e12036ba13c158997a337583caebac463ab3a2 Mon Sep 17 00:00:00 2001 From: Roo Code Date: Sat, 9 Aug 2025 20:58:56 +0000 Subject: [PATCH] fix: prevent duplicate MCP server instances on refresh - Add proper cleanup delays in restartConnection and refreshAllConnections - Ensure transport and client are properly closed before creating new connections - Fix race condition where new connections were created before old ones were fully cleaned up - Maintain backward compatibility with existing tests Fixes issue where refreshing MCP servers or individual server refresh was causing duplicate instances without cleaning up the old ones. --- src/services/mcp/McpHub.ts | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/services/mcp/McpHub.ts b/src/services/mcp/McpHub.ts index 271c6e1fb3..312f05e534 100644 --- a/src/services/mcp/McpHub.ts +++ b/src/services/mcp/McpHub.ts @@ -1007,8 +1007,13 @@ export class McpHub { for (const connection of connections) { try { if (connection.type === "connected") { - await connection.transport.close() - await connection.client.close() + // Close transport first, then client + if (connection.transport) { + await connection.transport.close() + } + if (connection.client) { + await connection.client.close() + } } } catch (error) { console.error(`Failed to close transport for ${name}:`, error) @@ -1188,7 +1193,13 @@ export class McpHub { await this.notifyWebviewOfServerChanges() await delay(500) // artificial delay to show user that server is restarting try { - await this.deleteConnection(serverName, connection.server.source) + // Ensure complete cleanup before restarting + const serverSource = connection.server.source || "global" + await this.deleteConnection(serverName, serverSource) + + // Add small delay to ensure cleanup is complete + await delay(100) + // Parse the config to validate it const parsedConfig = JSON.parse(config) try { @@ -1196,7 +1207,7 @@ export class McpHub { const validatedConfig = this.validateServerConfig(parsedConfig, serverName) // Try to connect again using validated config - await this.connectToServer(serverName, validatedConfig, connection.server.source || "global") + await this.connectToServer(serverName, validatedConfig, serverSource) vscode.window.showInformationMessage(t("mcp:info.server_connected", { serverName })) } catch (validationError) { this.showErrorMessage(`Invalid configuration for MCP server "${serverName}"`, validationError) @@ -1265,6 +1276,9 @@ export class McpHub { await this.deleteConnection(conn.server.name, conn.server.source) } + // Add small delay to ensure cleanup is complete + await delay(100) + // Re-initialize all servers from scratch // This ensures proper initialization including fetching tools, resources, etc. await this.initializeMcpServers("global")