Skip to content

fix(mcp): import MCP handler statically so the prod build emits it#227

Merged
vigneshrajsb merged 1 commit into
mainfrom
fix-mcp-handler-server-build
Jul 10, 2026
Merged

fix(mcp): import MCP handler statically so the prod build emits it#227
vigneshrajsb merged 1 commit into
mainfrom
fix-mcp-handler-server-build

Conversation

@vigneshrajsb

@vigneshrajsb vigneshrajsb commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the prod boot crash for the MCP server merged in #224. With MCP_SERVER_ENABLED=true, lifecycle-web pods crashloop at startup:

Error: Cannot find module './src/server/mcp/handler'
    at Object.<anonymous> (/app/.next/ws-server.js:87:28)

Root cause

ws-server.ts loaded the MCP handler via a deferred require('./src/server/mcp/handler'). Because that dynamic require is outside tsc's static import graph, tsc -p tsconfig.server.json never compiled the module into .next/ — so at boot the require of the never-emitted handler.js throws. (Local dev via ts-node and jest imports from src both resolve it, so only the prod build + MCP_SERVER_ENABLED=true exposed it.)

Why the deferred require is no longer needed

It existed solely to keep the ESM-only jose / MCP SDK off the boot path on Node < 20.19 (which can't require() ESM). That was a real concern when the MCP alphas shipped on node:20-slim — but #223 moved every build to node:22-slim before this code reached main. Since the Docker image welds the Node runtime to the app code, there is no artifact combining "MCP code + Node 20": old Node-20 images predate MCP entirely, and every MCP-carrying image is Node 22 (where require(esm) works). The workaround guards a state that can't occur.

Fix

Import the handler statically. tsc traces it through ws-server.ts's import graph and emits it normally, removing the build-vs-runtime gap at the root — no tsconfig.server.json include entry or build-time guard needed. The MCP_SERVER_ENABLED flag still gates whether the handler is wired up; only the module load moves to boot (a plain require on Node 22). Worker / MCP-off pods now load jose+SDK at boot too — negligible on Node 22.

Validation

  • tsc -p tsconfig.server.json now emits .next/src/server/mcp/handler.js (+ auth.js, server.js, truncate.js) via the static graph; confirmed absent before this change, reproducing the crash.
  • Server typecheck (tsconfig.server.json) exit 0; pnpm run lint clean; MCP unit tests match main baseline (build/boot-path change, no test impact).

Deploy: once merged, cut a fresh alpha from main and roll lifecycle-web — the prod realm and web env (MCP_SERVER_ENABLED, MCP_RESOURCE_URL) are already in place.

@vigneshrajsb vigneshrajsb requested a review from a team as a code owner July 10, 2026 20:17
@vigneshrajsb vigneshrajsb force-pushed the fix-mcp-handler-server-build branch from 0f8b0cc to 122df63 Compare July 10, 2026 20:26
With MCP_SERVER_ENABLED=true, lifecycle-web pods crashed at boot with
"Cannot find module './src/server/mcp/handler'": ws-server.ts loaded the
handler via a deferred require() that sits outside tsc's static import
graph, so `tsc -p tsconfig.server.json` never emitted the module.

The deferred require existed only to keep the ESM-only jose / MCP SDK off
the boot path on Node < 20.19 (require(esm) support). That was valid when
the MCP alphas shipped on node:20-slim, but #223 moved every build to
node:22-slim before this code reached main — and the Docker image welds the
Node runtime to the app code, so "MCP code on Node 20" can't occur. The
workaround now guards an impossible state.

Import the handler statically instead. tsc traces it through ws-server.ts's
import graph and emits it normally, eliminating the build-vs-runtime gap at
the root (no tsconfig "include" entry needed). The MCP_SERVER_ENABLED flag
still gates whether the handler is wired up; only the module load moves to
boot, which is a plain require on Node 22.

Verified: tsc emits .next/src/server/mcp/handler.js via the static graph
(absent before); server typecheck + lint clean.
@vigneshrajsb vigneshrajsb force-pushed the fix-mcp-handler-server-build branch from 122df63 to 5226282 Compare July 10, 2026 20:43
@vigneshrajsb vigneshrajsb changed the title fix(mcp): emit MCP server module in prod build fix(mcp): import MCP handler statically so the prod build emits it Jul 10, 2026
@vigneshrajsb vigneshrajsb merged commit 3ba4158 into main Jul 10, 2026
5 checks passed
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.

1 participant