diff --git a/api/server/routes/config.js b/api/server/routes/config.js index dd93037dd9..55d4cc3067 100644 --- a/api/server/routes/config.js +++ b/api/server/routes/config.js @@ -106,6 +106,7 @@ router.get('/', async function (req, res) { const serverConfig = config.mcpServers[serverName]; payload.mcpServers[serverName] = { customUserVars: serverConfig?.customUserVars || {}, + chatMenu: serverConfig?.chatMenu, }; } } diff --git a/client/src/components/Chat/Input/MCPSelect.tsx b/client/src/components/Chat/Input/MCPSelect.tsx index fd38e73c13..a3916def6a 100644 --- a/client/src/components/Chat/Input/MCPSelect.tsx +++ b/client/src/components/Chat/Input/MCPSelect.tsx @@ -17,9 +17,14 @@ function MCPSelect() { const { mcpSelect, startupConfig } = useBadgeRowContext(); const { mcpValues, setMCPValues, mcpToolDetails, isPinned } = mcpSelect; - // Get all configured MCP servers from config + // Get all configured MCP servers from config that allow chat menu const configuredServers = useMemo(() => { - return Object.keys(startupConfig?.mcpServers || {}); + if (!startupConfig?.mcpServers) { + return []; + } + return Object.entries(startupConfig.mcpServers) + .filter(([, config]) => config.chatMenu !== false) + .map(([serverName]) => serverName); }, [startupConfig?.mcpServers]); const [isConfigModalOpen, setIsConfigModalOpen] = useState(false); diff --git a/client/src/hooks/Plugins/useMCPSelect.ts b/client/src/hooks/Plugins/useMCPSelect.ts index a76ccdced5..a817a8aa45 100644 --- a/client/src/hooks/Plugins/useMCPSelect.ts +++ b/client/src/hooks/Plugins/useMCPSelect.ts @@ -2,7 +2,7 @@ import { useRef, useEffect, useCallback, useMemo } from 'react'; import { useRecoilState } from 'recoil'; import { Constants, LocalStorageKeys, EModelEndpoint } from 'librechat-data-provider'; import type { TPlugin } from 'librechat-data-provider'; -import { useAvailableToolsQuery } from '~/data-provider'; +import { useAvailableToolsQuery, useGetStartupConfig } from '~/data-provider'; import useLocalStorage from '~/hooks/useLocalStorageAlt'; import { ephemeralAgentByConvoId } from '~/store'; @@ -28,12 +28,13 @@ export function useMCPSelect({ conversationId }: UseMCPSelectOptions) { const key = conversationId ?? Constants.NEW_CONVO; const hasSetFetched = useRef(null); const [ephemeralAgent, setEphemeralAgent] = useRecoilState(ephemeralAgentByConvoId(key)); - const { data: mcpToolDetails, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, { + const { data: startupConfig } = useGetStartupConfig(); + const { data: rawMcpTools, isFetched } = useAvailableToolsQuery(EModelEndpoint.agents, { select: (data: TPlugin[]) => { const mcpToolsMap = new Map(); data.forEach((tool) => { const isMCP = tool.pluginKey.includes(Constants.mcp_delimiter); - if (isMCP && tool.chatMenu !== false) { + if (isMCP) { const parts = tool.pluginKey.split(Constants.mcp_delimiter); const serverName = parts[parts.length - 1]; if (!mcpToolsMap.has(serverName)) { @@ -50,6 +51,16 @@ export function useMCPSelect({ conversationId }: UseMCPSelectOptions) { }, }); + const mcpToolDetails = useMemo(() => { + if (!rawMcpTools || !startupConfig?.mcpServers) { + return rawMcpTools; + } + return rawMcpTools.filter((tool) => { + const serverConfig = startupConfig?.mcpServers?.[tool.name]; + return serverConfig?.chatMenu !== false; + }); + }, [rawMcpTools, startupConfig?.mcpServers]); + const mcpState = useMemo(() => { return ephemeralAgent?.mcp ?? []; }, [ephemeralAgent?.mcp]); diff --git a/packages/data-provider/src/config.ts b/packages/data-provider/src/config.ts index f97f193507..a1510d99a1 100644 --- a/packages/data-provider/src/config.ts +++ b/packages/data-provider/src/config.ts @@ -612,6 +612,7 @@ export type TStartupConfig = { description: string; } >; + chatMenu?: boolean; } >; mcpPlaceholder?: string;