Skip to content
This repository was archived by the owner on Jun 28, 2026. It is now read-only.

fix(mcp): register custom tools with a Zod input schema#243

Open
valentingoulier wants to merge 1 commit into
primefaces:mainfrom
valentingoulier:fix/mcp-custom-tools-zod-schema
Open

fix(mcp): register custom tools with a Zod input schema#243
valentingoulier wants to merge 1 commit into
primefaces:mainfrom
valentingoulier:fix/mcp-custom-tools-zod-schema

Conversation

@valentingoulier

Copy link
Copy Markdown

Problem

@primeng/mcp (which depends on @primeuix/mcp) crashes on startup:

Failed to start PrimeNG MCP Server: Error: Tool get_migration_guide expected a Zod schema or ToolAnnotations, but received an unrecognized object
    at McpServer.tool (.../@modelcontextprotocol/sdk/dist/esm/server/mcp.js)
    at .../@primeuix/mcp/dist/index.js

Reproduced with @modelcontextprotocol/sdk 1.29.0. Because @primeuix/mcp declares "@modelcontextprotocol/sdk": "^1.25.2", fresh/npx installs resolve the latest 1.x and hit the crash.

Root cause

registerCustomTools (packages/mcp/src/index.ts) registers framework-specific tools through the legacy server.tool(name, description, paramsObject, cb) overload, passing a plain object:

const params = { version: { type: 'string', description: '...' }, /* ... */ };
server.tool(tool.name, tool.description, params, handler);

As of @modelcontextprotocol/sdk 1.26, McpServer.tool() validates that third argument: it must be a Zod raw shape or ToolAnnotations. A { type, description } object is neither (its values are objects), so the SDK throws "expected a Zod schema or ToolAnnotations, but received an unrecognized object". PrimeNG's get_migration_guide is the first custom tool registered, so that's where the crash surfaces.

Every other tool in this package already uses server.registerTool(name, { description, inputSchema }, cb) with a Zod shape — only registerCustomTools still used the old path.

Fix

Translate the lightweight { type, description, required?, default? } parameter format into a Zod raw shape and register via registerTool, consistent with the rest of the package:

  • maps typez.string() / z.number() / z.boolean() / z.array(...) / z.record(...)
  • a parameter is .optional() unless required: true
  • honors default

Verification

  • Reproduced the exact crash on main with SDK 1.29.0.
  • After the fix, createPrimeMcpServer registers the custom tools without throwing on both SDK 1.29.0 and 1.25.2 (the declared floor).
  • tsup build (ESM + dts type-check) passes; Prettier clean against the repo config.

🤖 Generated with Claude Code

`registerCustomTools` passed a plain `{ type, description }` object as the
tool input schema through the legacy `server.tool()` API. Since
@modelcontextprotocol/sdk 1.26 the SDK validates that argument and throws
`Tool <name> expected a Zod schema or ToolAnnotations, but received an
unrecognized object`, crashing the server on startup — `@primeng/mcp` is
the first to hit it because `get_migration_guide` is a custom tool.

Translate the lightweight `{ type, description, required?, default? }`
parameter format into a Zod raw shape and register through `registerTool`,
consistent with every other tool in this package. Honors `required`/
`default` and works on both the pinned SDK (1.25.x) and current (1.29.x).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 17, 2026 22:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Fixes a startup crash in @primeuix/mcp when used with newer @modelcontextprotocol/sdk versions by registering framework-specific custom tools using a Zod input schema (matching the SDK’s post-1.26 validation rules and the rest of this package’s tool registrations).

Changes:

  • Added Zod import and a small mapper (customParameterSchema) to translate custom parameter type strings into Zod schemas.
  • Updated registerCustomTools to build a z.ZodRawShape from the lightweight { type, description, required?, default? } parameter format.
  • Switched custom tool registration from the legacy server.tool(...) overload to server.registerTool(...) with { description, inputSchema }.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@breadgrocery

Copy link
Copy Markdown

#228
I’m using primevue-mcp like this 😂:

{
  "command": "npx",
  "args": [
    "-y",
    "-p",
    "@primevue/mcp@4.5.5",
    "-p",
    "@modelcontextprotocol/sdk@1.27.1",
    "primevue-mcp"
  ]
}

It looks like @modelcontextprotocol/sdk >= 1.28.0 introduces API incompatibilities, so pinning @modelcontextprotocol/sdk@1.27.1 works around the issue for now.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants