diff --git a/api/server/controllers/AuthController.js b/api/server/controllers/AuthController.js
index 70491dcc61..588391b535 100644
--- a/api/server/controllers/AuthController.js
+++ b/api/server/controllers/AuthController.js
@@ -18,7 +18,6 @@ const {
findUser,
} = require('~/models');
const { getGraphApiToken } = require('~/server/services/GraphTokenService');
-const { getOAuthReconnectionManager } = require('~/config');
const { getOpenIdConfig } = require('~/strategies');
const registrationController = async (req, res) => {
@@ -166,17 +165,6 @@ const refreshController = async (req, res) => {
if (session && session.expiration > new Date()) {
const token = await setAuthTokens(userId, res, session);
- // trigger OAuth MCP server reconnection asynchronously (best effort)
- try {
- void getOAuthReconnectionManager()
- .reconnectServers(userId)
- .catch((err) => {
- logger.error('[refreshController] Error reconnecting OAuth MCP servers:', err);
- });
- } catch (err) {
- logger.warn(`[refreshController] Cannot attempt OAuth MCP servers reconnection:`, err);
- }
-
res.status(200).send({ token, user });
} else if (req?.query?.retry) {
// Retrying from a refresh token request that failed (401)
diff --git a/client/src/components/SidePanel/Agents/MCPTools.tsx b/client/src/components/SidePanel/Agents/MCPTools.tsx
index 552f2b313b..3dc9a19d6a 100644
--- a/client/src/components/SidePanel/Agents/MCPTools.tsx
+++ b/client/src/components/SidePanel/Agents/MCPTools.tsx
@@ -46,7 +46,7 @@ export default function MCPTools({
return null;
}
- if (serverInfo.isConnected) {
+ if (serverInfo?.tools?.length && serverInfo.tools.length > 0) {
return (
);
diff --git a/client/src/components/Tools/MCPToolSelectDialog.tsx b/client/src/components/Tools/MCPToolSelectDialog.tsx
index 487f767250..a27484d4e8 100644
--- a/client/src/components/Tools/MCPToolSelectDialog.tsx
+++ b/client/src/components/Tools/MCPToolSelectDialog.tsx
@@ -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) {
diff --git a/client/src/data-provider/MCP/queries.ts b/client/src/data-provider/MCP/queries.ts
index afc17f3a93..8590e43735 100644
--- a/client/src/data-provider/MCP/queries.ts
+++ b/client/src/data-provider/MCP/queries.ts
@@ -12,10 +12,10 @@ export const useMCPServersQuery = (
[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,
},
diff --git a/client/src/hooks/MCP/useMCPServerManager.ts b/client/src/hooks/MCP/useMCPServerManager.ts
index fcca040af2..af65ba4507 100644
--- a/client/src/hooks/MCP/useMCPServerManager.ts
+++ b/client/src/hooks/MCP/useMCPServerManager.ts
@@ -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,
diff --git a/packages/api/src/mcp/ConnectionsRepository.ts b/packages/api/src/mcp/ConnectionsRepository.ts
index 49d0799085..b14af57b29 100644
--- a/packages/api/src/mcp/ConnectionsRepository.ts
+++ b/packages/api/src/mcp/ConnectionsRepository.ts
@@ -4,6 +4,8 @@ import { MCPConnection } from './connection';
import { MCPServersRegistry } from '~/mcp/registry/MCPServersRegistry';
import type * as t from './types';
+const CONNECT_CONCURRENCY = 3;
+
/**
* Manages MCP connections with lazy loading and reconnection.
* Maintains a pool of connections and handles connection lifecycle management.
@@ -84,9 +86,17 @@ export class ConnectionsRepository {
/** Gets or creates connections for multiple servers concurrently */
async getMany(serverNames: string[]): Promise