mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-06-26 01:16:24 +00:00
* ⏳ fix: Extend and decouple MCP OAuth flow timeouts The OAuth auth button disappeared after 2 minutes (the internal OAuth handling timeout) while the flow state lived for 3 minutes, leaving users who didn't click immediately stuck in an unrecoverable re-auth loop. The handling timeouts also reused the connection/init timeout, so a short initTimeout would shrink the OAuth window further. - Add MCP_OAUTH_HANDLING_TIMEOUT (10m) and MCP_OAUTH_FLOW_TTL (15m) to mcpConfig - Decouple the reactive/proactive OAuth waits from initTimeout/connectionTimeout - Use OAUTH_FLOW_TTL for the FlowStateManager TTL and the UI status window - Ensure the flow TTL outlives the handling timeout, fixing the "Flow state not found" race - Remove dead FLOW_TTL constant and document new env vars Fixes #13615 * ⏳ fix: Coordinate OAuth pending window with handling timeout Address Codex review: the extended OAuth wait was still capped by other timeouts that were not updated. - Align PENDING_STALE_MS (button validity + pending-flow reuse window) with MCP_OAUTH_HANDLING_TIMEOUT so a flow stays reusable for the full wait instead of 2 minutes (Finding 3) - Clamp MCP_OAUTH_FLOW_TTL to never fall below the handling timeout so a callback near the deadline still finds its flow state (Finding 2) - Floor attemptToConnect's timeout to the handling window for OAuth servers so the reactive in-connect OAuth wait is not killed by the 30s connection timeout (Finding 1) - Update flow staleness tests to reference the threshold symbolically * ⏳ fix: Align OAuth window across status, action flows, and client polling Address Codex round 2: extending the server wait exposed three more windows that were still capped or now over-extended. - checkOAuthFlowStatus reports a PENDING flow as active only within the usable PENDING_STALE_MS window, not the longer Keyv retention TTL, so the connect button reappears instead of a stuck 'connecting' state - Give Action (custom tool) OAuth its own FlowStateManager on the prior 3-minute TTL so the longer MCP OAuth TTL can't leave an action tool call waiting up to 15 minutes - Extend the MCP server-card client polling to the 10-minute handling window so a user who completes OAuth after 3 minutes is still picked up * 🧪 test: Make stale-flow CSRF test track PENDING_STALE_MS The CSRF-fallback stale-flow test hardcoded a 3-minute age, which is now within the 10-minute PENDING_STALE_MS window and was wrongly treated as active. Derive the age from PENDING_STALE_MS so it tracks the constant. * ⏳ fix: Add grace buffers and surface OAuth timeout to the client Address Codex round 3 (near-deadline edges): - Clamp MCP_OAUTH_FLOW_TTL to handling timeout + 60s grace (not equality), so flow state outlives the wait instead of expiring at the same instant - Extend attemptToConnect's OAuth floor by a 60s grace so a user who authorizes near the deadline still gets the post-OAuth reconnect - Surface OAUTH_HANDLING_TIMEOUT on the connection-status response and have the client poll for the configured window instead of a hardcoded 10 minutes, so a tuned server deadline isn't capped on the client * ⏳ fix: Refresh client OAuth timeout from the first status refetch If the connection-status cache is empty when polling starts, the client captured the 10-minute fallback and never picked up a tuned oauthTimeout. Re-read it after each refetch so a longer configured deadline is honored even on a cold cache. * 📝 refactor: Type oauthTimeout on MCPConnectionStatusResponse Declare the oauthTimeout field on the shared response type in data-provider instead of an ad-hoc inline cast in the client hook, and replace the pre-existing 'as any' on the status query read with the typed getQueryData. Type-level only; no runtime change.
59 lines
1.7 KiB
JavaScript
59 lines
1.7 KiB
JavaScript
const { EventSource } = require('eventsource');
|
|
const { Time } = require('librechat-data-provider');
|
|
const {
|
|
mcpConfig,
|
|
MCPManager,
|
|
FlowStateManager,
|
|
MCPServersRegistry,
|
|
OAuthReconnectionManager,
|
|
} = require('@librechat/api');
|
|
const logger = require('./winston');
|
|
|
|
global.EventSource = EventSource;
|
|
|
|
/** @type {FlowStateManager} */
|
|
let flowManager = null;
|
|
/** @type {FlowStateManager} */
|
|
let actionFlowManager = null;
|
|
|
|
/**
|
|
* Flow manager for MCP OAuth flows. Uses the longer MCP OAuth TTL so the auth
|
|
* button and flow state outlive the user-completion window.
|
|
* @param {Keyv} flowsCache
|
|
* @returns {FlowStateManager}
|
|
*/
|
|
function getFlowStateManager(flowsCache) {
|
|
if (!flowManager) {
|
|
flowManager = new FlowStateManager(flowsCache, {
|
|
ttl: mcpConfig.OAUTH_FLOW_TTL,
|
|
});
|
|
}
|
|
return flowManager;
|
|
}
|
|
|
|
/**
|
|
* Flow manager for Action (custom tool) OAuth flows. Kept on the shorter TTL so an
|
|
* unclicked action login does not leave the tool call waiting for the MCP OAuth window.
|
|
* @param {Keyv} flowsCache
|
|
* @returns {FlowStateManager}
|
|
*/
|
|
function getActionFlowStateManager(flowsCache) {
|
|
if (!actionFlowManager) {
|
|
actionFlowManager = new FlowStateManager(flowsCache, {
|
|
ttl: Time.ONE_MINUTE * 3,
|
|
});
|
|
}
|
|
return actionFlowManager;
|
|
}
|
|
|
|
module.exports = {
|
|
logger,
|
|
createMCPServersRegistry: MCPServersRegistry.createInstance,
|
|
getMCPServersRegistry: MCPServersRegistry.getInstance,
|
|
createMCPManager: MCPManager.createInstance,
|
|
getMCPManager: MCPManager.getInstance,
|
|
getFlowStateManager,
|
|
getActionFlowStateManager,
|
|
createOAuthReconnectionManager: OAuthReconnectionManager.createInstance,
|
|
getOAuthReconnectionManager: OAuthReconnectionManager.getInstance,
|
|
};
|