Skip to content

Commit e4204d5

Browse files
authored
fix(core): create new McpClient on restart to apply updated config (#20126)
1 parent baccda9 commit e4204d5

2 files changed

Lines changed: 52 additions & 21 deletions

File tree

packages/core/src/tools/mcp-client-manager.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,40 @@ describe('McpClientManager', () => {
264264
'No MCP server registered with the name "non-existent"',
265265
);
266266
});
267+
268+
it('should create a new McpClient with updated config on restart', async () => {
269+
const originalConfig = { command: 'node', args: ['--port', '8000'] };
270+
const updatedConfig = { command: 'node', args: ['--port', '9000'] };
271+
272+
mockConfig.getMcpServers.mockReturnValue({
273+
'test-server': originalConfig,
274+
});
275+
276+
// Track McpClient constructor calls
277+
const constructorCalls: unknown[][] = [];
278+
vi.mocked(McpClient).mockImplementation((...args: unknown[]) => {
279+
constructorCalls.push(args);
280+
return mockedMcpClient;
281+
});
282+
mockedMcpClient.getServerConfig.mockReturnValue(originalConfig);
283+
284+
const manager = new McpClientManager('0.0.1', toolRegistry, mockConfig);
285+
await manager.startConfiguredMcpServers();
286+
287+
// First call should use the original config
288+
expect(constructorCalls).toHaveLength(1);
289+
expect(constructorCalls[0][1]).toBe(originalConfig);
290+
291+
// Simulate config file change and hot-reload
292+
mockConfig.getMcpServers.mockReturnValue({
293+
'test-server': updatedConfig,
294+
});
295+
await manager.startConfiguredMcpServers();
296+
297+
// A NEW McpClient should have been constructed with the updated config
298+
expect(constructorCalls).toHaveLength(2);
299+
expect(constructorCalls[1][1]).toBe(updatedConfig);
300+
});
267301
});
268302

269303
describe('getMcpInstructions', () => {

packages/core/src/tools/mcp-client-manager.ts

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -221,30 +221,27 @@ export class McpClientManager {
221221
(async () => {
222222
try {
223223
if (existing) {
224+
this.clients.delete(name);
224225
await existing.disconnect();
225226
}
226227

227-
const client =
228-
existing ??
229-
new McpClient(
230-
name,
231-
config,
232-
this.toolRegistry,
233-
this.cliConfig.getPromptRegistry(),
234-
this.cliConfig.getResourceRegistry(),
235-
this.cliConfig.getWorkspaceContext(),
236-
this.cliConfig,
237-
this.cliConfig.getDebugMode(),
238-
this.clientVersion,
239-
async () => {
240-
debugLogger.log('Tools changed, updating Gemini context...');
241-
await this.scheduleMcpContextRefresh();
242-
},
243-
);
244-
if (!existing) {
245-
this.clients.set(name, client);
246-
this.eventEmitter?.emit('mcp-client-update', this.clients);
247-
}
228+
const client = new McpClient(
229+
name,
230+
config,
231+
this.toolRegistry,
232+
this.cliConfig.getPromptRegistry(),
233+
this.cliConfig.getResourceRegistry(),
234+
this.cliConfig.getWorkspaceContext(),
235+
this.cliConfig,
236+
this.cliConfig.getDebugMode(),
237+
this.clientVersion,
238+
async () => {
239+
debugLogger.log('Tools changed, updating Gemini context...');
240+
await this.scheduleMcpContextRefresh();
241+
},
242+
);
243+
this.clients.set(name, client);
244+
this.eventEmitter?.emit('mcp-client-update', this.clients);
248245
try {
249246
await client.connect();
250247
await client.discover(this.cliConfig);

0 commit comments

Comments
 (0)