Skip to content

improvement(mcp): align tool discovery timeouts and retries with MCP protocol standard#5753

Merged
waleedlatif1 merged 4 commits into
stagingfrom
mcp-discovery-resilience
Jul 18, 2026
Merged

improvement(mcp): align tool discovery timeouts and retries with MCP protocol standard#5753
waleedlatif1 merged 4 commits into
stagingfrom
mcp-discovery-resilience

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Raise the tools/list idle timeout from an aggressive 10s → 30s (derived from the per-server timeout, clamped to the max execution timeout) with a 60s hard cap via maxTotalTimeout, matching the MCP TypeScript SDK's DEFAULT_REQUEST_TIMEOUT_MSEC (60s). Enable resetTimeoutOnProgress + an onprogress handler so slow-but-alive servers aren't spuriously failed with McpError -32001.
  • Retry read-only tools/list on transient transport errors (timeout, connection-closed, 429/5xx, session 404/400, network) with jittered backoff. tools/call stays conservative (session-error retry only) since it isn't idempotent. The SDK doesn't retry POST requests — only SSE streams — so the app owns this.
  • Wire client.onerror so out-of-band transport failures (SSE disconnects, exhausted reconnects) are observed instead of silently dropped, per the SDK's Protocol.onerror contract.
  • UX: map timeouts to a clear user-facing message, and surface refresh/remove failures through the standard emcn toast instead of swallowing them.

Context

A workspace MCP server whose tools/list intermittently took >10s was hard-failing discovery (-32001) even though connect/OAuth succeeded — surfacing as a stuck "Connecting…" / "Failed to discover MCP tools" with the tool count dropping from 40 → 0. The 10s cap was ~6× tighter than the SDK default and below every documented ecosystem norm; this loosens it toward the protocol standard and adds the resilience the SDK expects apps to implement themselves.

Type of Change

  • Bug fix
  • Improvement

Testing

  • apps/sim/lib/mcp unit tests (client/service/utils) + MCP route/component/hook tests pass (116 tests).
  • Added tests: tools/list timeout retries then succeeds; timeout maps to the user-facing lastError; listTools is bounded with idle timeout + hard cap + progress reset.
  • tsc --noEmit clean; biome clean.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

…protocol standard

- Raise tools/list idle timeout 10s -> 30s (derived from per-server config,
  clamped to max execution timeout) with a 60s hard cap via maxTotalTimeout,
  matching the SDK's DEFAULT_REQUEST_TIMEOUT_MSEC. Enable resetTimeoutOnProgress
  with an onprogress handler so slow-but-alive servers are not spuriously failed.
- Retry read-only tools/list on transient transport errors (timeout,
  connection-closed, 429/5xx, session 404/400, network) with jittered backoff.
  tools/call stays conservative (session-error retry only) since it is not
  idempotent. The MCP SDK does not retry POST requests, so the app owns this.
- Wire client.onerror so out-of-band transport failures are observed, not
  silently dropped.
- Map timeouts to a user-facing message and surface refresh/remove failures via
  the standard emcn toast instead of swallowing them.
@vercel

vercel Bot commented Jul 18, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Jul 18, 2026 12:46am

Request Review

@cursor

cursor Bot commented Jul 18, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes core MCP discovery and retry behavior used by refresh and workspace tool loading; scope is bounded to read-only tools/list and error handling, with broad test coverage.

Overview
MCP tool discovery is loosened and hardened so slow-but-healthy servers stop failing spuriously and transient outages recover without user action.

tools/list now uses a 30s idle timeout (from per-server config, clamped) and a 60s hard cap, with resetTimeoutOnProgress and progress logging. Discovery retries transient failures (timeouts, connection closed, 429/5xx, stale session 404/400, network blips) with jittered backoff; persisted lastError maps timeouts to a clear user-facing message. The MCP client logs transport errors via client.onerror.

The refresh API wraps post-discovery workflow schema sync in try/catch so a sync failure still returns 200 with connected status and zero workflows updated. MCP settings shows toasts on refresh/remove failures.

Reviewed by Cursor Bugbot for commit 561a32f. Configure here.

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR makes MCP tool discovery more resilient and improves failure reporting. The main changes are:

  • Adds bounded idle and total timeouts for tools/list.
  • Retries transient discovery failures with jittered backoff.
  • Records transport errors reported outside normal requests.
  • Maps discovery timeouts to clearer user-facing messages.
  • Shows refresh and removal failures through standard toasts.
  • Keeps successful refreshes from failing when workflow synchronization fails.

Confidence Score: 5/5

This looks safe to merge.

  • The updated timeout calculation keeps each discovery request within the intended limit.
  • The new test covers oversized server timeout settings.
  • No blocking issue remains in the changed fix path.

Important Files Changed

Filename Overview
apps/sim/lib/mcp/client.ts Adds transport error logging and applies bounded idle and total timeouts to tool discovery.
apps/sim/lib/mcp/client.test.ts Covers discovery timeout options and oversized configured timeout values.
apps/sim/lib/mcp/service.ts Adds transient discovery error classification, retries, backoff, and clearer timeout messages.
apps/sim/lib/mcp/service.test.ts Covers successful retry behavior and persisted timeout messages.
apps/sim/lib/mcp/utils.ts Defines separate idle and total timeout constants for tool discovery.
apps/sim/app/api/mcp/servers/[id]/refresh/route.ts Prevents secondary workflow synchronization failures from turning a successful refresh into an error response.
apps/sim/app/api/mcp/servers/[id]/refresh/route.test.ts Covers successful refresh responses when workflow synchronization fails.
apps/sim/app/workspace/[workspaceId]/settings/components/mcp/mcp.tsx Displays standard error toasts when server refresh or removal fails.

Reviews (2): Last reviewed commit: "fix(mcp): keep tools/list absolute timeo..." | Re-trigger Greptile

Comment thread apps/sim/lib/mcp/client.ts
…nc throws

Discovery already persists status and caches tools; a syncToolSchemasToWorkflows
failure was escaping the refactored try/catch and returning 500 despite the
refresh having succeeded. Guard the secondary sync so it degrades to zero
workflows updated instead.
A configured per-server timeout above 60s was expanding maxTotalTimeout past
the intended absolute discovery ceiling. Clamp the idle timeout to the ceiling
too so tools/list can never hang the UI beyond it; connect() and callTool()
still honor the full configured/execution timeout.
@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@greptile

@waleedlatif1

Copy link
Copy Markdown
Collaborator Author

@cursor review

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 561a32f. Configure here.

@waleedlatif1
waleedlatif1 merged commit c739dd6 into staging Jul 18, 2026
20 checks passed
@waleedlatif1
waleedlatif1 deleted the mcp-discovery-resilience branch July 18, 2026 00:50
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.

1 participant