feat(deps): make HTTP/SSE transport deps optional for stdio-only consumers#1964
Open
MukundaKatta wants to merge 1 commit intomodelcontextprotocol:v1.xfrom
Open
Conversation
🦋 Changeset detectedLatest commit: e344cbe The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
…umers Move `express`, `cors`, `express-rate-limit`, `@hono/node-server`, `raw-body`, `content-type`, `eventsource`, `eventsource-parser`, and `jose` from runtime `dependencies` to optional `peerDependencies`. Drop the unused-at-runtime `hono` package entirely (only referenced by an example). For stdio-only consumers (the most common deployment for local MCP servers) this removes ~22 MB / 60+ transitive packages from the install, eliminating supply-chain alerts for code paths the user never loads. Apps that already depend on Express, Hono, etc. via their own `package.json` continue to work unchanged. Adds a static-analysis test that asserts the stdio transport source files never grow a static import of an HTTP/SSE-only peer dep, so the lazy boundary cannot regress silently. Closes modelcontextprotocol#1924.
02b4a63 to
e344cbe
Compare
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1924.
Why
The published v1 SDK ships
express,cors,express-rate-limit,@hono/node-server,eventsource,eventsource-parser,raw-body,content-type,hono, andjoseas direct runtimedependencies. Stdio-only consumers (the most common deployment for local MCP servers) never load any of that code, but every install still pulls in ~22 MB / 60+ transitive packages and lights up supply-chain analyzers (Socket, Snyk, Scorecard) for code paths the user never imports.The issue author's
mercury-invoicing-mcpserver is a 33 KB stdio-only bundle that picks up 6 Socket alerts originating from the Express tree. A second commenter (jibbius) reports the dependency tree size is currently a blocker for adoption inside their workplace. None of those alerts are actionable for stdio-only maintainers.This PR implements Option 2 from the issue — the lightest-touch fix that doesn't require splitting the package or introducing new conditional exports.
What
package.jsonexpress,cors,express-rate-limit,@hono/node-server,raw-body,content-type,eventsource,eventsource-parser,josefromdependenciestopeerDependencieswithpeerDependenciesMeta.<name>.optional = true. npm 7+, pnpm, and yarn skip optional peers that aren't already in the consumer's tree, so stdio-only installs no longer pull them in.honofrom runtime deps entirely. It is only referenced bysrc/examples/server/honoWebStandardStreamableHttp.ts(kept available viadevDependencies); nothing insrc/server/**orsrc/client/**imports it.devDependenciesso the local repo (tests, examples, build) keeps a green install.README.md— add an "Optional peer dependencies" matrix mapping each transport / OAuth helper to the package(s) it now requires the consumer to install.test/stdio-only-imports.test.ts— new static-analysis test that readssrc/{client,server}/stdio.ts,src/shared/*.ts,src/types.ts, andsrc/inMemory.tsand asserts none of them staticallyimport/requirean HTTP-only peer. Catches future regressions where someone accidentally moves an HTTP dep behind a top-level import in a stdio path..changeset/optional-http-sse-deps.md—majorchangeset (peer-dep relocation is a soft breaking change for HTTP consumers who relied on the SDK to install Express transitively).The transport modules themselves are unchanged. Each HTTP/SSE module still imports its peer at the top of the file, so a consumer who imports
@modelcontextprotocol/sdk/server/streamableHttp.jswithout installing@hono/node-servergets an immediate, clearly-attributedERR_MODULE_NOT_FOUNDat load time pointing at the missing package.Tested
npm test— 49 files, 1586/1586 passing (no behavior changes).npm test -- --run test/stdio-only-imports.test.ts— new test passes 7/7.npm install --omit=dev --omit=optional --dry-runreports 290 packages removed from the production tree vs the priordependenciesset.test/server/streamableHttp.test.ts,test/server/sse.test.ts,test/server/auth/**,test/client/sse.test.ts,test/client/streamableHttp.test.ts) continue to pass — the peers resolve fine because they're declared indevDependencies.Notes for reviewers
majorchangeset bump is conservative — strictly speaking, this only breaks consumers who relied on the SDK to install Express / Hono transitively, which is a behavior change but not an API change. Happy to downgrade tominorif that matches the maintenance policy onv1.x.main) already addresses the same root cause architecturally via the@modelcontextprotocol/{client,server,node,express,hono}split; this PR is the equivalent fix for users on the published1.xline who can't wait for v2.honoan optional peer in the v2/nodepackage) — that change is scoped to v2 and doesn't address v1 consumers.