diff --git a/src/renderer/components/extensions/mcp/McpServersPanel.tsx b/src/renderer/components/extensions/mcp/McpServersPanel.tsx index 33419f5e..ba03a024 100644 --- a/src/renderer/components/extensions/mcp/McpServersPanel.tsx +++ b/src/renderer/components/extensions/mcp/McpServersPanel.tsx @@ -151,6 +151,10 @@ export const McpServersPanel = ({ return 'Checking runtime status...'; } + if (cliStatus === null || typeof cliStatus === 'undefined') { + return 'Checking runtime availability...'; + } + if (cliStatus?.installed === false) { if (cliStatus.binaryPath && cliStatus.launchError) { return 'The configured runtime was found but failed to start. Open the Dashboard to repair or reinstall it.'; diff --git a/test/renderer/components/extensions/mcp/McpServersPanel.test.ts b/test/renderer/components/extensions/mcp/McpServersPanel.test.ts index 0281c102..34997fc9 100644 --- a/test/renderer/components/extensions/mcp/McpServersPanel.test.ts +++ b/test/renderer/components/extensions/mcp/McpServersPanel.test.ts @@ -149,7 +149,12 @@ describe('McpServersPanel initial browse loading', () => { storeState.mcpDiagnosticsLastCheckedAtByProjectPath = undefined; storeState.runMcpDiagnostics = vi.fn(); storeState.cliStatusLoading = false; - storeState.cliStatus = undefined; + storeState.cliStatus = { + flavor: 'claude', + installed: true, + binaryPath: '/usr/local/bin/claude', + launchError: null, + }; }); afterEach(() => { @@ -359,6 +364,38 @@ describe('McpServersPanel initial browse loading', () => { }); }); + it('waits for runtime hydration before auto-running diagnostics', async () => { + storeState.cliStatus = null; + + const host = document.createElement('div'); + document.body.appendChild(host); + const root = createRoot(host); + + await act(async () => { + root.render( + React.createElement(McpServersPanel, { + projectPath: null, + mcpSearchQuery: '', + mcpSearch: vi.fn(), + mcpSearchResults: [], + mcpSearchLoading: false, + mcpSearchWarnings: [], + selectedMcpServerId: null, + setSelectedMcpServerId: vi.fn(), + }) + ); + await Promise.resolve(); + }); + + expect(storeState.runMcpDiagnostics).not.toHaveBeenCalled(); + expect(host.textContent).toContain('Checking runtime availability...'); + + await act(async () => { + root.unmount(); + await Promise.resolve(); + }); + }); + it('renders provider-neutral waiting copy while diagnostics are still running', async () => { storeState.mcpDiagnosticsLoading = true;