Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/dist-types-skiplibcheck.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@modelcontextprotocol/server': patch
'@modelcontextprotocol/client': patch
'@modelcontextprotocol/node': patch
---

Fix the published declaration files for consumers compiling with `skipLibCheck: false`: the bundled `.d.mts` no longer leaves a dangling `URIComponent` reference (ajv's published types import it from `fast-uri`, whose export-assigned namespace the dts bundler cannot link — the type is now inlined via a dts-only path mapping), and no longer imports `json-schema-typed` from an undeclared dependency (it is inlined via `dts.resolve`). `@modelcontextprotocol/node` and `@modelcontextprotocol/server` drop stale `typesVersions` entries pointing at subpaths that never shipped. Package READMEs note that TypeScript >=6.0 requires `"types": ["node"]` since the published declarations reference `Buffer`.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
- run: pnpm install
- run: pnpm run check:all
- run: pnpm run build:all
- run: node scripts/smoke-dist-types.mjs

test:
runs-on: ubuntu-latest
Expand Down
2 changes: 2 additions & 0 deletions packages/client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ The MCP (Model Context Protocol) TypeScript client SDK. Build MCP clients that c
npm install @modelcontextprotocol/client@alpha
```

TypeScript ≥6.0 no longer auto-includes `@types/*` — add `"types": ["node"]` to your `tsconfig.json` `compilerOptions` (the published `.d.mts` references `Buffer`).

## Documentation

- **[Repository README](https://github.com/modelcontextprotocol/typescript-sdk#readme)** — overview, package layout, examples
Expand Down
3 changes: 2 additions & 1 deletion packages/client/tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,11 @@ export default defineConfig({
shims: true,
dts: {
resolver: 'tsc',
resolve: ['ajv', 'ajv-formats'],
resolve: ['ajv', 'ajv-formats', 'json-schema-typed'],
compilerOptions: {
baseUrl: '.',
paths: {
'fast-uri': ['../core-internal/src/validators/fastUriShim.d.ts'],
'@modelcontextprotocol/core-internal': ['../core-internal/src/index.ts'],
'@modelcontextprotocol/core-internal/public': ['../core-internal/src/exports/public/index.ts'],
'@modelcontextprotocol/core-internal/validators/ajv': ['../core-internal/src/validators/ajvProvider.ts'],
Expand Down
31 changes: 31 additions & 0 deletions packages/core-internal/src/validators/fastUriShim.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* dts-bundling shim for `fast-uri`.
*
* ajv@8.18.0's published .d.ts does `import { URIComponent } from "fast-uri"`,
* but fast-uri ships its types as `export = namespace`, which rolldown's dts
* bundler can't destructure into a named import — it drops the import and
* leaves a dangling `URIComponent` reference in the bundled .d.mts (TS2304 for
* downstream consumers with `skipLibCheck: false`).
*
* The server/client tsdown configs map `fast-uri` to this file via
* `dts.compilerOptions.paths` so the type is inlined as a plain named export.
* Runtime code is unaffected (this is a `.d.ts`; the path mapping is dts-only).
*/
// Field-for-field copy of fast-uri@3.1.0's URIComponent (types/index.d.ts).
// Keep in sync when bumping fast-uri/ajv.
export interface URIComponent {
scheme?: string;
userinfo?: string;
host?: string;
port?: number | string;
path?: string;
query?: string;
fragment?: string;
reference?: string;
nid?: string;
nss?: string;
resourceName?: string;
secure?: boolean;
uuid?: string;
error?: string;
}
7 changes: 0 additions & 7 deletions packages/middleware/node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@
}
},
"types": "./dist/index.d.mts",
"typesVersions": {
"*": {
"sse": [
"dist/sse.d.mts"
]
}
},
"files": [
Comment thread
claude[bot] marked this conversation as resolved.
"dist"
],
Expand Down
2 changes: 2 additions & 0 deletions packages/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ The MCP (Model Context Protocol) TypeScript server SDK. Build MCP servers that e
npm install @modelcontextprotocol/server@alpha
```

TypeScript ≥6.0 no longer auto-includes `@types/*` — add `"types": ["node"]` to your `tsconfig.json` `compilerOptions` (the published `.d.mts` references `Buffer`).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 The new TS ≥6.0 note says consumers must add "types": ["node"] to compilerOptions, but the repo's own quickstart docs (docs/server-quickstart.md lines 99-116 and docs/client-quickstart.md lines 88-105) still present canonical tsconfig.json examples without a types entry while installing @types/node and using Node APIs (readline, process). Consider adding "types": ["node"] (or the same caveat) to those two quickstart tsconfig snippets so a TS ≥6.0 user following them verbatim doesn't hit exactly the problem this note warns about.

Extended reasoning...

What it is. This PR adds a note to packages/client/README.md and packages/server/README.md stating that TypeScript ≥6.0 no longer auto-includes @types/* and that consumers must add "types": ["node"] to their tsconfig.json compilerOptions (because the published .d.mts references Buffer). However, the repo's own consumer-facing setup docs — docs/server-quickstart.md (tsconfig at ~lines 99-116) and docs/client-quickstart.md (tsconfig at ~lines 88-105) — each present a complete, canonical tsconfig.json for new users that contains no types field, and were not updated by this PR.

The code path that triggers it. Both quickstarts instruct npm install -D @types/node typescript (i.e. latest TypeScript) and then ship sample code that relies heavily on Node APIs: the client quickstart imports readline/promises and uses process.argv, process.env, process.exit, process.stdin/stdout; the server quickstart uses console.error and the stdio transport. Under TS ≥6.0 (per the PR's own claim, verified by the author via the fresh-install smoke), @types/node is no longer auto-included from node_modules/@types, so without an explicit "types": ["node"] (or a triple-slash reference) those globals and modules are unresolved.

Why existing code doesn't prevent it. The quickstart tsconfig sets skipLibCheck: true, but that only suppresses errors inside declaration files (e.g. the dangling Buffer reference in the bundled .d.mts); it does not make Node globals or node:/readline/promises module types resolvable in the user's own code. Nothing else in the quickstart flow adds the types entry.

Step-by-step proof. (1) A new user follows docs/client-quickstart.md verbatim with TypeScript 6.x: npm install -D @types/node typescript, copies the tsconfig at lines 88-105, copies the sample client code (which imports readline/promises and uses process.*). (2) They run npx tsc. (3) Because TS ≥6.0 no longer auto-includes @types/* and the tsconfig has no types entry, the compiler cannot resolve readline/promises or the process global → TS2307 / TS2580-style errors in the user's own files, which skipLibCheck: true cannot mask. (4) The fix is exactly the guidance this PR adds to the READMEs — "types": ["node"] — but the quickstart, which is the canonical setup doc, never mentions it.

Impact and fix. This is a doc-consistency gap, not a code bug, and the quickstarts were equally untouched before this PR (the underlying need comes from TypeScript 6, not from this change) — hence nit severity, not blocking. The repo's review conventions call for checking whether docs/**/*.md describes old behavior when guidance changes; since this PR introduces the types: ["node"] guidance, the cheapest complete fix is a one-line addition of "types": ["node"] to the two quickstart tsconfig snippets (or a parallel one-sentence caveat next to them), which can be done in this PR or as an immediate follow-up.

