Conversation
|
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
| ``` | ||
|
|
||
| You can still explicitly override the validator if needed. The validators are available via the `_shims` export: | ||
| You can still explicitly override the validator if needed: | ||
|
|
||
| ```typescript | ||
| // Runtime-aware default (auto-selects AjvJsonSchemaValidator or CfWorkerJsonSchemaValidator) | ||
| import { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims'; | ||
| // or | ||
| import { AjvJsonSchemaValidator, CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server'; | ||
|
|
||
| // Specific validators | ||
| import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server'; | ||
| import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker'; |
There was a problem hiding this comment.
🟡 The migration docs (both docs/migration.md and docs/migration-SKILL.md) document explicit validator import paths only for @modelcontextprotocol/server, omitting the equivalent paths for @modelcontextprotocol/client. A client-only user who wants to explicitly override CfWorkerJsonSchemaValidator needs @modelcontextprotocol/client/validators/cf-worker (not the server equivalent), which this PR adds but the docs do not mention. Adding client package examples to Section 14 of both docs would make the guide complete.
Extended reasoning...
What the bug is and how it manifests
Section 14 of both docs/migration.md (lines 860–870) and docs/migration-SKILL.md (lines 484–486) was updated by this PR to document explicit validator import paths. However, every example references only the @modelcontextprotocol/server family:
import { DefaultJsonSchemaValidator } from '@modelcontextprotocol/server/_shims';
import { AjvJsonSchemaValidator } from '@modelcontextprotocol/server';
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker';The client package has identical sub-path exports added by this same PR: packages/client/package.json now exports ./validators/cf-worker and ./_shims, and packages/client/src/validators/cfWorker.ts exists as the corresponding entry file. Neither doc mentions @modelcontextprotocol/client/validators/cf-worker or @modelcontextprotocol/client/_shims.
The specific code path that triggers it
A developer using only @modelcontextprotocol/client (no server package) reads the migration guide to understand how to explicitly supply a jsonSchemaValidator to their Client instance. The ClientOptions.jsonSchemaValidator field is real and supported. They follow the import examples in Section 14, copy the server paths, and their bundler or runtime fails to resolve @modelcontextprotocol/server/validators/cf-worker because the server package is not installed.
Why existing code does not prevent it
There is no mechanism to keep migration-doc examples in sync with package.json exports. The PR author correctly added both server and client sub-path exports in code, but only updated the migration docs with server examples. The section uses McpServer in its primary example, making the server-centric framing natural, but the final explicit-override code block is generic enough to apply to both packages.
What the impact would be
This is a documentation-only gap with no runtime impact. The auto-selection behavior works correctly for both packages without any explicit import. The affected scenario is the niche explicit-override case (e.g., a CF Workers client-only user who needs to force CfWorkerJsonSchemaValidator). That user would see only server paths in the migration guide and either install an unneeded package or fail to find the correct import path. The migration-SKILL.md mechanical table is particularly affected: an LLM performing migration for a client-only project could incorrectly add @modelcontextprotocol/server as a dependency solely to import a validator class.
How to fix it
Extend the explicit-override example in both docs to mention both packages, e.g. add a note: "Replace server with client if using the client package only," or show both paths:
// For @modelcontextprotocol/server users:
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker';
// For @modelcontextprotocol/client users:
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/client/validators/cf-worker';Step-by-step proof
- Developer has only
@modelcontextprotocol/clientinstalled (CF Workers client-only project). - They need to explicitly pass
CfWorkerJsonSchemaValidatortonew Client({...}, { jsonSchemaValidator: ... }). - They consult
docs/migration.mdSection 14 for the correct import path. - The doc shows only
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/server/validators/cf-worker'. - They either run
npm install @modelcontextprotocol/serverunnecessarily, or copy the import and get a module-not-found error at runtime. - The correct path,
@modelcontextprotocol/client/validators/cf-worker, is never surfaced by the docs.
| * against their declared output schemas. | ||
| * | ||
| * @default {@linkcode DefaultJsonSchemaValidator} ({@linkcode index.AjvJsonSchemaValidator | AjvJsonSchemaValidator} on Node.js, {@linkcode index.CfWorkerJsonSchemaValidator | CfWorkerJsonSchemaValidator} on Cloudflare Workers) | ||
| * @default {@linkcode DefaultJsonSchemaValidator} ({@linkcode index.AjvJsonSchemaValidator | AjvJsonSchemaValidator} on Node.js, `CfWorkerJsonSchemaValidator` on Cloudflare Workers) |
There was a problem hiding this comment.
🟡 The @default JSDoc for jsonSchemaValidator in ClientOptions (client.ts:165) and ServerOptions (server.ts:87) mentions CfWorkerJsonSchemaValidator as the Cloudflare Workers default using a plain backtick with no import path, leaving developers with no way to find where to import it. Adding (import from @modelcontextprotocol/server/validators/cf-worker or @modelcontextprotocol/client/validators/cf-worker) to those lines would match the guidance already present in ajvProvider.ts.
Extended reasoning...
What the bug is and how it manifests
This PR correctly removed the broken {@linkcode index.CfWorkerJsonSchemaValidator} reference from the @default JSDoc in both packages/client/src/client/client.ts:165 and packages/server/src/server/server.ts:87, since CfWorkerJsonSchemaValidator is no longer exported from the main entry after this PR. However, the replacement is plain backtick without any import path hint, leaving developers unable to locate the class.
The specific code path that triggers it
A developer hovering over jsonSchemaValidator in their IDE will see: @default DefaultJsonSchemaValidator (AjvJsonSchemaValidator on Node.js, CfWorkerJsonSchemaValidator on Cloudflare Workers). There is no link, no import path, and no package name. Since CfWorkerJsonSchemaValidator is no longer exported from the main entry, searching the package exports yields nothing.
Why existing code does not prevent it
The @see comment added to AjvJsonSchemaValidator in ajvProvider.ts line 36 does include both import paths. However, that hint is only visible when hovering over AjvJsonSchemaValidator itself — not when reading the jsonSchemaValidator field documentation in ClientOptions/ServerOptions. Those are completely separate hover contexts in an IDE.
What the impact would be
This is purely a documentation quality issue with no runtime impact. The auto-selection behavior works correctly without any explicit import. Developers who want to explicitly pass CfWorkerJsonSchemaValidator see the class name but have no hint about where to find it after this PR removes it from the main entry.
How to fix it
Update both @default lines to append the import hint, for example:
@default DefaultJsonSchemaValidator (AjvJsonSchemaValidator on Node.js, CfWorkerJsonSchemaValidator on Cloudflare Workers — import from @modelcontextprotocol/server/validators/cf-worker or @modelcontextprotocol/client/validators/cf-worker)
Step-by-step proof
- Developer writes
new Client({ name: 'my-client', version: '1.0.0' }, { jsonSchemaValidator: ... })on a CF Workers project. - They hover over
jsonSchemaValidatorin their IDE to understand what to pass. - The tooltip shows
CfWorkerJsonSchemaValidator on Cloudflare Workerswith no import path. - They search for
CfWorkerJsonSchemaValidatorin@modelcontextprotocol/clientmain entry exports — it is not there (removed by this PR). - No import path, no
@seetag, no link — the developer must search GitHub or docs to find@modelcontextprotocol/client/validators/cf-worker. - The equivalent
@seenote onAjvJsonSchemaValidatorinajvProvider.tsdoes provide both paths, confirming the information exists and is just missing from the most visible location.
fix: bundle
@cfworker/json-schemainline and move to sub-path exportMotivation and Context
Consumers of
@modelcontextprotocol/serverand@modelcontextprotocol/clienton Node.js hit a runtime error when importing from the main entry:Root cause: tsdown bundles
@modelcontextprotocol/coreinto a single shared chunk. When it encounters@cfworker/json-schema, it checks the package'spackage.json— because it's listed inpeerDependencies, tsdown externalizes it (leaves a bareimport { Validator } from "@cfworker/json-schema"in the output). Meanwhile,ajvis NOT inpeerDependencies, so tsdown bundles it inline. This asymmetry means any import of the main entry eagerly triggers the cfworker import, which fails on Node.js where the optional peer dep isn't installed.Why this wasn't an issue in v1.x:
tsc(per-file transpilation), nottsdown(bundling) — the cfworker import stayed in its own isolated fileCfWorkerJsonSchemaValidatorfrom the main entry — it was only accessible via a dedicated sub-path (@modelcontextprotocol/sdk/validation/cfworker)The v2 monorepo restructuring inadvertently collapsed both of these safeguards.
How Has This Been Tested?
pnpm test:all)import from "@cfworker/json-schema"— the code is now bundled inline (same as ajv)Breaking Changes
CfWorkerJsonSchemaValidatoris no longer exported from the main entry of@modelcontextprotocol/serveror@modelcontextprotocol/client. It is now available via a dedicated sub-path:Most users are unaffected — the shims system (
shimsWorkerd.mjs) still automatically selectsCfWorkerJsonSchemaValidatoras the default validator on CF Workers/browser runtimes without any explicit import. Only users who were explicitly importing the class need to update.The
CfWorkerSchemaDrafttype remains available from the main entry (type-only exports have no runtime impact).Types of changes
Checklist
Additional context
Options considered
Remove from
peerDependencies(bundle inline like ajv) — Minimal change, consistent with ajv precedent, no API break. Increases shared chunk by ~38KB (dead code on Node.js). Doesn't address the v1.x regression where cfworker code was isolated behind a sub-path.Dynamic import with top-level
await+ try/catch — No bundle size increase, but top-levelawaitin the shared chunk makes it an async module, which can cause issues with downstream bundlers, test runners, and runtimes that don't fully support async module graphs.Separate sub-path export (restore v1.x pattern) — Matches v1.x design. Breaking change, but acceptable in alpha. Insufficient alone due to rolldown's shared chunk behavior (see below).
Both validators as separate sub-path exports — Move both
AjvJsonSchemaValidatorandCfWorkerJsonSchemaValidatorto sub-paths. More churn for no functional benefit since ajv is already working fine.Move to
dependencies(notpeerDependencies) — Forces all consumers to install@cfworker/json-schemaeven when they don't need it.Chosen: Option 1 + Option 3 combined (see rationale below).
Why two changes are needed, not one
Simply moving
CfWorkerJsonSchemaValidatorto a sub-path export is insufficient on its own. Rolldown merges all of@modelcontextprotocol/core's bundled code into a single shared chunk (because all entry points —index.ts,shimsNode.ts,shimsWorkerd.ts— import from core vianoExternal). Even after removing the re-export from the main entry, the shared chunk still contains the cfworker code (needed byshimsWorkerd.ts), and the bare external import remains at the top of that chunk — loaded by all entry points includingindex.mjs.The fix therefore combines two changes:
@cfworker/json-schemafrompeerDependencies— tsdown then bundles it inline (same treatmentajvalready gets). No bare external import → no runtime error. This increases the shared chunk size by ~38KB (the inlined cfworker code), which is dead code on Node.js — parsed but never executed.CfWorkerJsonSchemaValidatorto a sub-path export (./validators/cf-worker) — removes it from the main entry's public API, restoring the v1.x pattern where CF Workers-specific code is explicitly opt-in.Files changed
packages/core/src/exports/public/index.tsCfWorkerJsonSchemaValidatorvalue export (keptCfWorkerSchemaDrafttype)packages/server/package.jsonpeerDependencies/peerDependenciesMetafor cfworker; added./validators/cf-workerexportpackages/client/package.jsonpackages/server/tsdown.config.tssrc/validators/cfWorker.tsentry pointpackages/client/tsdown.config.tssrc/validators/cfWorker.tsentry pointpackages/server/src/validators/cfWorker.tspackages/client/src/validators/cfWorker.ts