fix(exports): resolve .js subpath imports to real declaration files - #2702
Open
johnhenry wants to merge 1 commit into
Open
fix(exports): resolve .js subpath imports to real declaration files#2702johnhenry wants to merge 1 commit into
johnhenry wants to merge 1 commit into
Conversation
Subpath imports such as `@modelcontextprotocol/sdk/server/mcp.js` fell through the `"./*"` pattern, whose types target is `./dist/esm/*.d.ts`. The wildcard captures the remainder including the extension, so types resolved to `dist/esm/server/mcp.js.d.ts`, which does not exist. TypeScript papers over this via the `typesVersions` fallback, so `tsc` is unaffected. Resolvers that implement `exports` without `typesVersions` - notably Deno - fail with TS2307, which then cascades into implicit-any errors on every inferred callback parameter. Add a `"./*.js"` pattern so the extension is excluded from the wildcard capture. Node prefers the more specific pattern, so ordering does not matter and runtime resolution is unchanged. Fixes modelcontextprotocol#2701
|
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.
Fixes #2701.
Problem
Subpath imports like
@modelcontextprotocol/sdk/server/mcp.jshave no explicit key inexports, so they fall through"./*":The wildcard captures the entire remainder including the extension, so
*=server/mcp.jsand the types target becomesdist/esm/server/mcp.js.d.ts— which does not exist. The real declaration file isdist/esm/server/mcp.d.ts.tscis unaffected because it falls back totypesVersions("*": ["./dist/esm/*"]), which resolves the.js→.d.tsstep itself. Resolvers that implementexportsbut nottypesVersions— notably Deno — fail withTS2307.Because the failure is a type resolution failure, it doesn't stop at one error: once
McpServeris unresolved, every zod-inferredserver.tool(...)callback parameter collapses toany. A server of mine with 3 SDK imports produced 1 ×TS2307plus 19 ×TS7031, all from this single root cause.This affects the import style used throughout the README and examples, so in practice it blocks type-checking any MCP server under Deno, and blocks publishing one to JSR.
Fix
Add a
"./*.js"pattern alongside the existing"./*", so the extension is excluded from the wildcard capture:Node's resolution algorithm prefers the pattern with the longest prefix before
*, so"./*.js"wins for.jsspecifiers regardless of key order, and everything else continues to fall through"./*"exactly as before.typesVersionsis left alone — it already handles this case.Verification
Against 1.30.0, before and after:
deno checkonimport { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"TS2307node --input-type=moduleimporting the same specifiertsc --module nodenext --moduleResolution nodenext --strictSo it fixes Deno without changing Node or tsc behaviour.
Tests
test/issues/test_2701_js_subpath_exports.test.ts, following the existingtest/issues/convention. It resolves subpaths through the realexportsmap frompackage.jsonand asserts the types target is a genuine.d.ts, that runtime targets are unchanged, that explicit keys still take precedence, and that extensionless subpaths still work.The four types assertions fail without the
package.jsonchange and pass with it. The runtime-target assertions pass either way, which is the intended demonstration that runtime resolution is untouched.Full suite on this branch: 10 failed, 1643 passed. On unmodified
v1.xon the same machine: 10 failed, 1629 passed — the same 10 pre-existing failures (they spawn/usr/bin/tee, which doesn't exist on NixOS), plus the 14 new passing tests.npm run lintandnpm run typecheckboth clean.Based on
v1.xper CONTRIBUTING, since this is a v1 packaging fix.