#2520·mcp-use

cli: boolean flags silently discard an inline value, so mcp-use dev --tunnel=false opens a public tunnel

Author: aishwary-dongreCreated Sep 11, 2026Updated Sep 13, 2026
LabelsbugTypeScriptserver

Summary

parseArgs in libraries/typescript/packages/cli/src/bin/args.ts splits --flag=value for every ---prefixed token (lines 98-107), but the boolean cases in the switch (lines 147-164) never read the inline value. They assign unconditionally:

typescript
      case "--tunnel":
        args.tunnel = true;
        break;
      case "--no-open":
        args.open = false;
        break;

So --tunnel=false is parsed as --tunnel. The false is discarded and the flag fires anyway.

The Problem

  1. mcp-use dev --tunnel=false and mcp-use start --tunnel=false open a public tunnel. A tunnel exposes a local dev server to the internet, so the result is the inverse of an explicit instruction, in the direction that widens exposure.
  2. There is no diagnostic. Unknown flags throw at line 167, so a user reasonably concludes that an accepted flag was understood.
  3. args.tunnel reaches a real tunnel: main.ts:285 passes it to runStart, start.ts:172 gates on options.tunnel === true, and dev.ts:1017 calls tunnelManager.start(port).
  4. The same defect affects --no-open, --no-inspector, --with-inspector, --source-maps, --inline, --help and --version.
  5. The docstring advertises --flag value and --flag=value as generally supported, without excluding boolean switches.

Reproduced on main at 2ef6367. Unit level:

parseArgs(["dev", "--tunnel=false"]).tunnel             // true
parseArgs(["dev", "--no-open=false"]).open              // false
parseArgs(["build", "--source-maps=false"]).sourceMaps  // true

End to end through main(), with only @mcp-use/tunnel stubbed at its module boundary so no real tunnel is created:

main(["start", "--path", cwd, "--port", "4567", "--tunnel=false"])
// resolves 0
// createTunnelManager called once
// tunnelManager.start called with 4567
// stdout: "mcp-use public MCP URL: https://public-test.local.mcp-use.run/mcp"

Existing coverage in tests/bin-start.test.ts:227-274 exercises these flags in bare form only; =value is tested on string and number flags only (--port=8080, --mcp-dir=src/mcp).

Proposed fix

Reject a value on a boolean switch rather than interpret it. The CLI has no truthiness parsing anywhere else, so honouring the value invites follow-up questions about --tunnel=0 and --tunnel=no. takeValue records that it consumed the inline value; any flag reaching the end of the loop with an unconsumed inline value is an error.

typescript
    let inlineConsumed = false;

    const takeValue = (): string => {
      if (inline !== undefined) {
        inlineConsumed = true;
        return inline;
      }
      // ...unchanged
    };

    switch (flag) { /* ...unchanged... */ }

    if (inline !== undefined && !inlineConsumed) {
      throw new Error(`${flag} does not take a value`);
    }

--tunnel=false then exits with --tunnel does not take a value. Bare booleans, --flag value, and --flag=value on value-taking flags are unaffected.

Happy to switch to honouring the value instead if you would prefer that direction.