Skip to content

Bundled CLI: split main() out of src/index.ts so the bootstrap needs no env flag; e2e project is not run by CI #732

Description

@debugmcpdev

Problem

#717 was fixed (#719) by narrowing the window in which DEBUG_MCP_SKIP_AUTO_START is set: the bundled CLI (packages/mcp-debugger/src/cli-entry.ts) sets the flag, dynamically imports src/index.js so the core's auto-start guard sees it, and restores the caller's value in finally before calling main(). That is correct today, but its correctness rests on a bundler detail — esbuild emits a lazy init_src() for the dynamic import — and nothing CI runs would catch the natural regression:

  • Converting the await import('../../../src/index.js') to a static import (the file already spells typeof import('../../../src/index.js') for the type) hoists src/index.ts above the bootstrap body; the guard sees the flag unset and auto-runs main(), then bootstrap() runs entrypoint.main() again — two Commander parses, two servers on one stdin. Verified with the repo's esbuild.
  • tests/integration/cli/bundled-bootstrap.test.ts runs --version, which process.exit()s inside the first main(), so its output and its env report are identical between the correct and the regressed ordering.
  • The one assertion of the real behaviour, tests/e2e/mcp-server-self-debug.test.ts, lives in the e2e project, which test:ci-coverage (--project unit --project integration) and every workflow except the container job skip.

The env var is an inheritance channel by design; narrowing when it is set does not close the channel (see the sibling leak in the exit-code shim ticket).

Proposed direction

Split main() out of src/index.ts into a side-effect-free module (e.g. src/main.ts) that cli-entry.ts imports directly. Then there is no flag, no window, and isMainModule's heuristics stop being load-bearing for the bundle. Until then, keep a CI-visible guard: an integration test that starts the bundled CLI in stdio mode, sends one initialize, and asserts exactly one response frame (a double main() answers twice).

Separately worth a decision: the pre-push hook prints "full e2e runs in CI", but .github/workflows/ci.yml runs only test:ci-coverage (unit + integration) and the Docker container e2e. Either run the non-Docker e2e project in a CI job or correct the hook's message and CLAUDE.md so nobody relies on it.

Raised in the review of #719.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions