LibreChat/packages
Danny Avila 41c92dfd06
⏱️ fix: Bound MCP Tool Discovery With a Caller Deadline (#15346)
* fix: bound MCP tool discovery end to end with a caller deadline

connectionTimeout bounds a single connect() only. Discovery then spends
it again on the unauthenticated fallback and hands tools/list its own
30s budget, so a caller working to a deadline had no way to cap the
whole operation.

Thread an optional absolute deadline through discovery into both
connect() and the tools/list walk, and dispose a timed-out authenticated
connection before the fallback opens its own socket — withTimeout does
not cancel the connect it abandoned, so the two were briefly concurrent.

Passive catalog recovery now sets one 3s per-server budget instead of a
per-attempt timeout it could spend several times over.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xr1Dabvdn1mzzyYgpJgU5B

* fix: close deadline gaps in the app path, refresh wait, and disposal race

Codex review of the deadline threading found three real gaps:

- discoverServerTools returns through an app-connection fast path that
  never reached the factory, so its tools/list kept the 30s default.
- fetchOrderedToolsSnapshot checked the deadline before awaiting a
  refresh but the refresh runs on the connection's own budget, so an
  in-flight one could still hold a budgeted caller for that budget.
  Stop waiting on it rather than adopting it.
- connectClient never rechecked isDisposed after awaiting
  constructTransport, so a connect abandoned by its caller could
  assign a transport and connect after dispose() had already found
  nothing to close. Disposing before the fallback widened that window,
  so bound the attempt to its own disposal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xr1Dabvdn1mzzyYgpJgU5B

* fix: close the transport itself when disposal beats connect

Rewriting the disposal-race test against a real SDK server and transport
exposed a defect the mocked version could not see: client.close() only
closes a transport the client has adopted, and it has not adopted one
when disposal lands before client.connect(). The abandoned attempt's
session therefore stayed open and the reference was merely dropped.

Close the transport directly before closing the client. The test now
asserts the server observed the close, which fails against the previous
fix.
2026-08-30 07:44:52 -04:00
..
api ⏱️ fix: Bound MCP Tool Discovery With a Caller Deadline (#15346) 2026-08-30 07:44:52 -04:00
client 🖼️ refactor: Consolidate Provider Icons Into a Single Registry (#15148) 2026-08-24 13:00:38 -04:00
data-provider 📬 feat: Establish Background Continuation Admission (#15348) 2026-08-30 06:51:36 -04:00
data-schemas 🛎️ fix: Enroll Remote Agent Runs in the Generation Lifecycle (#15349) 2026-08-30 07:14:13 -04:00