diff --git a/packages/core/src/tools/mcp-client-manager.test.ts b/packages/core/src/tools/mcp-client-manager.test.ts index bbab5ef12d..352c2c12f0 100644 --- a/packages/core/src/tools/mcp-client-manager.test.ts +++ b/packages/core/src/tools/mcp-client-manager.test.ts @@ -103,6 +103,43 @@ describe('McpClientManager', () => { expect(manager.getDiscoveryState()).toBe(MCPDiscoveryState.COMPLETED); }); + it('should mark discovery completed when all configured servers are user-disabled', async () => { + mockConfig.getMcpServers.mockReturnValue({ + 'test-server': {}, + }); + mockConfig.getMcpEnablementCallbacks.mockReturnValue({ + isSessionDisabled: vi.fn().mockReturnValue(false), + isFileEnabled: vi.fn().mockResolvedValue(false), + }); + + const manager = new McpClientManager('0.0.1', toolRegistry, mockConfig); + const promise = manager.startConfiguredMcpServers(); + expect(manager.getDiscoveryState()).toBe(MCPDiscoveryState.IN_PROGRESS); + await promise; + + expect(manager.getDiscoveryState()).toBe(MCPDiscoveryState.COMPLETED); + expect(manager.getMcpServerCount()).toBe(0); + expect(mockedMcpClient.connect).not.toHaveBeenCalled(); + expect(mockedMcpClient.discover).not.toHaveBeenCalled(); + }); + + it('should mark discovery completed when all configured servers are blocked', async () => { + mockConfig.getMcpServers.mockReturnValue({ + 'test-server': {}, + }); + mockConfig.getBlockedMcpServers.mockReturnValue(['test-server']); + + const manager = new McpClientManager('0.0.1', toolRegistry, mockConfig); + const promise = manager.startConfiguredMcpServers(); + expect(manager.getDiscoveryState()).toBe(MCPDiscoveryState.IN_PROGRESS); + await promise; + + expect(manager.getDiscoveryState()).toBe(MCPDiscoveryState.COMPLETED); + expect(manager.getMcpServerCount()).toBe(0); + expect(mockedMcpClient.connect).not.toHaveBeenCalled(); + expect(mockedMcpClient.discover).not.toHaveBeenCalled(); + }); + it('should not discover tools if folder is not trusted', async () => { mockConfig.getMcpServers.mockReturnValue({ 'test-server': {}, diff --git a/packages/core/src/tools/mcp-client-manager.ts b/packages/core/src/tools/mcp-client-manager.ts index b38b00616b..a6783788e8 100644 --- a/packages/core/src/tools/mcp-client-manager.ts +++ b/packages/core/src/tools/mcp-client-manager.ts @@ -337,6 +337,15 @@ export class McpClientManager { this.maybeDiscoverMcpServer(name, config), ), ); + + // If every configured server was skipped (for example because all are + // disabled by user settings), no discovery promise is created. In that + // case we must still mark discovery complete or the UI will wait forever. + if (this.discoveryState === MCPDiscoveryState.IN_PROGRESS) { + this.discoveryState = MCPDiscoveryState.COMPLETED; + this.eventEmitter?.emit('mcp-client-update', this.clients); + } + await this.cliConfig.refreshMcpContext(); }