Skip to content

fix: declare @cosyte/fhir optional and run without the MCP SDK - #99

Merged
NSchatz merged 1 commit into
mainfrom
fix/install-without-optional-deps
Nov 8, 2026
Merged

NSchatz merged 1 commit into
mainfrom
fix/install-without-optional-deps

Conversation

@NSchatz

@NSchatz NSchatz commented Nov 8, 2026

Copy link
Copy Markdown
Contributor

Two install fixes, shipped together as one patch (0.1.6).

1. @cosyte/fhir is declared. It moves from devDependencies to optionalDependencies at ^0.1.0, the same range @cosyte/transform uses. The published fhir (0.1.5) satisfies transform's ^0.1.0 peer range. Before this, an npm install --legacy-peer-deps kept transform and left fhir out, so FHIR and convert exited 69. The ERESOLVE that kept it a devDependency (#27) no longer reproduces. The CLAUDE.md rule and the ci.yml comment are updated to say so.

2. --omit=optional no longer crashes cosyte. @modelcontextprotocol/sdk was already optional. The fault was in the build: the bins are bundled without code splitting, so the server module that cosyte mcp reached by a dynamic import() was inlined into the bin. The bundler then hoisted that module's static SDK imports to the top of the bin, and every command loaded them. Both bins now start the server through src/mcp/launch.ts, which imports the SDK with a dynamic import() of the package (this stays dynamic in the bundle). An absent SDK maps to CLI_PARSER_UNAVAILABLE (exit 69), which names the package to install. The request wiring moved to src/mcp/wire.ts, which takes the SDK classes as arguments. The @cosyte/cli/mcp subpath API is unchanged. No new CLI_* code was added.

Tests:

  • test/absent-mcp-sdk.test.ts checks the mapping. It also walks every module either bin can reach, following dynamic imports, and fails on a static SDK import. It includes negative controls.
  • pnpm smoke runs both built bins with the SDK hidden from Node's resolver, with a negative control. It reds against the old source.

Clean-room proof from the packed tarball (recorded in RELEASING.md):

install exit FHIR parse convert MCP server
npm install 0 0 0 starts
pnpm add 0 0 0 starts
npm install --legacy-peer-deps 0 0 0 starts
npm install --omit=optional 0 69 69 69 (value-free)

The local gate passes in full.

https://claude.ai/code/session_01MXLcW95gf97vs9RBU1YsXf

Declare @cosyte/fhir as an optional dependency at ^0.1.0 beside
@cosyte/transform, so an npm install with --legacy-peer-deps keeps it. The
published fhir 0.1.5 satisfies transform's ^0.1.0 peer range, and a packed
tarball installs with exit 0 under npm install, pnpm add and npm install
--legacy-peer-deps, with FHIR parse and convert working in each.

An install with --omit=optional crashed at startup on the missing
@modelcontextprotocol/sdk. The SDK was already optional; the bins are
bundled without code splitting, so the server module reached by a dynamic
import was inlined and its static SDK imports hoisted to the top of the bin.
Both bins now start the server through src/mcp/launch.ts, which imports the
SDK dynamically and maps an absent one to CLI_PARSER_UNAVAILABLE (69) naming
the package to install. The request wiring moves to src/mcp/wire.ts, which
takes the SDK classes as arguments; the @cosyte/cli/mcp subpath is unchanged.

Tests: absent-mcp-sdk.test.ts walks every module either bin reaches and
fails on a static SDK import; pnpm smoke runs both built bins with the SDK
hidden from the resolver. Docs that called this a known defect, the
CLAUDE.md devDependency rule and the ci.yml comment are updated.

Claude-Session: https://claude.ai/code/session_01MXLcW95gf97vs9RBU1YsXf
@NSchatz
NSchatz merged commit 6fd6e56 into main Nov 8, 2026
13 checks passed
@NSchatz
NSchatz deleted the fix/install-without-optional-deps branch November 8, 2026 15:08
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