Context
packages/loopover-mcp/bin/loopover-mcp.ts has two top-level entry gates:
// packages/loopover-mcp/bin/loopover-mcp.ts:1645-1652
if (runAsCliEntrypoint && cliArgs[0] && cliArgs[0] !== "--stdio") {
try {
const exitCode = await runCli(cliArgs);
process.exit(typeof exitCode === "number" ? exitCode : 0);
} catch (error) {
process.exit(reportCliFailure(argsWantJson(cliArgs), describeCliError(error), 1));
}
}
// packages/loopover-mcp/bin/loopover-mcp.ts:3754-3756
// #7764: only bind the shared stdin/stdout transport when actually launched as the CLI/stdio process. ...
if (runAsCliEntrypoint) await server.connect(new StdioServerTransport());
The CLI-dispatch block only runs when cliArgs[0] is truthy (and isn't "--stdio"). Running the bare command with no arguments — the natural first thing a new user tries — leaves cliArgs[0] as undefined, so the whole block at line 1645 is skipped: no runCli call, no process.exit. Execution falls through unconditionally past every tool registration to line 3756, which binds StdioServerTransport() to the process's real stdin/stdout — the exact same effective behavior as loopover-mcp --stdio. In an interactive terminal (or any invocation without a JSON-RPC client on the other end of stdin) this makes the process sit idle waiting for MCP protocol input instead of printing the usage banner a bare invocation should show.
runCli (line 4103) already has an explicit --help/help branch (printHelp()), and test/unit/mcp-cli-help.test.ts (added under #6991) tests both run(["--help"]) and run(["help"]) produce the usage banner — but neither that file nor anywhere else in test/unit/ tests run([]) (zero args). There is no /* v8 ignore */ or design comment anywhere near line 1645 explaining the empty-args fallthrough as intentional — the only nearby comment (line 1643-1644) explains the runAsCliEntrypoint testability gate, not this specific branch.
The README's ## Commands section documents loopover-mcp --stdio explicitly alongside every other named command; it never documents or implies that a bare loopover-mcp with no arguments is also a valid way to start the stdio server.
Requirements
- Running
loopover-mcp with zero arguments must print the same usage banner as loopover-mcp --help (via printHelp()) and exit 0 — it must NOT bind the stdio MCP transport or wait for input.
- Only an explicit
loopover-mcp --stdio invocation should start the MCP stdio server. This is the only intended entry point for that mode; the fix must not change --stdio's own existing behavior.
- The fix must be at the entry-gate condition itself (
packages/loopover-mcp/bin/loopover-mcp.ts:1645), not a special-case check buried later — e.g. if (runAsCliEntrypoint && cliArgs[0] !== "--stdio"), letting runCli([]) run and reach its own existing command === undefined fallthrough (which must itself route to printHelp(), mirroring the existing command === "--help" || command === "help" branch at line 4105 — add a command === undefined case, or extend that same condition to include it).
Deliverables
Test Coverage Requirements
99%+ Codecov patch coverage, branch-counted, on the changed condition at both line 1645 and the new command === undefined branch in runCli.
⚠️ Test-writing note: test/unit/support/mcp-cli-harness.ts's synchronous run() helper spawns the real CLI as a subprocess with stdio: ["ignore", "pipe", "pipe"] and no execution timeout — calling run([]) directly against the CURRENT (buggy) behavior would risk hanging the test runner rather than failing fast, since the process would sit blocked on the stdio transport rather than exiting. Once the fix lands this stops being a concern (bare invocation exits promptly), but write the regression test to assert on the FIXED behavior (prompt exit + usage banner in stdout) rather than adding a bare run([]) call to a shared synchronous harness without a timeout guard — extend test/unit/mcp-cli-help.test.ts's existing pattern (run(["--help"])/run(["help"])) with run([]), matching those two cases' assertions, once the underlying process no longer blocks.
Expected Outcome
loopover-mcp with no arguments behaves like every other documented CLI's bare invocation: it shows usage help and exits, instead of silently starting an MCP stdio server that hangs waiting for JSON-RPC input a plain terminal invocation will never send.
Links & Resources
packages/loopover-mcp/bin/loopover-mcp.ts:1643-1652 (the CLI-dispatch gate to fix)
packages/loopover-mcp/bin/loopover-mcp.ts:3754-3756 (the stdio-transport bind this bug reaches unintentionally)
packages/loopover-mcp/bin/loopover-mcp.ts:4103-4145 (runCli, its existing --help/help branch to extend)
test/unit/mcp-cli-help.test.ts (existing --help/help coverage, the pattern to extend)
test/unit/support/mcp-cli-harness.ts (the run()/runAsync() test harness)
packages/loopover-mcp/README.md's ## Commands section (documents --stdio explicitly; never documents bare invocation)
Context
packages/loopover-mcp/bin/loopover-mcp.tshas two top-level entry gates:The CLI-dispatch block only runs when
cliArgs[0]is truthy (and isn't"--stdio"). Running the bare command with no arguments — the natural first thing a new user tries — leavescliArgs[0]asundefined, so the whole block at line 1645 is skipped: norunClicall, noprocess.exit. Execution falls through unconditionally past every tool registration to line 3756, which bindsStdioServerTransport()to the process's real stdin/stdout — the exact same effective behavior asloopover-mcp --stdio. In an interactive terminal (or any invocation without a JSON-RPC client on the other end of stdin) this makes the process sit idle waiting for MCP protocol input instead of printing the usage banner a bare invocation should show.runCli(line 4103) already has an explicit--help/helpbranch (printHelp()), andtest/unit/mcp-cli-help.test.ts(added under#6991) tests bothrun(["--help"])andrun(["help"])produce the usage banner — but neither that file nor anywhere else intest/unit/testsrun([])(zero args). There is no/* v8 ignore */or design comment anywhere near line 1645 explaining the empty-args fallthrough as intentional — the only nearby comment (line 1643-1644) explains therunAsCliEntrypointtestability gate, not this specific branch.The README's
## Commandssection documentsloopover-mcp --stdioexplicitly alongside every other named command; it never documents or implies that a bareloopover-mcpwith no arguments is also a valid way to start the stdio server.Requirements
loopover-mcpwith zero arguments must print the same usage banner asloopover-mcp --help(viaprintHelp()) and exit 0 — it must NOT bind the stdio MCP transport or wait for input.loopover-mcp --stdioinvocation should start the MCP stdio server. This is the only intended entry point for that mode; the fix must not change--stdio's own existing behavior.packages/loopover-mcp/bin/loopover-mcp.ts:1645), not a special-case check buried later — e.g.if (runAsCliEntrypoint && cliArgs[0] !== "--stdio"), lettingrunCli([])run and reach its own existingcommand === undefinedfallthrough (which must itself route toprintHelp(), mirroring the existingcommand === "--help" || command === "help"branch at line 4105 — add acommand === undefinedcase, or extend that same condition to include it).Deliverables
packages/loopover-mcp/bin/loopover-mcp.ts:1645: change the guard so a bare (zero-argument) invocation reachesrunCli([])instead of falling through to the stdio-transport bind.packages/loopover-mcp/bin/loopover-mcp.ts:4105(runCli): addcommand === undefinedto the existing--help/helpbranch (or an equivalent explicit check) sorunCli([])prints the usage banner viaprintHelp()and does not fall through to the "Unknown command" error path.--help/helpand exits 0 without hanging.Test Coverage Requirements
99%+ Codecov patch coverage, branch-counted, on the changed condition at both line 1645 and the new
command === undefinedbranch inrunCli.Expected Outcome
loopover-mcpwith no arguments behaves like every other documented CLI's bare invocation: it shows usage help and exits, instead of silently starting an MCP stdio server that hangs waiting for JSON-RPC input a plain terminal invocation will never send.Links & Resources
packages/loopover-mcp/bin/loopover-mcp.ts:1643-1652(the CLI-dispatch gate to fix)packages/loopover-mcp/bin/loopover-mcp.ts:3754-3756(the stdio-transport bind this bug reaches unintentionally)packages/loopover-mcp/bin/loopover-mcp.ts:4103-4145(runCli, its existing--help/helpbranch to extend)test/unit/mcp-cli-help.test.ts(existing--help/helpcoverage, the pattern to extend)test/unit/support/mcp-cli-harness.ts(therun()/runAsync()test harness)packages/loopover-mcp/README.md's## Commandssection (documents--stdioexplicitly; never documents bare invocation)