MCP 2026 Spec: JSON Schema 2020-12 Migration Guide for TypeScript Developers
The MCP 2026 RC introduces two breaking JSON changes: JSON Schema upgraded to draft 2020-12 and error code -32002 changed to -32602. Fix your MCP server before the July 28 cutover.
Have broken JSON right now? Fix it free in under 1 second — no signup.
Fix My JSON →The Model Context Protocol 2026 Release Candidate introduces two breaking changes that affect any MCP server or client using JSON Schema validation. If your MCP tools, prompts, or resources define schemas — and virtually all of them do — you need to act before the July 28, 2026 stable release.
This guide covers exactly what changed, how to detect affected schemas, and how to migrate safely.
What Changed in MCP 2026
Breaking Change 1: JSON Schema upgraded to draft 2020-12
MCP 2025.x used JSON Schema draft-07. The MCP 2026 RC upgrades the wire format to JSON Schema 2020-12 (also called draft/2020-12).
The practical consequences depend on which keywords you use:
| Feature | Draft-07 | 2020-12 | Impact |
|---|---|---|---|
$recursiveRef | Supported | Removed — use $dynamicRef | BREAKING |
$recursiveAnchor | Supported | Removed — use $dynamicAnchor | BREAKING |
definitions | Standard | Replaced by $defs | BREAKING (07 used definitions) |
items for array schemas | Single schema applies to all | Split into items (positional) + prefixItems | BREAKING |
additionalItems | Controlled extra array items | Removed — use items (the new meaning) | BREAKING |
unevaluatedProperties | Not supported | Fully supported | New capability |
unevaluatedItems | Not supported | Fully supported | New capability |
Boolean schemas in if/then/else | Supported | Supported | No change |
definitions (draft-07 style) instead of $defs, or schemas generated by zod-to-json-schema with an older version that targets draft-07.
Breaking Change 2: Error code -32002 changed to -32602
JSON-RPC error code -32002 (previously used for "Invalid params" in some MCP contexts) has been remapped to -32602 to align with the official JSON-RPC 2.0 spec.
If your client code checks for -32002 to detect parameter validation failures, it will miss errors after the MCP 2026 update.
Are You Affected?
Check 1: Your JSON Schema $schema declaration
Open any schema you define in MCP tools, prompts, or resources. If you see:
{
"$schema": "http://json-schema.org/draft-07/schema#"
}
You're on draft-07. You need to migrate or verify compatibility.
If you see no $schema field, MCP will now interpret your schema as 2020-12. This can silently change behavior if you use any of the breaking keywords above.
Check 2: definitions vs $defs
Search your MCP server codebase for "definitions":
grep -r '"definitions"' src/
Any hit that lives inside a JSON Schema object needs to be renamed to "$defs".
Check 3: Zod version and zod-to-json-schema target
The MCP TypeScript SDK (as of @modelcontextprotocol/sdk v1.x) now uses Standard Schema — you can bring Zod v4, Valibot, or ArkType. Under the hood, schemas are serialized as JSON Schema 2020-12 on the wire.
If you're using zod-to-json-schema, verify it targets 2020-12:
import { zodToJsonSchema } from 'zod-to-json-schema'
import { z } from 'zod'
const schema = z.object({
name: z.string(),
count: z.number().int(),
})
// Explicit target — DO this:
const jsonSchema = zodToJsonSchema(schema, { target: 'jsonSchema2020-12' })
If you omit target, the library defaults to draft-07, which the 2026 MCP spec will no longer expect.
Check 4: Error code handling
Search your client code for the old error code:
grep -r '\-32002\|32002' src/
Update any conditional that checks for -32002 to use -32602.
Migration Walkthrough
Step 1: Update $defs (was definitions)
Before (draft-07):
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"address": { "$ref": "#/definitions/Address" }
},
"definitions": {
"Address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
}
}
}
}
After (2020-12):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"address": { "$ref": "#/$defs/Address" }
},
"$defs": {
"Address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
}
}
}
}
Note: the $ref path also changed from #/definitions/ to #/$defs/.
Step 2: Replace $recursiveRef with $dynamicRef
Before:
{
"$recursiveAnchor": true,
"type": "object",
"properties": {
"children": {
"type": "array",
"items": { "$recursiveRef": "#" }
}
}
}
After:
{
"$dynamicAnchor": "node",
"type": "object",
"properties": {
"children": {
"type": "array",
"items": { "$dynamicRef": "#node" }
}
}
}
Step 3: Fix additionalItems → items (new meaning)
In draft-07, items applied to all array elements and additionalItems handled extras after a tuple. In 2020-12, the tuple role moved to prefixItems, and items now handles the "additional" role.
{
"type": "array",
"items": [
{ "type": "string" },
{ "type": "number" }
],
"additionalItems": false
}
After (2020-12):
{
"type": "array",
"prefixItems": [
{ "type": "string" },
{ "type": "number" }
],
"items": false
}
Step 4: Update error handling
// Before
if (error.code === -32002) {
console.error('Parameter validation failed')
}
// After
if (error.code === -32602) {
console.error('Parameter validation failed')
}
Step 5: Update $schema declarations
Change all:
"$schema": "http://json-schema.org/draft-07/schema#"
To:
"$schema": "https://json-schema.org/draft/2020-12/schema"
Validate Your Schemas After Migration
After migrating, validate each schema using the AI JSONMedic JSON repair tool to catch structural errors (missing commas, unclosed brackets, bad $ref paths) before they hit the MCP runtime.
For deep JSON Schema validation — checking that your schema itself is a valid JSON Schema 2020-12 document — use the JSON Schema validator. It will flag unknown keywords, invalid $ref targets, and structural issues.
Quick validation script
# Install ajv-cli with 2020-12 support
npm install -g ajv-cli ajv-formats
Validate your schema against the 2020-12 meta-schema
ajv validate \
-s node_modules/ajv/dist/refs/json-schema-2020-12/schema.json \
-d your-mcp-tool-schema.json \
--spec=draft2020
TypeScript MCP Server Template (2020-12 Compatible)
Here's a minimal MCP tool definition that's fully compatible with the 2026 spec:
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { z } from 'zod'
const server = new McpServer({ name: 'my-server', version: '1.0.0' })
// Zod v4 schema — Standard Schema compatible
// The MCP SDK serializes this as JSON Schema 2020-12 on the wire
const repairInputSchema = z.object({
json_string: z.string().describe('Broken JSON string to repair'),
strict: z.boolean().optional().default(false).describe(
'If true, raise an error on ambiguous constructs instead of guessing'
),
})
server.tool(
'repair_json',
'Repairs malformed JSON strings from LLM output',
repairInputSchema.shape,
async ({ json_string, strict }) => {
// Your repair logic here
return {
content: [{ type: 'text', text: JSON.stringify({ repaired: true }) }],
}
}
)
The SDK handles the draft-07 → 2020-12 serialization automatically when you use Zod v4 via Standard Schema. You only need to manually migrate schemas you've written as raw JSON Schema objects.
Dual-Version Support (Bridge Period)
If you need to support both MCP 2025.x clients (draft-07) and MCP 2026 clients (2020-12) during the bridge period before July 28:
function getSchemaForVersion(mcpVersion: string) {
const is2026 = mcpVersion.startsWith('2026')
return {
$schema: is2026
? 'https://json-schema.org/draft/2020-12/schema'
: 'http://json-schema.org/draft-07/schema#',
type: 'object',
properties: {
name: { type: 'string' },
},
// Use $defs in 2026, definitions in 2025
...(is2026
? { $defs: { Config: { type: 'object' } } }
: { definitions: { Config: { type: 'object' } } }),
}
}
Timeline
| Date | Event |
|---|---|
| Now | MCP 2026 RC available — migration window open |
| June 15 | Claude Sonnet 4 + Opus 4 API retire — JSON output behavior shifts with new model |
| July 28 | MCP 2026 stable release — 2020-12 is canonical, older schemas may behave differently |
| Post July 28 | Clients expecting 2020-12 keywords will fail against unmigrated servers |
Common Migration Errors (and How to Fix Them)
Error: $ref "#/definitions/Foo" not found
Your schema still uses definitions but the validator is running under 2020-12 rules. Rename definitions to $defs and update all $ref paths from #/definitions/ to #/$defs/.
Paste the broken schema into the JSON repair tool to fix structural issues first, then check the $ref paths manually.
Error: unknown keyword: additionalItems
You're using a draft-07 tuple schema. Replace items: [...] with prefixItems: [...] and rename additionalItems to items.
Error: unknown keyword: $recursiveRef
Replace with $dynamicRef and add $dynamicAnchor on the referenced schema. See the migration example above.
Error code -32002 not caught
Update your error handling to check for -32602 instead.
Frequently Asked Questions
Does the MCP TypeScript SDK handle 2020-12 migration automatically?
Partially. If you define schemas using Zod v4 (Standard Schema), the SDK serializes them as 2020-12. If you write raw JSON Schema objects, you're responsible for the migration.
Will my draft-07 schemas silently break or loudly fail?
It depends on which keywords you use. Schemas that only use universal keywords (type, properties, required, enum, format) work in both drafts. Schemas using definitions, $recursiveRef, additionalItems, or tuple-style items will silently return wrong results or throw validation errors.
Does zod-to-json-schema need to be updated?
Yes — add { target: 'jsonSchema2020-12' } to your zodToJsonSchema() calls. Default is still draft-07 in most versions.
What about Pydantic / Python MCP servers?
pydantic-to-json-schema (used by FastMCP and similar frameworks) targets draft-07 by default. Add schema_mode='serialization' and check the Pydantic v2 docs for json_schema_mode to control the output dialect. Expect FastMCP updates before July 28.
Where do I paste schemas to check for structural errors?
Use the AI JSONMedic JSON repair tool for structural repairs (missing commas, unclosed brackets, bad escaping). Use the JSON Schema validator for semantic validation of the schema itself.
Is JSON Schema 2020-12 backward compatible with draft-07?
For most schemas, yes. The breaking keywords (definitions, $recursiveRef, tuple items, additionalItems) are the minority. If you only use type, properties, required, enum, const, anyOf, oneOf, allOf, and not, your schema works in both drafts.
Summary
The MCP 2026 RC has two breaking JSON changes:
- JSON Schema: draft-07 → 2020-12 — rename
definitions→$defs, update$refpaths, replace$recursiveRef→$dynamicRef, fix tuple schemas - Error code: -32002 → -32602 — update client-side error handling
The migration is mechanical. Run the grep checks above, apply the changes, validate with ajv-cli --spec=draft2020, and test against the MCP 2026 RC SDK before July 28.
For related MCP JSON errors, see the MCP JSON Schema Validation Errors guide and the JSON Schema validation guide.
Still dealing with broken JSON?
Paste it in and get it fixed in under 1 second — free, no signup, no install. Works with ChatGPT, Claude, n8n, and any AI output.
Fix My JSON Free →Related Articles