🤖 feat: add 'Manage MCP servers' modal on chat creation#3364
Open
Neppkun wants to merge 1 commit into
Open
Conversation
Replace the 'Add MCP server' button on the project's new-chat page with
'Manage MCP servers', opening a draft-mode WorkspaceMCPModal that lets
the user stage per-workspace enable/disable overrides and add new
servers before the workspace exists. Staged overrides are applied via
api.workspace.mcp.set immediately after workspace creation
(fire-and-forget so the first prompt is never blocked on remote
runtimes).
Refactors:
- Extract MCPAddServerForm and MCPOAuth helpers out of MCPSettingsSection
so the new modal and Settings → MCP share one Add-server surface.
- Introduce shared workspaceMcpEffective helper (three-way precedence
rule + toggle/hasAnyOverride) with 14 unit tests so the modal toggles
and the overview count always agree.
- WorkspaceMCPModal becomes a discriminated-union dual-mode component
('workspace' = unchanged behavior, 'draft' = no live get/set, hides
tool-allowlist UI, embeds MCPAddServerForm).
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
Replaces the "Add MCP server" button in the MCP Servers box on the project's new-chat page with "Manage MCP servers", which opens a modal where the user can toggle each MCP server on/off for the workspace this chat will create and add new MCP servers — without detouring to global Settings.
Demo
https://owo.whats-th.is/3DqYvnr.mp4
Background
Today the button on the creation page only links into the global Settings → MCP panel, which is awkward when the user knows up-front they want a different set of servers for the next workspace (e.g. opt into a heavyweight server only for one chat, or shut a noisy one off for a single task). The backend already supports per-workspace overrides at
<workspace>/.mux/mcp.local.jsoncviaapi.workspace.mcp.{get,set}(theWorkspaceMCPOverridesschema insrc/common/orpc/schemas/mcp.ts), and the existingWorkspaceMCPModalexposes that for already-created workspaces. This PR brings the same affordance to the moment of creation by staging the overrides client-side and applying them right afterapi.workspace.createreturns.Implementation
Creation-page UX
ProjectMCPOverviewnow:SlidersHorizontalicon).effectiveEnabledServerNameshelper, so the count reflects staged overrides.WorkspaceMCPModalinstance inmode="draft".Dual-mode WorkspaceMCPModal
The existing modal becomes a discriminated-union dual-mode component:
mode: "workspace"(default, unchanged forWorkspaceMenuBar/WorkspaceActionsMenuContent): still loads viaapi.workspace.mcp.get, persists viaapi.workspace.mcp.set, still shows the per-server tool-allowlist UI.mode: "draft"(new): takesinitialOverrides+onSave(overrides)callback. Skips the live get/save (the parent stages the result). Hides the tool-allowlist UI (out of scope here — workspace-mode keeps it). Embeds the newMCPAddServerForminline so the user can add a server without leaving the modal.Staged-then-applied flow
The
mcp.setcall is intentionally fire-and-forget: remote runtimes (SSH/Coder) can make the override write slow, and the user expects their first prompt to start streaming immediately. On failure weconsole.warn; the workspace simply uses project defaults until the user re-applies via the post-creation modal.The staged map is keyed by
pendingDraftId ?? "__pending__"(matchesChatInput's draft scoping) and is reset onprojectPathchange so drafts can't leak across projects.Refactors
MCPAddServerForm(new component): extracted verbatim fromMCPSettingsSectionso the new modal and Settings → MCP share one Add-server surface (transport policy clamp, headers editor, Test, OAuth callout, post-add remote test, etc.).MCPOAuth.tsx(new): OAuth helpers +MCPOAuthRequiredCalloutmoved out ofMCPSettingsSectionsoMCPAddServerFormcan use them without creating a circular import.workspaceMcpEffective.ts(new shared helper, 14 unit tests): centralizes the three-way precedence rule (enabledServers > disabledServers > project disabled) so the modal toggles and the overview count can never disagree. Also exportstoggleServerOverrideandhasAnyOverride.MCPSettingsSection.tsx: dropped from 1614 → 882 lines after pulling out the shared form/helpers. No behavior change for Settings users.Validation
make typecheck— greenmake lint— greenbun test src/common/utils/workspaceMcpEffective.test.ts— 14/14 pass (3-way rule, toggle preserves allowlist + doesn't dup, hasAnyOverride edge cases)make dev-server-sandbox: button copy/icon, staged-modified count, save persists viaapi.workspace.mcp.setafter creation (verified by reopening the post-creationWorkspaceMCPModal), add-server flow inside the modal, Settings → MCP unchanged for stdio + http + OAuth servers.Risks
Moderate, contained mostly to the creation/MCP surface:
WorkspaceMCPModalrefactor: the existing workspace-mode call sites (WorkspaceMenuBar,WorkspaceActionsMenuContent) keep the same prop shape; the new optionalmodediscriminator defaults to"workspace"so untouched call sites behave identically. Tool-allowlist UI is only hidden in draft mode.MCPSettingsSectionextraction: largest mechanical risk — the inline<details>Add server</details>JSX, headers editor wiring, OAuth callout, and post-add remote test were moved toMCPAddServerFormbyte-for-byte. Settings now consumes that component; no public oRPC calls changed.useCreationWorkspacepost-create call: gated behindhasAnyOverride(stagedMcpOverrides)so creation paths that don't touch the new UI emit zero extra IPC. The call isvoid-ed so it cannot reject into the workspace-creation try/catch.projectPath(reset effect) andpendingDraftId ?? "__pending__"to mirror existing draft semantics.Pains
WorkspaceMCPModaltypes its meta against the component's discriminated-union prop type; switching that union forced a narrow cast (WorkspaceMCPModal as ComponentType<WorkspaceMCPModalWorkspaceProps>) plus an exported workspace-mode props alias so the stories'StoryObj<typeof meta>doesn't resolve tonever. Documented inline with a comment.Generated with
mux• Model:anthropic:claude-opus-4-7• Thinking:high• Cost:$20.69