diff --git a/.changeset/no-dangling-declaration-maps.md b/.changeset/no-dangling-declaration-maps.md new file mode 100644 index 0000000000..94a0ed3360 --- /dev/null +++ b/.changeset/no-dangling-declaration-maps.md @@ -0,0 +1,18 @@ +--- +'@modelcontextprotocol/core': patch +'@modelcontextprotocol/client': patch +'@modelcontextprotocol/server': patch +'@modelcontextprotocol/server-legacy': patch +'@modelcontextprotocol/codemod': patch +'@modelcontextprotocol/express': patch +'@modelcontextprotocol/fastify': patch +'@modelcontextprotocol/hono': patch +'@modelcontextprotocol/node': patch +--- + +Stop shipping broken declaration source maps (`.d.mts.map`/`.d.cts.map`). The published +packages only include `dist/`, so the declaration maps pointed at `src/` paths (and the +private `core-internal` workspace package) that do not exist in the tarball and carried no +embedded source content — declaration-map-aware tooling could only ever resolve them to +"source not found". The declaration maps and their `sourceMappingURL` references are no +longer emitted; runtime JS source maps (which embed `sourcesContent`) are unchanged. diff --git a/common/tsdown/stripDtsSourceMappingUrl.d.mts b/common/tsdown/stripDtsSourceMappingUrl.d.mts new file mode 100644 index 0000000000..838038f320 --- /dev/null +++ b/common/tsdown/stripDtsSourceMappingUrl.d.mts @@ -0,0 +1,8 @@ +import type { Rolldown } from 'tsdown'; + +/** + * tsdown `inputOptions` hook that removes the trailing `//# sourceMappingURL=` comment from the + * emitted `.d.ts` / `.d.mts` / `.d.cts` chunks. See the implementation in + * `./stripDtsSourceMappingUrl.mjs` for the full rationale (#2233). + */ +export function stripDtsSourceMappingUrl(options: Rolldown.InputOptions): void; diff --git a/common/tsdown/stripDtsSourceMappingUrl.mjs b/common/tsdown/stripDtsSourceMappingUrl.mjs new file mode 100644 index 0000000000..366fd925be --- /dev/null +++ b/common/tsdown/stripDtsSourceMappingUrl.mjs @@ -0,0 +1,38 @@ +// Plain .mjs (with a sibling .d.mts) so tsdown's native config loader can import it from the +// per-package tsdown.config.ts files on every supported Node version. + +const RE_DTS_CHUNK = /\.d\.[cm]?ts$/; +const RE_DTS_SOURCE_MAPPING_URL = /\n?\/\/# sourceMappingURL=\S+\s*$/; + +/** + * tsdown `inputOptions` hook that removes the trailing `//# sourceMappingURL=` comment from the + * emitted `.d.ts` / `.d.mts` / `.d.cts` chunks. + * + * The published packages ship only `dist/` (`"files": ["dist"]`), and tsc cannot embed + * `sourcesContent` into declaration maps, so shipped `.d.*ts.map` files would always point at + * `src/` paths that do not exist on a consumer's machine (#2233). Setting `dts.sourcemap: false` + * stops the maps from being emitted, but the JS-level `sourcemap: true` still makes rolldown + * append a sourceMappingURL comment to the declaration chunks; this hook strips that comment so + * the shipped declaration files do not reference maps that are not there. + * + * Registered via `inputOptions` rather than `plugins` because tsdown does not forward user + * plugins to the extra CJS dts pass that emits the `.d.cts` files. + * + * @param {import('tsdown').Rolldown.InputOptions} options + * @returns {void} + */ +export function stripDtsSourceMappingUrl(options) { + options.plugins = [ + options.plugins, + { + name: 'strip-dts-source-mapping-url', + generateBundle(_outputOptions, bundle) { + for (const output of Object.values(bundle)) { + if (output.type === 'chunk' && RE_DTS_CHUNK.test(output.fileName)) { + output.code = output.code.replace(RE_DTS_SOURCE_MAPPING_URL, '\n'); + } + } + } + } + ]; +} diff --git a/packages/client/tsdown.config.ts b/packages/client/tsdown.config.ts index 45e0d7a28e..90f4b5c8bf 100644 --- a/packages/client/tsdown.config.ts +++ b/packages/client/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: [ @@ -20,6 +22,11 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', resolve: ['ajv', 'ajv-formats', 'json-schema-typed'], compilerOptions: { @@ -37,5 +44,7 @@ export default defineConfig({ // The schema modules live in @modelcontextprotocol/core (a real runtime dependency); the // bundled core-internal shims import them via the './internal' subpath, which must stay an // external import (explicit entry — the tsconfig paths alias would otherwise inline it). - external: ['@modelcontextprotocol/client/_shims', '@modelcontextprotocol/core/internal'] + external: ['@modelcontextprotocol/client/_shims', '@modelcontextprotocol/core/internal'], + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/codemod/tsdown.config.ts b/packages/codemod/tsdown.config.ts index 44976b8256..d20cb8640f 100644 --- a/packages/codemod/tsdown.config.ts +++ b/packages/codemod/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: ['src/cli.ts', 'src/index.ts'], @@ -12,6 +14,13 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc' - } + }, + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/core/tsdown.config.ts b/packages/core/tsdown.config.ts index e947feab67..bbd5e74ab2 100644 --- a/packages/core/tsdown.config.ts +++ b/packages/core/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + // core owns the schema source modules (src/schemas.ts, src/auth.ts, src/constants.ts) and builds // two entries from them: // - src/index.ts → the curated public surface (spec + OAuth `*Schema` constants only) @@ -17,6 +19,13 @@ export default defineConfig({ target: 'esnext', platform: 'neutral', dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc' - } + }, + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/middleware/express/tsdown.config.ts b/packages/middleware/express/tsdown.config.ts index 5fb5f7b39b..4a8b48d584 100644 --- a/packages/middleware/express/tsdown.config.ts +++ b/packages/middleware/express/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: ['src/index.ts'], @@ -12,6 +14,11 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', // Keep workspace deps as external imports in the bundled .d.ts instead of // inlining their type graph — see ../node/tsdown.config.ts for the rationale. @@ -19,5 +26,7 @@ export default defineConfig({ paths: {}, preserveSymlinks: true } - } + }, + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/middleware/fastify/tsdown.config.ts b/packages/middleware/fastify/tsdown.config.ts index 5fb5f7b39b..4a8b48d584 100644 --- a/packages/middleware/fastify/tsdown.config.ts +++ b/packages/middleware/fastify/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: ['src/index.ts'], @@ -12,6 +14,11 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', // Keep workspace deps as external imports in the bundled .d.ts instead of // inlining their type graph — see ../node/tsdown.config.ts for the rationale. @@ -19,5 +26,7 @@ export default defineConfig({ paths: {}, preserveSymlinks: true } - } + }, + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/middleware/hono/tsdown.config.ts b/packages/middleware/hono/tsdown.config.ts index 5fb5f7b39b..4a8b48d584 100644 --- a/packages/middleware/hono/tsdown.config.ts +++ b/packages/middleware/hono/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: ['src/index.ts'], @@ -12,6 +14,11 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', // Keep workspace deps as external imports in the bundled .d.ts instead of // inlining their type graph — see ../node/tsdown.config.ts for the rationale. @@ -19,5 +26,7 @@ export default defineConfig({ paths: {}, preserveSymlinks: true } - } + }, + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/middleware/node/tsdown.config.ts b/packages/middleware/node/tsdown.config.ts index 2af784601f..8f68afe55d 100644 --- a/packages/middleware/node/tsdown.config.ts +++ b/packages/middleware/node/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', // 1. Entry Points @@ -21,6 +23,11 @@ export default defineConfig({ // 4. Type Definitions // Bundles d.ts files into a single output dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', // The dev tsconfig.json maps @modelcontextprotocol/* to workspace source via // `paths` so typecheck/IDE work without a prior build. For declaration emit we @@ -40,5 +47,7 @@ export default defineConfig({ paths: {}, preserveSymlinks: true } - } + }, + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/server-legacy/tsdown.config.ts b/packages/server-legacy/tsdown.config.ts index 3e2f0ced3d..2aee5e7f3f 100644 --- a/packages/server-legacy/tsdown.config.ts +++ b/packages/server-legacy/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: ['src/index.ts', 'src/sse/index.ts', 'src/auth/index.ts'], @@ -12,6 +14,11 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', compilerOptions: { baseUrl: '.', @@ -25,5 +32,7 @@ export default defineConfig({ // The schema modules live in @modelcontextprotocol/core (a real runtime dependency); the // bundled core-internal shims import them via the './internal' subpath, which must stay an // external import (explicit entry — the tsconfig paths alias would otherwise inline it). - external: ['@modelcontextprotocol/core/internal'] + external: ['@modelcontextprotocol/core/internal'], + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl }); diff --git a/packages/server/tsdown.config.ts b/packages/server/tsdown.config.ts index 88004cfc06..b8352ab943 100644 --- a/packages/server/tsdown.config.ts +++ b/packages/server/tsdown.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'tsdown'; +import { stripDtsSourceMappingUrl } from '../../common/tsdown/stripDtsSourceMappingUrl.mjs'; + export default defineConfig({ failOnWarn: 'ci-only', entry: [ @@ -20,6 +22,11 @@ export default defineConfig({ platform: 'node', shims: true, dts: { + // Declaration maps would reference src/ (and, where bundled, the private + // core-internal's src/), which is not shipped ("files": ["dist"]); tsc cannot + // embed sourcesContent into .d.ts maps, so the shipped maps could never resolve + // on a consumer's machine. Don't emit them (#2233). + sourcemap: false, resolver: 'tsc', resolve: ['ajv', 'ajv-formats', 'json-schema-typed'], compilerOptions: { @@ -37,5 +44,7 @@ export default defineConfig({ // The schema modules live in @modelcontextprotocol/core (a real runtime dependency); the // bundled core-internal shims import them via the './internal' subpath, which must stay an // external import (explicit entry — the tsconfig paths alias would otherwise inline it). - external: ['@modelcontextprotocol/server/_shims', '@modelcontextprotocol/core/internal'] + external: ['@modelcontextprotocol/server/_shims', '@modelcontextprotocol/core/internal'], + // Drop the dangling sourceMappingURL comment rolldown leaves on the (map-less) declaration output. + inputOptions: stripDtsSourceMappingUrl });