From 7973cb42ef3da972877b45dbd608c623972cf611 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 27 Oct 2025 20:33:51 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=83=20refactor:=20Clear=20MCP=20only?= =?UTF-8?q?=20on=20Model=20Spec=20Selection=20without=20MCP=20Servers=20(#?= =?UTF-8?q?10273)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hooks/Agents/useApplyModelSpecAgents.ts | 4 +-- .../hooks/MCP/__tests__/useMCPSelect.test.tsx | 36 ++++++++++++++++++- client/src/hooks/MCP/useMCPSelect.ts | 6 ++-- client/src/utils/endpoints.ts | 2 +- packages/data-provider/src/config.ts | 2 ++ 5 files changed, 43 insertions(+), 7 deletions(-) diff --git a/client/src/hooks/Agents/useApplyModelSpecAgents.ts b/client/src/hooks/Agents/useApplyModelSpecAgents.ts index e7f15741cb..4e51a42339 100644 --- a/client/src/hooks/Agents/useApplyModelSpecAgents.ts +++ b/client/src/hooks/Agents/useApplyModelSpecAgents.ts @@ -9,7 +9,7 @@ import { getModelSpec, applyModelSpecEphemeralAgent } from '~/utils'; */ export function useApplyModelSpecEffects() { const updateEphemeralAgent = useUpdateEphemeralAgent(); - const applyPresetModelSpec = useCallback( + const applyModelSpecEffects = useCallback( ({ convoId, specName, @@ -37,7 +37,7 @@ export function useApplyModelSpecEffects() { [updateEphemeralAgent], ); - return applyPresetModelSpec; + return applyModelSpecEffects; } export function useApplyAgentTemplate() { diff --git a/client/src/hooks/MCP/__tests__/useMCPSelect.test.tsx b/client/src/hooks/MCP/__tests__/useMCPSelect.test.tsx index ab10ec6d76..4741bba328 100644 --- a/client/src/hooks/MCP/__tests__/useMCPSelect.test.tsx +++ b/client/src/hooks/MCP/__tests__/useMCPSelect.test.tsx @@ -431,7 +431,41 @@ describe('useMCPSelect', () => { }); }); - // Values should sync to empty array when ephemeralAgent.mcp is set to [] + // Values should remain unchanged since empty mcp array doesn't trigger update + // (due to the condition: ephemeralAgent?.mcp && ephemeralAgent.mcp.length > 0) + expect(result.current.mcpHook.mcpValues).toEqual(['initial-value']); + }); + + it('should handle ephemeralAgent with clear mcp value', async () => { + // Create a shared wrapper + const wrapper = createWrapper(['server1', 'server2']); + + // Create a component that uses both hooks + const TestComponent = () => { + const mcpHook = useMCPSelect({}); + const setEphemeralAgent = useSetRecoilState(ephemeralAgentByConvoId(Constants.NEW_CONVO)); + return { mcpHook, setEphemeralAgent }; + }; + + const { result } = renderHook(() => TestComponent(), { wrapper }); + + // Set initial values + act(() => { + result.current.mcpHook.setMCPValues(['server1', 'server2']); + }); + + await waitFor(() => { + expect(result.current.mcpHook.mcpValues).toEqual(['server1', 'server2']); + }); + + // Set ephemeralAgent with clear value + act(() => { + result.current.setEphemeralAgent({ + mcp: [Constants.mcp_clear as string], + }); + }); + + // mcpValues should be cleared await waitFor(() => { expect(result.current.mcpHook.mcpValues).toEqual([]); }); diff --git a/client/src/hooks/MCP/useMCPSelect.ts b/client/src/hooks/MCP/useMCPSelect.ts index 3ce7999346..1ee2fe05b3 100644 --- a/client/src/hooks/MCP/useMCPSelect.ts +++ b/client/src/hooks/MCP/useMCPSelect.ts @@ -21,12 +21,12 @@ export function useMCPSelect({ conversationId }: { conversationId?: string | nul // Sync Jotai state with ephemeral agent state useEffect(() => { const mcps = ephemeralAgent?.mcp ?? []; - if (mcps.length > 0) { + if (mcps.length === 1 && mcps[0] === Constants.mcp_clear) { + setMCPValuesRaw([]); + } else if (mcps.length > 0) { // Strip out servers that are not available in the startup config const activeMcps = mcps.filter((mcp) => configuredServers.has(mcp)); setMCPValuesRaw(activeMcps); - } else { - setMCPValuesRaw([]); } }, [ephemeralAgent?.mcp, setMCPValuesRaw, configuredServers]); diff --git a/client/src/utils/endpoints.ts b/client/src/utils/endpoints.ts index 1de9e2845c..9ceee3e178 100644 --- a/client/src/utils/endpoints.ts +++ b/client/src/utils/endpoints.ts @@ -203,7 +203,7 @@ export function applyModelSpecEphemeralAgent({ return; } updateEphemeralAgent((convoId ?? Constants.NEW_CONVO) || Constants.NEW_CONVO, { - mcp: modelSpec.mcpServers ?? [], + mcp: modelSpec.mcpServers ?? [Constants.mcp_clear as string], web_search: modelSpec.webSearch ?? false, file_search: modelSpec.fileSearch ?? false, execute_code: modelSpec.executeCode ?? false, diff --git a/packages/data-provider/src/config.ts b/packages/data-provider/src/config.ts index c3f872eaec..ab8b88ec0f 100644 --- a/packages/data-provider/src/config.ts +++ b/packages/data-provider/src/config.ts @@ -1603,6 +1603,8 @@ export enum Constants { mcp_prefix = 'mcp_', /** Unique value to indicate all MCP servers. For backend use only. */ mcp_all = 'sys__all__sys', + /** Unique value to indicate clearing MCP servers from UI state. For frontend use only. */ + mcp_clear = 'sys__clear__sys', /** * Unique value to indicate the MCP tool was added to an agent. * This helps inform the UI if the mcp server was previously added.