mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-09-21 21:50:49 +02:00
🚌 fix: MCP Runtime Errors while Initializing (#9046)
* chore: Remove eslint-plugin-perfectionist from dependencies
* 🚌 fix: MCP Runtime Errors while Initializing
* chore: Bump @librechat/api version to 1.3.1
* chore: import order
* chore: import order
This commit is contained in:
parent
3eb6debe6a
commit
e6cebdf2b6
10 changed files with 52 additions and 112 deletions
|
@ -113,20 +113,26 @@ const getAvailableTools = async (req, res) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// If not in cache, build from manifest
|
||||
let pluginManifest = availableTools;
|
||||
if (customConfig?.mcpServers != null) {
|
||||
const mcpManager = getMCPManager();
|
||||
const flowsCache = getLogStores(CacheKeys.FLOWS);
|
||||
const flowManager = flowsCache ? getFlowStateManager(flowsCache) : null;
|
||||
const serverToolsCallback = createServerToolsCallback();
|
||||
const getServerTools = createGetServerTools();
|
||||
const mcpTools = await mcpManager.loadManifestTools({
|
||||
flowManager,
|
||||
serverToolsCallback,
|
||||
getServerTools,
|
||||
});
|
||||
pluginManifest = [...mcpTools, ...pluginManifest];
|
||||
try {
|
||||
const mcpManager = getMCPManager();
|
||||
const flowsCache = getLogStores(CacheKeys.FLOWS);
|
||||
const flowManager = flowsCache ? getFlowStateManager(flowsCache) : null;
|
||||
const serverToolsCallback = createServerToolsCallback();
|
||||
const getServerTools = createGetServerTools();
|
||||
const mcpTools = await mcpManager.loadManifestTools({
|
||||
flowManager,
|
||||
serverToolsCallback,
|
||||
getServerTools,
|
||||
});
|
||||
pluginManifest = [...mcpTools, ...pluginManifest];
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
'[getAvailableTools] Error loading MCP Tools, servers may still be initializing:',
|
||||
error,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** @type {TPlugin[]} */
|
||||
|
|
|
@ -109,10 +109,10 @@ router.get('/', async function (req, res) {
|
|||
for (const serverName in config.mcpServers) {
|
||||
const serverConfig = config.mcpServers[serverName];
|
||||
payload.mcpServers[serverName] = {
|
||||
customUserVars: serverConfig?.customUserVars || {},
|
||||
chatMenu: serverConfig?.chatMenu,
|
||||
isOAuth: oauthServers.has(serverName),
|
||||
startup: serverConfig?.startup,
|
||||
chatMenu: serverConfig?.chatMenu,
|
||||
isOAuth: oauthServers?.has(serverName),
|
||||
customUserVars: serverConfig?.customUserVars || {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,21 @@
|
|||
const { z } = require('zod');
|
||||
const { tool } = require('@langchain/core/tools');
|
||||
const { logger } = require('@librechat/data-schemas');
|
||||
const { Time, CacheKeys, StepTypes } = require('librechat-data-provider');
|
||||
const { Constants: AgentConstants, Providers, GraphEvents } = require('@librechat/agents');
|
||||
const { Constants, ContentTypes, isAssistantsEndpoint } = require('librechat-data-provider');
|
||||
const {
|
||||
sendEvent,
|
||||
MCPOAuthHandler,
|
||||
normalizeServerName,
|
||||
convertWithResolvedRefs,
|
||||
} = require('@librechat/api');
|
||||
const {
|
||||
Time,
|
||||
CacheKeys,
|
||||
StepTypes,
|
||||
Constants,
|
||||
ContentTypes,
|
||||
isAssistantsEndpoint,
|
||||
} = require('librechat-data-provider');
|
||||
const { findToken, createToken, updateToken } = require('~/models');
|
||||
const { getMCPManager, getFlowStateManager } = require('~/config');
|
||||
const { getCachedTools, loadCustomConfig } = require('./Config');
|
||||
|
@ -254,15 +260,21 @@ async function getMCPSetupData(userId) {
|
|||
}
|
||||
|
||||
const mcpManager = getMCPManager(userId);
|
||||
const appConnections = mcpManager.getAllConnections() || new Map();
|
||||
/** @type {ReturnType<MCPManager['getAllConnections']>} */
|
||||
let appConnections = new Map();
|
||||
try {
|
||||
appConnections = (await mcpManager.getAllConnections()) || new Map();
|
||||
} catch (error) {
|
||||
logger.error(`[MCP][User: ${userId}] Error getting app connections:`, error);
|
||||
}
|
||||
const userConnections = mcpManager.getUserConnections(userId) || new Map();
|
||||
const oauthServers = mcpManager.getOAuthServers() || new Set();
|
||||
|
||||
return {
|
||||
mcpConfig,
|
||||
oauthServers,
|
||||
appConnections,
|
||||
userConnections,
|
||||
oauthServers,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ async function initializeMCPs(app) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Filter out servers with startup: false
|
||||
/** Servers filtered with `startup: false` */
|
||||
const filteredServers = {};
|
||||
for (const [name, config] of Object.entries(mcpServers)) {
|
||||
if (config.startup === false) {
|
||||
|
@ -41,7 +41,7 @@ async function initializeMCPs(app) {
|
|||
return;
|
||||
}
|
||||
|
||||
const mcpTools = mcpManager.getAppToolFunctions();
|
||||
const mcpTools = mcpManager.getAppToolFunctions() ?? {};
|
||||
await setCachedTools({ ...cachedTools, ...mcpTools }, { isGlobal: true });
|
||||
|
||||
const cache = getLogStores(CacheKeys.CONFIG_STORE);
|
||||
|
|
|
@ -2,7 +2,6 @@ import { fileURLToPath } from 'node:url';
|
|||
import path from 'node:path';
|
||||
import typescriptEslintEslintPlugin from '@typescript-eslint/eslint-plugin';
|
||||
import { fixupConfigRules, fixupPluginRules } from '@eslint/compat';
|
||||
import perfectionist from 'eslint-plugin-perfectionist';
|
||||
import reactHooks from 'eslint-plugin-react-hooks';
|
||||
import tsParser from '@typescript-eslint/parser';
|
||||
import importPlugin from 'eslint-plugin-import';
|
||||
|
@ -62,7 +61,6 @@ export default [
|
|||
'jsx-a11y': fixupPluginRules(jsxA11Y),
|
||||
'import/parsers': tsParser,
|
||||
i18next,
|
||||
perfectionist,
|
||||
prettier: fixupPluginRules(prettier),
|
||||
},
|
||||
|
||||
|
@ -139,46 +137,6 @@ export default [
|
|||
'no-restricted-syntax': 'off',
|
||||
'react/prop-types': 'off',
|
||||
'react/display-name': 'off',
|
||||
|
||||
'perfectionist/sort-imports': [
|
||||
'error',
|
||||
{
|
||||
type: 'line-length',
|
||||
order: 'desc',
|
||||
newlinesBetween: 'never',
|
||||
customGroups: {
|
||||
value: {
|
||||
react: ['^react$'],
|
||||
local: ['^(\\.{1,2}|~)/', '^librechat-data-provider'],
|
||||
},
|
||||
},
|
||||
groups: [
|
||||
'react',
|
||||
'builtin',
|
||||
'external',
|
||||
['builtin-type', 'external-type'],
|
||||
['internal-type'],
|
||||
'local',
|
||||
['parent', 'sibling', 'index'],
|
||||
'object',
|
||||
'unknown',
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
// 'perfectionist/sort-named-imports': [
|
||||
// 'error',
|
||||
// {
|
||||
// type: 'line-length',
|
||||
// order: 'asc',
|
||||
// ignoreAlias: false,
|
||||
// ignoreCase: true,
|
||||
// specialCharacters: 'keep',
|
||||
// groupKind: 'mixed',
|
||||
// partitionByNewLine: false,
|
||||
// partitionByComment: false,
|
||||
// },
|
||||
// ],
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
31
package-lock.json
generated
31
package-lock.json
generated
|
@ -30,7 +30,6 @@
|
|||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jest": "^28.11.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-perfectionist": "^4.8.0",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint-plugin-react-hooks": "^5.1.0",
|
||||
|
@ -33994,24 +33993,6 @@
|
|||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-perfectionist": {
|
||||
"version": "4.8.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-perfectionist/-/eslint-plugin-perfectionist-4.8.0.tgz",
|
||||
"integrity": "sha512-ZF04IAPGItYMlj9xjgvvl/QpksZf79g0dkxbNcuxDjbcUSZ4CwucJ7h5Yzt5JuHe+i6igQbUYEp40j4ndfbvWQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "^8.23.0",
|
||||
"@typescript-eslint/utils": "^8.23.0",
|
||||
"natural-orderby": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-prettier": {
|
||||
"version": "5.2.3",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.3.tgz",
|
||||
|
@ -41452,16 +41433,6 @@
|
|||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/natural-orderby": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/natural-orderby/-/natural-orderby-5.0.0.tgz",
|
||||
"integrity": "sha512-kKHJhxwpR/Okycz4HhQKKlhWe4ASEfPgkSWNmKFHd7+ezuQlxkA5cM3+XkBPvm1gmHen3w53qsYAv+8GwRrBlg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
|
@ -51345,7 +51316,7 @@
|
|||
},
|
||||
"packages/api": {
|
||||
"name": "@librechat/api",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.21.5",
|
||||
|
|
|
@ -102,7 +102,6 @@
|
|||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-jest": "^28.11.0",
|
||||
"eslint-plugin-jsx-a11y": "^6.10.2",
|
||||
"eslint-plugin-perfectionist": "^4.8.0",
|
||||
"eslint-plugin-prettier": "^5.2.3",
|
||||
"eslint-plugin-react": "^7.37.4",
|
||||
"eslint-plugin-react-hooks": "^5.1.0",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@librechat/api",
|
||||
"version": "1.3.0",
|
||||
"version": "1.3.1",
|
||||
"type": "commonjs",
|
||||
"description": "MCP services for LibreChat",
|
||||
"main": "dist/index.js",
|
||||
|
|
|
@ -5,10 +5,10 @@ import type { TUser } from 'librechat-data-provider';
|
|||
import type { MCPOAuthTokens, MCPOAuthFlowMetadata } from '~/mcp/oauth';
|
||||
import type { FlowStateManager } from '~/flow/manager';
|
||||
import type { FlowMetadata } from '~/flow/types';
|
||||
import type * as t from './types';
|
||||
import { MCPTokenStorage, MCPOAuthHandler } from '~/mcp/oauth';
|
||||
import { MCPConnection } from './connection';
|
||||
import { processMCPEnv } from '~/utils';
|
||||
import type * as t from './types';
|
||||
|
||||
export interface BasicConnectionOptions {
|
||||
serverName: string;
|
||||
|
@ -350,15 +350,9 @@ export class MCPConnectionFactory {
|
|||
logger.info(`${this.logPrefix} OAuth flow started, issued authorization URL to user`);
|
||||
await this.oauthStart(authorizationUrl);
|
||||
} else {
|
||||
logger.info(`
|
||||
═══════════════════════════════════════════════════════════════════════
|
||||
Please visit the following URL to authenticate:
|
||||
|
||||
${authorizationUrl}
|
||||
|
||||
${this.logPrefix} Flow ID: ${newFlowId}
|
||||
═══════════════════════════════════════════════════════════════════════
|
||||
`);
|
||||
logger.info(
|
||||
`${this.logPrefix} OAuth flow started, no \`oauthStart\` handler defined, relying on callback endpoint`,
|
||||
);
|
||||
}
|
||||
|
||||
/** Tokens from the new flow */
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { CallToolResultSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
||||
import { logger } from '@librechat/data-schemas';
|
||||
import pick from 'lodash/pick';
|
||||
import { logger } from '@librechat/data-schemas';
|
||||
import { CallToolResultSchema, ErrorCode, McpError } from '@modelcontextprotocol/sdk/types.js';
|
||||
import type { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
||||
import type { TokenMethods } from '@librechat/data-schemas';
|
||||
import type { TUser } from 'librechat-data-provider';
|
||||
import type { FlowStateManager } from '~/flow/manager';
|
||||
import type { TUser } from 'librechat-data-provider';
|
||||
import type { MCPOAuthTokens } from '~/mcp/oauth';
|
||||
import type * as t from './types';
|
||||
import { UserConnectionManager } from '~/mcp/UserConnectionManager';
|
||||
import { ConnectionsRepository } from '~/mcp/ConnectionsRepository';
|
||||
import { formatToolContent } from './parsers';
|
||||
import { MCPConnection } from './connection';
|
||||
import { CONSTANTS } from './enum';
|
||||
import type * as t from './types';
|
||||
|
||||
/**
|
||||
* Centralized manager for MCP server connections and tool execution.
|
||||
|
@ -43,17 +43,17 @@ export class MCPManager extends UserConnectionManager {
|
|||
}
|
||||
|
||||
/** Returns all app-level connections */
|
||||
public async getAllConnections(): Promise<Map<string, MCPConnection>> {
|
||||
public async getAllConnections(): Promise<Map<string, MCPConnection> | null> {
|
||||
return this.appConnections!.getAll();
|
||||
}
|
||||
|
||||
/** Get servers that require OAuth */
|
||||
public getOAuthServers(): Set<string> {
|
||||
public getOAuthServers(): Set<string> | null {
|
||||
return this.serversRegistry.oauthServers!;
|
||||
}
|
||||
|
||||
/** Returns all available tool functions from app-level connections */
|
||||
public getAppToolFunctions(): t.LCAvailableTools {
|
||||
public getAppToolFunctions(): t.LCAvailableTools | null {
|
||||
return this.serversRegistry.toolFunctions!;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue