🐛 fix: Display OAuth MCP servers according to Chat Menu Setting (#8643)

* fix: chatMenu not being respected in MCPSelect

* fix: chatMenu not being respected in MCPSubMenu
This commit is contained in:
Dustin Healy 2025-07-25 07:21:10 -07:00 committed by GitHub
parent ec67cf2d3a
commit 3dc9e85fab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 23 additions and 5 deletions

View file

@ -106,6 +106,7 @@ router.get('/', async function (req, res) {
const serverConfig = config.mcpServers[serverName];
payload.mcpServers[serverName] = {
customUserVars: serverConfig?.customUserVars || {},
chatMenu: serverConfig?.chatMenu,
};
}
}

View file

@ -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);

View file

@ -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<string | null>(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<string, TPlugin>();
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]);

View file

@ -612,6 +612,7 @@ export type TStartupConfig = {
description: string;
}
>;
chatMenu?: boolean;
}
>;
mcpPlaceholder?: string;