diff --git a/src/services/mcp/McpServerManager.ts b/src/services/mcp/McpServerManager.ts index 20ed2b8322..e15f9db0a7 100644 --- a/src/services/mcp/McpServerManager.ts +++ b/src/services/mcp/McpServerManager.ts @@ -10,21 +10,44 @@ export class McpServerManager { private static instance: McpHub | null = null private static readonly GLOBAL_STATE_KEY = "mcpHubInstanceId" private static providers: Set = new Set() + private static initializationPromise: Promise | null = null /** * Get the singleton McpHub instance. * Creates a new instance if one doesn't exist. + * Thread-safe implementation using a promise-based lock. */ static async getInstance(context: vscode.ExtensionContext, provider: ClineProvider): Promise { // Register the provider this.providers.add(provider) - if (!this.instance) { - this.instance = new McpHub(provider) - // Store a unique identifier in global state to track the primary instance - await context.globalState.update(this.GLOBAL_STATE_KEY, Date.now().toString()) + // If we already have an instance, return it + if (this.instance) { + return this.instance } - return this.instance + + // If initialization is in progress, wait for it + if (this.initializationPromise) { + return this.initializationPromise + } + + // Create a new initialization promise + this.initializationPromise = (async () => { + try { + // Double-check instance in case it was created while we were waiting + if (!this.instance) { + this.instance = new McpHub(provider) + // Store a unique identifier in global state to track the primary instance + await context.globalState.update(this.GLOBAL_STATE_KEY, Date.now().toString()) + } + return this.instance + } finally { + // Clear the initialization promise after completion or error + this.initializationPromise = null + } + })() + + return this.initializationPromise } /**