fix(web): carry a landed stdio env/cwd onto the config it connects with

The Server Settings modal edits a stdio server's `env` and `cwd` as
settings, while the transport reads them off the *config* — so #2091's
tracker, which resolves settings through the last write known to have
reached disk, left those two behind: `server.config` still came straight
off a `servers` entry that stops advancing once a list read fails. A save
that landed during such a window kept spawning the child process with the
pre-save environment, while the modal (re-seeded from the tracker) showed
the new value. Credentials live in `env`, so the symptom is the inspected
server failing to authorize rather than a visibly lost edit.

Adds the settings→config mapping to `core/mcp/serverList.ts` — the one
place both sides of the wire can share — and routes the `/api/servers` PUT
write-through and the web client's connect path through it, so the value
persisted and the value spawned cannot be derived differently.

Closes #2096

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0177mPHAdECD18nLLCTwR5rh
Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
cliffhall 2026-08-25 00:36:09 -04:00
commit d9b5f4f8a7

View file

@ -70,6 +70,7 @@ import { ManagedResourceTemplatesState } from "@inspector/core/mcp/state/managed
import { ManagedRequestorTasksState } from "@inspector/core/mcp/state/managedRequestorTasksState.js";
import { ResourceSubscriptionsState } from "@inspector/core/mcp/state/resourceSubscriptionsState.js";
import {
applyStdioSettingsToConfig,
cleanRoots,
oauthAuthorizationParamsFromSettings,
oauthEndpointOverridesFromSettings,
@ -2650,7 +2651,19 @@ function App() {
...(activeCimdUrl && { clientMetadataUrl: activeCimdUrl }),
}
: undefined;
const client = new InspectorClient(server.config, {
// The stdio `env` / `cwd` are edited as *settings* but stored on — and
// read by the transport from — *config*, so the tracker's account of the
// former has to be carried onto the latter. `server.config` comes off the
// same frozen `servers` entry `server.settings` does, so without this a
// save that landed while list reads were failing spawns the child process
// with the pre-save environment while the modal, re-seeded from the
// tracker, shows the new one (#2096). Same mapping the PUT route applies
// when persisting it, from the same helper.
const effectiveConfig = applyStdioSettingsToConfig(
server.config,
savedSettings,
);
const client = new InspectorClient(effectiveConfig, {
environment,
// The Tasks tab needs the receiver-task pipeline; the
// requestor-task list comes from the client's task store.