All four verifiers independently confirmed the quickstart tsconfig snippets lack a types entry while the sample code depends on Node APIs, and all rated this nit-level; there were no refutations.


Optional framework adapters: [`@modelcontextprotocol/express`](https://www.npmjs.com/package/@modelcontextprotocol/express), [`@modelcontextprotocol/hono`](https://www.npmjs.com/package/@modelcontextprotocol/hono),
[`@modelcontextprotocol/node`](https://www.npmjs.com/package/@modelcontextprotocol/node).

Expand Down
3 changes: 0 additions & 3 deletions packages/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,6 @@
"validators/cf-worker": [
"dist/validators/cfWorker.d.mts"
],
"zod-schemas": [
"dist/zodSchemas.d.mts"
],
"stdio": [
"dist/stdio.d.mts"
]
Expand Down
3 changes: 2 additions & 1 deletion packages/server/tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ export default defineConfig({
shims: true,
dts: {
resolver: 'tsc',
resolve: ['ajv', 'ajv-formats'],
resolve: ['ajv', 'ajv-formats', 'json-schema-typed'],
compilerOptions: {
baseUrl: '.',
paths: {
'fast-uri': ['../core-internal/src/validators/fastUriShim.d.ts'],
'@modelcontextprotocol/core-internal': ['../core-internal/src/index.ts'],
'@modelcontextprotocol/core-internal/public': ['../core-internal/src/exports/public/index.ts'],
'@modelcontextprotocol/core-internal/validators/ajv': ['../core-internal/src/validators/ajvProvider.ts'],
Expand Down
70 changes: 70 additions & 0 deletions scripts/smoke-dist-types.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Compiles a small consumer against the BUILT declaration files with
// `skipLibCheck: false`, catching dangling type references that the dts
// bundler emits only as non-fatal warnings (its failOnWarn does not fail on
// MISSING_EXPORT). Run after `pnpm build:all`.
import { execFileSync } from 'node:child_process';
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
import { tmpdir } from 'node:os';
import path from 'node:path';

const repo = path.resolve(import.meta.dirname, '..');
const dir = mkdtempSync(path.join(tmpdir(), 'dist-types-smoke-'));
try {
writeFileSync(
path.join(dir, 'consumer.ts'),
[
"import { Client } from '@modelcontextprotocol/client';",
"import type { AjvJsonSchemaValidator as ClientAjv } from '@modelcontextprotocol/client';",
"import { AjvJsonSchemaValidator } from '@modelcontextprotocol/client/validators/ajv';",
"import { CfWorkerJsonSchemaValidator as ClientCf } from '@modelcontextprotocol/client/validators/cf-worker';",
"import { StdioClientTransport } from '@modelcontextprotocol/client/stdio';",
"import { McpServer } from '@modelcontextprotocol/server';",
"import { AjvJsonSchemaValidator as ServerAjv } from '@modelcontextprotocol/server/validators/ajv';",
"import { CfWorkerJsonSchemaValidator as ServerCf } from '@modelcontextprotocol/server/validators/cf-worker';",
"import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';",
"export const c = new Client({ name: 'smoke', version: '1.0.0' });",
"export const s = new McpServer({ name: 'smoke', version: '1.0.0' });",
'export type T = ClientAjv;',
'export { AjvJsonSchemaValidator, ServerAjv, ClientCf, ServerCf, StdioClientTransport, StdioServerTransport };',
''
].join('\n')
Comment thread
claude[bot] marked this conversation as resolved.
);
writeFileSync(
path.join(dir, 'tsconfig.json'),
JSON.stringify(
{
compilerOptions: {
strict: true,
noEmit: true,
skipLibCheck: false,
module: 'esnext',
moduleResolution: 'bundler',
target: 'es2022',
types: ['node'],
typeRoots: [path.join(repo, 'node_modules', '@types')],
paths: {
'@modelcontextprotocol/client': [path.join(repo, 'packages/client/dist/index.d.mts')],
'@modelcontextprotocol/client/validators/ajv': [path.join(repo, 'packages/client/dist/validators/ajv.d.mts')],
'@modelcontextprotocol/client/validators/cf-worker': [
path.join(repo, 'packages/client/dist/validators/cfWorker.d.mts')
],
'@modelcontextprotocol/client/stdio': [path.join(repo, 'packages/client/dist/stdio.d.mts')],
'@modelcontextprotocol/server': [path.join(repo, 'packages/server/dist/index.d.mts')],
'@modelcontextprotocol/server/validators/ajv': [path.join(repo, 'packages/server/dist/validators/ajv.d.mts')],
'@modelcontextprotocol/server/validators/cf-worker': [
path.join(repo, 'packages/server/dist/validators/cfWorker.d.mts')
],
'@modelcontextprotocol/server/stdio': [path.join(repo, 'packages/server/dist/stdio.d.mts')]
}
},
include: ['consumer.ts']
},
null,
2
)
);
execFileSync('pnpm', ['exec', 'tsc', '-p', dir], { cwd: repo, stdio: 'inherit' });
console.log('dist-types smoke: clean (skipLibCheck: false)');
} finally {
rmSync(dir, { recursive: true, force: true });
}
Loading