Repository navigation
🔌 fix: Preserve Ephemeral MCP Selections Across Model Switches - #13697
Merged
Merged
Conversation
The no-spec branch of `useApplyModelSpecEffects` (added in #11796) reset `ephemeralAgentByConvoId` to null on every `newConversation` call when model specs are configured. On in-place model/endpoint switches (modular chat, same conversation or new-chat draft), BadgeRowContext never refills from localStorage — its init effect only re-runs when the storage suffix or spec changes — so the MCP selection (and tool toggles) were silently dropped from subsequent request payloads while the MCP badge kept displaying them. Reset now only happens on context transitions (leaving a spec, or moving to a different conversation key), where a BadgeRowContext refill is guaranteed; in-place non-spec switches preserve the ephemeral agent. - Gate the no-spec reset on `prevSpecName` / `prevConvoId`, passed from `newConversation` via a snapshot read of the pre-switch conversation - Add jest coverage for all five branches of the no-spec path - Add e2e spec asserting `ephemeralAgent.mcp` stays in the chat payload after a new-chat model switch and after regenerate on a switched conversation (verified failing before the fix, passing after) - Add non-spec "Mock Provider D" endpoint to the e2e config so tests can switch between two real ephemeral endpoints; widen `MockEndpoint` type
Collaborator
Author
|
@codex review |
|
Codex Review: Didn't find any major issues. 🎉 ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
fuuuzzy
pushed a commit
to fuuuzzy/LibreChat
that referenced
this pull request
Jun 18, 2026
…Chat-AI#13697) The no-spec branch of `useApplyModelSpecEffects` (added in LibreChat-AI#11796) reset `ephemeralAgentByConvoId` to null on every `newConversation` call when model specs are configured. On in-place model/endpoint switches (modular chat, same conversation or new-chat draft), BadgeRowContext never refills from localStorage — its init effect only re-runs when the storage suffix or spec changes — so the MCP selection (and tool toggles) were silently dropped from subsequent request payloads while the MCP badge kept displaying them. Reset now only happens on context transitions (leaving a spec, or moving to a different conversation key), where a BadgeRowContext refill is guaranteed; in-place non-spec switches preserve the ephemeral agent. - Gate the no-spec reset on `prevSpecName` / `prevConvoId`, passed from `newConversation` via a snapshot read of the pre-switch conversation - Add jest coverage for all five branches of the no-spec path - Add e2e spec asserting `ephemeralAgent.mcp` stays in the chat payload after a new-chat model switch and after regenerate on a switched conversation (verified failing before the fix, passing after) - Add non-spec "Mock Provider D" endpoint to the e2e config so tests can switch between two real ephemeral endpoints; widen `MockEndpoint` type
ThomasVuNguyen
pushed a commit
to ThomasVuNguyen/LibreChat
that referenced
this pull request
Jul 15, 2026
…Chat-AI#13697) The no-spec branch of `useApplyModelSpecEffects` (added in LibreChat-AI#11796) reset `ephemeralAgentByConvoId` to null on every `newConversation` call when model specs are configured. On in-place model/endpoint switches (modular chat, same conversation or new-chat draft), BadgeRowContext never refills from localStorage — its init effect only re-runs when the storage suffix or spec changes — so the MCP selection (and tool toggles) were silently dropped from subsequent request payloads while the MCP badge kept displaying them. Reset now only happens on context transitions (leaving a spec, or moving to a different conversation key), where a BadgeRowContext refill is guaranteed; in-place non-spec switches preserve the ephemeral agent. - Gate the no-spec reset on `prevSpecName` / `prevConvoId`, passed from `newConversation` via a snapshot read of the pre-switch conversation - Add jest coverage for all five branches of the no-spec path - Add e2e spec asserting `ephemeralAgent.mcp` stays in the chat payload after a new-chat model switch and after regenerate on a switched conversation (verified failing before the fix, passing after) - Add non-spec "Mock Provider D" endpoint to the e2e config so tests can switch between two real ephemeral endpoints; widen `MockEndpoint` type
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
I fixed a regression where switching the provider/model mid-conversation (or on a new chat draft) silently dropped the ephemeral MCP selection — and tool toggles — from subsequent request payloads, while the MCP badge kept displaying the selection as active. Regenerating or sending after a switch ran without MCP tools.
Root cause: the no-spec branch of
useApplyModelSpecEffects(introduced in #11796) resetephemeralAgentByConvoIdtonullon everynewConversationcall when model specs are configured. That reset is paired with aBadgeRowContextlocalStorage refill — but the refill effect only re-runs when the storage suffix or active spec changes, so on in-place modular switches (same conversation id, non-spec → non-spec) nothing restored the state and submissions read anullephemeral agent.BadgeRowContextrefill is guaranteed to follow; in-place switches now preserve the ephemeral agent.prevSpecName/prevConvoIdintoapplyModelSpecEffectsfromnewConversationvia a snapshot read of the pre-switch conversation.__defaults__, and leaving a spec still discards spec-applied values.ephemeralAgent.mcpstays in the chat request payload after a model switch on a new chat and after regenerate on a switched conversation — verified both tests fail on the unfixed build and pass with the fix.MockEndpointhelper type accordingly.Change Type
Testing
Reproduced the original report first: new chat with an MCP server selected → first payload includes
ephemeralAgent.mcp→ switch provider/model → regenerate → payload omitsephemeralAgententirely while the MCP select still shows the server. Also confirmed the new-chat variant (switch before the first send) drops it the same way.cd client && npx jest useApplyModelSpecAgents useMCPSelect useToolToggle agents.spec— 67 tests pass.npx playwright test --config=e2e/playwright.config.mock.ts mcp-ephemeral— 2 pass with the fix; both fail on the unfixed build withephemeralAgent.mcpundefined in the captured request payload (regression-proof).chat,mcp,model-switching,soft-default,model-spec-branding) — 15 tests pass with the e2e config additions.sort-imports:checkclean on all changed files.Test Configuration:
playwright.config.mock.ts) withE2E_BASE_URL=http://localhost:3334 MOCK_LLM_PORT=8899; bug requiresmodelSpecsconfigured, which the e2e config already has.Checklist