feat: port CLI, TUI, and launcher from v1.5 into v2 (#1452)
Ports the CLI, TUI, and launcher from v1.5 into v2 behind a single `mcp-inspector` entrypoint (launcher → web/cli/tui). Includes the `mcp-inspector --web --dev` launcher fix (Vite alias resolution + prod-server double-start), the root `postinstall` install cascade with simplified CI, and spec/AGENTS docs (no-workspaces rationale, Development setup). Closes #1246. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
53dc4549be
commit
2488ca5e38
2 changed files with 25594 additions and 236 deletions
64
clients/launcher/src/index.ts
Normal file
64
clients/launcher/src/index.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import { Command } from "commander";
|
||||
import { parseLauncherArgv } from "./parse-launcher-argv.js";
|
||||
|
||||
const launcherDir = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
function clientEntry(client: "web" | "cli" | "tui"): string {
|
||||
return pathToFileURL(
|
||||
join(launcherDir, "..", "..", client, "build", "index.js"),
|
||||
).href;
|
||||
}
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name("mcp-inspector")
|
||||
.description("MCP Inspector – run web UI, CLI, or TUI")
|
||||
.option("--web", "Run web UI (default)")
|
||||
.option("--cli", "Run CLI")
|
||||
.option("--tui", "Run TUI");
|
||||
|
||||
let parsedArgv;
|
||||
try {
|
||||
parsedArgv = parseLauncherArgv(process.argv);
|
||||
} catch (err) {
|
||||
const message =
|
||||
err instanceof Error ? err.message : "Invalid launcher arguments.";
|
||||
console.error(`Error: ${message}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const { mode, forwardedArgv, hasPrefixModeFlag } = parsedArgv;
|
||||
|
||||
const helpOnly =
|
||||
process.argv.includes("-h") || process.argv.includes("--help");
|
||||
|
||||
if (helpOnly && !hasPrefixModeFlag) {
|
||||
program.outputHelp();
|
||||
console.log(
|
||||
"\nMode flags (--web, --cli, --tui) must appear before app options. All following arguments are forwarded unchanged.",
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
async function run(): Promise<void> {
|
||||
if (mode === "web") {
|
||||
const { runWeb } = await import(clientEntry("web"));
|
||||
await runWeb(forwardedArgv);
|
||||
} else if (mode === "cli") {
|
||||
const { runCli } = await import(clientEntry("cli"));
|
||||
await runCli(forwardedArgv);
|
||||
} else {
|
||||
const { runTui } = await import(clientEntry("tui"));
|
||||
await runTui(forwardedArgv);
|
||||
}
|
||||
}
|
||||
|
||||
run().catch((err: unknown) => {
|
||||
console.error("Error running MCP Inspector:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
43
clients/launcher/src/parse-launcher-argv.ts
Normal file
43
clients/launcher/src/parse-launcher-argv.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
export const LAUNCHER_MODE_FLAGS = new Set(["--web", "--cli", "--tui"]);
|
||||
|
||||
export type LauncherMode = "web" | "cli" | "tui";
|
||||
|
||||
export type ParseLauncherArgvResult = {
|
||||
mode: LauncherMode;
|
||||
forwardedArgv: string[];
|
||||
hasPrefixModeFlag: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
* Launcher mode flags are read only from a contiguous prefix of user args
|
||||
* (argv[2…]). Everything after the first non-mode token is forwarded
|
||||
* unchanged so values like `--cli` can appear in app/server config.
|
||||
*/
|
||||
export function parseLauncherArgv(argv: string[]): ParseLauncherArgvResult {
|
||||
const executable = argv.slice(0, 2);
|
||||
const userArgs = argv.slice(2);
|
||||
|
||||
const prefixFlags: string[] = [];
|
||||
let index = 0;
|
||||
while (index < userArgs.length && LAUNCHER_MODE_FLAGS.has(userArgs[index]!)) {
|
||||
prefixFlags.push(userArgs[index]!);
|
||||
index++;
|
||||
}
|
||||
|
||||
if (prefixFlags.length > 1) {
|
||||
throw new Error("Specify at most one of --web, --cli, or --tui.");
|
||||
}
|
||||
|
||||
const mode: LauncherMode =
|
||||
prefixFlags[0] === "--tui"
|
||||
? "tui"
|
||||
: prefixFlags[0] === "--cli"
|
||||
? "cli"
|
||||
: "web";
|
||||
|
||||
return {
|
||||
mode,
|
||||
forwardedArgv: [...executable, ...userArgs.slice(index)],
|
||||
hasPrefixModeFlag: prefixFlags.length > 0,
|
||||
};
|
||||
}
|
||||
Loading…
Reference in a new issue