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

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions