🧬 refactor: Wire Database Methods into MCP Package via Registry Pattern (#10715)

* Refactor: MCPServersRegistry Singleton Pattern with Dependency Injection for DB methods consumption

* refactor: error handling in MCP initialization and improve logging for MCPServersRegistry instance creation.

- Added checks for mongoose instance in ServerConfigsDB constructor and refined error messages for clarity.
- Reorder and use type imports

---------

Co-authored-by: Atef Bellaaj <slalom.bellaaj@external.daimlertruck.com>
Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Atef Bellaaj 2025-12-01 00:57:46 +01:00 committed by Danny Avila
parent da473bf43a
commit ad6ba4b6d1
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
24 changed files with 328 additions and 150 deletions

View file

@ -3,7 +3,6 @@ const { Tools, CacheKeys, Constants, FileSources } = require('librechat-data-pro
const {
MCPOAuthHandler,
MCPTokenStorage,
mcpServersRegistry,
normalizeHttpError,
extractWebSearchEnvVars,
} = require('@librechat/api');
@ -34,9 +33,9 @@ const {
const { updateUserPluginAuth, deleteUserPluginAuth } = require('~/server/services/PluginService');
const { updateUserPluginsService, deleteUserKey } = require('~/server/services/UserService');
const { verifyEmail, resendVerificationEmail } = require('~/server/services/AuthService');
const { getMCPManager, getFlowStateManager, getMCPServersRegistry } = require('~/config');
const { needsRefresh, getNewS3URL } = require('~/server/services/Files/S3/crud');
const { processDeleteRequest } = require('~/server/services/Files/process');
const { getMCPManager, getFlowStateManager } = require('~/config');
const { getAppConfig } = require('~/server/services/Config');
const { deleteToolCalls } = require('~/models/ToolCall');
const { deleteUserPrompts } = require('~/models/Prompt');
@ -321,9 +320,9 @@ const maybeUninstallOAuthMCP = async (userId, pluginKey, appConfig) => {
const serverName = pluginKey.replace(Constants.mcp_prefix, '');
const serverConfig =
(await mcpServersRegistry.getServerConfig(serverName, userId)) ??
(await getMCPServersRegistry().getServerConfig(serverName, userId)) ??
appConfig?.mcpServers?.[serverName];
const oauthServers = await mcpServersRegistry.getOAuthServers();
const oauthServers = await getMCPServersRegistry().getOAuthServers();
if (!oauthServers.has(serverName)) {
// this server does not use OAuth, so nothing to do here as well
return;

View file

@ -5,8 +5,7 @@
const { logger } = require('@librechat/data-schemas');
const { Constants } = require('librechat-data-provider');
const { cacheMCPServerTools, getMCPServerTools } = require('~/server/services/Config');
const { getMCPManager } = require('~/config');
const { mcpServersRegistry } = require('@librechat/api');
const { getMCPManager, getMCPServersRegistry } = require('~/config');
/**
* Get all MCP tools available to the user
@ -19,7 +18,7 @@ const getMCPTools = async (req, res) => {
return res.status(401).json({ message: 'Unauthorized' });
}
const mcpConfig = await mcpServersRegistry.getAllServerConfigs(userId);
const mcpConfig = await getMCPServersRegistry().getAllServerConfigs(userId);
const configuredServers = mcpConfig ? Object.keys(mcpConfig) : [];
if (!mcpConfig || Object.keys(mcpConfig).length == 0) {
@ -69,7 +68,7 @@ const getMCPTools = async (req, res) => {
// Get server config once
const serverConfig = mcpConfig[serverName];
const rawServerConfig = await mcpServersRegistry.getServerConfig(serverName, userId);
const rawServerConfig = await getMCPServersRegistry().getServerConfig(serverName, userId);
// Initialize server object with all server-level data
const server = {
@ -137,7 +136,7 @@ const getMCPServersList = async (req, res) => {
// TODO - Ensure DB servers loaded into registry (configs only)
// 2. Get all server configs from registry (YAML + DB)
const serverConfigs = await mcpServersRegistry.getAllServerConfigs(userId);
const serverConfigs = await getMCPServersRegistry().getAllServerConfigs(userId);
return res.json(serverConfigs);
} catch (error) {