feat(web): catalog vs read-only session launch model + apply --header (#1481, #1483)#1496
feat(web): catalog vs read-only session launch model + apply --header (#1481, #1483)#1496cliffhall wants to merge 2 commits into
Conversation
…#1481, #1483) Per specification/v2_catalog_launch_config.md, `mcp-inspector --web` now selects the backend's server-list source and a session-wide writability, instead of seeding an inert `initialMcpConfig` the UI never read: - `--catalog <path>` (and `MCP_CATALOG_PATH`) → active WRITABLE catalog (seed/CRUD/watch), like the default catalog. - `--config <path>` → READ-ONLY session file: served in the UI but never written, seeded, or plaintext-secret-migrated — safe to point at a foreign config (e.g. claude_desktop_config.json). - ad-hoc `--server-url`/command (+ `--header`) → one server held IN MEMORY (no file written); `--header` is lifted onto the entry so the seeded connection actually uses it (closes the #1483 warn-only no-op). - nothing → default catalog (writable), unchanged. Backend (`createRemoteApp`): new `writable` + `initialServers` options. GET /api/servers branches three ways (in-memory / read-only file with no seed+no migrate / writable catalog); the four mutating routes return 403 when read-only; `/api/config` carries `writable`; the file watcher is skipped for in-memory sessions. `--catalog`/`--config` are mutually exclusive and neither combines with an ad-hoc target or `--header`; `--header` requires an ad-hoc HTTP/SSE server (clear errors otherwise — no silent no-op). UI: `useServerListWritable` reads `writable` from /api/config; the Servers screen hides add/edit/clone/remove/reorder/settings and shows a read-only banner when false. All new props default to writable=true (back-compatible). Docs: spec gaps G2/G3/G4 updated; launcher README documents the flags. Verified end-to-end against the built launcher: --config (writable:false, file byte-stable, mutations 403), ad-hoc --header (in-memory, header lifted), and --catalog (writable:true, POST persists). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@claude review |
|
Claude finished @cliffhall's task in 1m 46s —— View job Code Review: catalog vs read-only session launch model (#1481, #1483)
Overall this is a well-structured, carefully-documented PR. The three-way server-list model (in-memory / read-only-file / writable-catalog) is cleanly factored, the comments explain the why (foreign-config safety, no-migration-on-read, 403-not-404 to avoid id leaks), the conflict matrix closes the #1483 "silent no-op" gap, and the test coverage is genuinely thorough (byte-stability, no-seed, 403-uniformity, in-memory serve, events no-broadcast). Nothing here blocks merge. Below are observations grouped by severity. Correctness / design — minor
Style / conventions — minor
Things verified as correct ✅
Suggestion (optional)The duplicate-fetch item (#1) is the only one I'd consider acting on, and only as a follow-up. Consolidate the two /api/config hooks → |
…larify watcher comment - Replace raw <code> with Mantine <Code> in the read-only-session Alert (repo convention: prefer Mantine primitives over raw HTML). - Add a comment near `watchable` clarifying that a read-only `--config` file is still watched on purpose (read-only blocks UI writes, not external observation; `writable` does not gate watching). Deferred (per reviewer): consolidating useSandboxUrl + useServerListWritable into one useConfig hook to avoid the duplicate /api/config fetch — optional follow-up. The redundant ad-hoc header type-guard is kept as defensive. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the review! Addressed the two worthwhile nits in 7e619ac:
Deferred / left as-is (agree these aren't blockers):
@claude review |
|
Claude finished @cliffhall's task in 34s —— View job Re-review: review fixes in
|




Closes #1481. Closes #1483.
Implements the full catalog/session launch model from
specification/v2_catalog_launch_config.mdfor the web client. Previouslymcp-inspector --webresolved aninitialMcpConfigthat the v2 UI never read (thedefault*fields of/api/confighave no consumer), so--server-url/--configshowed nothing and--headeronly printed a warning.Behaviour
writablemcp-inspector --web~/.mcp-inspector/mcp.json--catalog <path>/MCP_CATALOG_PATH--config <path>--server-url/command (+--header)--catalog/--configare mutually exclusive; neither combines with an ad-hoc target or--header;--headerrequires an ad-hoc HTTP/SSE server. Every illegal combination exits with a clear error — no silent no-op remains (the #1483 acceptance criterion).The read-only design deliberately protects a foreign config passed via
--config(e.g.claude_desktop_config.json): the backend never writes, seeds, or migrates plaintext secrets from it.Changes
core/mcp/remote/node/server.ts):writable+initialServersoptions onRemoteServerOptions; three-way GET/api/servers(in-memory / read-only-file-no-seed-no-migrate / writable); 403 guard on POST/PUT/DELETE/order;writableon/api/config; watcher skipped for in-memory sessions.writable/initialServersthreaded throughWebServerConfig→ bothcreateRemoteAppcall sites;run-webflag resolution rewritten (adds--catalog/MCP_CATALOG_PATH, makes--configread-only, seeds ad-hoc in-memory with--header, conflict matrix).useServerListWritablehook (reads/api/config);App → InspectorView → ServerListScreenthreadwritable; Servers screen hides add/edit/clone/remove/reorder/settings and shows a read-only banner when false. All new props default towritable=true(back-compatible).Scope / follow-ups (out of scope, separate issues)
--serverselection /defaultServerId+ auto-connect (#1183), UC2 import (#1348/#1435), and the CLI/TUIresolveServerList+ writable unification (#1482/#1432).Verification
npm run validate(web format/lint/build/coverage + cli/tui + launcher smoke) andnpm run test:storybookboth green.run-webresolution matrix + conflicts; backend read-only 403 + in-memory serve + file byte-stability after GET (no migration) + no-seed-on-missing;/api/configwritable; events no-broadcast for in-memory;useServerListWritable;ServerCard/ServerListScreenwritable=falsegating.--config→writable:false, file byte-identical, mutations 403; ad-hoc--header→ in-memory server withheaders;--catalog→writable:true, POST persists to the file.🤖 Generated with Claude Code