mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-02-19 08:58:09 +01:00
♻️ refactor: On-demand MCP connections: remove proactive reconnect, default to available (#11839)
* feat: Implement reconnection staggering and backoff jitter for MCP connections
- Enhanced the reconnection logic in OAuthReconnectionManager to stagger reconnection attempts for multiple servers, reducing the risk of connection storms.
- Introduced a backoff delay with random jitter in MCPConnection to improve reconnection behavior during network issues.
- Updated the ConnectionsRepository to handle multiple server connections concurrently with a defined concurrency limit.
Added tests to ensure the new reconnection strategy works as intended.
* refactor: Update MCP server query configuration for improved data freshness
- Reduced stale time from 5 minutes to 30 seconds to ensure quicker updates on server initialization.
- Enabled refetching on window focus and mount to enhance data accuracy during user interactions.
* ♻️ refactor: On-demand MCP connections; remove proactive reconnection, default to available
- Remove reconnectServers() from refresh controller (connection storm root cause)
- Stop gating server selection on connection status; add to selection immediately
- Render agent panel tools from DB cache, not live connection status
- Proceed to cached tools on init failure (only gate on OAuth)
- Remove unused batchToggleServers()
- Reduce useMCPServersQuery staleTime from 5min to 30s, enable refetchOnMount/WindowFocus
* refactor: Optimize MCP tool initialization and server connection logic
- Adjusted tool initialization to only occur if no cached tools are available, improving efficiency.
- Updated comments for clarity on server connection and tool fetching processes.
- Removed unnecessary connection status checks during server selection to streamline the user experience.
This commit is contained in:
parent
dbf8cd40d3
commit
3bf715e05e
9 changed files with 101 additions and 63 deletions
|
|
@ -46,7 +46,7 @@ export default function MCPTools({
|
|||
return null;
|
||||
}
|
||||
|
||||
if (serverInfo.isConnected) {
|
||||
if (serverInfo?.tools?.length && serverInfo.tools.length > 0) {
|
||||
return (
|
||||
<MCPTool key={`${serverInfo.serverName}-${agentId}`} serverInfo={serverInfo} />
|
||||
);
|
||||
|
|
|
|||
|
|
@ -96,17 +96,17 @@ function MCPToolSelectDialog({
|
|||
await new Promise((resolve) => setTimeout(resolve, 500));
|
||||
}
|
||||
|
||||
// Then initialize server if needed
|
||||
// Only initialize if no cached tools exist; skip if tools are already available from DB
|
||||
const serverInfo = mcpServersMap.get(serverName);
|
||||
if (!serverInfo?.isConnected) {
|
||||
if (!serverInfo?.tools?.length) {
|
||||
const result = await initializeServer(serverName);
|
||||
if (result?.success && result.oauthRequired && result.oauthUrl) {
|
||||
if (result?.oauthRequired && result.oauthUrl) {
|
||||
setIsInitializing(null);
|
||||
return;
|
||||
return; // OAuth flow must complete first
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, add tools to form
|
||||
// Add tools to form (refetches from backend's persisted cache)
|
||||
await addToolsToForm(serverName);
|
||||
setIsInitializing(null);
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ export const useMCPServersQuery = <TData = t.MCPServersListResponse>(
|
|||
[QueryKeys.mcpServers],
|
||||
() => dataService.getMCPServers(),
|
||||
{
|
||||
staleTime: 1000 * 60 * 5, // 5 minutes - data stays fresh longer
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: 30 * 1000, // 30 seconds — short enough to pick up servers that finish initializing after first load
|
||||
refetchOnWindowFocus: true,
|
||||
refetchOnReconnect: false,
|
||||
refetchOnMount: false,
|
||||
refetchOnMount: true,
|
||||
retry: false,
|
||||
...config,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -433,33 +433,6 @@ export function useMCPServerManager({
|
|||
[startupConfig?.interface?.mcpServers?.placeholder, localize],
|
||||
);
|
||||
|
||||
const batchToggleServers = useCallback(
|
||||
(serverNames: string[]) => {
|
||||
const connectedServers: string[] = [];
|
||||
const disconnectedServers: string[] = [];
|
||||
|
||||
serverNames.forEach((serverName) => {
|
||||
if (isInitializing(serverName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const serverStatus = connectionStatus?.[serverName];
|
||||
if (serverStatus?.connectionState === 'connected') {
|
||||
connectedServers.push(serverName);
|
||||
} else {
|
||||
disconnectedServers.push(serverName);
|
||||
}
|
||||
});
|
||||
|
||||
setMCPValues(connectedServers);
|
||||
|
||||
disconnectedServers.forEach((serverName) => {
|
||||
initializeServer(serverName);
|
||||
});
|
||||
},
|
||||
[connectionStatus, setMCPValues, initializeServer, isInitializing],
|
||||
);
|
||||
|
||||
const toggleServerSelection = useCallback(
|
||||
(serverName: string) => {
|
||||
if (isInitializing(serverName)) {
|
||||
|
|
@ -473,15 +446,10 @@ export function useMCPServerManager({
|
|||
const filteredValues = currentValues.filter((name) => name !== serverName);
|
||||
setMCPValues(filteredValues);
|
||||
} else {
|
||||
const serverStatus = connectionStatus?.[serverName];
|
||||
if (serverStatus?.connectionState === 'connected') {
|
||||
setMCPValues([...currentValues, serverName]);
|
||||
} else {
|
||||
initializeServer(serverName);
|
||||
}
|
||||
setMCPValues([...currentValues, serverName]);
|
||||
}
|
||||
},
|
||||
[mcpValues, setMCPValues, connectionStatus, initializeServer, isInitializing],
|
||||
[mcpValues, setMCPValues, isInitializing],
|
||||
);
|
||||
|
||||
const handleConfigSave = useCallback(
|
||||
|
|
@ -677,7 +645,6 @@ export function useMCPServerManager({
|
|||
isPinned,
|
||||
setIsPinned,
|
||||
placeholderText,
|
||||
batchToggleServers,
|
||||
toggleServerSelection,
|
||||
localize,
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue