Skip to content

v2 alpha: @modelcontextprotocol/server has @cfworker/json-schema as optional peer but imports it unconditionally #2093

@thkim-us

Description

@thkim-us

Summary

In @modelcontextprotocol/server@2.0.0-alpha.2, @cfworker/json-schema is declared as an optional peer dependency, but it is imported unconditionally at module-init time. Any consumer that doesn't install @cfworker/json-schema gets ERR_MODULE_NOT_FOUND the moment they import { McpServer } — even if they only use Standard Schema (Zod) inputs and never touch the JSON-Schema validator.

Repro

mkdir repro && cd repro
npm init -y
npm pkg set type=module
npm install @modelcontextprotocol/server@2.0.0-alpha.2
echo 'import { McpServer } from "@modelcontextprotocol/server"; new McpServer({ name: "x", version: "0" });' > index.mjs
node index.mjs

Result:

Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@cfworker/json-schema' imported from .../node_modules/@modelcontextprotocol/server/dist/src-IKPjmxu7.mjs

@cfworker/json-schema is not installed (it's peerDependenciesMeta.optional: true), and yet the failing import is at line 2 of the chunk:

// node_modules/@modelcontextprotocol/server/dist/src-IKPjmxu7.mjs:2
import { Validator } from "@cfworker/json-schema";

Why this is a bug

The peer is declared optional precisely because Standard Schema users (Zod / ArkType / Valibot) shouldn't need it — only fromJsonSchema() / CfWorkerJsonSchemaValidator consumers do. But because the import is at the top of a bundled chunk that's pulled in by McpServer itself, the optionality is unenforceable: every consumer must install it.

This effectively makes @cfworker/json-schema a hard dependency. The peerDependenciesMeta declaration is misleading.

Suggestions

  1. Lazy import — load @cfworker/json-schema only inside CfWorkerJsonSchemaValidator / fromJsonSchema() via dynamic import(). The validator is only constructed at user request, not at SDK init.
  2. Move to a sub-export — e.g. @modelcontextprotocol/server/cfworker, importable only by users who opt in.
  3. Promote to a hard dependency — if lazy loading is rejected, drop the optional flag and make it a regular dep so npm install @modelcontextprotocol/server always works.

Option 1 preserves the original intent of the optional peer.

Environment

  • Node v25.8.1
  • @modelcontextprotocol/server@2.0.0-alpha.2
  • npm v11.x

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions