🔃 refactor: Clear MCP only on Model Spec Selection without MCP Servers (#10273)
Some checks are pending
Docker Dev Branch Images Build / build (Dockerfile, lc-dev, node) (push) Waiting to run
Docker Dev Branch Images Build / build (Dockerfile.multi, lc-dev-api, api-build) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile, librechat-dev, node) (push) Waiting to run
Docker Dev Images Build / build (Dockerfile.multi, librechat-dev-api, api-build) (push) Waiting to run
Sync Locize Translations & Create Translation PR / Sync Translation Keys with Locize (push) Waiting to run
Sync Locize Translations & Create Translation PR / Create Translation PR on Version Published (push) Blocked by required conditions

This commit is contained in:
Danny Avila 2025-10-27 20:33:51 -04:00 committed by GitHub
parent 0446d0e190
commit 7973cb42ef
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 43 additions and 7 deletions

View file

@ -9,7 +9,7 @@ import { getModelSpec, applyModelSpecEphemeralAgent } from '~/utils';
*/ */
export function useApplyModelSpecEffects() { export function useApplyModelSpecEffects() {
const updateEphemeralAgent = useUpdateEphemeralAgent(); const updateEphemeralAgent = useUpdateEphemeralAgent();
const applyPresetModelSpec = useCallback( const applyModelSpecEffects = useCallback(
({ ({
convoId, convoId,
specName, specName,
@ -37,7 +37,7 @@ export function useApplyModelSpecEffects() {
[updateEphemeralAgent], [updateEphemeralAgent],
); );
return applyPresetModelSpec; return applyModelSpecEffects;
} }
export function useApplyAgentTemplate() { export function useApplyAgentTemplate() {

View file

@ -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(() => { await waitFor(() => {
expect(result.current.mcpHook.mcpValues).toEqual([]); expect(result.current.mcpHook.mcpValues).toEqual([]);
}); });

View file

@ -21,12 +21,12 @@ export function useMCPSelect({ conversationId }: { conversationId?: string | nul
// Sync Jotai state with ephemeral agent state // Sync Jotai state with ephemeral agent state
useEffect(() => { useEffect(() => {
const mcps = ephemeralAgent?.mcp ?? []; 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 // Strip out servers that are not available in the startup config
const activeMcps = mcps.filter((mcp) => configuredServers.has(mcp)); const activeMcps = mcps.filter((mcp) => configuredServers.has(mcp));
setMCPValuesRaw(activeMcps); setMCPValuesRaw(activeMcps);
} else {
setMCPValuesRaw([]);
} }
}, [ephemeralAgent?.mcp, setMCPValuesRaw, configuredServers]); }, [ephemeralAgent?.mcp, setMCPValuesRaw, configuredServers]);

View file

@ -203,7 +203,7 @@ export function applyModelSpecEphemeralAgent({
return; return;
} }
updateEphemeralAgent((convoId ?? Constants.NEW_CONVO) || Constants.NEW_CONVO, { updateEphemeralAgent((convoId ?? Constants.NEW_CONVO) || Constants.NEW_CONVO, {
mcp: modelSpec.mcpServers ?? [], mcp: modelSpec.mcpServers ?? [Constants.mcp_clear as string],
web_search: modelSpec.webSearch ?? false, web_search: modelSpec.webSearch ?? false,
file_search: modelSpec.fileSearch ?? false, file_search: modelSpec.fileSearch ?? false,
execute_code: modelSpec.executeCode ?? false, execute_code: modelSpec.executeCode ?? false,

View file

@ -1603,6 +1603,8 @@ export enum Constants {
mcp_prefix = 'mcp_', mcp_prefix = 'mcp_',
/** Unique value to indicate all MCP servers. For backend use only. */ /** Unique value to indicate all MCP servers. For backend use only. */
mcp_all = 'sys__all__sys', 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. * Unique value to indicate the MCP tool was added to an agent.
* This helps inform the UI if the mcp server was previously added. * This helps inform the UI if the mcp server was previously added.