modelcontextprotocol / modelcontextprotocol/typescript-sdk
Deno: TS2307 on all .js subpath imports — './*' exports map types to '*.js.d.ts'
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 13.4k
- Forks
- 2.2k
- Avg merge
- 3d 15h
- Merged PRs (30d)
- 4
Description
Summary
Under Deno, every .js-suffixed subpath import of the SDK fails type resolution with TS2307, because the ./* export pattern maps types to ./dist/esm/*.d.ts. For the specifier @modelcontextprotocol/sdk/server/mcp.js, * captures server/mcp.js, so the types path resolves to dist/esm/server/mcp.js.d.ts — which does not exist. The real declaration file is dist/esm/server/mcp.d.ts.
tsc resolves this fine (it strips the .js before matching), so the problem is invisible to Node-only users. Deno applies the substitution literally and fails.
This affects the import style used throughout the SDK's own README and examples, so it hits essentially any MCP server that tries to type-check under Deno or publish to JSR.
Reproduction
Clean directory, no tsconfig:
mkdir repro && cd repro
echo '{"name":"repro","type":"module","dependencies":{"@modelcontextprotocol/sdk":"1.30.0"}}' > package.json
npm install
echo '{"nodeModulesDir":"manual"}' > deno.json
printf 'import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";\nexport const s: McpServer | null = null;\n' > mod.ts
deno check mod.ts
Result:
Check mod.ts
TS2307 [ERROR]: Cannot find module '@modelcontextprotocol/sdk/server/mcp.js'.
at file:///.../repro/mod.ts:1:27
error: Type checking failed.
The identical file under tsc 5.9.3 exits 0:
tsc --noEmit --module nodenext --moduleResolution nodenext --strict mod.ts # exit 0
Why it's worse than one error
Once McpServer is unresolved, the zod-inferred parameter types on every server.tool(...) callback collapse to any. In a real server this cascades: a file of mine with 3 SDK imports produced 1 × TS2307 plus 19 × TS7031 ("Binding element 'sessionId' implicitly has an 'any' type"), all downstream of the single resolution failure. The error output makes it look like a codebase problem rather than a one-line packaging one.
Versions
@modelcontextprotocol/sdk1.30.0- Deno 2.9.0 (stable, x86_64-unknown-linux-gnu)
- TypeScript 5.9.3
- Node 24
Suggested fix
Add a ./*.js pattern alongside the existing ./*. Node's exports resolution prefers the more specific pattern, so ordering doesn't matter and existing consumers are unaffected:
"./*.js": {
"types": "./dist/esm/*.d.ts",
"import": "./dist/esm/*.js",
"require": "./dist/cjs/*.js"
},
"./*": {
"types": "./dist/esm/*.d.ts",
"import": "./dist/esm/*",
"require": "./dist/cjs/*"
}
I verified this against 1.30.0 by patching node_modules:
deno check mod.ts→ exit 0node --input-type=module -e 'import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; ...'→ still resolves,typeof McpServer === "function"
So it fixes Deno without regressing Node.
Note on prior art
#1269 ("Non-Node environment support (Bun, Deno, React Native)") was closed as completed in March, but this type-resolution path appears not to be covered by it — runtime import works under Deno, only type-checking fails. Happy to open a PR if the suggested shape looks right.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the package export map and reproduce the failure using the provided mod.ts and deno check command. Verify the .js subpath pattern resolves declarations under Deno, then confirm the existing tsc and Node checks still pass without affecting the ./* entries.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- deno, typescript
- Domain
- build-system, tooling
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 84/100