Skip to content

Commit 5949d56

Browse files
authored
feat(ui): Show waiting MCP servers in ConfigInitDisplay (#13721)
1 parent 5bed970 commit 5949d56

File tree

3 files changed

+64
-7
lines changed

3 files changed

+64
-7
lines changed

packages/cli/src/ui/components/ConfigInitDisplay.test.tsx

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { act } from 'react';
88
import { render } from '../../test-utils/render.js';
9+
import { waitFor } from '../../test-utils/async.js';
910
import { ConfigInitDisplay } from './ConfigInitDisplay.js';
1011
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
1112
import { AppEvent } from '../../utils/events.js';
@@ -63,7 +64,7 @@ describe('ConfigInitDisplay', () => {
6364
const { lastFrame } = render(<ConfigInitDisplay />);
6465

6566
// Wait for listener to be registered
66-
await vi.waitFor(() => {
67+
await waitFor(() => {
6768
if (!listener) throw new Error('Listener not registered yet');
6869
});
6970

@@ -84,7 +85,42 @@ describe('ConfigInitDisplay', () => {
8485
});
8586

8687
// Wait for the UI to update
87-
await vi.waitFor(() => {
88+
await waitFor(() => {
89+
expect(lastFrame()).toMatchSnapshot();
90+
});
91+
});
92+
93+
it('truncates list of waiting servers if too many', async () => {
94+
let listener: ((clients?: Map<string, McpClient>) => void) | undefined;
95+
mockOn.mockImplementation((event, fn) => {
96+
if (event === AppEvent.McpClientUpdate) {
97+
listener = fn;
98+
}
99+
});
100+
101+
const { lastFrame } = render(<ConfigInitDisplay />);
102+
103+
await waitFor(() => {
104+
if (!listener) throw new Error('Listener not registered yet');
105+
});
106+
107+
const mockClientConnecting = {
108+
getStatus: () => MCPServerStatus.CONNECTING,
109+
} as McpClient;
110+
111+
const clients = new Map<string, McpClient>([
112+
['s1', mockClientConnecting],
113+
['s2', mockClientConnecting],
114+
['s3', mockClientConnecting],
115+
['s4', mockClientConnecting],
116+
['s5', mockClientConnecting],
117+
]);
118+
119+
act(() => {
120+
listener!(clients);
121+
});
122+
123+
await waitFor(() => {
88124
expect(lastFrame()).toMatchSnapshot();
89125
});
90126
});
@@ -99,7 +135,7 @@ describe('ConfigInitDisplay', () => {
99135

100136
const { lastFrame } = render(<ConfigInitDisplay />);
101137

102-
await vi.waitFor(() => {
138+
await waitFor(() => {
103139
if (!listener) throw new Error('Listener not registered yet');
104140
});
105141

@@ -110,7 +146,7 @@ describe('ConfigInitDisplay', () => {
110146
});
111147
}
112148

113-
await vi.waitFor(() => {
149+
await waitFor(() => {
114150
expect(lastFrame()).toMatchSnapshot();
115151
});
116152
});

packages/cli/src/ui/components/ConfigInitDisplay.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,28 @@ export const ConfigInitDisplay = () => {
2121
return;
2222
}
2323
let connected = 0;
24-
for (const client of clients.values()) {
24+
const connecting: string[] = [];
25+
for (const [name, client] of clients.entries()) {
2526
if (client.getStatus() === MCPServerStatus.CONNECTED) {
2627
connected++;
28+
} else {
29+
connecting.push(name);
2730
}
2831
}
29-
setMessage(`Connecting to MCP servers... (${connected}/${clients.size})`);
32+
33+
if (connecting.length > 0) {
34+
const maxDisplay = 3;
35+
const displayedServers = connecting.slice(0, maxDisplay).join(', ');
36+
const remaining = connecting.length - maxDisplay;
37+
const suffix = remaining > 0 ? `, +${remaining} more` : '';
38+
setMessage(
39+
`Connecting to MCP servers... (${connected}/${clients.size}) - Waiting for: ${displayedServers}${suffix}`,
40+
);
41+
} else {
42+
setMessage(
43+
`Connecting to MCP servers... (${connected}/${clients.size})`,
44+
);
45+
}
3046
};
3147

3248
appEvents.on(AppEvent.McpClientUpdate, onChange);

packages/cli/src/ui/components/__snapshots__/ConfigInitDisplay.test.tsx.snap

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ exports[`ConfigInitDisplay > renders initial state 1`] = `
1010
Spinner Initializing..."
1111
`;
1212

13+
exports[`ConfigInitDisplay > truncates list of waiting servers if too many 1`] = `
14+
"
15+
Spinner Connecting to MCP servers... (0/5) - Waiting for: s1, s2, s3, +2 more"
16+
`;
17+
1318
exports[`ConfigInitDisplay > updates message on McpClientUpdate event 1`] = `
1419
"
15-
Spinner Connecting to MCP servers... (1/2)"
20+
Spinner Connecting to MCP servers... (1/2) - Waiting for: server2"
1621
`;

0 commit comments

Comments
 (0)