From 23f03f0e4c4295b50fa3c8bd6fedcb219e53d97e Mon Sep 17 00:00:00 2001 From: Sehlani042 <257166922+Sehlani042@users.noreply.github.com> Date: Fri, 3 Jul 2026 02:44:44 +0800 Subject: [PATCH 1/3] fix: keep validator providers off root declarations --- packages/client/test/client/barrelClean.test.ts | 16 ++++++++++++++++ .../core-internal/src/exports/public/index.ts | 7 +++---- packages/core-internal/src/index.ts | 7 +++---- packages/server/test/server/barrelClean.test.ts | 16 ++++++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) diff --git a/packages/client/test/client/barrelClean.test.ts b/packages/client/test/client/barrelClean.test.ts index a0f716581e..a218c49a0c 100644 --- a/packages/client/test/client/barrelClean.test.ts +++ b/packages/client/test/client/barrelClean.test.ts @@ -12,6 +12,7 @@ const requireDist = createRequire(join(pkgDir, 'package.json')); const NODE_ONLY = /\b(child_process|cross-spawn|node:stream|node:child_process)\b/; // Anchored at start-of-line so JSDoc-example `from 'ajv'` strings in vendored chunks don't match. const VALIDATOR_BACKEND_IMPORT = /^import[^\n]*?from\s+["'](?:ajv|ajv-formats|@cfworker\/json-schema)["']/m; +const ROOT_VALIDATOR_EXPORTS = ['AjvJsonSchemaValidator', 'CfWorkerJsonSchemaValidator', 'CfWorkerSchemaDraft']; function chunkImportsOf(entryPath: string): string[] { const visited = new Set(); @@ -29,6 +30,12 @@ function chunkImportsOf(entryPath: string): string[] { return [...visited]; } +function rootExportBlockOf(content: string): string { + const blocks = content.match(/(?:^|\n)export \{[\s\S]*?\};/g); + expect(blocks).toBeTruthy(); + return blocks!.at(-1)!; +} + describe('@modelcontextprotocol/client root entry is browser-safe', () => { beforeAll(() => { if (!existsSync(join(distDir, 'index.mjs')) || !existsSync(join(distDir, 'stdio.mjs'))) { @@ -80,4 +87,13 @@ describe('@modelcontextprotocol/client root entry is browser-safe', () => { expect(new AjvJsonSchemaValidator(ajv)).toBeInstanceOf(AjvJsonSchemaValidator); }); + + test('root declarations do not advertise validator provider classes', () => { + for (const declaration of ['index.d.mts', 'index.d.cts']) { + const rootExportBlock = rootExportBlockOf(readFileSync(join(distDir, declaration), 'utf8')); + for (const symbol of ROOT_VALIDATOR_EXPORTS) { + expect(rootExportBlock).not.toMatch(new RegExp(`\\b(?:type\\s+)?${symbol}\\b`)); + } + } + }); }); diff --git a/packages/core-internal/src/exports/public/index.ts b/packages/core-internal/src/exports/public/index.ts index 3fd909d69d..0a50e00dd5 100644 --- a/packages/core-internal/src/exports/public/index.ts +++ b/packages/core-internal/src/exports/public/index.ts @@ -131,10 +131,9 @@ export { export type { SpecTypeName, SpecTypes } from '../../types/specTypeSchema'; export { isSpecType, specTypeSchemas } from '../../types/specTypeSchema'; export type { StandardSchemaV1, StandardSchemaV1Sync, StandardSchemaWithJSON } from '../../util/standardSchema'; -// Validator providers are type-only here — import the runtime classes from the explicit -// `@modelcontextprotocol/{client,server}/validators/{ajv,cf-worker}` subpaths to customise. -export type { AjvJsonSchemaValidator } from '../../validators/ajvProvider'; -export type { CfWorkerJsonSchemaValidator, CfWorkerSchemaDraft } from '../../validators/cfWorkerProvider'; +// Validator provider classes stay subpath-only. Re-exporting them here, even as +// `type`, can make generated root declarations advertise runtime-shaped root +// exports that the package root does not provide. // fromJsonSchema is intentionally NOT exported here — the server and client packages // provide runtime-aware wrappers that default to the appropriate validator via _shims. export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '../../validators/types'; diff --git a/packages/core-internal/src/index.ts b/packages/core-internal/src/index.ts index 50238566cf..7ea56117c7 100644 --- a/packages/core-internal/src/index.ts +++ b/packages/core-internal/src/index.ts @@ -33,9 +33,8 @@ export * from './util/standardSchema'; export * from './util/zodCompat'; export { codecForVersion, MODERN_WIRE_REVISION } from './wire/codec'; -// Validator providers are type-only here — import the runtime classes from the explicit -// `@modelcontextprotocol/{client,server}/validators/{ajv,cf-worker}` subpaths to customise. -export type { AjvJsonSchemaValidator } from './validators/ajvProvider'; -export type { CfWorkerJsonSchemaValidator, CfWorkerSchemaDraft } from './validators/cfWorkerProvider'; +// Validator provider classes stay subpath-only. Re-exporting them here, even as +// `type`, can make generated client/server root declarations advertise +// runtime-shaped root exports that the package root does not provide. export * from './validators/fromJsonSchema'; export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from './validators/types'; diff --git a/packages/server/test/server/barrelClean.test.ts b/packages/server/test/server/barrelClean.test.ts index 184a590d10..7b1e4898c7 100644 --- a/packages/server/test/server/barrelClean.test.ts +++ b/packages/server/test/server/barrelClean.test.ts @@ -12,6 +12,7 @@ const requireDist = createRequire(join(pkgDir, 'package.json')); const NODE_ONLY = /\b(child_process|cross-spawn|node:stream|node:child_process)\b/; // Anchored at start-of-line so JSDoc-example `from 'ajv'` strings in vendored chunks don't match. const VALIDATOR_BACKEND_IMPORT = /^import[^\n]*?from\s+["'](?:ajv|ajv-formats|@cfworker\/json-schema)["']/m; +const ROOT_VALIDATOR_EXPORTS = ['AjvJsonSchemaValidator', 'CfWorkerJsonSchemaValidator', 'CfWorkerSchemaDraft']; function chunkImportsOf(entryPath: string): string[] { const visited = new Set(); @@ -29,6 +30,12 @@ function chunkImportsOf(entryPath: string): string[] { return [...visited]; } +function rootExportBlockOf(content: string): string { + const blocks = content.match(/(?:^|\n)export \{[\s\S]*?\};/g); + expect(blocks).toBeTruthy(); + return blocks!.at(-1)!; +} + describe('@modelcontextprotocol/server root entry is browser-safe', () => { beforeAll(() => { if (!existsSync(join(distDir, 'index.mjs')) || !existsSync(join(distDir, 'stdio.mjs'))) { @@ -81,4 +88,13 @@ describe('@modelcontextprotocol/server root entry is browser-safe', () => { expect(new AjvJsonSchemaValidator(ajv)).toBeInstanceOf(AjvJsonSchemaValidator); }); + + test('root declarations do not advertise validator provider classes', () => { + for (const declaration of ['index.d.mts', 'index.d.cts']) { + const rootExportBlock = rootExportBlockOf(readFileSync(join(distDir, declaration), 'utf8')); + for (const symbol of ROOT_VALIDATOR_EXPORTS) { + expect(rootExportBlock).not.toMatch(new RegExp(`\\b(?:type\\s+)?${symbol}\\b`)); + } + } + }); }); From 57587570d1b8f635269cd4ffb11e653ef47f42c0 Mon Sep 17 00:00:00 2001 From: Sehlani042 <257166922+Sehlani042@users.noreply.github.com> Date: Fri, 3 Jul 2026 02:48:36 +0800 Subject: [PATCH 2/3] chore: add validator declarations changeset --- .changeset/silent-validators-wave.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/silent-validators-wave.md diff --git a/.changeset/silent-validators-wave.md b/.changeset/silent-validators-wave.md new file mode 100644 index 0000000000..7394c4c1ea --- /dev/null +++ b/.changeset/silent-validators-wave.md @@ -0,0 +1,6 @@ +--- +'@modelcontextprotocol/client': patch +'@modelcontextprotocol/server': patch +--- + +Stop advertising validator provider classes from the root client/server type declarations. The provider classes remain available from the explicit validator subpaths. From 412bddd23e94bff3ca8ff7e3061605dcb331c22d Mon Sep 17 00:00:00 2001 From: Sehlani042 <257166922+Sehlani042@users.noreply.github.com> Date: Fri, 3 Jul 2026 02:57:30 +0800 Subject: [PATCH 3/3] test: update dist type smoke for validator subpaths --- scripts/smoke-dist-types.mjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/smoke-dist-types.mjs b/scripts/smoke-dist-types.mjs index 16af6605f4..7effbb92cd 100644 --- a/scripts/smoke-dist-types.mjs +++ b/scripts/smoke-dist-types.mjs @@ -14,7 +14,7 @@ try { path.join(dir, 'consumer.ts'), [ "import { Client } from '@modelcontextprotocol/client';", - "import type { AjvJsonSchemaValidator as ClientAjv } from '@modelcontextprotocol/client';", + "import type { JsonSchemaType as ClientSchema } 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';", @@ -24,7 +24,7 @@ try { "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 type T = ClientSchema;', 'export { AjvJsonSchemaValidator, ServerAjv, ClientCf, ServerCf, StdioClientTransport, StdioServerTransport };', '' ].join('\n')