diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 060e79a68d..c38126ec0f 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -115,6 +115,7 @@ export class ClineProvider extends EventEmitter implements McpServerManager.getInstance(this.context, this) .then((hub) => { this.mcpHub = hub + this.mcpHub.registerClient() }) .catch((error) => { this.outputChannel.appendLine(`Failed to initialize MCP Hub: ${error}`) @@ -221,7 +222,7 @@ export class ClineProvider extends EventEmitter implements this.workspaceTracker?.dispose() this.workspaceTracker = undefined - this.mcpHub?.dispose() + await this.mcpHub?.unregisterClient() this.mcpHub = undefined this.customModesManager?.dispose() this.outputChannel.appendLine("Disposed all disposables") diff --git a/src/services/mcp/McpHub.ts b/src/services/mcp/McpHub.ts index 037ff6a9f9..31d0dd8020 100644 --- a/src/services/mcp/McpHub.ts +++ b/src/services/mcp/McpHub.ts @@ -109,6 +109,7 @@ export class McpHub { private isDisposed: boolean = false connections: McpConnection[] = [] isConnecting: boolean = false + private refCount: number = 0 // Reference counter for active clients constructor(provider: ClineProvider) { this.providerRef = new WeakRef(provider) @@ -118,6 +119,27 @@ export class McpHub { this.initializeGlobalMcpServers() this.initializeProjectMcpServers() } + /** + * Registers a client (e.g., ClineProvider) using this hub. + * Increments the reference count. + */ + public registerClient(): void { + this.refCount++ + console.log(`McpHub: Client registered. Ref count: ${this.refCount}`) + } + + /** + * Unregisters a client. Decrements the reference count. + * If the count reaches zero, disposes the hub. + */ + public async unregisterClient(): Promise { + this.refCount-- + console.log(`McpHub: Client unregistered. Ref count: ${this.refCount}`) + if (this.refCount <= 0) { + console.log("McpHub: Last client unregistered. Disposing hub.") + await this.dispose() + } + } /** * Validates and normalizes server configuration @@ -1247,6 +1269,12 @@ export class McpHub { } async dispose(): Promise { + // Prevent multiple disposals + if (this.isDisposed) { + console.log("McpHub: Already disposed.") + return + } + console.log("McpHub: Disposing...") this.isDisposed = true this.removeAllFileWatchers() for (const connection of this.connections) {