Skip to content

Make MCP client initialization timeout configurable via ToolOptions - #256

Closed
Grant Harris (gwharris7) wants to merge 7 commits into
mainfrom
feature/configurable-mcp-timeout
Closed

Grant Harris (gwharris7) wants to merge 7 commits into
mainfrom
feature/configurable-mcp-timeout

Conversation

@gwharris7

Copy link
Copy Markdown
Contributor

Summary

  • Add nullable McpClientInitializationTimeoutSeconds property to ToolOptions so consumers can override the MCP client initialization timeout
  • When not set (null), the MCP SDK default (60s) is used — no behavioral change for existing consumers
  • When set, both McpClientOptions.InitializationTimeout and HttpClient.Timeout are configured to match

Motivation

Consumers connecting to the MCP platform may experience OperationCanceledException when downstream dependencies are slow. The MCP SDK's default 60-second initialization timeout is not configurable through ToolOptions, leaving no way for consumers to adjust it for their agents.

Usage

// Default behavior — no change needed, SDK default timeout applies
var options = new ToolOptions();
await configService.GetMcpClientToolsAsync(turnContext, serverConfig, token, options);

// Custom timeout for slow environments
var options = new ToolOptions
{
    McpClientInitializationTimeoutSeconds = 180 // 3 minutes
};
await configService.GetMcpClientToolsAsync(turnContext, serverConfig, token, options);

Changes

  • src/Tooling/Core/Models/ToolOptions.cs — Add int? McpClientInitializationTimeoutSeconds property
  • src/Tooling/Core/Services/McpToolServerConfigurationService.cs — Apply timeout only when explicitly set

Test plan

  • Verified default behavior (null) uses MCP SDK default timeout
  • Verified explicit value is applied to both McpClientOptions.InitializationTimeout and HttpClient.Timeout
  • Built and tested end-to-end with sample-agent against MCP platform

Replaces #212 (fork PR could not trigger CodeQL default setup)
Original approvals: Sellakumaran Kanagarathnam (@sellakumaran) ajmfehr

Rodrigo Matiazo and others added 7 commits March 10, 2026 15:49
Add nullable McpClientInitializationTimeoutSeconds property to ToolOptions
so consumers can override the MCP client initialization timeout. When null
(default), the MCP SDK default is used. When set, both McpClientOptions
and HttpClient.Timeout are configured to match.

Co-Authored-By: Claude Code <noreply@anthropic.com>
- Add input validation (1-600s range) with ArgumentOutOfRangeException
- Document valid range in ToolOptions XML docs
- Preserve original SDK behavior when timeout is null: call
  McpClientFactory.CreateAsync without McpClientOptions instead of
  passing a default instance
- Add 13 unit tests covering: null default, valid/invalid values,
  ArgumentOutOfRangeException for out-of-bounds inputs

Co-Authored-By: Claude Code <noreply@anthropic.com>
- Extract GetValidatedInitializationTimeout internal static helper so the
  timeout TimeSpan is computed once and reused for both HttpClient.Timeout
  and McpClientOptions.InitializationTimeout.
- Use nameof(ToolOptions.McpClientInitializationTimeoutSeconds) as the
  ArgumentOutOfRangeException ParamName so the offending property is
  obvious to consumers.
- Loosen the GetMcpClientToolsAsync exception assertion to accept either
  a direct ArgumentOutOfRangeException or one wrapped by
  InvalidOperationException so the test is decoupled from the outer
  catch behavior.
- Remove the unused IConfiguration mock field from the timeout test class.
- Add direct unit coverage for GetValidatedInitializationTimeout (null,
  valid, and invalid inputs) so the behavioral change is verifiable
  without a McpClientFactory seam.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@gwharris7

Copy link
Copy Markdown
Contributor Author

No longer needed — PR #212 was merged successfully.

Copilot AI 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.

Pull request overview

This PR adds an opt-in configuration surface on ToolOptions that allows consumers to override the MCP client initialization timeout, and wires that value through to MCP client creation so slow downstream dependencies don’t cause premature initialization cancellations.

Changes:

  • Added ToolOptions.McpClientInitializationTimeoutSeconds (int?) to allow overriding the MCP SDK’s initialization timeout while preserving default behavior when unset.
  • Applied the configured timeout (when set) to both McpClientOptions.InitializationTimeout and the HttpClient.Timeout used by the SSE transport.
  • Added unit tests covering default/null behavior, validation bounds, and timeout conversion logic.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/Tooling/Core/Services/McpToolServerConfigurationService.cs Validates and applies an optional initialization timeout during MCP client creation; adds helper to validate/convert seconds to TimeSpan?.
src/Tooling/Core/Models/ToolOptions.cs Introduces a nullable McpClientInitializationTimeoutSeconds option with XML documentation.
src/Tests/Microsoft.Agents.A365.Tooling.Tests/Services/McpClientInitializationTimeoutTests.cs Adds unit tests for the new option and validation helper.

/// and the underlying HTTP connection. Increase this value if the MCP server performs
/// slow operations during initialization (e.g., token exchanges in test environments).
/// When null, the MCP SDK default timeout is used.
/// Valid range: 1 to 600 seconds. Values outside this range will throw <see cref="ArgumentOutOfRangeException"/>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants