Skip to content

fix(mcp): bound initial tool discovery to a short timeout - #29398

Closed
sanjibani wants to merge 1 commit into
google-gemini:mainfrom
sanjibani:fix/issue-28355-discovery-timeout
Closed

sanjibani wants to merge 1 commit into
google-gemini:mainfrom
sanjibani:fix/issue-28355-discovery-timeout

Conversation

@sanjibani

Copy link
Copy Markdown

Closes #28355

What

When an MCP server declares a tools capability but then sends a tools/list reply with a mismatched JSON-RPC id, the @modelcontextprotocol/sdk drops the bad response (correct per JSON-RPC 2.0) and then waits the full MCP_DEFAULT_TIMEOUT_MSEC (10 minutes) for a matching reply before sending notifications/cancelled.

During that window gemini-cli shows no spinner, no warning, and no partial tool list. The user sees a frozen terminal on every startup, regardless of how many other servers are healthy.

The 10-minute cap is appropriate for active tool calls but wrong for the initial one-shot discovery probe.

Fix

Add a new constant MCP_DISCOVERY_TIMEOUT_MSEC = 10 * 1000 (10 seconds) and use it for the initial discovery path:

  • connectAndDiscover() — the entrypoint that gemini-cli calls at startup
  • McpClient.discoverTools() — the instance method used for post-connection refresh

Active tool calls continue to use MCP_DEFAULT_TIMEOUT_MSEC. An explicit serverConfig.timeout in the user's MCP config still wins over both defaults.

A misbehaving server now fails discovery in 10 seconds with the existing error path (Error discovering tools from <server> emitted via emitMcpDiagnostic) instead of silently blocking startup for the full default window.

Tests

Two new tests in packages/core/src/tools/mcp-client.test.ts under describe('connectAndDiscover discovery timeout (#28355)'):

  1. uses a short discovery timeout by default, not the 10m active-call default — asserts that connectAndDiscover calls mcpClient.listTools with timeout: MCP_DISCOVERY_TIMEOUT_MSEC when no serverConfig.timeout is set, and that the constant is under one minute.
  2. honors an explicit serverConfig.timeout over the discovery default — asserts that a user-configured timeout still wins.

Existing tests for the refresh timeout continue to pass unchanged.

When an MCP server declares a tools capability but then sends a
tools/list reply with a mismatched JSON-RPC id, the @modelcontextprotocol/sdk
drops the bad response (correct per JSON-RPC 2.0) and then waits the full
MCP_DEFAULT_TIMEOUT_MSEC (10 minutes) for a matching reply before sending
notifications/cancelled.

During that window gemini-cli shows no spinner, no warning, and no partial
tool list — the user sees a frozen terminal on every startup. The cap of 10
minutes is appropriate for ongoing tool calls but wrong for the initial
one-shot discovery probe.

Add MCP_DISCOVERY_TIMEOUT_MSEC = 10s and use it for:
- connectAndDiscover() initial listTools
- McpClient.discoverTools() default

Active tool calls continue to use MCP_DEFAULT_TIMEOUT_MSEC. Per-server
serverConfig.timeout still wins over both defaults.

Closes google-gemini#28355
@sanjibani
sanjibani requested a review from a team as a code owner September 18, 2026 18:16
@google-cla

google-cla Bot commented Sep 18, 2026

Copy link
Copy Markdown

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses a startup performance issue where the CLI would hang for up to 10 minutes when an MCP server provided an invalid response during initial tool discovery. By implementing a shorter, dedicated timeout for the discovery phase, the system now fails fast on misbehaving servers, allowing the CLI to remain responsive while maintaining the existing long-duration timeout for active tool calls.

Highlights

  • Timeout Optimization: Introduced a new constant MCP_DISCOVERY_TIMEOUT_MSEC set to 10 seconds to replace the 10-minute default during initial tool discovery.
  • Improved Startup Reliability: Prevents the CLI from hanging during startup when an MCP server fails to respond correctly to discovery probes.
  • Configuration Precedence: Ensures that explicit user-defined timeouts in server configurations still take precedence over the new discovery default.
  • Regression Testing: Added comprehensive unit tests to verify the new short timeout behavior and ensure user-defined timeouts are respected.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩

@github-actions

Copy link
Copy Markdown

🛑 Action Required: Evaluation Approval

Steering changes have been detected in this PR. To prevent regressions, a maintainer must approve the evaluation run before this PR can be merged.

Maintainers:

  1. Go to the Workflow Run Summary.
  2. Click the yellow 'Review deployments' button.
  3. Select the 'eval-gate' environment and click 'Approve'.

Once approved, the evaluation results will be posted here automatically.

@github-actions github-actions Bot added the size/m A medium sized PR label Sep 18, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/M

  • Lines changed: 131
  • Additions: +128
  • Deletions: -3
  • Files changed: 2

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a shorter 10-second discovery timeout (MCP_DISCOVERY_TIMEOUT_MSEC) for initial MCP tool and prompt discovery to prevent misbehaving servers from hanging CLI startup, along with corresponding unit tests. The review feedback correctly identifies a bug in the timeout fallback logic within McpClient: using the nullish coalescing operator on the entire options object causes the default timeout to be completely discarded when options is a truthy object that lacks a timeout property (such as when only a signal is passed). The reviewer suggests spreading the options to ensure the default timeout is correctly applied.

Comment on lines 349 to 352
...(options ?? {
timeout: this.serverConfig.timeout ?? MCP_DEFAULT_TIMEOUT_MSEC,
timeout:
this.serverConfig.timeout ?? MCP_DISCOVERY_TIMEOUT_MSEC,
}),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current implementation uses a nullish coalescing operator on the entire options object (options ?? { timeout: ... }). When refreshTools() calls discoverTools() with { signal: abortController.signal }, options is truthy, so the default timeout is completely omitted. This means the timeout is not applied during post-connection refresh. Using object spreading with the default timeout defined first ensures that the default is always applied unless explicitly overridden by options.timeout. Additionally, we should rely on the schema as the single source of truth for the configuration default of this.serverConfig.timeout, avoiding the redundant nullish coalescing operator with MCP_DISCOVERY_TIMEOUT_MSEC.

        timeout: this.serverConfig.timeout,
        ...options,
References
  1. Rely on the schema as the single source of truth for configuration defaults, avoiding redundant nullish coalescing operators.

@gemini-cli gemini-cli Bot added priority/p1 Important and should be addressed in the near term. area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality labels Sep 18, 2026
@gemini-cli

gemini-cli Bot commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Hi there! Thank you for your interest in contributing to Gemini CLI.

To ensure we maintain high code quality and focus on our prioritized roadmap, we only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'.

This PR will be closed in 7 days if it remains without that designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.

@gemini-cli

gemini-cli Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.

This branch is waiting to be deployed

1 waiting deployment
eval-gate — d595006b Waiting Sep 18, 2026 by sanjibani via Evaluate Steering & Regressions #2009
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality priority/p1 Important and should be addressed in the near term. size/m A medium sized PR status/pr-nudge-sent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MCP tool discovery silently blocks for 10 minutes when server returns a mismatched response id

1 participant