How do TS MCP servers conventionally handle build, types, and publishing? #2

Closed
opened 2026-09-06 14:41:29 +00:00 by haylan · 1 comment
Owner

Part of TypeScript project conventions for delegate-ai-mcp

Question

We currently run src/*.ts directly via Node 24's native TS type-stripping — no build step, no tsconfig.json, and critically no real typechecking (stripping is syntax-only; a wrong type won't fail the run). We might npm-publish this package later.

Research:

  • How does the official modelcontextprotocol/typescript-sdk repo, and its example servers, structure build/typecheck/package.json? (tsc vs tsup vs esbuild vs tsx vs native strip-types; is there a de facto standard?)
  • What Node engine range do published MCP servers on npm typically target, and how does that interact with using Node's native TS stripping for dev vs shipping compiled JS for consumers on older Node?
  • Do published MCP servers ship a bin entry for npx execution? What do their package.json exports/files/bin fields look like?
  • Is there a lightweight typecheck-only convention (e.g. tsc --noEmit as a separate script/CI step) commonly paired with native-strip-types-for-execution, so you get real type safety without a build step for local/global use?

Answer should be findings + a recommendation, not a final decision — the grilling tickets this unblocks will decide.

Part of [TypeScript project conventions for delegate-ai-mcp](https://git.arthurerlich.de/haylan/delegate-ai-mcp/issues/1) ## Question We currently run src/*.ts directly via Node 24's native TS type-stripping — no build step, no tsconfig.json, and critically **no real typechecking** (stripping is syntax-only; a wrong type won't fail the run). We might npm-publish this package later. Research: - How does the official modelcontextprotocol/typescript-sdk repo, and its example servers, structure build/typecheck/package.json? (tsc vs tsup vs esbuild vs tsx vs native strip-types; is there a de facto standard?) - What Node engine range do published MCP servers on npm typically target, and how does that interact with using Node's native TS stripping for dev vs shipping compiled JS for consumers on older Node? - Do published MCP servers ship a bin entry for npx execution? What do their package.json exports/files/bin fields look like? - Is there a lightweight typecheck-only convention (e.g. tsc --noEmit as a separate script/CI step) commonly paired with native-strip-types-for-execution, so you get real type safety without a build step for local/global use? Answer should be findings + a recommendation, not a final decision — the grilling tickets this unblocks will decide.
haylan added the wayfinder:research label 2026-09-06 14:41:29 +00:00
Author
Owner

Findings on branch research/ts-mcp-conventions (research/ts-mcp-project-conventions.md): tsc-to-dist is the de facto build standard (official SDK v1 + all example servers + real third-party servers like playwright-mcp); tsup/esbuild shows up as a minority pattern but always pairs with a separate 'tsc --noEmit' for real typechecking. Published servers target engines >=18/>=20 and always ship a bin entry pointing at compiled dist/*.js with a shebang, files:['dist'], and exports only on library-shaped packages. Critically, Node refuses to strip-execute .ts under node_modules, so native strip-types cannot be the shipped model once this is npm-published -- but running via strip-types + a tsc --noEmit sidecar (no build) is a sound, Node-docs-endorsed pattern for the current pre-publish/global-only state. Recommendation section at the end covers all 4 questions.

Findings on branch research/ts-mcp-conventions (research/ts-mcp-project-conventions.md): tsc-to-dist is the de facto build standard (official SDK v1 + all example servers + real third-party servers like playwright-mcp); tsup/esbuild shows up as a minority pattern but always pairs with a separate 'tsc --noEmit' for real typechecking. Published servers target engines >=18/>=20 and always ship a bin entry pointing at compiled dist/*.js with a shebang, files:['dist'], and exports only on library-shaped packages. Critically, Node refuses to strip-execute .ts under node_modules, so native strip-types cannot be the shipped model once this is npm-published -- but running via strip-types + a tsc --noEmit sidecar (no build) is a sound, Node-docs-endorsed pattern for the current pre-publish/global-only state. Recommendation section at the end covers all 4 questions.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: haylan/delegate-ai-mcp#2