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.