mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-17 08:50:15 +01:00
🪵 chore: Remove Unnecessary Comments
This commit is contained in:
parent
6fd3b569ac
commit
32081245da
3 changed files with 8 additions and 37 deletions
|
|
@ -93,7 +93,6 @@ router.get('/:serverName/oauth/callback', async (req, res) => {
|
||||||
return res.redirect('/oauth/error?error=missing_state');
|
return res.redirect('/oauth/error?error=missing_state');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract flow ID from state
|
|
||||||
const flowId = state;
|
const flowId = state;
|
||||||
logger.debug('[MCP OAuth] Using flow ID from state', { flowId });
|
logger.debug('[MCP OAuth] Using flow ID from state', { flowId });
|
||||||
|
|
||||||
|
|
@ -116,22 +115,17 @@ router.get('/:serverName/oauth/callback', async (req, res) => {
|
||||||
hasCodeVerifier: !!flowState.codeVerifier,
|
hasCodeVerifier: !!flowState.codeVerifier,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Complete the OAuth flow
|
|
||||||
logger.debug('[MCP OAuth] Completing OAuth flow');
|
logger.debug('[MCP OAuth] Completing OAuth flow');
|
||||||
const tokens = await MCPOAuthHandler.completeOAuthFlow(flowId, code, flowManager);
|
const tokens = await MCPOAuthHandler.completeOAuthFlow(flowId, code, flowManager);
|
||||||
logger.info('[MCP OAuth] OAuth flow completed, tokens received in callback route');
|
logger.info('[MCP OAuth] OAuth flow completed, tokens received in callback route');
|
||||||
|
|
||||||
// Try to establish the MCP connection with the new tokens
|
|
||||||
try {
|
try {
|
||||||
const mcpManager = getMCPManager(flowState.userId);
|
const mcpManager = getMCPManager(flowState.userId);
|
||||||
logger.debug(`[MCP OAuth] Attempting to reconnect ${serverName} with new OAuth tokens`);
|
logger.debug(`[MCP OAuth] Attempting to reconnect ${serverName} with new OAuth tokens`);
|
||||||
|
|
||||||
// For user-level OAuth, try to establish the connection
|
|
||||||
if (flowState.userId !== 'system') {
|
if (flowState.userId !== 'system') {
|
||||||
// We need to get the user object - in this case we'll need to reconstruct it
|
|
||||||
const user = { id: flowState.userId };
|
const user = { id: flowState.userId };
|
||||||
|
|
||||||
// Try to establish connection with the new tokens
|
|
||||||
const userConnection = await mcpManager.getUserConnection({
|
const userConnection = await mcpManager.getUserConnection({
|
||||||
user,
|
user,
|
||||||
serverName,
|
serverName,
|
||||||
|
|
@ -148,10 +142,8 @@ router.get('/:serverName/oauth/callback', async (req, res) => {
|
||||||
`[MCP OAuth] Successfully reconnected ${serverName} for user ${flowState.userId}`,
|
`[MCP OAuth] Successfully reconnected ${serverName} for user ${flowState.userId}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch and cache tools now that we have a successful connection
|
|
||||||
const userTools = (await getCachedTools({ userId: flowState.userId })) || {};
|
const userTools = (await getCachedTools({ userId: flowState.userId })) || {};
|
||||||
|
|
||||||
// Remove any old tools from this server in the user's cache
|
|
||||||
const mcpDelimiter = Constants.mcp_delimiter;
|
const mcpDelimiter = Constants.mcp_delimiter;
|
||||||
for (const key of Object.keys(userTools)) {
|
for (const key of Object.keys(userTools)) {
|
||||||
if (key.endsWith(`${mcpDelimiter}${serverName}`)) {
|
if (key.endsWith(`${mcpDelimiter}${serverName}`)) {
|
||||||
|
|
@ -159,7 +151,6 @@ router.get('/:serverName/oauth/callback', async (req, res) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new tools from this server
|
|
||||||
const tools = await userConnection.fetchTools();
|
const tools = await userConnection.fetchTools();
|
||||||
for (const tool of tools) {
|
for (const tool of tools) {
|
||||||
const name = `${tool.name}${Constants.mcp_delimiter}${serverName}`;
|
const name = `${tool.name}${Constants.mcp_delimiter}${serverName}`;
|
||||||
|
|
@ -173,7 +164,6 @@ router.get('/:serverName/oauth/callback', async (req, res) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the updated user tool cache
|
|
||||||
await setCachedTools(userTools, { userId: flowState.userId });
|
await setCachedTools(userTools, { userId: flowState.userId });
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
|
|
@ -183,7 +173,6 @@ router.get('/:serverName/oauth/callback', async (req, res) => {
|
||||||
logger.debug(`[MCP OAuth] System-level OAuth completed for ${serverName}`);
|
logger.debug(`[MCP OAuth] System-level OAuth completed for ${serverName}`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Don't fail the OAuth callback if reconnection fails - the tokens are still saved
|
|
||||||
logger.warn(
|
logger.warn(
|
||||||
`[MCP OAuth] Failed to reconnect ${serverName} after OAuth, but tokens are saved:`,
|
`[MCP OAuth] Failed to reconnect ${serverName} after OAuth, but tokens are saved:`,
|
||||||
error,
|
error,
|
||||||
|
|
@ -219,7 +208,6 @@ router.get('/oauth/tokens/:flowId', requireJwtAuth, async (req, res) => {
|
||||||
return res.status(401).json({ error: 'User not authenticated' });
|
return res.status(401).json({ error: 'User not authenticated' });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow system flows or user-owned flows
|
|
||||||
if (!flowId.startsWith(`${user.id}:`) && !flowId.startsWith('system:')) {
|
if (!flowId.startsWith(`${user.id}:`) && !flowId.startsWith('system:')) {
|
||||||
return res.status(403).json({ error: 'Access denied' });
|
return res.status(403).json({ error: 'Access denied' });
|
||||||
}
|
}
|
||||||
|
|
@ -287,11 +275,7 @@ router.post('/oauth/cancel/:serverName', requireJwtAuth, async (req, res) => {
|
||||||
|
|
||||||
const flowsCache = getLogStores(CacheKeys.FLOWS);
|
const flowsCache = getLogStores(CacheKeys.FLOWS);
|
||||||
const flowManager = getFlowStateManager(flowsCache);
|
const flowManager = getFlowStateManager(flowsCache);
|
||||||
|
|
||||||
// Generate the flow ID for this user/server combination
|
|
||||||
const flowId = MCPOAuthHandler.generateFlowId(user.id, serverName);
|
const flowId = MCPOAuthHandler.generateFlowId(user.id, serverName);
|
||||||
|
|
||||||
// Check if flow exists
|
|
||||||
const flowState = await flowManager.getFlowState(flowId, 'mcp_oauth');
|
const flowState = await flowManager.getFlowState(flowId, 'mcp_oauth');
|
||||||
|
|
||||||
if (!flowState) {
|
if (!flowState) {
|
||||||
|
|
@ -302,7 +286,6 @@ router.post('/oauth/cancel/:serverName', requireJwtAuth, async (req, res) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel the flow by marking it as failed
|
|
||||||
await flowManager.failFlow(flowId, 'mcp_oauth', 'User cancelled OAuth flow');
|
await flowManager.failFlow(flowId, 'mcp_oauth', 'User cancelled OAuth flow');
|
||||||
|
|
||||||
logger.info(`[MCP OAuth Cancel] Successfully cancelled OAuth flow for ${serverName}`);
|
logger.info(`[MCP OAuth Cancel] Successfully cancelled OAuth flow for ${serverName}`);
|
||||||
|
|
@ -379,8 +362,7 @@ router.post('/:serverName/reinitialize', requireJwtAuth, async (req, res) => {
|
||||||
createToken,
|
createToken,
|
||||||
deleteTokens,
|
deleteTokens,
|
||||||
},
|
},
|
||||||
returnOnOAuth: true, // Return immediately when OAuth is initiated
|
returnOnOAuth: true,
|
||||||
// Add OAuth handlers to capture the OAuth URL when needed
|
|
||||||
oauthStart: async (authURL) => {
|
oauthStart: async (authURL) => {
|
||||||
logger.info(`[MCP Reinitialize] OAuth URL received: ${authURL}`);
|
logger.info(`[MCP Reinitialize] OAuth URL received: ${authURL}`);
|
||||||
oauthUrl = authURL;
|
oauthUrl = authURL;
|
||||||
|
|
@ -395,7 +377,6 @@ router.post('/:serverName/reinitialize', requireJwtAuth, async (req, res) => {
|
||||||
`[MCP Reinitialize] OAuth state - oauthRequired: ${oauthRequired}, oauthUrl: ${oauthUrl ? 'present' : 'null'}`,
|
`[MCP Reinitialize] OAuth state - oauthRequired: ${oauthRequired}, oauthUrl: ${oauthUrl ? 'present' : 'null'}`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check if this is an OAuth error - if so, the flow state should be set up now
|
|
||||||
const isOAuthError =
|
const isOAuthError =
|
||||||
err.message?.includes('OAuth') ||
|
err.message?.includes('OAuth') ||
|
||||||
err.message?.includes('authentication') ||
|
err.message?.includes('authentication') ||
|
||||||
|
|
@ -408,7 +389,6 @@ router.post('/:serverName/reinitialize', requireJwtAuth, async (req, res) => {
|
||||||
`[MCP Reinitialize] OAuth required for ${serverName} (isOAuthError: ${isOAuthError}, oauthRequired: ${oauthRequired}, isOAuthFlowInitiated: ${isOAuthFlowInitiated})`,
|
`[MCP Reinitialize] OAuth required for ${serverName} (isOAuthError: ${isOAuthError}, oauthRequired: ${oauthRequired}, isOAuthFlowInitiated: ${isOAuthFlowInitiated})`,
|
||||||
);
|
);
|
||||||
oauthRequired = true;
|
oauthRequired = true;
|
||||||
// Don't return error - continue so frontend can handle OAuth
|
|
||||||
} else {
|
} else {
|
||||||
logger.error(
|
logger.error(
|
||||||
`[MCP Reinitialize] Error initializing MCP server ${serverName} for user:`,
|
`[MCP Reinitialize] Error initializing MCP server ${serverName} for user:`,
|
||||||
|
|
@ -418,11 +398,9 @@ router.post('/:serverName/reinitialize', requireJwtAuth, async (req, res) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only fetch and cache tools if we successfully connected (no OAuth required)
|
|
||||||
if (userConnection && !oauthRequired) {
|
if (userConnection && !oauthRequired) {
|
||||||
const userTools = (await getCachedTools({ userId: user.id })) || {};
|
const userTools = (await getCachedTools({ userId: user.id })) || {};
|
||||||
|
|
||||||
// Remove any old tools from this server in the user's cache
|
|
||||||
const mcpDelimiter = Constants.mcp_delimiter;
|
const mcpDelimiter = Constants.mcp_delimiter;
|
||||||
for (const key of Object.keys(userTools)) {
|
for (const key of Object.keys(userTools)) {
|
||||||
if (key.endsWith(`${mcpDelimiter}${serverName}`)) {
|
if (key.endsWith(`${mcpDelimiter}${serverName}`)) {
|
||||||
|
|
@ -430,7 +408,6 @@ router.post('/:serverName/reinitialize', requireJwtAuth, async (req, res) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the new tools from this server
|
|
||||||
const tools = await userConnection.fetchTools();
|
const tools = await userConnection.fetchTools();
|
||||||
for (const tool of tools) {
|
for (const tool of tools) {
|
||||||
const name = `${tool.name}${Constants.mcp_delimiter}${serverName}`;
|
const name = `${tool.name}${Constants.mcp_delimiter}${serverName}`;
|
||||||
|
|
@ -444,7 +421,6 @@ router.post('/:serverName/reinitialize', requireJwtAuth, async (req, res) => {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save the updated user tool cache
|
|
||||||
await setCachedTools(userTools, { userId: user.id });
|
await setCachedTools(userTools, { userId: user.id });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -593,19 +569,16 @@ router.get('/:serverName/auth-values', requireJwtAuth, async (req, res) => {
|
||||||
const pluginKey = `${Constants.mcp_prefix}${serverName}`;
|
const pluginKey = `${Constants.mcp_prefix}${serverName}`;
|
||||||
const authValueFlags = {};
|
const authValueFlags = {};
|
||||||
|
|
||||||
// Check existence of saved values for each custom user variable (don't fetch actual values)
|
|
||||||
if (serverConfig.customUserVars && typeof serverConfig.customUserVars === 'object') {
|
if (serverConfig.customUserVars && typeof serverConfig.customUserVars === 'object') {
|
||||||
for (const varName of Object.keys(serverConfig.customUserVars)) {
|
for (const varName of Object.keys(serverConfig.customUserVars)) {
|
||||||
try {
|
try {
|
||||||
const value = await getUserPluginAuthValue(user.id, varName, false, pluginKey);
|
const value = await getUserPluginAuthValue(user.id, varName, false, pluginKey);
|
||||||
// Only store boolean flag indicating if value exists
|
|
||||||
authValueFlags[varName] = !!(value && value.length > 0);
|
authValueFlags[varName] = !!(value && value.length > 0);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(
|
logger.error(
|
||||||
`[MCP Auth Value Flags] Error checking ${varName} for user ${user.id}:`,
|
`[MCP Auth Value Flags] Error checking ${varName} for user ${user.id}:`,
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
// Default to false if we can't check
|
|
||||||
authValueFlags[varName] = false;
|
authValueFlags[varName] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,10 @@ function MCPSelect() {
|
||||||
const statusIconProps = getServerStatusIconProps(serverName);
|
const statusIconProps = getServerStatusIconProps(serverName);
|
||||||
const isServerInitializing = isInitializing(serverName);
|
const isServerInitializing = isInitializing(serverName);
|
||||||
|
|
||||||
// Common wrapper for the main content (check mark + text)
|
/**
|
||||||
// Ensures Check & Text are adjacent and the group takes available space.
|
Common wrapper for the main content (check mark + text).
|
||||||
|
Ensures Check & Text are adjacent and the group takes available space.
|
||||||
|
*/
|
||||||
const mainContentWrapper = (
|
const mainContentWrapper = (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -66,12 +68,10 @@ function MCPSelect() {
|
||||||
[getServerStatusIconProps, isInitializing],
|
[getServerStatusIconProps, isInitializing],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Don't render if no servers are selected and not pinned
|
|
||||||
if ((!mcpValues || mcpValues.length === 0) && !isPinned) {
|
if ((!mcpValues || mcpValues.length === 0) && !isPinned) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't render if no MCP servers are configured
|
|
||||||
if (!configuredServers || configuredServers.length === 0) {
|
if (!configuredServers || configuredServers.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,15 @@ import { useToastContext } from '@librechat/client';
|
||||||
import { useQueryClient } from '@tanstack/react-query';
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
import { Constants, QueryKeys } from 'librechat-data-provider';
|
import { Constants, QueryKeys } from 'librechat-data-provider';
|
||||||
import {
|
import {
|
||||||
|
useCancelMCPOAuthMutation,
|
||||||
useUpdateUserPluginsMutation,
|
useUpdateUserPluginsMutation,
|
||||||
useReinitializeMCPServerMutation,
|
useReinitializeMCPServerMutation,
|
||||||
useCancelMCPOAuthMutation,
|
|
||||||
} from 'librechat-data-provider/react-query';
|
} from 'librechat-data-provider/react-query';
|
||||||
import { useMCPConnectionStatusQuery } from '~/data-provider/Tools/queries';
|
|
||||||
import type { TUpdateUserPlugins, TPlugin } from 'librechat-data-provider';
|
import type { TUpdateUserPlugins, TPlugin } from 'librechat-data-provider';
|
||||||
import type { ConfigFieldDetail } from '~/components/MCP/MCPConfigDialog';
|
import type { ConfigFieldDetail } from '~/components/MCP/MCPConfigDialog';
|
||||||
import { useLocalize } from '~/hooks';
|
import { useMCPConnectionStatusQuery } from '~/data-provider/Tools/queries';
|
||||||
import { useBadgeRowContext } from '~/Providers';
|
import { useBadgeRowContext } from '~/Providers';
|
||||||
|
import { useLocalize } from '~/hooks';
|
||||||
|
|
||||||
interface ServerState {
|
interface ServerState {
|
||||||
isInitializing: boolean;
|
isInitializing: boolean;
|
||||||
|
|
@ -273,10 +273,8 @@ export function useMCPServerManager() {
|
||||||
|
|
||||||
const cancelOAuthFlow = useCallback(
|
const cancelOAuthFlow = useCallback(
|
||||||
(serverName: string) => {
|
(serverName: string) => {
|
||||||
// Call backend cancellation first, then clean up frontend state on success
|
|
||||||
cancelOAuthMutation.mutate(serverName, {
|
cancelOAuthMutation.mutate(serverName, {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
// Only clean up frontend state after backend confirms cancellation
|
|
||||||
cleanupServerState(serverName);
|
cleanupServerState(serverName);
|
||||||
queryClient.invalidateQueries([QueryKeys.mcpConnectionStatus]);
|
queryClient.invalidateQueries([QueryKeys.mcpConnectionStatus]);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue