Skip to content

Commit b1ea30f

Browse files
committed
feat(client,server): re-expose validator classes via explicit subpaths
Restore the public entry points for the built-in JSON Schema validator classes via symmetric subpaths so consumers can customize the bundled backends without having to reimplement the entire 'jsonSchemaValidator' interface: - @modelcontextprotocol/{client,server}/validators/ajv exports AjvJsonSchemaValidator (was unreachable since #2088) - @modelcontextprotocol/{client,server}/validators/cf-worker exports CfWorkerJsonSchemaValidator (was reachable on main, removed by #2088; restored here) The named classes are intentionally NOT re-exported from the root barrel (@modelcontextprotocol/server / @modelcontextprotocol/client). Re-exporting either as a runtime value would pull the corresponding peer dep ('ajv' or '@cfworker/json-schema') into every consumer's root index chunk, defeating the purpose of the runtime shim's pay-only-for-what-you-use default. Consumers who never customize get the validator transparently via the shim; consumers who customize import from the subpath and install the peer dep themselves. The shim continues to bundle 'ajv' + 'ajv-formats' (Node) and '@cfworker/json-schema' (workerd/browser) via tsdown noExternal so the default code path remains zero-install. The barrel-clean regression tests are tightened to match top-of-line bare imports only, so JSDoc examples that reference 'from "ajv"' inside vendored chunks do not trigger false positives. The migration docs and changesets are rewritten to document the new customization path.
1 parent 088dfd3 commit b1ea30f

22 files changed

Lines changed: 175 additions & 114 deletions

File tree

.changeset/cfworker-out-of-barrel.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@
33
'@modelcontextprotocol/client': patch
44
---
55

6-
Stop bundling `@cfworker/json-schema` into the main package barrel. Previously `CfWorkerJsonSchemaValidator` was re-exported from the core internal barrel, so tsdown inlined the `@cfworker/json-schema` dev dependency into every consumer's bundle even when it was never used. The validator is now reachable only via the `_shims` conditional (workerd/browser), so consumers that don't opt into it no longer ship that code. The interim `@modelcontextprotocol/{server,client}/validators/cf-worker` subpath this introduced has been removed in a follow-up — the runtime shim is now the only entry point.
6+
Stop bundling `@cfworker/json-schema` into the main package barrel. Previously `CfWorkerJsonSchemaValidator` was re-exported from the core internal barrel, so tsdown inlined the `@cfworker/json-schema` dependency into every consumer's bundle even when it was never used. The named validator classes are now reachable only via the explicit `@modelcontextprotocol/{client,server}/validators/{ajv,cf-worker}` subpaths and the runtime `_shims` conditional, so consumers that import only from the root entry point no longer ship the validator dep.

.changeset/workerd-shim-vendors-cfworker.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66

77
Bundle automatic JSON Schema validator defaults in `@modelcontextprotocol/client` and `@modelcontextprotocol/server` runtime shims.
88

9-
Client/server select defaults automatically based on the runtime: Node shims use AJV, while browser/workerd shims use `@cfworker/json-schema`. Those backends are bundled into the shim chunks that select them, so consumers do not need to install validator packages or import explicit validators for default behavior. Advanced users can still pass their own `jsonSchemaValidator` interface implementation.
9+
Client and server pick the right validator automatically based on the runtime: the Node shim uses AJV, the browser/workerd shim uses `@cfworker/json-schema`. Both backends are bundled into the shim chunks that select them, so the default code path needs no extra installs — `import { McpServer } from '@modelcontextprotocol/server'` does not pull `ajv` or `@cfworker/json-schema` into the root entry chunk.
1010

11-
The `@modelcontextprotocol/{client,server}/validators/cf-worker` subpath export has been removed — there is no longer any public entry point for the SDK's built-in validator classes. `AjvJsonSchemaValidator` and `CfWorkerJsonSchemaValidator` are now `@internal` and no longer exported from `@modelcontextprotocol/client` or `@modelcontextprotocol/server` (not even as types). The `jsonSchemaValidator` interface remains the public extension point for custom validators, and example JSDoc snippets no longer demonstrate direct validator instantiation.
11+
The named validator classes remain part of the public surface for consumers who want to customize the built-in backend (pre-register schemas by `$id`, register custom AJV formats, switch dialects, change `@cfworker/json-schema` draft). They are exposed through explicit subpaths so they do not bloat the root index chunk:
12+
13+
- `import { AjvJsonSchemaValidator } from '@modelcontextprotocol/{client,server}/validators/ajv'`
14+
- `import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/{client,server}/validators/cf-worker'`
15+
16+
Importing from one of these subpaths means the corresponding peer dep (`ajv` + `ajv-formats`, or `@cfworker/json-schema`) must be in your `package.json`. The shim keeps its own vendored copy for the default path, so a project can use the subpath in some files and rely on the default in others.
17+
18+
The `jsonSchemaValidator` interface remains the public extension point for replacing validation entirely with a custom implementation.

docs/migration-SKILL.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,9 +530,9 @@ new McpServer({ name: 'server', version: '1.0.0' }, {});
530530
Validator behavior:
531531

532532
- Do not add validator imports for normal migrations.
533-
- Do not install `ajv`, `ajv-formats`, or `@cfworker/json-schema`; client/server bundle the runtime-selected defaults.
534-
- The SDK's built-in validator classes (`AjvJsonSchemaValidator`, `CfWorkerJsonSchemaValidator`) are not exported from `@modelcontextprotocol/{client,server}` (not even as types). The `@modelcontextprotocol/{client,server}/validators/cf-worker` subpath that existed in v2 pre-releases has been removed.
535-
- Advanced users may pass `jsonSchemaValidator: myCustomValidator` with their own implementation of the `jsonSchemaValidator` interface.
533+
- Do not install `ajv`, `ajv-formats`, or `@cfworker/json-schema` for the default path; client/server bundle the runtime-selected defaults and the root entry point does not pull either dep in.
534+
- To customize the built-in backend (e.g. register custom AJV formats, change `@cfworker/json-schema` draft), import the named class from the package subpath: `@modelcontextprotocol/{client,server}/validators/ajv` for `AjvJsonSchemaValidator`, `@modelcontextprotocol/{client,server}/validators/cf-worker` for `CfWorkerJsonSchemaValidator`. Importing from a subpath means the corresponding peer dep must be in your `package.json`.
535+
- To replace validation entirely, pass `jsonSchemaValidator: myCustomValidator` with your own implementation of the `jsonSchemaValidator` interface.
536536

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

docs/migration.md

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -933,21 +933,44 @@ const server = new McpServer(
933933
);
934934
```
935935

936-
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.
936+
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, so a normal `import { McpServer } from '@modelcontextprotocol/server'` does not pull `ajv` or `@cfworker/json-schema` into your bundle until you choose to customize.
937937

938-
Advanced users can still override validation by passing an object that implements the SDK's JSON Schema validator interface:
938+
If you want to customize the **built-in** backend (for example, pre-register schemas by `$id`, register custom AJV formats, or change the `@cfworker/json-schema` draft), import the named class from the explicit subpath and pass an instance through `jsonSchemaValidator`:
939939

940940
```typescript
941+
import { Ajv } from 'ajv';
942+
import addFormats from 'ajv-formats';
943+
import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server/validators/ajv';
944+
945+
const ajv = new Ajv({ strict: true, allErrors: true });
946+
addFormats(ajv);
947+
948+
const server = new McpServer(
949+
{ name: 'my-server', version: '1.0.0' },
950+
{
951+
capabilities: { tools: {} },
952+
jsonSchemaValidator: new AjvJsonSchemaValidator(ajv)
953+
}
954+
);
955+
```
956+
957+
```typescript
958+
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker';
959+
941960
const server = new McpServer(
942961
{ name: 'my-server', version: '1.0.0' },
943962
{
944963
capabilities: { tools: {} },
945-
jsonSchemaValidator: myCustomValidator
964+
jsonSchemaValidator: new CfWorkerJsonSchemaValidator({ draft: '2020-12', shortcircuit: false })
946965
}
947966
);
948967
```
949968

950-
The SDK's built-in validator classes (`AjvJsonSchemaValidator`, `CfWorkerJsonSchemaValidator`) are not part of the public surface — `@modelcontextprotocol/{client,server}` no longer export them as runtime values or types, and the `@modelcontextprotocol/{client,server}/validators/cf-worker` subpath that briefly existed in v2 pre-releases has been removed. To customise validation, implement the `jsonSchemaValidator` interface yourself and pass your implementation through the option above.
969+
(both subpaths are also available on `@modelcontextprotocol/client/validators/...`)
970+
971+
If you import from one of these subpaths in your own code, the corresponding peer dep (`ajv` + `ajv-formats`, or `@cfworker/json-schema`) needs to be installed in your `package.json`. The runtime shim continues to vendor a copy for the default code path, so you can use the subpath in some files and rely on the default in others.
972+
973+
To replace validation wholesale rather than customizing the built-in classes, implement the `jsonSchemaValidator` interface and pass your own implementation through the option above.
951974

952975
## Unchanged APIs
953976

packages/client/package.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@
2828
"types": "./dist/stdio.d.mts",
2929
"import": "./dist/stdio.mjs"
3030
},
31+
"./validators/ajv": {
32+
"types": "./dist/validators/ajv.d.mts",
33+
"import": "./dist/validators/ajv.mjs"
34+
},
35+
"./validators/cf-worker": {
36+
"types": "./dist/validators/cfWorker.d.mts",
37+
"import": "./dist/validators/cfWorker.mjs"
38+
},
3139
"./_shims": {
3240
"workerd": {
3341
"types": "./dist/shimsWorkerd.d.mts",
@@ -50,6 +58,12 @@
5058
"types": "./dist/index.d.mts",
5159
"typesVersions": {
5260
"*": {
61+
"validators/ajv": [
62+
"dist/validators/ajv.d.mts"
63+
],
64+
"validators/cf-worker": [
65+
"dist/validators/cfWorker.d.mts"
66+
],
5367
"stdio": [
5468
"dist/stdio.d.mts"
5569
]
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/**
2+
* Customisation entry point for the AJV validator. Re-exports `Ajv` + `addFormats` from the
3+
* SDK's bundled copy, so customising the validator needs no extra installs.
4+
*
5+
* @example
6+
* ```ts
7+
* import { Ajv, addFormats, AjvJsonSchemaValidator } from '@modelcontextprotocol/client/validators/ajv';
8+
*
9+
* const ajv = new Ajv({ strict: true, allErrors: true });
10+
* addFormats(ajv);
11+
* const validator = new AjvJsonSchemaValidator(ajv);
12+
* ```
13+
*/
14+
export { addFormats, Ajv, AjvJsonSchemaValidator } from '@modelcontextprotocol/core/validators/ajv';
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/** Customisation entry point for the `@cfworker/json-schema` validator. */
2+
export type { CfWorkerSchemaDraft } from '@modelcontextprotocol/core/validators/cfWorker';
3+
export { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/core/validators/cfWorker';

packages/client/test/client/barrelClean.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { beforeAll, describe, expect, test } from 'vitest';
88
const pkgDir = join(dirname(fileURLToPath(import.meta.url)), '../..');
99
const distDir = join(pkgDir, 'dist');
1010
const NODE_ONLY = /\b(child_process|cross-spawn|node:stream|node:child_process)\b/;
11-
const VALIDATOR_BACKEND_IMPORT = /from\s+["'](?:ajv|ajv-formats|@cfworker\/json-schema)["']/;
11+
// Anchored at start-of-line so JSDoc-example `from 'ajv'` strings in vendored chunks don't match.
12+
const VALIDATOR_BACKEND_IMPORT = /^import[^\n]*?from\s+["'](?:ajv|ajv-formats|@cfworker\/json-schema)["']/m;
1213

1314
function chunkImportsOf(entryPath: string): string[] {
1415
const visited = new Set<string>();

packages/client/tsdown.config.ts

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,25 @@ import { defineConfig } from 'tsdown';
22

33
export default defineConfig({
44
failOnWarn: 'ci-only',
5-
// 1. Entry Points
6-
// Directly matches package.json include/exclude globs
7-
entry: ['src/index.ts', 'src/stdio.ts', 'src/shimsNode.ts', 'src/shimsWorkerd.ts', 'src/shimsBrowser.ts'],
8-
9-
// 2. Output Configuration
5+
entry: [
6+
'src/index.ts',
7+
'src/stdio.ts',
8+
'src/shimsNode.ts',
9+
'src/shimsWorkerd.ts',
10+
'src/shimsBrowser.ts',
11+
'src/validators/ajv.ts',
12+
'src/validators/cfWorker.ts'
13+
],
1014
format: ['esm'],
1115
outDir: 'dist',
12-
clean: true, // Recommended: Cleans 'dist' before building
16+
clean: true,
1317
sourcemap: true,
14-
15-
// 3. Platform & Target
1618
target: 'esnext',
1719
platform: 'node',
18-
shims: true, // Polyfills common Node.js shims (__dirname, etc.)
19-
20-
// 4. Type Definitions
21-
// Bundles d.ts files into a single output
20+
shims: true,
2221
dts: {
2322
resolver: 'tsc',
24-
// override just for DTS generation:
23+
resolve: ['ajv', 'ajv-formats'],
2524
compilerOptions: {
2625
baseUrl: '.',
2726
paths: {
@@ -32,15 +31,6 @@ export default defineConfig({
3231
}
3332
}
3433
},
35-
// 5. Vendoring Strategy - Bundle this package's core implementation into the output,
36-
// but treat most dependencies as external (require/import).
37-
//
38-
// The runtime `_shims` entries choose default JSON Schema validators: AJV on Node and
39-
// @cfworker/json-schema on workerd/browser. Client users should not have to install a
40-
// validator backend just to use the runtime default, so bundle the default backends into
41-
// the shim chunks that select them.
4234
noExternal: ['@modelcontextprotocol/core', 'ajv', 'ajv-formats', '@cfworker/json-schema'],
43-
44-
// 6. External packages - keep self-reference imports external for runtime resolution
4535
external: ['@modelcontextprotocol/client/_shims']
4636
});

packages/core/src/exports/public/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,10 @@ export { InMemoryTaskMessageQueue, InMemoryTaskStore } from '../../experimental/
142142
export type { SpecTypeName, SpecTypes } from '../../types/specTypeSchema.js';
143143
export { isSpecType, specTypeSchemas } from '../../types/specTypeSchema.js';
144144
export type { StandardSchemaV1, StandardSchemaV1Sync, StandardSchemaWithJSON } from '../../util/standardSchema.js';
145-
// Concrete validator providers (AjvJsonSchemaValidator, CfWorkerJsonSchemaValidator) are
146-
// intentionally NOT exported: client/server bundle them via the runtime shim and end users
147-
// cannot reach them. To override validation, implement the `jsonSchemaValidator` interface.
145+
// Validator providers are type-only here — import the runtime classes from the explicit
146+
// `@modelcontextprotocol/{client,server}/validators/{ajv,cf-worker}` subpaths to customise.
147+
export type { AjvJsonSchemaValidator } from '../../validators/ajvProvider.js';
148+
export type { CfWorkerJsonSchemaValidator, CfWorkerSchemaDraft } from '../../validators/cfWorkerProvider.js';
148149
// fromJsonSchema is intentionally NOT exported here — the server and client packages
149150
// provide runtime-aware wrappers that default to the appropriate validator via _shims.
150151
export type { JsonSchemaType, JsonSchemaValidator, jsonSchemaValidator, JsonSchemaValidatorResult } from '../../validators/types.js';

0 commit comments

Comments
 (0)