feat(cli,tui): normalize --catalog / --config with web; update --help (#1347) - #1499
Conversation
…#1347) Bring the CLI and TUI in line with the web catalog vs read-only session model introduced in #1481/#1483, and close the outstanding --help item from #1347. Core (core/mcp/node/config.ts): - Add `catalogPath` to ServerConfigOptions (writable catalog slot). - `resolveServerSource()` picks the active source: `--catalog` (writable, seed-if-missing) wins over `--config` (read-only, error-if-missing). - Writable sources seed an empty `{"mcpServers":{}}` on first run (matches the web backend) instead of erroring; read-only `--config` still errors. - `serverSourceConflict()` shared conflict matrix (mirrors run-web): --catalog/--config mutually exclusive; neither combines with an ad-hoc target. - `readServerListFile()` public loader for runners (TUI) needing the raw map. - Rename `withDefaultConfigPath` → `withDefaultCatalogPath`; the no-flag default now fills the writable catalog slot, not --config. CLI / TUI: - Add `--catalog <path>` (+ MCP_CATALOG_PATH) and re-document `--config` as a read-only session in --help. - Enforce the shared conflict matrix before resolution. Full writable persistence/CRUD threading remains deferred to #1482 / #1432 (CLI/TUI are read consumers today; the split surfaces as seed- vs error-on-missing). Tests: core resolution matrix (source/conflict/seed/read-only), CLI catalog + conflict integration tests, TUI loadTuiServers unit tests. READMEs updated. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The launcher smokes only checked `--help` for --cli/--tui; nothing exercised the launcher → CLI/TUI → core path on the built artifact (only smoke:web did, for web). Add two end-to-end smokes wired into validate:launcher between smoke:launcher and smoke:web: - smoke:cli (scripts/smoke-cli.mjs): runs `--cli` against the bundled stdio test server via a temp --catalog and asserts tools/list returns the tools, plus the #1347 resolution paths — default-catalog seed-on-missing, read-only --config error-without-seed, and the --catalog/--config conflict. - smoke:tui (scripts/smoke-tui.mjs): launches `--tui --catalog <temp>` and asserts the Ink app renders its first frame ("MCP Servers") within a timeout, then SIGTERMs it (shallow boot/render check). Both build test-servers/build on demand if missing. Docs updated (AGENTS.md validate description, launcher README). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@claude review |
|
Claude finished @cliffhall's task in 1m 34s —— View job Review: PR #1499 — normalize
|
…ity) Review feedback from @claude on PR #1499 (all non-blocking): - Align CLI catalogPath resolution with the TUI: `options.catalog?.trim() || process.env.MCP_CATALOG_PATH` so an explicit empty `--catalog ""` falls back to MCP_CATALOG_PATH identically in both front-ends (CLI used `??`, which only guards undefined/null). - Clarify the `serverSourceConflict` comment: it mirrors only the source-selection portion of web's matrix and deliberately omits web's `--header` rejection, since CLI/TUI merge --header into per-server settings. - Note the deliberate --header broadcast semantics in loadTuiServers. - Share an EMPTY_CATALOG_CONTENT constant between seedEmptyCatalog and readServerListContent instead of two separate literals. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks for the review! Addressed in f496577 (all non-blocking):
Left |
|
@claude review |
|
Claude finished @cliffhall's task in 1m 3s —— View job Re-review: PR #1499 — normalize
|
…view) Cosmetic uniformity follow-up from the re-review: configPath now uses `options.config?.trim() || undefined`, matching the catalog slot above it and the TUI. Behavior is unchanged (resolveServerSource/serverSourceConflict already trim downstream). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Thanks — addressed the two new observations in 899c20a:
CLI suite (38) + |
|
@claude review |
|
Claude finished @cliffhall's task in 1m 14s —— View job Re-review: PR #1499 — normalize
|
|
Thanks for the thorough three passes (and the cross-check against
No further changes; PR is ready for maintainer review. |
Closes #1347.
Brings the CLI and TUI in line with the web catalog vs. read-only session model introduced in #1481/#1483, and closes the outstanding
--helpacceptance item. The original default-fallback ask (getDefaultMcpConfigPath()when no flag is given) was already delivered with the CLI/TUI port; this PR normalizes the--catalog/--configvocabulary and behavior everywhere.What changed
Core —
core/mcp/node/config.tscatalogPathtoServerConfigOptions(the writable catalog slot).resolveServerSource()picks the active source:--catalog(writable, seed-if-missing) wins over--config(read-only, error-if-missing).{"mcpServers":{}}on first run (matches the web backend) instead of erroring; a read-only--configstill errors if absent.serverSourceConflict()— shared conflict matrix (mirrorsrun-web):--catalog/--configare mutually exclusive, and neither combines with an ad-hoc target.readServerListFile()— public loader for runners (TUI) that need the raw server map.withDefaultConfigPath→withDefaultCatalogPath; the no-flag default now fills the writable catalog slot, not--config.CLI / TUI
--catalog <path>(+MCP_CATALOG_PATH) and re-document--configas a read-only session in--help.Decisions (confirmed with maintainer)
--configerrors.Tests
resolveServerSource,serverSourceConflict, seed-on-missing (writable), error-on-missing (read-only),readServerListFile,withDefaultCatalogPath, and catalog branches ofresolveServerConfigs(single + multi).--catalogsuccess +--catalog/--configand--catalog/ad-hoc conflict integration tests.loadTuiServersunit tests (catalog seed, config error, conflicts, ad-hoc, header merge).npm run validatepasses end-to-end (web format/lint/build/coverage, CLI + TUI suites, launcher build,smoke:launcher,smoke:web).🤖 Generated with Claude Code