Skip to content
Open
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
11 changes: 11 additions & 0 deletions .changeset/workerd-shim-vendors-cfworker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
'@modelcontextprotocol/core': minor
'@modelcontextprotocol/client': patch
'@modelcontextprotocol/server': patch
---

Make validator backends symmetrical in core and bundle automatic defaults in client/server runtime shims.

Core no longer re-exports concrete validator providers as runtime values from the root/public barrels. AJV/AJV formats and `@cfworker/json-schema` are optional peer backends behind explicit core validator provider subpaths, used internally by client/server shims.

Client/server continue to select defaults automatically: Node shims use AJV, while browser/workerd shims use `@cfworker/json-schema`. Those backends are bundled into the shim chunks that select them, so users do not need to install validator packages or import explicit validators for default behavior. Advanced users can still pass their own `jsonSchemaValidator` implementation.

Check warning on line 11 in .changeset/workerd-shim-vendors-cfworker.md

View check run for this annotation

Claude / Claude Code Review

Changeset omits removal of ./validators/cf-worker public subpath

nit: this changeset describes the core barrel change and the shim bundling, but never says that the `./validators/cf-worker` subpath export was *removed* from `@modelcontextprotocol/{client,server}` — line 11's "do not need to … import explicit validators" reads as a convenience, not a removal. Worth one explicit sentence here, especially since the open comment on `packages/server/package.json:31` suggests deleting `.changeset/cfworker-out-of-barrel.md`, which would leave this as the only change
Comment on lines +7 to +11
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 nit: this changeset describes the core barrel change and the shim bundling, but never says that the ./validators/cf-worker subpath export was removed from @modelcontextprotocol/{client,server} — line 11's "do not need to … import explicit validators" reads as a convenience, not a removal. Worth one explicit sentence here, especially since the open comment on packages/server/package.json:31 suggests deleting .changeset/cfworker-out-of-barrel.md, which would leave this as the only changeset covering the subpath and the removal entirely undocumented in the generated CHANGELOG.

Extended reasoning...

What the issue is

This PR removes a public subpath export from two published packages: ./validators/cf-worker is deleted from the exports and typesVersions maps in packages/{client,server}/package.json, both src/validators/cfWorker.ts re-export files are deleted, and the entry is dropped from both tsdown.config.ts arrays. The previously-documented pattern import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker' now resolves to ERR_PACKAGE_PATH_NOT_EXPORTED.

The PR's own changeset, .changeset/workerd-shim-vendors-cfworker.md, describes two things: (a) core no longer re-exporting concrete validator providers as runtime values from its barrels, and (b) client/server bundling default backends into their shim chunks. Line 11 says "users do not need to install validator packages or import explicit validators for default behavior" — but that frames explicit imports as no longer necessary, not as no longer possible. Nowhere does the changeset state that the ./validators/cf-worker subpath was removed from client/server.

Why this isn't covered by existing comments

The still-open inline comment on packages/server/package.json:31 is about other prose that still references the removed subpath (.changeset/cfworker-out-of-barrel.md, ajvProvider.ts:36's @see, .changeset/support-standard-json-schema.md). This finding is the inverse: the PR's own new changeset fails to announce the removal it introduces.

The two interact: that open comment's first suggested fix is "delete cfworker-out-of-barrel.md (its purpose is subsumed by workerd-shim-vendors-cfworker.md)". If the author follows that suggestion as-is, workerd-shim-vendors-cfworker.md becomes the only changeset touching this area — and it doesn't mention the subpath removal, so the generated CHANGELOG would contain no record that @modelcontextprotocol/{client,server}/validators/cf-worker ever went away.

The resolved comment on exports/public/index.ts:145 did raise the patch-vs-breaking concern, but for the earlier export type change. The author's resolution expanded the breaking surface (it removed the subpath entirely instead of adding a parallel one) without revisiting the changeset prose. The bump-level concern itself is muted by 2.0.0-alpha.2 pre-release status, so the actionable residue is just the missing prose.

Step-by-step proof

  1. A consumer on @modelcontextprotocol/server@2.0.0-alpha.2 has import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker' — the exact pattern the pre-PR docs/migration.md and docs/migration-SKILL.md documented.
  2. They upgrade to the next alpha containing this PR. packages/server/package.json no longer has "./validators/cf-worker" in exports; Node throws ERR_PACKAGE_PATH_NOT_EXPORTED.
  3. They open the generated packages/server/CHANGELOG.md for that version. The entry from workerd-shim-vendors-cfworker.md reads: "Client/server continue to select defaults automatically … users do not need to install validator packages or import explicit validators for default behavior. Advanced users can still pass their own jsonSchemaValidator implementation."
  4. Nothing in that text says the subpath was removed. The consumer has to infer the API removal from a sentence about defaults, or grep the diff.
  5. If .changeset/cfworker-out-of-barrel.md is also deleted per the open comment's suggestion, there is no CHANGELOG entry mentioning /validators/cf-worker at all.

Impact

Doc-only; no runtime effect. The PR description and updated migration guides do call this out ("Public surface: explicit concrete validator subpaths are removed from client/server"), so the gap is specifically in the changeset → CHANGELOG path. Filed as a nit given the alpha pre-release context and that three related doc nits are already open — but it's a one-line addition while the changeset is being touched anyway.

How to fix

Add one sentence to .changeset/workerd-shim-vendors-cfworker.md, e.g. after line 11:

The explicit ./validators/cf-worker subpath export has been removed from @modelcontextprotocol/client and @modelcontextprotocol/server; rely on automatic runtime selection or pass a custom jsonSchemaValidator.

(If .changeset/cfworker-out-of-barrel.md is kept and rewritten per the other open comment instead of deleted, that would also cover it — either location works as long as one changeset states the removal.)

8 changes: 4 additions & 4 deletions docs/migration-SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,11 +518,11 @@ new McpServer(
new McpServer({ name: 'server', version: '1.0.0' }, {});
```

Access validators explicitly:
Validator behavior:

- Runtime-aware default: `import { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims';`
- AJV (Node.js): `import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server';`
- CF Worker: `import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker';`
- Do not add validator imports for normal migrations.
- Do not install `ajv`, `ajv-formats`, or `@cfworker/json-schema`; client/server bundle the runtime-selected defaults.
- Advanced users may pass `jsonSchemaValidator: myCustomValidator` with their own validator implementation.

## 15. Migration Steps (apply in this order)

Expand Down
17 changes: 10 additions & 7 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -932,15 +932,18 @@ const server = new McpServer(
);
```

You can still explicitly override the validator if needed:
You do not need to install or import validator packages for the default behavior. The client and server packages bundle the validator backend selected by the runtime shim.

```typescript
// Runtime-aware default (auto-selects AjvJsonSchemaValidator or CfWorkerJsonSchemaValidator)
import { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims';
Advanced users can still override validation by passing an object that implements the SDK's JSON Schema validator interface:

// Specific validators
import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server';
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker';
```typescript
const server = new McpServer(
{ name: 'my-server', version: '1.0.0' },
{
capabilities: { tools: {} },
jsonSchemaValidator: myCustomValidator
}
);
```

## Unchanged APIs
Expand Down
9 changes: 2 additions & 7 deletions packages/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@
"types": "./dist/stdio.d.mts",
"import": "./dist/stdio.mjs"
},
"./validators/cf-worker": {
"types": "./dist/validators/cfWorker.d.mts",
"import": "./dist/validators/cfWorker.mjs"
},
"./_shims": {
"workerd": {
"types": "./dist/shimsWorkerd.d.mts",
Expand All @@ -54,9 +50,6 @@
"types": "./dist/index.d.mts",
"typesVersions": {
"*": {
"validators/cf-worker": [
"dist/validators/cfWorker.d.mts"
],
"stdio": [
"dist/stdio.d.mts"
]
Expand Down Expand Up @@ -93,6 +86,8 @@
"@modelcontextprotocol/eslint-config": "workspace:^",
"@modelcontextprotocol/test-helpers": "workspace:^",
"@cfworker/json-schema": "catalog:runtimeShared",
"ajv": "catalog:runtimeShared",
"ajv-formats": "catalog:runtimeShared",
"@types/content-type": "catalog:devTools",
"@types/cross-spawn": "catalog:devTools",
"@types/eventsource": "catalog:devTools",
Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export type ClientOptions = ProtocolOptions & {
* The validator is used to validate structured content returned by tools
* against their declared output schemas.
*
* @default {@linkcode DefaultJsonSchemaValidator} ({@linkcode index.AjvJsonSchemaValidator | AjvJsonSchemaValidator} on Node.js, `CfWorkerJsonSchemaValidator` on Cloudflare Workers)
* @default Runtime-selected validator (`AjvJsonSchemaValidator` on Node.js, `CfWorkerJsonSchemaValidator` on browser/workerd runtimes)
*/
jsonSchemaValidator?: jsonSchemaValidator;

Expand Down
2 changes: 1 addition & 1 deletion packages/client/src/shimsNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* This file is selected via package.json export conditions when running in Node.js.
*/
export { AjvJsonSchemaValidator as DefaultJsonSchemaValidator } from '@modelcontextprotocol/core';
export { AjvJsonSchemaValidator as DefaultJsonSchemaValidator } from '@modelcontextprotocol/core/validators/ajv';

/**
* Whether `fetch()` may throw `TypeError` due to CORS. CORS is a browser-only concept —
Expand Down
10 changes: 0 additions & 10 deletions packages/client/src/validators/cfWorker.ts

This file was deleted.

14 changes: 14 additions & 0 deletions packages/client/test/client/barrelClean.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { beforeAll, describe, expect, test } from 'vitest';
const pkgDir = join(dirname(fileURLToPath(import.meta.url)), '../..');
const distDir = join(pkgDir, 'dist');
const NODE_ONLY = /\b(child_process|cross-spawn|node:stream|node:child_process)\b/;
const VALIDATOR_BACKEND_IMPORT = /from\s+["'](?:ajv|ajv-formats|@cfworker\/json-schema)["']/;

function chunkImportsOf(entryPath: string): string[] {
const visited = new Set<string>();
Expand Down Expand Up @@ -52,4 +53,17 @@ describe('@modelcontextprotocol/client root entry is browser-safe', () => {
expect(stdio).toMatch(/\bgetDefaultEnvironment\b/);
expect(stdio).toMatch(/\bDEFAULT_INHERITED_ENV_VARS\b/);
});

test('runtime shims vendor default validator backends instead of requiring consumers to install them', () => {
for (const shim of ['shimsNode.mjs', 'shimsWorkerd.mjs', 'shimsBrowser.mjs']) {
const entry = join(distDir, shim);
expect(readFileSync(entry, 'utf8')).not.toMatch(VALIDATOR_BACKEND_IMPORT);

for (const chunk of chunkImportsOf(entry)) {
expect({ chunk, content: readFileSync(chunk, 'utf8') }).not.toEqual(
expect.objectContaining({ content: expect.stringMatching(VALIDATOR_BACKEND_IMPORT) })
);
}
}
});
});
110 changes: 110 additions & 0 deletions packages/client/test/client/jsonSchemaValidatorOverride.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import type { JSONRPCMessage, JsonSchemaType, JsonSchemaValidatorResult, jsonSchemaValidator } from '@modelcontextprotocol/core';
import { InMemoryTransport, LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/core';
import { Client } from '../../src/client/client.js';
import { fromJsonSchema } from '../../src/fromJsonSchema.js';

class RecordingValidator implements jsonSchemaValidator {
schemas: JsonSchemaType[] = [];
values: unknown[] = [];

getValidator<T>(schema: JsonSchemaType) {
this.schemas.push(schema);
return (value: unknown): JsonSchemaValidatorResult<T> => {
this.values.push(value);
return { valid: true, data: value as T, errorMessage: undefined };
};
}
}

async function connectInitializedClient(client: Client) {
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
serverTransport.onmessage = async message => {
if ('method' in message && 'id' in message && message.method === 'initialize') {
await serverTransport.send({
jsonrpc: '2.0',
id: message.id,
result: {
protocolVersion: LATEST_PROTOCOL_VERSION,
capabilities: { tools: {} },
serverInfo: { name: 'test-server', version: '1.0.0' }
}
});
} else if ('method' in message && 'id' in message && message.method === 'tools/list') {
await serverTransport.send({
jsonrpc: '2.0',
id: message.id,
result: {
tools: [
{
name: 'structured-tool',
description: 'A tool with structured output',
inputSchema: { type: 'object' },
outputSchema: {
type: 'object',
properties: { count: { type: 'number' } },
required: ['count']
}
}
]
}
} satisfies JSONRPCMessage);
}
};

await Promise.all([client.connect(clientTransport), serverTransport.start()]);
return { clientTransport, serverTransport };
}

describe('client JSON Schema validator overrides', () => {
test('Client constructor uses a custom validator for tool output schema caching', async () => {
const validator = new RecordingValidator();
const client = new Client(
{ name: 'test-client', version: '1.0.0' },
{
capabilities: {},
jsonSchemaValidator: validator
}
);
const { clientTransport, serverTransport } = await connectInitializedClient(client);

await expect(client.listTools()).resolves.toMatchObject({
tools: [
{
name: 'structured-tool',
outputSchema: {
type: 'object',
properties: { count: { type: 'number' } },
required: ['count']
}
}
]
});

expect(validator.schemas).toEqual([
{
type: 'object',
properties: { count: { type: 'number' } },
required: ['count']
}
]);

await client.close();
await clientTransport.close();
await serverTransport.close();
});

test('fromJsonSchema uses an explicitly supplied custom validator', async () => {
const validator = new RecordingValidator();
const schema: JsonSchemaType = {
type: 'object',
properties: { name: { type: 'string' } },
required: ['name']
};

const standardSchema = fromJsonSchema<{ name: string }>(schema, validator);
expect(standardSchema['~standard'].validate({ name: 123 })).toEqual({ value: { name: 123 } });

expect(validator.schemas).toEqual([schema]);
expect(validator.values).toEqual([{ name: 123 }]);
});
});
1 change: 1 addition & 0 deletions packages/client/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"*": ["./*"],
"@modelcontextprotocol/core": ["./node_modules/@modelcontextprotocol/core/src/index.ts"],
"@modelcontextprotocol/core/public": ["./node_modules/@modelcontextprotocol/core/src/exports/public/index.ts"],
"@modelcontextprotocol/core/validators/ajv": ["./node_modules/@modelcontextprotocol/core/src/validators/ajvProvider.ts"],
"@modelcontextprotocol/core/validators/cfWorker": [
"./node_modules/@modelcontextprotocol/core/src/validators/cfWorkerProvider.ts"
],
Expand Down
14 changes: 10 additions & 4 deletions packages/client/tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export default defineConfig({
failOnWarn: 'ci-only',
// 1. Entry Points
// Directly matches package.json include/exclude globs
entry: ['src/index.ts', 'src/stdio.ts', 'src/shimsNode.ts', 'src/shimsWorkerd.ts', 'src/shimsBrowser.ts', 'src/validators/cfWorker.ts'],
entry: ['src/index.ts', 'src/stdio.ts', 'src/shimsNode.ts', 'src/shimsWorkerd.ts', 'src/shimsBrowser.ts'],

// 2. Output Configuration
format: ['esm'],
Expand All @@ -27,13 +27,19 @@ export default defineConfig({
paths: {
'@modelcontextprotocol/core': ['../core/src/index.ts'],
'@modelcontextprotocol/core/public': ['../core/src/exports/public/index.ts'],
'@modelcontextprotocol/core/validators/ajv': ['../core/src/validators/ajvProvider.ts'],
'@modelcontextprotocol/core/validators/cfWorker': ['../core/src/validators/cfWorkerProvider.ts']
}
}
},
// 5. Vendoring Strategy - Bundle the code for this specific package into the output,
// but treat all other dependencies as external (require/import).
noExternal: ['@modelcontextprotocol/core'],
// 5. Vendoring Strategy - Bundle this package's core implementation into the output,
// but treat most dependencies as external (require/import).
//
// The runtime `_shims` entries choose default JSON Schema validators: AJV on Node and
// @cfworker/json-schema on workerd/browser. Client users should not have to install a
// validator backend just to use the runtime default, so bundle the default backends into
// the shim chunks that select them.
noExternal: ['@modelcontextprotocol/core', 'ajv', 'ajv-formats', '@cfworker/json-schema'],

// 6. External packages - keep self-reference imports external for runtime resolution
external: ['@modelcontextprotocol/client/_shims']
Expand Down
16 changes: 14 additions & 2 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
"types": "./src/exports/public/index.ts",
"import": "./src/exports/public/index.ts"
},
"./validators/ajv": {
"types": "./src/validators/ajvProvider.ts",
"import": "./src/validators/ajvProvider.ts"
},
"./validators/cfWorker": {
"types": "./src/validators/cfWorkerProvider.ts",
"import": "./src/validators/cfWorkerProvider.ts"
Expand All @@ -49,19 +53,25 @@
"client": "tsx scripts/cli.ts client"
},
"dependencies": {
"ajv": "catalog:runtimeShared",
"ajv-formats": "catalog:runtimeShared",
"json-schema-typed": "catalog:runtimeShared",
"zod": "catalog:runtimeShared"
},
"peerDependencies": {
"@cfworker/json-schema": "catalog:runtimeShared",
"ajv": "catalog:runtimeShared",
"ajv-formats": "catalog:runtimeShared",
"zod": "catalog:runtimeShared"
},
"peerDependenciesMeta": {
"@cfworker/json-schema": {
"optional": true
},
"ajv": {
"optional": true
},
"ajv-formats": {
"optional": true
},
"zod": {
"optional": false
}
Expand All @@ -71,6 +81,8 @@
"@modelcontextprotocol/vitest-config": "workspace:^",
"@modelcontextprotocol/eslint-config": "workspace:^",
"@cfworker/json-schema": "catalog:runtimeShared",
"ajv": "catalog:runtimeShared",
"ajv-formats": "catalog:runtimeShared",
"@eslint/js": "catalog:devTools",
"@types/content-type": "catalog:devTools",
"@types/cors": "catalog:devTools",
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/exports/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@ export { InMemoryTaskMessageQueue, InMemoryTaskStore } from '../../experimental/
export type { SpecTypeName, SpecTypes } from '../../types/specTypeSchema.js';
export { isSpecType, specTypeSchemas } from '../../types/specTypeSchema.js';
export type { StandardSchemaV1, StandardSchemaWithJSON } from '../../util/standardSchema.js';
export { AjvJsonSchemaValidator } from '../../validators/ajvProvider.js';
export type { CfWorkerSchemaDraft } from '../../validators/cfWorkerProvider.js';
export type { AjvJsonSchemaValidator } from '../../validators/ajvProvider.js';
export type { CfWorkerJsonSchemaValidator, CfWorkerSchemaDraft } from '../../validators/cfWorkerProvider.js';
// 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.js';
23 changes: 13 additions & 10 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,28 @@ export * from './util/zodCompat.js';

// experimental exports
export * from './experimental/index.js';
export * from './validators/ajvProvider.js';
// cfWorkerProvider is intentionally NOT re-exported here: it statically imports
// `@cfworker/json-schema` (an optional peer), and bundling it into the main barrel
// would force that import on all Node consumers. Import via `@modelcontextprotocol/core/validators/cfWorker`
// (used by the workerd/browser `_shims` and the public `/validators/cf-worker` subpaths).
export type { CfWorkerSchemaDraft } from './validators/cfWorkerProvider.js';
export type { AjvJsonSchemaValidator } from './validators/ajvProvider.js';
// Validator providers are intentionally NOT re-exported as runtime values here: AJV
// and @cfworker/json-schema are optional peers, and importing either provider from
// the root barrel would force that backend on all consumers. Internal runtime shims
// import concrete defaults via explicit core validator subpaths.
export type { CfWorkerJsonSchemaValidator, CfWorkerSchemaDraft } from './validators/cfWorkerProvider.js';
export * from './validators/fromJsonSchema.js';
/**
* JSON Schema validation
*
* This module provides configurable JSON Schema validation for the MCP SDK.
* Choose a validator based on your runtime environment:
*
* - {@linkcode AjvJsonSchemaValidator}: Best for Node.js (default, fastest)
* Bundled — no additional dependencies required.
* - `AjvJsonSchemaValidator`: Best for Node.js (default, fastest)
* Used automatically by client/server Node shims.
*
* - `CfWorkerJsonSchemaValidator`: Best for edge runtimes
* Import from: `@modelcontextprotocol/server/validators/cf-worker` or `@modelcontextprotocol/client/validators/cf-worker`
* Bundled — no additional dependencies required.
* Used automatically by client/server browser/workerd shims.
*
* Client and server packages bundle their runtime default validator backends, so most users should
* rely on automatic runtime selection. Advanced users can pass their own validator implementation
* through client/server options.
*
* @example For Node.js with AJV
* ```ts source="./index.examples.ts#validation_ajv"
Comment on lines +41 to 46
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 nit: the prose update here stops one line short — the two @example blocks immediately below (lines 45-53, sourced from index.examples.ts#validation_ajv / #validation_cfWorker) still render new AjvJsonSchemaValidator() / new CfWorkerJsonSchemaValidator(), which now directly contradicts the rewritten paragraph saying to rely on automatic selection or pass a custom jsonSchemaValidator. This is separate from the three sites in the open comment on packages/server/package.json:31 (the suggested validators/cf-worker grep won't find these); easiest fix is to drop both @example blocks and the corresponding regions in index.examples.ts, or rewrite them to show { jsonSchemaValidator: myCustomValidator }.

Extended reasoning...

What the issue is

This PR's hunk for packages/core/src/index.ts rewrites the @module validation JSDoc: lines 22/27 demote AjvJsonSchemaValidator and CfWorkerJsonSchemaValidator to export type, and lines 35-43 replace the old "Import from: …/validators/cf-worker" guidance with new prose saying "Client and server packages bundle their runtime default validator backends, so most users should rely on automatic runtime selection. Advanced users can pass their own validator implementation through client/server options." The diff hunk's last context line is @example For Node.js with AJV — i.e. the edit stops exactly at the example boundary.

Lines 45-53, immediately below, are unchanged and still render:

// @example For Node.js with AJV
const validator = new AjvJsonSchemaValidator();
// @example For Cloudflare Workers
const validator = new CfWorkerJsonSchemaValidator();

Both snippets are sourced from packages/core/src/index.examples.ts (#validation_ajv at lines 16-21, #validation_cfWorker at lines 26-31), which still imports the concrete classes from ./validators/{ajv,cfWorker}Provider.js. So the examples file still compiles — this is purely a rendered-doc contradiction, not a build break.

Why it matters / why existing checks don't catch it

After this PR, both validator classes are type-only in both core barrels (src/index.ts:22,27 and src/exports/public/index.ts:144-145), and the published ./validators/cf-worker subpaths are removed from client and server. There is no published runtime path a reader could use to do new AjvJsonSchemaValidator() — yet the very JSDoc block this PR edits still demonstrates exactly that, two lines below prose telling them not to. Because index.examples.ts imports via internal relative paths, neither tsc nor the barrelClean tests flag the staleness.

Not a duplicate of the open comments

  • The still-open inline comment on packages/server/package.json:31 enumerates three other stale-prose sites (.changeset/cfworker-out-of-barrel.md, ajvProvider.ts:36, .changeset/support-standard-json-schema.md) and suggests grepping for validators/cf-worker. These @example blocks contain neither that string nor any import path, so that grep would not find them.
  • The resolved inline comment on exports/public/index.ts:145 did name "the JSDoc in packages/core/src/index.ts" — and the author updated the prose paragraph in response, but stopped before the adjacent @example snippets. This is the leftover half of that fix.

Step-by-step proof

  1. Open the rendered @module validation JSDoc (or just read packages/core/src/index.ts:30-53 after this PR).
  2. Lines 41-43 say: "most users should rely on automatic runtime selection. Advanced users can pass their own validator implementation through client/server options."
  3. Line 45 (@example For Node.js with AJV) renders const validator = new AjvJsonSchemaValidator();.
  4. AjvJsonSchemaValidator is export type on line 22 of this same file and on line 144 of exports/public/index.ts; the /validators/ajv and /validators/cf-worker subpaths are gone from packages/{client,server}/package.json. A reader following the example has no published constructor to call.
  5. Line 50 repeats the same for CfWorkerJsonSchemaValidator.
  6. The same JSDoc block therefore tells readers "don't instantiate concrete validators" and then shows them doing so — an internal contradiction introduced by this PR's prose rewrite.

Impact

Doc-only. @modelcontextprotocol/core is private: true and this is the internal root barrel's @module-level comment, so end-user exposure is limited (it's unclear it even surfaces in published .d.mts). But it's an inconsistency within the very block this PR edits, cheap to fold into the same cleanup pass that addresses the open packages/server/package.json:31 comment — hence nit.

How to fix

Either:

  • Delete the two @example blocks (lines 45-53) and the corresponding validation_ajv / validation_cfWorker regions in packages/core/src/index.examples.ts; or
  • Rewrite them to demonstrate the override pattern the new prose teaches, e.g. new McpServer(info, { jsonSchemaValidator: myCustomValidator }), mirroring the updated docs/migration.md snippet.

Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/validators/ajvProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function createDefaultAjvInstance(): Ajv {
* const validator = new AjvJsonSchemaValidator(ajv);
* ```
*
* @see `CfWorkerJsonSchemaValidator` for an edge-runtime-compatible alternative (import from `@modelcontextprotocol/server/validators/cf-worker` or `@modelcontextprotocol/client/validators/cf-worker`)
* @see `CfWorkerJsonSchemaValidator` for the edge-runtime-compatible validator selected automatically by client/server browser/workerd shims.
*/
export class AjvJsonSchemaValidator implements jsonSchemaValidator {
private _ajv: Ajv;
Expand Down
Loading
Loading