Skip to content

fix(exports): resolve .js subpath imports to real declaration files - #2702

Open
johnhenry wants to merge 1 commit into
modelcontextprotocol:v1.xfrom
johnhenry:fix/js-subpath-exports-types
Open

fix(exports): resolve .js subpath imports to real declaration files#2702
johnhenry wants to merge 1 commit into
modelcontextprotocol:v1.xfrom
johnhenry:fix/js-subpath-exports-types

Conversation

@johnhenry

Copy link
Copy Markdown

Fixes #2701.

Problem

Subpath imports like @modelcontextprotocol/sdk/server/mcp.js have no explicit key in exports, so they fall through "./*":

"./*": { "types": "./dist/esm/*.d.ts", "import": "./dist/esm/*", "require": "./dist/cjs/*" }

The wildcard captures the entire remainder including the extension, so * = server/mcp.js and the types target becomes dist/esm/server/mcp.js.d.ts — which does not exist. The real declaration file is dist/esm/server/mcp.d.ts.

tsc is unaffected because it falls back to typesVersions ("*": ["./dist/esm/*"]), which resolves the .js.d.ts step itself. Resolvers that implement exports but not typesVersions — notably Deno — fail with TS2307.

Because the failure is a type resolution failure, it doesn't stop at one error: once McpServer is unresolved, every zod-inferred server.tool(...) callback parameter collapses to any. A server of mine with 3 SDK imports produced 1 × TS2307 plus 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:

"./*.js": { "types": "./dist/esm/*.d.ts", "import": "./dist/esm/*.js", "require": "./dist/cjs/*.js" }

Node's resolution algorithm prefers the pattern with the longest prefix before *, so "./*.js" wins for .js specifiers regardless of key order, and everything else continues to fall through "./*" exactly as before. typesVersions is left alone — it already handles this case.

Verification

Against 1.30.0, before and after:

before after
deno check on import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js" TS2307 exit 0
node --input-type=module importing the same specifier resolves resolves
tsc --module nodenext --moduleResolution nodenext --strict exit 0 exit 0

So it fixes Deno without changing Node or tsc behaviour.

Tests

test/issues/test_2701_js_subpath_exports.test.ts, following the existing test/issues/ convention. It resolves subpaths through the real exports map from package.json and 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.json change 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.x on 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 lint and npm run typecheck both clean.

Based on v1.x per CONTRIBUTING, since this is a v1 packaging fix.

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
@johnhenry
johnhenry requested a review from a team as a code owner August 22, 2026 18:34
@changeset-bot

changeset-bot Bot commented Aug 22, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 29c61f6

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Aug 22, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@2702

commit: 29c61f6

@claude claude Bot added the v1 Issues / PRs related to v1.x label Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v1 Issues / PRs related to v1.x

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant