First pass at pulling the v1.5 CLI, TUI, and Launcher clients into v2.
This commit is contained in:
parent
d5f12b2a82
commit
467b01edd6
2 changed files with 24043 additions and 203 deletions
520
specification/v2_catalog_launch_config.md
Normal file
520
specification/v2_catalog_launch_config.md
Normal file
|
|
@ -0,0 +1,520 @@
|
|||
# Inspector V2 Tech Stack - Storage - Catalog and Launch Configuration
|
||||
|
||||
### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | V2 Tech Stack | [V2 UX](v2_ux.md)
|
||||
|
||||
#### [Web Client](v2_web_client.md) | [Server](v2_server.md) | [Storage](v2_storage.md)
|
||||
##### [Overview](v2_storage.md) | [Server List File](v2_servers_file.md) | Catalog and Launch
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Summary](#summary)
|
||||
* [Goals](#goals)
|
||||
* [Non-goals](#non-goals)
|
||||
* [Related specifications](#related-specifications)
|
||||
* [Terminology](#terminology)
|
||||
* [User intents (UC1–UC5)](#user-intents-uc1uc5)
|
||||
* [Flag reference](#flag-reference)
|
||||
* [Background (v1.5)](#background-v15)
|
||||
* [Normalization](#normalization)
|
||||
* [Cross-client list contract](#cross-client-list-contract)
|
||||
* [Launch behavior by client](#launch-behavior-by-client)
|
||||
* [Import (UC2)](#import-uc2)
|
||||
* [Write-back policy](#write-back-policy)
|
||||
* [Web launch behavior](#web-launch-behavior)
|
||||
* [Target API (core)](#target-api-core)
|
||||
* [Open decisions](#open-decisions)
|
||||
* [Known gaps](#known-gaps)
|
||||
* [Decision matrix](#decision-matrix)
|
||||
* [Engineering follow-ups](#engineering-follow-ups)
|
||||
* [Related GitHub issues](#related-github-issues)
|
||||
* [References](#references)
|
||||
|
||||
## Summary
|
||||
|
||||
v2 treats `~/.mcp-inspector/mcp.json` as the default **catalog** — a persistent, Inspector-owned grouping of MCP servers. The web client loads and mutates it via `/api/servers`. CLI and TUI resolve servers from that path when launch args omit both `--config` and ad-hoc targets (`withDefaultConfigPath()` in `core/mcp/node/config.ts`).
|
||||
|
||||
This specification defines **launch-time configuration** across web, CLI, and TUI: how `--catalog`, `--config`, `--server`, and ad-hoc flags select a server list; which paths are writable; and how import differs from session launch. On-disk catalog format and web CRUD are specified in [Server List File](v2_servers_file.md). CLI/TUI/launcher build and per-client implementation gaps are in [CLI, TUI, and Launcher](v2_cli_tui_launcher.md).
|
||||
|
||||
## Goals
|
||||
|
||||
- One **catalog** model shared by web, CLI, and TUI, with a clear split between **catalog modes** (writable, UC1/UC4) and **session mode** (read-only, UC3).
|
||||
- **`--catalog`** selects the active writable catalog; **`--config`** without catalog intent supplies a read-only session file — not overloaded.
|
||||
- All reads **parse → normalize → lift** into canonical `ServerEntry[]`; catalog writes serialize through the same contract as [Server List File](v2_servers_file.md).
|
||||
- **List clients** (web, TUI) consume the same resolved list plus `writable`, `defaultServerId`, and optional `autoConnect` — resolution in **core**, not the launcher.
|
||||
- **Import** is an explicit catalog mutation (`servers/import` on CLI; web Import menu) — never a side effect of launch.
|
||||
- **CLI** resolves a single server through the same normalizer as list clients, including disk **settings** lift.
|
||||
- **Web** follows **catalog-first** launch: full catalog visible; `--server` selects an entry; ad-hoc launches do not auto-persist.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Syncing with Claude Desktop, Cursor, or other tools' config paths (symlinking is the user's choice — see [Server List File](v2_servers_file.md)).
|
||||
- Silent write-back of launch overrides (`-e`, `--cwd`, `--header`) to catalog or session files.
|
||||
- Launcher as config arbitrator — it routes mode and forwards argv only.
|
||||
- Requiring import support on all three clients at startup (UC2 is CLI + web UI).
|
||||
- Auto-importing ad-hoc launches into the catalog.
|
||||
- File watching or two-way sync with external MCP client configs.
|
||||
|
||||
## Related specifications
|
||||
|
||||
| Document | Owns |
|
||||
|----------|------|
|
||||
| [v2_servers_file.md](v2_servers_file.md) | Catalog path, on-disk shape, web CRUD, `/api/servers`, per-server settings |
|
||||
| [v2_cli_tui_launcher.md](v2_cli_tui_launcher.md) | Bins, tsup, tests, `runWeb`, CLI config-file settings gap (G1) |
|
||||
| [v2_ux.md](v2_ux.md) | Import config vs Import server.json menu UX |
|
||||
| v1.5 `docs/mcp-server-configuration.md` | Baseline shared launch flags (port to v2 pending, G6) |
|
||||
|
||||
---
|
||||
|
||||
## Terminology
|
||||
|
||||
| Term | Meaning |
|
||||
|------|---------|
|
||||
| **Catalog** | Inspector-owned `mcp.json` used as a persistent server grouping. Default: `~/.mcp-inspector/mcp.json`. Active catalog selected by `--catalog <path>` or default (UC1/UC4). CRUD when `writable: true`. |
|
||||
| **`--catalog`** | Selects the **active catalog** for this run (`writable: true`). Omitted → default path (UC1). |
|
||||
| **Alternate config file** | Any JSON passed via `--config <path>` without catalog intent. **Read-only, run-scoped** server set (UC3). Inspector does not write to this path. |
|
||||
| **Canonical catalog format** | Normalized `MCPConfig` / `ServerEntry[]` after `normalizeServerType`, `normalizeMcpServers`, and `mcpConfigToServerEntries` — the only shape written to a catalog. |
|
||||
| **Catalog lookup** | `--server <name>` with no `--config` and no ad-hoc target. `withDefaultConfigPath()` injects the catalog path, then the named entry is resolved. |
|
||||
| **Ad-hoc / inline config** | Positional command/URL and/or `--transport`, `--server-url`, `-e`, `--cwd`, `--header` without `--config`. Ephemeral unless the user persists via CRUD or import. |
|
||||
| **Launch-time initial config (web)** | `initialMcpConfig` from `runWeb(argv)` → `GET /api/config`. Legacy v1.5 channel; largely unused by the v2 web UI today (G2). |
|
||||
|
||||
---
|
||||
|
||||
## User intents (UC1–UC5)
|
||||
|
||||
Five distinct user goals. They share flags (`--config`, `--server`, `--catalog`) but differ in **whether the list is the catalog, read-only, or mutated**, and **which client** owns each action.
|
||||
|
||||
### UC1 — Default catalog: run and manage servers in place
|
||||
|
||||
**Intent:** Use the usual server list at `~/.mcp-inspector/mcp.json` — the default active catalog (UC4 with default path). Add, edit, remove, and configure settings through the UX; CLI invokes methods against a named catalog entry.
|
||||
|
||||
| | Today | Target |
|
||||
|---|--------|--------|
|
||||
| **Web** | Works — `useServers` + `/api/servers` CRUD | Same |
|
||||
| **TUI** | Loads default catalog via `withDefaultConfigPath` in `loadTuiServers`; **no CRUD UX yet** | Catalog CRUD in TUI (planned) |
|
||||
| **CLI** | `--server foo --method …` with no `--config` resolves against default catalog | Same; lift settings from catalog entries (G1) |
|
||||
|
||||
```bash
|
||||
mcp-inspector --web
|
||||
mcp-inspector --cli --server my-api --method tools/list
|
||||
mcp-inspector --tui
|
||||
```
|
||||
|
||||
The catalog is both the **data source** and the **write target** (`writable: true`).
|
||||
|
||||
### UC2 — Import into a catalog (automation / one-off CLI)
|
||||
|
||||
**Intent:** Add servers **into** an Inspector catalog (default or `--catalog` target). Distinct from “launch and use for this session” (UC3). Import is a **catalog write**, not a launch mode.
|
||||
|
||||
| Source | CLI shape | Stored |
|
||||
|--------|-----------|--------|
|
||||
| **A — `mcpServers` file** | `--config /path/to/source.json` [ `--server <name>` ] `--method servers/import` | One or all entries, canonicalized |
|
||||
| **B — Ad-hoc parts** | Same argv as ad-hoc launch (`[target...]`, `--transport`, `--server-url`, `-e`, `--cwd`, `--header`, …); no `--config`. Method → `servers/import`. | One entry; **`--server <id>`** = catalog map key (required for B) |
|
||||
|
||||
```bash
|
||||
# A: import all from a foreign mcp.json
|
||||
mcp-inspector --cli --config /path/to/claude.json --method servers/import
|
||||
|
||||
# A: one named entry from source file (--server = name in source)
|
||||
mcp-inspector --cli --config /path/to/claude.json --server acme --method servers/import
|
||||
|
||||
# B: stdio — launch vs import differ only by --method and --server (catalog id)
|
||||
mcp-inspector --cli \
|
||||
-e API_KEY=dev --cwd /path/to/server \
|
||||
node ./build/index.js --method tools/list
|
||||
|
||||
mcp-inspector --cli \
|
||||
--server my-local \
|
||||
-e API_KEY=dev --cwd /path/to/server \
|
||||
node ./build/index.js --method servers/import
|
||||
|
||||
# B: streamable HTTP
|
||||
mcp-inspector --cli \
|
||||
--transport streamable-http \
|
||||
--server-url https://api.example.com/mcp \
|
||||
--header "Authorization: Bearer xxx" \
|
||||
--method tools/list
|
||||
|
||||
mcp-inspector --cli \
|
||||
--server staging-api \
|
||||
--transport streamable-http \
|
||||
--server-url https://api.example.com/mcp \
|
||||
--header "Authorization: Bearer xxx" \
|
||||
--method servers/import
|
||||
|
||||
# Into a non-default catalog (UC4)
|
||||
mcp-inspector --cli --catalog ./project/.mcp-inspector/mcp.json \
|
||||
--config ./vendor.json --method servers/import
|
||||
```
|
||||
|
||||
**Not UC2:** `mcp-inspector --cli node ./server.js --method tools/list` without `servers/import` is UC3/UC1 (use now), not import.
|
||||
|
||||
| | Today | Target |
|
||||
|---|--------|--------|
|
||||
| **CLI** | Not implemented | `servers/import` for A and B via `importServersIntoCatalog` in core |
|
||||
| **Web** | Import menu items stubbed | Interactive import per [v2_ux.md](v2_ux.md); [#1348](https://github.com/modelcontextprotocol/inspector/issues/1348), [#1435](https://github.com/modelcontextprotocol/inspector/issues/1435) |
|
||||
| **TUI** | N/A | No requirement |
|
||||
|
||||
See [Import (UC2)](#import-uc2) for behavior rules.
|
||||
|
||||
### UC3 — Launch with a specific config (session list, not the catalog)
|
||||
|
||||
**Intent:** Run against **another** server set for **this session only** — ad-hoc (one server from command/URL) or file (all servers in TUI; one selected by `--server` for CLI). User sees those servers in list UI; Add/Edit/Remove must not mutate the file (`writable: false`).
|
||||
|
||||
| | Today | Target |
|
||||
|---|--------|--------|
|
||||
| **TUI** | Works for `--config <file>` and ad-hoc via `loadTuiServers` | Same + explicit `writable: false` for non-catalog paths |
|
||||
| **Web** | UI always shows default catalog; `runWeb --config` only sets legacy `initialMcpConfig` | Session `mcpConfigPath` → `/api/servers` serves that file; `writable: false`; disable CRUD |
|
||||
| **CLI** | Single resolved server (file + `--server`, ad-hoc, or default catalog) | Same; shared normalizer + settings lift |
|
||||
|
||||
```bash
|
||||
mcp-inspector --tui --config ~/Library/Application\ Support/Claude/claude_desktop_config.json
|
||||
mcp-inspector --cli --config ./project/mcp.json --server local --method tools/list
|
||||
mcp-inspector --cli node ./server.js --method tools/list
|
||||
```
|
||||
|
||||
Launching with `--config` does **not** import unless the user separately runs UC2.
|
||||
|
||||
### UC4 — Choose which catalog (grouping), not only the default
|
||||
|
||||
**Intent:** Catalogs **group** MCP configs for reuse. Most users only use the default (UC1). Power users switch catalogs — per-project files, work vs personal, repo-local `.mcp-inspector/mcp.json`.
|
||||
|
||||
**`--catalog <path>`** selects the **active catalog** for this run. Omitting it → default (UC1).
|
||||
|
||||
```bash
|
||||
mcp-inspector --web
|
||||
mcp-inspector --web --catalog ./.mcp-inspector/mcp.json
|
||||
mcp-inspector --tui --catalog ~/work/mcp.json
|
||||
mcp-inspector --cli --catalog ~/work/mcp.json --server api --method tools/list
|
||||
```
|
||||
|
||||
**Distinction from UC3:** UC3 uses **`--config`** (or ad-hoc) for a foreign/session file — show servers, **do not write**. UC4 uses **`--catalog`** — this file **is** the Inspector catalog for this run.
|
||||
|
||||
| | Today | Target |
|
||||
|---|--------|--------|
|
||||
| **Web** | Only default catalog — backend always `getDefaultMcpConfigPath()` | `runWeb --catalog <path>` → `mcpConfigPath`; CRUD on active catalog |
|
||||
| **TUI** | `--config` loads a file; no catalog vs session distinction | `--catalog` = writable active catalog; `--config` without `--catalog` → UC3 |
|
||||
| **CLI** | `--config` for one-shot reads; default path when only `--server` | `--catalog` scopes UC1/UC2/UC5; `--config` remains session-only |
|
||||
|
||||
**Env alternative:** `MCP_CATALOG_PATH` — same semantics as `--catalog` for scripts/CI.
|
||||
|
||||
### UC5 — Default selection within any list
|
||||
|
||||
**Intent:** Among loaded servers (catalog or session), focus one entry — required for CLI (one server), useful for web/TUI.
|
||||
|
||||
| | Today | Target |
|
||||
|---|--------|--------|
|
||||
| **CLI** | `--server` with catalog (UC1) or `--config` file (UC3) | Same |
|
||||
| **TUI** | All servers shown; no `--server` flag | Optional highlight / initial selection |
|
||||
| **Web** | Ignores `--server` for list/selection | `defaultServerId` from launch + optional auto-connect ([#1183](https://github.com/modelcontextprotocol/inspector/issues/1183)) |
|
||||
|
||||
### Use-case map (quick reference)
|
||||
|
||||
| UC | User goal | How selected | Writable? | Primary clients | Import? |
|
||||
|----|-----------|--------------|-----------|-----------------|---------|
|
||||
| **1** | Manage default catalog | (no `--catalog`) | Yes | Web (now), TUI (CRUD planned), CLI | No |
|
||||
| **2** | Add servers to a catalog | `--method servers/import` | Writes **active catalog** only | CLI; web UI | Yes |
|
||||
| **3** | Session with external config | `--config` or ad-hoc | **No** | TUI (now), Web (gap), CLI | No |
|
||||
| **4** | Switch / use another catalog | `--catalog <path>` | Yes (that path) | Web/TUI (gaps) | Via UC2 |
|
||||
| **5** | Pick one server by name | `--server` | — | CLI (required), Web/TUI (hint) | — |
|
||||
|
||||
**Design principle:** UC1 is UC4 with the default path. Catalog modes (UC1/UC4): `writable: true`. Session mode (UC3): `writable: false`. UC2 mutates the active catalog only — not a launch side-effect on all clients.
|
||||
|
||||
---
|
||||
|
||||
## Flag reference
|
||||
|
||||
Shared launch flags (full detail in v1.5 `docs/mcp-server-configuration.md`, port pending):
|
||||
|
||||
| Flag | UC1/UC4 (catalog) | UC3 (session) | UC2 (import) |
|
||||
|------|-------------------|---------------|--------------|
|
||||
| `--catalog <path>` | Active writable catalog | — | Target catalog for write |
|
||||
| `--config <path>` | — | Read-only session file | **Source** file (A only) |
|
||||
| `--server <name>` | Catalog entry id (UC5) | Entry in session file | Source name (A) or new catalog id (B) |
|
||||
| `[target...]`, `-e`, `--cwd`, `--transport`, `--server-url`, `--header` | Ad-hoc overrides on connect | Ad-hoc session server | Same argv as launch (B) |
|
||||
|
||||
**`--server` overload (by context — no new flags):**
|
||||
|
||||
| Context | `--server` means |
|
||||
|---------|------------------|
|
||||
| `servers/import` + `--config` | Entry to copy **from source file** |
|
||||
| `servers/import` + ad-hoc (no `--config`) | Catalog **id** for new entry |
|
||||
| `tools/list` (etc.) + no `--config` | Lookup **from active catalog** |
|
||||
| `tools/list` + `--config` | Lookup **from session file** |
|
||||
|
||||
Optional import flags (target): `--on-conflict skip|error|replace`.
|
||||
|
||||
---
|
||||
|
||||
## Background (v1.5)
|
||||
|
||||
v1.5 (`docs/mcp-server-configuration.md`) had no default catalog: omitting `--config` and positional args failed resolution. Config-file `headers` lived on `MCPServerConfig`. Web had no file-backed list — launcher argv became `initialMcpConfig` for form pre-fill only. v2 adds the persistent catalog ([Server List File](v2_servers_file.md)), flat on-disk settings (post-#1358), and `withDefaultConfigPath()` for CLI/TUI/web runners.
|
||||
|
||||
---
|
||||
|
||||
## Normalization
|
||||
|
||||
External config files (Claude Desktop, Cursor, hand-edited JSON) are not reliably conformant. **Read path:** always parse → normalize → lift; never connect from raw file bytes.
|
||||
|
||||
| Stage | Where | What |
|
||||
|-------|-------|------|
|
||||
| Parse | `loadMcpServersConfig` / backend JSON parse | Structural check; tolerate unknown keys |
|
||||
| Normalize transport | `normalizeServerType` (`core/mcp/serverList.ts`) | Missing type → `stdio`; `http` → `streamable-http` |
|
||||
| Normalize catalog entries | `normalizeMcpServers` (`core/mcp/remote/node/server.ts`) | Legacy `settings` hard-cutover; secret migration |
|
||||
| Lift to runtime | `mcpConfigToServerEntries` | Map key → `id`; flat disk fields → `InspectorServerSettings` |
|
||||
|
||||
**Write path (catalog only):** `serverEntriesToMcpConfig` / `buildStoredEntry` / `writeStoreFile` per [Server List File](v2_servers_file.md).
|
||||
|
||||
**UC3 session files:** normalize on read; no silent writes. Persistence into a catalog requires UC2, web CRUD, or manual edit outside Inspector.
|
||||
|
||||
**Ad-hoc inline config:** ephemeral; never written by the runner.
|
||||
|
||||
---
|
||||
|
||||
## Cross-client list contract
|
||||
|
||||
Web and TUI are **list clients**: display servers, pick/connect, edit only when `writable`. They need not distinguish catalog path from session path in the UI — only the resolved list and flags.
|
||||
|
||||
Required inputs:
|
||||
|
||||
1. **Canonical list** — `ServerEntry[]` after normalize + `mcpConfigToServerEntries`.
|
||||
2. **`writable`** — if false, hide/disable Add, Edit, Remove, settings-save-to-disk.
|
||||
3. **`defaultServerId`** — from `--server` (UC5).
|
||||
4. Optional **`autoConnect`** — [#1183](https://github.com/modelcontextprotocol/inspector/issues/1183).
|
||||
|
||||
Centralization belongs in **core**, not the launcher. Today:
|
||||
|
||||
| Piece | Today | Target |
|
||||
|-------|--------|--------|
|
||||
| **Canonical conversion** | `mcpConfigToServerEntries` | Same |
|
||||
| **TUI** | `loadTuiServers` — full settings; no `writable` | `resolveServerList`; gate UI on `writable` |
|
||||
| **Web** | `useServers` → always default catalog; CRUD always on | `/api/servers` returns session or catalog list + `writable` |
|
||||
| **CLI** | Single server via `resolveServerConfigs` | `resolveSingleServer` from same normalizer |
|
||||
| **Launcher** | Forwards argv | Unchanged |
|
||||
|
||||
Import is not a list-client concern — catalog mutation via UC2 or web CRUD when `writable`.
|
||||
|
||||
---
|
||||
|
||||
## Launch behavior by client
|
||||
|
||||
### Web
|
||||
|
||||
| Launch | Catalog (`/api/servers`) | `initialMcpConfig` → `/api/config` | Connect |
|
||||
|--------|--------------------------|--------------------------------------|---------|
|
||||
| No server args | Default catalog via `useServers` | Empty | User selects catalog server |
|
||||
| Ad-hoc server flags | **Still full default catalog** | Populated (transport fields) | **Launch config not consumed** — no auto-connect, no form pre-fill (G2) |
|
||||
| `--config` + `--server` | **Still default catalog** | Populated from resolved config (settings stripped) | User sees catalog, not launch file |
|
||||
|
||||
**Target:** `/api/servers` serves the **resolved** list for the session (catalog or UC3 file) with `writable` and `defaultServerId`. See [Web launch behavior](#web-launch-behavior).
|
||||
|
||||
### CLI and TUI
|
||||
|
||||
CLI connects to exactly one resolved config per invocation; TUI shows all entries from the resolved list. Resolution paths, settings lift, and port gaps are documented in [v2_cli_tui_launcher.md](v2_cli_tui_launcher.md). Key catalog-specific gaps: **G1** (CLI drops disk settings on catalog/file lookup), **G4** (web `runWeb --header` warns only).
|
||||
|
||||
### Shared resolver (`resolveServerConfigs`)
|
||||
|
||||
```
|
||||
withDefaultConfigPath(options)
|
||||
→ if no --config and no ad-hoc target: configPath = ~/.mcp-inspector/mcp.json
|
||||
|
||||
single mode (CLI):
|
||||
configPath + serverName → loadServerFromConfig (MCPServerConfig only — G1)
|
||||
configPath, no serverName → sole entry or error if multiple
|
||||
ad-hoc → buildConfigFromOptions
|
||||
|
||||
multi mode (TUI):
|
||||
configPath → all entries via mcpConfigToServerEntries (settings lifted)
|
||||
ad-hoc → one config
|
||||
```
|
||||
|
||||
`loadServerFromConfig` returns bare `MCPServerConfig`. Only `mcpConfigToServerEntries()` lifts flat disk fields into `InspectorServerSettings`.
|
||||
|
||||
---
|
||||
|
||||
## Import (UC2)
|
||||
|
||||
**`servers/import`** on CLI only (plus web Import menu for interactive use). Targets the **active catalog** (default or `--catalog`). No launcher `--import` flag — `mcp-inspector --cli … --method servers/import` is sufficient.
|
||||
|
||||
| Approach | Rationale |
|
||||
|----------|-----------|
|
||||
| **CLI method** | Explicit, scriptable, reuses `--config` / ad-hoc argv parsing; same normalization as `POST /api/servers` |
|
||||
| **Not launcher flag** | Launcher routes only; catalog mutation blurs responsibilities |
|
||||
| **Not all clients at startup** | TUI/web import is UI concern (paste/upload) |
|
||||
|
||||
**Behavior:**
|
||||
|
||||
1. **UC2-A:** read `--config` source → canonicalize → one or all entries (`--server` optional).
|
||||
2. **UC2-B:** build one entry from ad-hoc argv (same resolver as UC3 launch) → `--server <id>` names catalog entry → canonicalize.
|
||||
3. Write to **active catalog** via `importServersIntoCatalog` — never to the UC3 source file.
|
||||
4. Collision policy per entry: skip, replace, or error (default TBD).
|
||||
5. Exit 0 with summary JSON (imported ids, skipped duplicates).
|
||||
|
||||
Web **Import config** vs **Import server.json** menu semantics: [v2_ux.md](v2_ux.md) and [Server List File](v2_servers_file.md). Registry conversion: [#922](https://github.com/modelcontextprotocol/inspector/issues/922), [#1435](https://github.com/modelcontextprotocol/inspector/issues/1435).
|
||||
|
||||
---
|
||||
|
||||
## Write-back policy
|
||||
|
||||
No silent write-back to **any** file on launch. Catalog mutations go through `/api/servers`, `servers/import`, or explicit user CRUD.
|
||||
|
||||
| Action | Writes catalog? | Writes session `--config` file? |
|
||||
|--------|-----------------|--------------------------------|
|
||||
| Launch ad-hoc command/URL | No | No |
|
||||
| Launch `--server` + overrides (`-e`, `--cwd`, `--header`) | No | No |
|
||||
| Launch `--config /other.json` | No | **No** (read-only) |
|
||||
| User Add/Edit/Settings (web UI) | Yes (canonical serialize) | No |
|
||||
| Import config / server.json (web UI, future) | Yes | No |
|
||||
| `--cli --method servers/import` | Yes (active catalog) | No |
|
||||
| Future explicit `--save-as <id>` | Opt-in only | No |
|
||||
|
||||
**Runtime overlay model (CLI/TUI):**
|
||||
|
||||
```
|
||||
catalog entry (config + settings)
|
||||
+ override flags for this process only
|
||||
→ effective connect payload
|
||||
→ never persisted unless explicit CRUD or import
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Web launch behavior
|
||||
|
||||
**Target model: catalog-first (B1).** The catalog always exists in the UI. Launch args influence selection and connect ergonomics; they do not replace the catalog or auto-persist ad-hoc servers.
|
||||
|
||||
| Behavior | Rule |
|
||||
|----------|------|
|
||||
| Catalog UI | Always show full resolved catalog (or UC3 session list when wired) |
|
||||
| `--server <id>` | Set `activeServerId` / `defaultServerId` to matching catalog entry |
|
||||
| Ad-hoc inline config | Temporary “session server” or “Quick connect” — **do not** auto-`POST /api/servers` |
|
||||
| Auto-connect | Optional `--connect` or `?autoConnect=true` ([#1183](https://github.com/modelcontextprotocol/inspector/issues/1183)) |
|
||||
|
||||
**Rejected alternatives:** launch-only UI hiding catalog (B2); v1.5 form pre-fill without catalog (B3).
|
||||
|
||||
**Implementation sketch:**
|
||||
|
||||
1. Extend `GET /api/config` with `initialServerId` and/or settings reference.
|
||||
2. `App.tsx` on load: if `initialServerId` matches an entry, set selection; optional auto-connect behind flag.
|
||||
3. Ad-hoc without catalog id: non-persisted session card or “Save to catalog?” prompt.
|
||||
|
||||
---
|
||||
|
||||
## Target API (core)
|
||||
|
||||
Evolve `loadTuiServers` / `resolveServerConfigs` in core (not launcher):
|
||||
|
||||
```ts
|
||||
interface ResolvedServerList {
|
||||
servers: ServerEntry[];
|
||||
writable: boolean;
|
||||
source: "catalog" | "alternate-file" | "adhoc";
|
||||
configPath?: string;
|
||||
defaultServerId?: string;
|
||||
}
|
||||
|
||||
resolveServerList(options: ServerConfigOptions): ResolvedServerList;
|
||||
resolveSingleServer(options: ServerConfigOptions): { entry: ServerEntry; ... }; // CLI
|
||||
|
||||
importServersIntoCatalog(
|
||||
entries: ServerEntry[],
|
||||
opts?: { onConflict: "skip" | "error" | "replace" },
|
||||
): ImportResult;
|
||||
```
|
||||
|
||||
**Rules:**
|
||||
|
||||
1. Ad-hoc (no `--config`, no `--catalog`) → one entry, `writable: false` (UC3).
|
||||
2. `--catalog` or default → active catalog, `writable: true` (UC1/UC4).
|
||||
3. `--config` without catalog intent → canonicalize → `ServerEntry[]`, `writable: false` (UC3).
|
||||
4. `defaultServerId` from `--server`.
|
||||
5. Runtime overlays on connect, not on disk.
|
||||
6. Web `/api/servers` and TUI use `resolveServerList`; CLI uses `resolveSingleServer`.
|
||||
|
||||
---
|
||||
|
||||
## Open decisions
|
||||
|
||||
| Topic | Status | Notes |
|
||||
|-------|--------|-------|
|
||||
| Import collision default | TBD | `skip` vs `error` vs `replace` for duplicate catalog ids |
|
||||
| `MCP_CATALOG_PATH` env name | Proposed | Alias for `--catalog` |
|
||||
| Ad-hoc web UX detail | Partially decided | B1 catalog-first; exact “Quick connect” vs banner TBD |
|
||||
| TUI `--server` initial selection | Open | Optional highlight when UC5 used from launcher |
|
||||
|
||||
Resolved (documented above): catalog vs session flag split; no launch write-back; CLI-only `servers/import`; core-owned `resolveServerList`; web catalog-first (B1).
|
||||
|
||||
---
|
||||
|
||||
## Known gaps
|
||||
|
||||
| # | Gap | Severity | Clients |
|
||||
|---|-----|----------|---------|
|
||||
| G1 | CLI catalog/file lookup drops settings — `loadServerFromConfig` not `mcpConfigToServerEntries` | Functional | CLI |
|
||||
| G2 | Web ignores launch-time `initialMcpConfig` for list/selection/connect | Functional / UX | Web |
|
||||
| G3 | `InitialConfigPayload` has no settings — cannot pass headers/oauth at web launch | Functional | Web + launcher |
|
||||
| G4 | `runWeb --header` warns only | Functional | Web launcher |
|
||||
| G5 | Two config pipelines — `config.ts` vs `serverList.ts` | Design debt | CLI vs TUI vs web |
|
||||
| G6 | v1.5 `docs/mcp-server-configuration.md` not ported to v2 | Docs | All |
|
||||
| G7 | CLI test expects `--server` without `--config` to fail — predates default catalog | Tests | CLI |
|
||||
| G8 | No auto-connect ([#1183](https://github.com/modelcontextprotocol/inspector/issues/1183)) | Enhancement | Web |
|
||||
| G9 | Import config / Import server.json menu stubbed | UX | Web |
|
||||
| G10 | CLI thin parse path — no full `normalizeMcpServers` / settings lift on catalog GET parity | Consistency | CLI |
|
||||
|
||||
G1, G4, and launcher details: [v2_cli_tui_launcher.md](v2_cli_tui_launcher.md).
|
||||
|
||||
---
|
||||
|
||||
## Decision matrix
|
||||
|
||||
| User launches with… | File read | Canonicalize on read? | Catalog UI (web) | Writable? |
|
||||
|---------------------|-----------|----------------------|------------------|-----------|
|
||||
| Nothing (defaults) | Default catalog | Yes | Full list | Catalog only |
|
||||
| `--server foo` | Default catalog | Yes | Full list; should select `foo` | Catalog only |
|
||||
| `--config other.json` | Alternate file (UC3) | Yes | Session list (target); today default catalog | **No** |
|
||||
| `--catalog ./proj/mcp.json` | Project catalog | Yes | That catalog (target) | That path |
|
||||
| Ad-hoc `node srv.js` | None | N/A | Full catalog + session hint (target) | Catalog only if user saves |
|
||||
| Web Add / Edit / Import | N/A | Yes before write | Full list | Catalog only |
|
||||
| `servers/import` | Source (A) or ad-hoc (B) | Yes before write | N/A (CLI) | Active catalog |
|
||||
|
||||
---
|
||||
|
||||
## Engineering follow-ups
|
||||
|
||||
1. **Core:** `resolveServerList`, `resolveSingleServer`, `importServersIntoCatalog`.
|
||||
2. **CLI:** resolve through shared normalizer; implement `--method servers/import` (G1, G10).
|
||||
3. **Web:** `/api/servers` serves resolved session or catalog list + `writable` + `defaultServerId` (G2).
|
||||
4. **TUI:** `resolveServerList`; respect `writable` (no CRUD on UC3 files).
|
||||
5. **Launcher / web:** extend `InitialConfigPayload` for settings at launch (G3, G4).
|
||||
6. **Tests:** CLI default-catalog success with tmp catalog; import method tests (G7).
|
||||
7. **Docs:** port `docs/mcp-server-configuration.md` to v2 (G6); close/update [#1347](https://github.com/modelcontextprotocol/inspector/issues/1347).
|
||||
|
||||
---
|
||||
|
||||
## Related GitHub issues
|
||||
|
||||
| Issue | Status | Relevance |
|
||||
|-------|--------|-----------|
|
||||
| [#1347](https://github.com/modelcontextprotocol/inspector/issues/1347) — default `--config` | Open (likely closable) | Implemented via `withDefaultConfigPath()` |
|
||||
| [#1246](https://github.com/modelcontextprotocol/inspector/issues/1246) — port CLI/TUI/launcher | Done in worktree | Parent of default-catalog behavior |
|
||||
| [#1183](https://github.com/modelcontextprotocol/inspector/issues/1183) — auto-connect | Open | UC5 web ergonomics |
|
||||
| [#1348](https://github.com/modelcontextprotocol/inspector/issues/1348) — import from other clients | Open | UC2 web UI |
|
||||
| [#1435](https://github.com/modelcontextprotocol/inspector/issues/1435) — registry import | Open | UC2 registry path |
|
||||
| [#1432](https://github.com/modelcontextprotocol/inspector/issues/1432) — CLI v2 | Open | Session CLI umbrella |
|
||||
| [#1352](https://github.com/modelcontextprotocol/inspector/pull/1352) / [#1358](https://github.com/modelcontextprotocol/inspector/pull/1358) | Merged | Flat settings on disk |
|
||||
| [#1356](https://github.com/modelcontextprotocol/inspector/pull/1356) | Merged | Secrets in keychain |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [v2_servers_file.md](v2_servers_file.md) — catalog format, CRUD, settings on disk
|
||||
- [v2_cli_tui_launcher.md](v2_cli_tui_launcher.md) — CLI/TUI/launcher architecture and port gaps
|
||||
- [v2_ux.md](v2_ux.md) — Import config vs Import server.json UX
|
||||
- `core/mcp/node/config.ts` — `withDefaultConfigPath`, `resolveServerConfigs`
|
||||
- `core/mcp/serverList.ts` — `mcpConfigToServerEntries`
|
||||
- `clients/tui/src/tui-servers.ts` — TUI catalog + settings load path
|
||||
- `clients/cli/src/cli.ts` — single-config resolve; settings gap (G1)
|
||||
- `clients/web/server/run-web.ts` — launcher argv → `initialMcpConfig`
|
||||
- `clients/web/src/App.tsx` — catalog via `useServers`
|
||||
- `clients/web/src/components/groups/ImportServerJsonPanel/` — registry panel (unwired)
|
||||
- `clients/web/src/components/groups/ServerAddMenu/ServerAddMenu.tsx` — Add menu labels
|
||||
234
specification/v2_cli_tui_launcher.md
Normal file
234
specification/v2_cli_tui_launcher.md
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
# Inspector V2 Tech Stack - CLI, TUI, and Launcher
|
||||
|
||||
### [Brief](README.md) | [V1 Problems](v1_problems.md) | [V2 Scope](v2_scope.md) | V2 Tech Stack | [V2 UX](v2_ux.md)
|
||||
|
||||
#### [Web Client](v2_web_client.md) | CLI, TUI, Launcher | [Server](v2_server.md) | [Storage](v2_storage.md)
|
||||
|
||||
## Summary
|
||||
|
||||
v2 ships three non-web Inspector incarnations alongside the web client: a **one-shot CLI**, an **interactive TUI**, and a **launcher** that routes to web, CLI, or TUI from a single `mcp-inspector` binary. All three consume the same `core/` source as the web client via the `@inspector/core` path alias and run on the shared `InspectorClient` stack ported from v1.5/main.
|
||||
|
||||
This document describes how those clients are built, wired, and tested today, and records known gaps. For catalog vs launch-time config semantics (`--config`, `--catalog`, import), see [Catalog and Launch Configuration](v2_catalog_launch_config.md).
|
||||
|
||||
## Goals
|
||||
|
||||
- One published entry binary (`mcp-inspector`) that forwards argv to the selected client.
|
||||
- CLI and TUI use the same `InspectorClient`, managed-state classes, and `resolveServerConfigs()` path as v1.5 — adapted to v2's `InspectorServerSettings` model (post-#1358).
|
||||
- Bundle `core/` into CLI/TUI Node artifacts with **tsup** (analogous to Vite bundling core for the browser).
|
||||
- Port v1.5 CLI integration tests (86 cases) and TUI smoke tests without duplicating `core/` unit tests (web suite remains canonical for core).
|
||||
- CI runs CLI and TUI tests plus a launcher `--help` smoke step on every PR.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- **CLI v2 sessions** (connect once, many subcommands) — tracked separately in [#1432](https://github.com/modelcontextprotocol/inspector/issues/1432).
|
||||
- **npm workspaces** — v2 uses a fat root package plus per-client `package.json` for dev dependencies; launcher resolves sibling `build/` outputs via relative paths, not workspace hoisting.
|
||||
- **Per-client coverage gates** — `core/` coverage stays on the web suite; CLI/TUI source gates are follow-up work (see [Known gaps](#known-gaps)).
|
||||
- **Catalog CRUD in TUI** — TUI loads and connects; persistent catalog editing remains web-first today.
|
||||
|
||||
---
|
||||
|
||||
## Packaging and entrypoints
|
||||
|
||||
| Artifact | Path | Build | Published bin |
|
||||
|----------|------|-------|---------------|
|
||||
| Launcher | `clients/launcher/` | `tsc` → `build/index.js` | Root `mcp-inspector` → `clients/launcher/build/index.js` |
|
||||
| CLI | `clients/cli/` | `tsup` → `build/index.js` | `mcp-inspector-cli` (client package only) |
|
||||
| TUI | `clients/tui/` | `tsup` → `build/index.js` | `mcp-inspector-tui` (client package only) |
|
||||
| Web runner | `clients/web/server/run-web.ts` | `tsup` (`build:runner`) → `clients/web/build/index.js` | `mcp-inspector-web` (client package only) |
|
||||
|
||||
Root `package.json` (`@modelcontextprotocol/inspector` v2) publishes a **fat package**: merged runtime `dependencies`, `files` manifest listing each client's `build/` (and web `dist/`), and `prepack` → full `npm run build`. The launcher does not declare `file:` sibling dependencies; it dynamically imports `../web/build/index.js`, `../cli/build/index.js`, or `../tui/build/index.js` relative to its own `build/` directory.
|
||||
|
||||
**Typical invocations:**
|
||||
|
||||
```bash
|
||||
mcp-inspector # web (prod Hono server)
|
||||
mcp-inspector --web --dev # web (Vite dev server)
|
||||
mcp-inspector --cli --config mcp.json --server my-api --method tools/list
|
||||
mcp-inspector --tui --config mcp.json
|
||||
```
|
||||
|
||||
Root scripts `inspector`, `web`, and `web:dev` are thin wrappers around the launcher binary.
|
||||
|
||||
---
|
||||
|
||||
## Launcher
|
||||
|
||||
`clients/launcher/src/index.ts` parses only mode flags (`--web`, `--cli`, `--tui`; default **web**), strips the mode flag from `process.argv`, and dynamically imports the selected client's `runWeb`, `runCli`, or `runTui`.
|
||||
|
||||
- **No core imports** — plain TypeScript compile is sufficient.
|
||||
- **Argv forwarding** — all other flags pass through unchanged so each client's Commander parser owns server and method options.
|
||||
- **Help** — `mcp-inspector --help` shows launcher help; `mcp-inspector --cli --help` forwards to CLI help.
|
||||
|
||||
**Production web caveat:** launcher `prebuild` chains `build:runner` for web, not a full `vite build`. Running `mcp-inspector --web` (without `--dev`) requires `clients/web/dist/` from a prior `cd clients/web && npm run build`. CI builds TUI and launcher but does not currently validate prod web startup end-to-end.
|
||||
|
||||
---
|
||||
|
||||
## Shared core consumption
|
||||
|
||||
All three clients import from `@inspector/core/...` (mapped to `../../core/` source).
|
||||
|
||||
| Concern | Web | CLI / TUI | Launcher |
|
||||
|---------|-----|-----------|----------|
|
||||
| Dev typecheck | `tsconfig.app.json` paths | per-client `tsconfig.json` paths | `tsconfig.json` (no core) |
|
||||
| Runtime bundle | Vite alias | tsup `noExternal: [/^@inspector\/core/]` + esbuild alias | n/a |
|
||||
| Tests | Vitest projects in `clients/web/` | Vitest + `vitest.shared.mts` aliases | none |
|
||||
|
||||
`vitest.shared.mts` at repo root centralizes `@inspector/core` and test-server aliases plus bare-module pins (`react`, `pino`, SDK, etc.) so CLI/TUI Vitest configs stay aligned with web.
|
||||
|
||||
**Resolved design choices:**
|
||||
|
||||
| Topic | Decision |
|
||||
|-------|----------|
|
||||
| Core package | No separate `inspector-core` npm package; source-only `core/` |
|
||||
| CLI/TUI build | tsup bundles `@inspector/core` into `build/index.js` |
|
||||
| Core tests | Not duplicated under cli/tui; web unit + integration suites cover `core/` |
|
||||
| Default config path | `resolveServerConfigs()` calls `withDefaultConfigPath()` → `~/.mcp-inspector/mcp.json` when no `--config` and no ad-hoc target |
|
||||
|
||||
---
|
||||
|
||||
## CLI
|
||||
|
||||
**Model:** one-shot — each invocation connects, runs a single `--method`, prints JSON to stdout, disconnects, exits. Same surface as v1.5; session-oriented CLI v2 is future work ([#1432](https://github.com/modelcontextprotocol/inspector/issues/1432)).
|
||||
|
||||
**Entry:** `clients/cli/src/index.ts` exports `runCli(argv)`; `src/cli.ts` owns Commander parsing and `InspectorClient` orchestration.
|
||||
|
||||
**Server resolution:**
|
||||
|
||||
1. Positional `[target...]` (command/URL) and/or `--config` + `--server`, plus `-e`, `--cwd`, `--transport`, `--server-url`.
|
||||
2. `resolveServerConfigs(serverOptions, "single")` in `core/mcp/node/config.ts` — applies default catalog path when appropriate.
|
||||
3. Ad-hoc `--header` pairs map to `InspectorServerSettings` and pass into `InspectorClient` via `serverSettings` (not `MCPServerConfig.headers`).
|
||||
|
||||
**Gap — config-file settings:** when loading from a config file, CLI uses `loadServerFromConfig()` / bare `MCPServerConfig` only. Persisted `headers`, timeouts, and OAuth fields on disk (post-#1358 flat entry shape) are **not** lifted into `serverSettings`. TUI uses `mcpConfigToServerEntries()` and does lift them. Ad-hoc `--header` on CLI works; file-backed settings do not.
|
||||
|
||||
**Tests:** 86 cases in `clients/cli/__tests__/` spawn `node build/index.js` via `cli-runner.ts` (`pretest` builds test-servers + CLI). Core behavior is exercised; Vitest coverage on `src/cli.ts` is invisible to the coverage instrumenter because tests run out-of-process (see [Known gaps](#known-gaps)).
|
||||
|
||||
---
|
||||
|
||||
## TUI
|
||||
|
||||
**Model:** interactive terminal UI (Ink + React 19) mirroring web information architecture: Servers, Tools, Prompts, Resources, Logs, OAuth, etc.
|
||||
|
||||
**Entry:** `clients/tui/index.ts` exports `runTui(argv)`; `tui.tsx` parses argv and renders `App`.
|
||||
|
||||
**Server resolution:** `loadTuiServers()` in `clients/tui/src/tui-servers.ts`:
|
||||
|
||||
- **Config file path:** reads JSON, runs `mcpConfigToServerEntries()` — returns `{ config, settings }` per server (correct post-#1358 path; matches web `useServers`).
|
||||
- **Ad-hoc:** `resolveServerConfigs(..., "multi")` for a single inline server; merges launch-time `--header` into `settings`.
|
||||
- Applies `withDefaultConfigPath()` before resolution.
|
||||
|
||||
**Core hooks:** TUI uses the same managed-state and `useInspectorClient` patterns as web (`ManagedToolsState`, etc.) inside Ink components.
|
||||
|
||||
**Behavior note:** v2 core only auto-refreshes tool/resource lists when `autoRefreshOnListChanged` is true in server settings; v1.5 TUI always auto-refreshed. Port accepts v2 core behavior; UI indicator parity with web is open ([#1402](https://github.com/modelcontextprotocol/inspector/issues/1402)).
|
||||
|
||||
**Tests:** 2 cases in `clients/tui/__tests__/tui.test.ts` assert `tabsConfig` shape only. Config parsing, OAuth, and Ink component flows are untested.
|
||||
|
||||
**Dev:** `npm run dev` in `clients/tui` uses `vite-node` + `dev.ts` for fast iteration without a full tsup rebuild.
|
||||
|
||||
---
|
||||
|
||||
## Web runner (`runWeb`)
|
||||
|
||||
The launcher `--web` path does not start Vite via the `npm run dev` script. It calls `runWeb(argv)` from `clients/web/server/run-web.ts`, which:
|
||||
|
||||
1. Parses the same server-selection flags as CLI/TUI (`--config`, `--server`, positional target, `-e`, `--cwd`, `--transport`, `--server-url`, `--header`, `--dev`).
|
||||
2. Resolves one `MCPServerConfig` via `resolveServerConfigs()` when server input is present.
|
||||
3. Passes `initialMcpConfig` into `buildWebServerConfig()` → `GET /api/config` legacy channel.
|
||||
4. Starts `startViteDevServer()` (`--dev`) or `startHonoServer()` (prod).
|
||||
|
||||
**Gap — launch-time headers:** `--header` is accepted but logs a warning; headers are not applied to the web session. The v2 web UI configures HTTP headers via per-server settings in the catalog (`ServerSettingsForm`), not via `initialMcpConfig`. Extending `InitialConfigPayload` (or equivalent) is required for launcher-passed headers to reach the UI.
|
||||
|
||||
Day-to-day web development still uses `cd clients/web && npm run dev` (Vite CLI + env-based `buildWebServerConfigFromEnv`).
|
||||
|
||||
---
|
||||
|
||||
## Server configuration flags (shared)
|
||||
|
||||
CLI, TUI, and `runWeb` share launch-time server options documented in v1.5's `docs/mcp-server-configuration.md` (port to v2 pending). Common flags:
|
||||
|
||||
| Flag | Purpose |
|
||||
|------|---------|
|
||||
| `--config <path>` | MCP servers JSON file |
|
||||
| `--server <name>` | Named entry within config (required when file has multiple servers) |
|
||||
| `[target...]` | Ad-hoc stdio command/args or HTTP URL |
|
||||
| `-e KEY=VALUE` | Stdio environment overrides |
|
||||
| `--cwd <path>` | Stdio working directory |
|
||||
| `--transport` | `stdio`, `sse`, or `http` |
|
||||
| `--server-url <url>` | HTTP/SSE endpoint |
|
||||
| `--header "Name: Value"` | Launch-time HTTP headers (CLI/TUI ad-hoc → `serverSettings`; web → warning only) |
|
||||
|
||||
CLI additionally requires `--method` and method-specific args (`--tool-name`, `--uri`, etc.). Semantics for catalog vs session config, `--catalog`, and `servers/import` are in [v2_catalog_launch_config.md](v2_catalog_launch_config.md).
|
||||
|
||||
---
|
||||
|
||||
## Testing and CI
|
||||
|
||||
| Suite | Location | Count | How |
|
||||
|-------|----------|-------|-----|
|
||||
| CLI | `clients/cli/__tests__/` | 86 | Subprocess `node build/index.js` |
|
||||
| TUI | `clients/tui/__tests__/` | 2 | In-process imports |
|
||||
| Launcher | CI smoke only | 3 | `--help`, `--cli --help`, `--tui --help` |
|
||||
| Core | `clients/web/src/test/` | — | Canonical; not duplicated in cli/tui |
|
||||
|
||||
**Root orchestration:** `npm run test` chains web unit tests, then `clients/cli` and `clients/tui` tests. `npm run test:coverage` runs web coverage only.
|
||||
|
||||
**CI** (`.github/workflows/main.yml`): after web validate + coverage, installs and tests CLI and TUI, builds TUI + launcher, runs launcher help smoke.
|
||||
|
||||
**Prerequisites:** CLI `pretest` runs `test-servers:build` (`tsc -p test-servers`) so stdio integration tests can spawn `test-servers/build/test-server-stdio.js`.
|
||||
|
||||
---
|
||||
|
||||
## Developer setup
|
||||
|
||||
v2 does not use npm workspaces. Each client maintains its own `package.json` and `node_modules`:
|
||||
|
||||
```bash
|
||||
npm install # root (launcher runtime deps)
|
||||
cd clients/web && npm install # required for web dev/test
|
||||
cd clients/cli && npm install # required for CLI build/test
|
||||
cd clients/tui && npm install # required for TUI build/test
|
||||
cd clients/launcher && npm install
|
||||
```
|
||||
|
||||
**Build order for a full local smoke:**
|
||||
|
||||
```bash
|
||||
npm run build:web # includes build:runner for runWeb
|
||||
npm run build:cli
|
||||
npm run build:tui
|
||||
npm run build:launcher
|
||||
```
|
||||
|
||||
Root `npm run validate` currently runs web validate only; extending it to CLI/TUI build + test is follow-up work.
|
||||
|
||||
---
|
||||
|
||||
## Known gaps
|
||||
|
||||
| Area | Gap | Tracking |
|
||||
|------|-----|----------|
|
||||
| **CLI config-file settings** | Disk `headers` / timeouts / OAuth not lifted when `--config` is used | This spec; [catalog doc](v2_catalog_launch_config.md) G1 |
|
||||
| **Web launch headers** | `runWeb --header` warns but does not apply settings to UI | This spec; [#1246](https://github.com/modelcontextprotocol/inspector/issues/1246) |
|
||||
| **TUI list-changed UX** | No stale-list indicator when `autoRefreshOnListChanged` is false | [#1402](https://github.com/modelcontextprotocol/inspector/issues/1402) |
|
||||
| **TUI test coverage** | Only `tabsConfig` shape tested | Expand `tui-servers.ts`, Ink flows |
|
||||
| **CLI coverage gates** | Subprocess tests don't instrument `src/cli.ts` | In-process `runCli()` runner + thin binary E2E suite |
|
||||
| **Prod web via launcher** | Requires pre-built `clients/web/dist/` | Document or wire into launcher prebuild |
|
||||
| **Import / `--catalog`** | `servers/import`, `--catalog` not implemented | [catalog doc](v2_catalog_launch_config.md); [#1348](https://github.com/modelcontextprotocol/inspector/issues/1348) |
|
||||
| **README refresh** | Client READMEs may lag v2 install/build commands | `clients/*/README.md`, `AGENTS.md` |
|
||||
| **Root validate** | Does not build/test CLI/TUI | Root `package.json` |
|
||||
| **Root postinstall** | Optional one-shot `npm install` in all clients | Declined workspaces; lighter alternative |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- `clients/launcher/src/index.ts` — mode routing and dynamic import
|
||||
- `clients/cli/src/cli.ts` — CLI parsing, `InspectorClient` one-shot flow
|
||||
- `clients/tui/src/tui-servers.ts` — config + settings load path (correct for v2)
|
||||
- `clients/web/server/run-web.ts` — launcher web entry
|
||||
- `core/mcp/node/config.ts` — `resolveServerConfigs`, `withDefaultConfigPath`
|
||||
- `core/mcp/serverList.ts` — `mcpConfigToServerEntries`
|
||||
- `vitest.shared.mts` — shared Vitest aliases
|
||||
- [v2_catalog_launch_config.md](v2_catalog_launch_config.md) — catalog and launch config, import, UC1–UC5
|
||||
- [v2_servers_file.md](v2_servers_file.md) — catalog file format and web CRUD
|
||||
- [#1246](https://github.com/modelcontextprotocol/inspector/issues/1246) — port tracking issue
|
||||
- v1.5 sources: `v1.5/main/clients/{cli,tui,launcher}`
|
||||
Loading…
Reference in a new issue