Skip to content

fix(mcp): do not enable production mode at module import time#602

Merged
tobi merged 2 commits into
tobi:mainfrom
fxstein:fix/mcp-production-mode-test-leak
May 3, 2026
Merged

fix(mcp): do not enable production mode at module import time#602
tobi merged 2 commits into
tobi:mainfrom
fxstein:fix/mcp-production-mode-test-leak

Conversation

@fxstein

@fxstein fxstein commented Apr 23, 2026

Copy link
Copy Markdown
Contributor

Problem

Upstream CI on main has been failing on Bun (ubuntu-latest) since 2026-04-09 — 14+ consecutive runs — with a single test failure:

(fail) Store Creation > createStore throws without explicit path in test mode
Expected substring: "Database path not set"
Received function did not throw

Root Cause

#537 fixed a real bug — the MCP server was resolving the wrong database path at startup — by adding enableProductionMode() at module scope in src/mcp/server.ts:

import { enableProductionMode } from "../store.js";

enableProductionMode();  // ← runs on every import

This flips the global _productionMode flag as a side effect of importing the module. test/mcp.test.ts imports startMcpHttpServer from this module, and while the HTTP Transport describe block is skipIf(!!process.env.CI), the import happens regardless of skip status. So _productionMode flips to true in CI, which later makes store.test.ts fail:

test("createStore throws without explicit path in test mode", () => {
  delete process.env.INDEX_PATH;
  expect(() => createStore()).toThrow("Database path not set");
});

In production mode, getDefaultDbPath() resolves a cache path instead of throwing — so the assertion fails.

Fix

Move enableProductionMode() from module scope into the two server entry points — startMcpServer() (stdio) and startMcpHttpServer() (HTTP). Both entry points still flip the flag before getDefaultDbPath() runs, so #537's original fix is preserved. Merely importing the module for its exports no longer mutates global state.

Testing

Verified against current main:

  • Reproduced the CI failure on unmodified main (as expected — every main run since fix(mcp): call enableProductionMode before getDefaultDbPath #537 has failed).
  • With this change applied, the failing test passes.
  • qmd mcp and qmd mcp --http still enter production mode before path resolution — behaviour identical to before for end users.

Notes

This is a module-scope vs function-scope question rather than a conceptual disagreement with #537. If you'd prefer a different approach (e.g. explicit getDefaultDbPath({ production: true }) parameter, or moving the whole path-resolution logic), happy to adjust.

Relationship to #411 and #537

  • #411 originally reported that qmd mcp crashed on startup because enableProductionMode() was never called before getDefaultDbPath().
  • #537 fixed that by adding the call at module top level in src/mcp/server.ts.
  • This PR keeps fix(mcp): call enableProductionMode before getDefaultDbPath #537's fix working — both startMcpServer (stdio) and startMcpHttpServer (HTTP) still enable production mode before resolving the database path — but moves the call out of module scope so importing the module for its exports (e.g. from test/mcp.test.ts) does not leak the flag into unrelated tests.

Net effect on #411's original symptom: unchanged (still fixed). Net effect on CI: Bun (ubuntu-latest) goes green again.

The top-level enableProductionMode() call added in tobi#537 fixed a real issue
(MCP server resolving the wrong database path at startup) but introduced
test-isolation breakage as a side effect: merely importing src/mcp/server.ts
flipped the global _productionMode flag, which then broke unrelated tests
that depend on the default (development) database path resolution.

This shows up concretely as "Store Creation > createStore throws without
explicit path in test mode" failing on Bun (ubuntu-latest) in CI, because
test/mcp.test.ts imports startMcpHttpServer from this module.

Move the enableProductionMode() call from module scope into the two server
entry points (startMcpServer and startMcpHttpServer). The fix originally
intended by tobi#537 — ensuring production mode is active before getDefaultDbPath
runs — is preserved because both call sites still flip the flag before
createStore / getDefaultDbPath. Importing the module for its exports no longer
mutates global state.

Verified locally against current main: CI failure on Bun (ubuntu-latest)
reproduces on unmodified upstream main (14+ consecutive failed runs since
tobi#537 merged on 2026-04-09) and is resolved by this change.

Refs: tobi#537
@fxstein fxstein marked this pull request as draft April 23, 2026 17:39
src/cli/qmd.ts has the same module-scope enableProductionMode() call that
src/mcp/server.ts had — and the same test-isolation leak. test/cli.test.ts
imports buildEditorUri and termLink from this module, which executes the
top-level enableProductionMode() as a side effect of import, flipping the
global _productionMode flag for every later test file in the Bun process.

This is the actual driver of the Store Creation > createStore throws
without explicit path in test mode failure — test/cli.test.ts runs
alphabetically before test/store.test.ts, so the flag is already true by
the time store.test.ts checks it.

Mirror the fix applied to src/mcp/server.ts in the previous commit: move
enableProductionMode() from module scope into the if (isMain) guard so
the flag is only flipped when qmd is actually invoked as the CLI
entrypoint, not when the module is imported for its exports.
@fxstein fxstein marked this pull request as ready for review April 23, 2026 17:45
@tobi tobi merged commit a2fcac8 into tobi:main May 3, 2026
10 checks passed
lucndm pushed a commit to lucndm/qmd that referenced this pull request Jun 7, 2026
…-leak

fix(mcp): do not enable production mode at module import time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants