Closes #1811 Four README links pointed at files that don't exist on `v2/main`, and the launcher README described catalog seeding as one behavior when it is two. - `docs/mcp-server-configuration.md` — written fresh for v2 (the v1.5 file predates the `--catalog`/`--config` split) - `docs/launcher-config-consolidation-plan.md` — restored from `v1.5/main`, path drift corrected, v2 notes appended - `docs/images/tui-screenshot.png` — regenerated against the current TUI - launcher README seeding wording — split into the two real behaviors (web seeds two sample servers; cli/tui seed empty) Review across three rounds also corrected several claims verified against source: the `--` separator is inverted between web and cli, a cli target placed after a flag is silently discarded, `--server` is a no-op on web and an unknown-option error on tui, the `MCP_CATALOG_PATH` ad-hoc guard is cli-only, and the conflict matrix diverges on both `--header` and `--transport stdio`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD
5.2 KiB
Launcher and config consolidation
This document explains the architecture of the mcp-inspector application entrypoints and configuration processing.
How things used to work (and the challenges)
Previously, the project suffered from split config logic and an unnecessary process boundary for the web server:
- Two processes for web and CLI: The main
mcp-inspectorentrypoint would parse arguments and thenspawn()a child process for the actual web server (either Vite for dev, ornode dist/server.jsfor prod). - Config via environment variables: To pass config (like server command, transport, auth token, etc.) from the launcher to the child process, the runner serialized everything into an unwieldy list of environment variables (
MCP_INITIAL_*,MCP_ENV_VARS, etc.). - Doesn't scale: Multi-server or complex config required more environment variables and ad-hoc encoding (e.g. JSON in env). This was fragile and easy to get out of sync.
- Config logic split: Config parsing was duplicated across the web runner, the CLI runner, and the TUI runner.
- Direct launch was inconsistent: Running
npm run devor calling a client's binary directly skipped parts of the launcher logic, leading to inconsistent behavior.
How things work now (Current Design)
The architecture is now consolidated into a single-process model with a shared configuration processor.
1. Dedicated Launcher
A dedicated package under clients/launcher/ (src/index.ts → build/index.js) serves as the global mcp-inspector binary.
- Responsibility: Its only job is to choose which app to run (
--web,--cli, or--tui) and to forwardprocess.argv. - No spawn: It dynamically imports the chosen app's runner and calls it in-process.
2. Shared Config Processor
All configuration parsing and merging rules live in core (core/mcp/node/config.ts).
- Input: Parsed argument options (file path, server name, env vars, transport, headers) and a mode (
singleormulti). - Output: A list of
MCPServerConfigobjects. - Benefits: Web, CLI, and TUI all share the exact same rules for loading config files, applying command-line overrides, and resolving environment variables.
3. App Runners
Each app (Web, CLI, TUI) exposes a runner function (runWeb(argv), runCli(argv), runTui(argv)).
- The runner uses Commander to parse the arguments.
- It calls the shared core config processor with the relevant server-config subset.
- It receives the config list and starts the application logic.
- Direct launch (e.g.
node clients/cli/build/index.js, or a client's ownnpm run dev) just imports the runner and passesprocess.argv. This guarantees identical behavior whether invoked via the launcher or directly. v2 ships a singlemcp-inspectorbin; there are no longer per-client binaries.
4. Web Server In-Process (Config as Object)
The web app no longer uses spawn() or environment variable handoffs. The runner process is the web server.
- WebServerConfig Object: The runner builds a typed
WebServerConfigobject (containing port, initial MCP config, auth, etc.) and passes it directly to the server. - Vite Dev:
startViteDevServer(config)uses Vite's Node API (createServerfromvite) in the same process. It passes the config directly to the Hono Vite plugin viahonoMiddlewarePlugin(config). - Hono Prod:
startHonoServer(config)starts the production server in the same process. - Benefits:
- Simpler & Scalable: No env var encoding/decoding. Multi-server config is easily passed as a standard JS object.
- Easier debugging: A single Node process means no spawn/kill plumbing and clear shutdown logic.
5. Summary of Execution Flow
| Component | Responsibility |
|---|---|
| Launcher | Detects --web/--cli/--tui and calls the app runner in-process. |
| Runner | Parses argv using Commander and calls the core config processor. |
| Core Config | Applies file/cli merging rules, returns MCPServerConfig object(s). |
| App Execution | Runner uses the config object to directly start Vite API (dev), Hono API (prod), CLI method, or TUI app. |
v2 notes
This document was written for v1.5 and describes an architecture that still
holds on v2/main; only the paths moved. Two things worth knowing when reading
it against the current tree:
- The clients live under
clients/*(clients/web,clients/cli,clients/tui,clients/launcher). v2 is not an npm workspace — each client keeps its ownpackage.jsonandnode_modules, and shared code incore/is consumed through the@inspector/corebuild-time alias rather than as a dependency. See the root README. - The shared config processor gained the
--catalog(writable) vs.--config(read-only) split, which the launcher's argument tables and MCP server configuration describe.