google-gemini / google-gemini/gemini-cli

bug: MCP tools/list refresh path drops the configured server timeout (silently capped at 60s by SDK default)

Open Beginner friendly
#29,041 0 comments 0 reactions 0 assignees View on GitHub
area/agent status/need-triage
Dominant language
TypeScript
Stars
107k
Forks
14.6k
Avg merge
2d 3h
Merged PRs (30d)
45

Description

## What happened?

`MCPClient.discover()` builds the options for `discoverTools()` with a spread that **replaces** rather than merges the configured timeout when any options object is provided. The `tools/list_changed` refresh path passes `{ signal }`, so `timeout` ends up `undefined` and falls back to the MCP SDK's default **60 seconds** — silently discarding `serverConfig.timeout` (default 10 minutes) and making the surrounding 10-minute abort controller dead in practice, since the SDK's own timer fires first.

## Affected code

`packages/core/src/tools/mcp-client.ts:334-346`:

```ts
return discoverTools(
this.serverName,
this.serverConfig,
this.client!,
cliConfig,
messageBus,
{
...(options ?? {
timeout: this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
}),
progressReporter: this,
},
);
```

The refresh caller (`packages/core/src/tools/mcp-client.ts:717-725`):

```ts
const timeoutMs = this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC;
const abortController = new AbortController();
const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
// ...
let newTools = await this.discoverTools(this.cliConfig,
registries.toolRegistry.getMessageBus(),
{ signal: abortController.signal }, // options present -> timeout branch skipped
);
```

Verified in the SDK: `@modelcontextprotocol/sdk` `shared/protocol.js` uses `options?.timeout ?? DEFAULT_REQUEST_TIMEOUT_MSEC` (60000).

## How can this be reproduced?

1. Configure an MCP server with `timeout: 600000` whose `tools/list` takes >60 s on regeneration.
2. Initial discovery at startup works (explicit timeout passed).
3. Trigger a tool-list-changed notification → refresh fails/times out at ~60 s despite the configured 10-minute budget.

## What did you expect to happen?

Refresh requests honor `serverConfig.timeout` like initial discovery does.

## Suggested direction

Merge instead of replace:

```ts
{
timeout: this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
...options,
progressReporter: this,
}
```

---

*Found by source audit on current `main` (commit `5411f113c`); platform-independent. Related but distinct: #28355 covers discovery blocking on mismatched responses; this is the dropped-timeout spread on the refresh path.*

Contributor guide

Open the contributing guide

Research direction

Start in packages/core/src/tools/mcp-client.ts, reading MCPClient.discoverTools at lines 334-346 and the tools/list_changed refresh path at lines 717-725. Trace how the options object reaches discoverTools and verify that refresh requests retain serverConfig.timeout rather than the SDK default; done when a configured timeout is honored on both initial discovery and refresh.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
88/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.