If you build an MCP server in TypeScript, the v2 SDK changed one small thing that ripples further than it looks: tool and prompt schemas now use Standard Schema. The beta announcement puts it plainly — "Tool and prompt schemas use Standard Schema, so you can bring Zod v4, Valibot, ArkType, or any compatible library." Zod is no longer wired in. It is now one option among several.
The short version: you are free to define a tool's inputSchema with whatever validator you like — but the decision that matters is not syntax taste. It is that MCP still advertises each tool's schema to clients as JSON Schema, and that JSON Schema is what the model reads to decide how to call your tool. So pick your validator on bundle size and how faithfully it emits JSON Schema, not on which chaining API feels nicer.
What actually changed#
In the v1 SDK, Zod was effectively the schema language. In v2, the server codes against Standard Schema — a shared interface, backed by the authors of Zod, Valibot, and ArkType, that lets any tool accept any of them without a per-library adapter. The tool-registration call is otherwise familiar:
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";
const server = new McpServer({ name: "weather", version: "1.0.0" });
server.registerTool(
"get_forecast",
{
description: "Forecast for a city, up to 7 days out",
inputSchema: z.object({ city: z.string(), days: z.number().max(7) }),
},
async ({ city, days }) => ({
content: [{ type: "text", text: `Forecast for ${city}, ${days} days.` }],
}),
);
Swap the import and the inputSchema value, and the same tool takes a Valibot schema instead:
import * as v from "valibot";
const inputSchema = v.object({
city: v.string(),
days: v.pipe(v.number(), v.maxValue(7)),
});
Or an ArkType schema, whose syntax reads like the TypeScript type it validates:
import { type } from "arktype";
const inputSchema = type({ city: "string", days: "number<=7" });
All three satisfy Standard Schema, so all three drop into registerTool() unchanged. If your codebase already standardized on Zod — as most do, and as our FastMCP vs the official SDK walkthrough assumed — you rewrite nothing. Zod v4 is a Standard Schema library; your existing objects keep working.
The catch nobody puts on the label#
Here is the part worth ten minutes. Standard Schema standardizes validation — it defines how a value gets checked at runtime through a ~standard property every library exposes. It does not define JSON Schema output. And MCP tools live and die by JSON Schema: the SDK publishes each tool's inputSchema as JSON Schema in tools/list, and that document is the entire contract the model sees. Get it wrong and the model calls your tool wrong, no matter how strict your runtime validation is.
So the real axis is: does your validator emit faithful JSON Schema, and how?
- Zod v4 ships native conversion via
z.toJSONSchema()— one of the headline v4 features, no companion package. - ArkType ships native
.toJsonSchema()out of the box. - Valibot keeps its core tiny by not bundling this; you add the
@valibot/to-json-schemacompanion package to convert.
None of these is disqualifying, but they are not interchangeable. A constraint that round-trips cleanly to JSON Schema in one library may degrade to a looser type in another, which quietly weakens the contract the model reads. Before you ship, dump the generated JSON Schema for one real tool and eyeball it — that is the artifact that reaches the LLM, not your TypeScript.
How to choose#
Standard Schema freed you from Zod. JSON Schema fidelity is what should decide where you land.
If your team already runs Zod, stay — v4's native JSON Schema export makes it the path of least resistance. If you are shipping to edge or serverless and every kilobyte counts, Valibot is the tree-shakeable pick; just budget for the @valibot/to-json-schema companion. If you want terse, TypeScript-shaped schemas and fast runtime validation, ArkType with native JSON Schema is a clean fit.
Whatever you pick, this is a v2 decision — the SDK is ESM-only and runs on Node 20+, Bun, and Deno, and it is still in beta (npm install @modelcontextprotocol/server@beta). If you are not ready for the beta, the stable SDK still ships a stateless server today on the Zod-based path. But once you move to v2, the validator is your call — so make it on the schema the model actually reads.



