Advertise JSON Schema 2020-12 dialect on emitted tool schemas#342
Open
koic wants to merge 1 commit into
Open
Conversation
## Motivation and Context MCP 2025-11-25 (SEP-1613) establishes JSON Schema 2020-12 as the default dialect for MCP schema definitions. modelcontextprotocol/modelcontextprotocol#1613 The Ruby SDK was emitting tool input and output schemas with no `$schema` field, leaving the dialect implicit and inconsistent with the TypeScript SDK (`packages/core/src/util/standardSchema.ts`, which emits with `target: 'draft-2020-12'`) and the Python SDK (which preserves `$schema` in its types and conformance fixtures). `Tool::Schema#to_h` now includes `"$schema": "https://json-schema.org/draft/2020-12/schema"` unless the user supplied a different `$schema` value, so clients see the canonical dialect URI on the wire. Runtime metaschema and argument validation remain on draft-04 because the `json-schema` gem does not yet support 2020-12. Switching the runtime validator is left as a separate change because it requires either replacing the gem or waiting for upstream 2020-12 support. ## How Has This Been Tested? Updated `Tool::Schema#to_h` expectations across `input_schema_test`, `output_schema_test`, `tool_test`, and the `tools/list` server tests to reflect the new `$schema` field. Added focused regression tests: - `to_h` preserves a user-supplied `$schema` URI rather than overwriting it (covered for both symbol-keyed input and the string-keyed Hash form that goes through the initializer's `symbolize_names` normalization) - `validate_arguments` / `validate_result` continue to work when the user supplies a 2020-12 `$schema` URI on the schema (the validator strips the unknown top-level dialect URI before invoking the draft-04 validator, instead of raising `JSON::Schema::SchemaError`) - `tools/list` JSON-RPC response includes the 2020-12 `$schema` on both `inputSchema` and `outputSchema` (transport-boundary assertion) `bundle exec rake test` and `bundle exec rake rubocop` both pass. ## Breaking Changes Additive change. Tolerant consumers of the `tools/list` payload are unaffected. Consumers that strictly assert hash equality on the emitted `inputSchema` / `outputSchema` need to account for the new `$schema` key, but no schema semantics change. Schemas using 2020-12-only keywords (e.g. `prefixItems`, nested `$schema` on subschemas) are still rejected by the draft-04 metaschema validator, as before. Lifting that restriction depends on adopting a 2020-12-capable validator and is out of scope for this change.
atesgoral
approved these changes
May 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
MCP 2025-11-25 (SEP-1613) establishes JSON Schema 2020-12 as the default dialect for MCP schema definitions.
modelcontextprotocol/modelcontextprotocol#1613
The Ruby SDK was emitting tool input and output schemas with no
$schemafield, leaving the dialect implicit and inconsistent with the TypeScript SDK (packages/core/src/util/standardSchema.ts, which emits withtarget: 'draft-2020-12') and the Python SDK (which preserves$schemain its types and conformance fixtures).Tool::Schema#to_hnow includes"$schema": "https://json-schema.org/draft/2020-12/schema"unless the user supplied a different$schemavalue, so clients see the canonical dialect URI on the wire.Runtime metaschema and argument validation remain on draft-04 because the
json-schemagem does not yet support 2020-12. Switching the runtime validator is left as a separate change because it requires either replacing the gem or waiting for upstream 2020-12 support.How Has This Been Tested?
Updated
Tool::Schema#to_hexpectations acrossinput_schema_test,output_schema_test,tool_test, and thetools/listserver tests to reflect the new$schemafield. Added focused regression tests:to_hpreserves a user-supplied$schemaURI rather than overwriting it (covered for both symbol-keyed input and the string-keyed Hash form that goes through the initializer'ssymbolize_namesnormalization)validate_arguments/validate_resultcontinue to work when the user supplies a 2020-12$schemaURI on the schema (the validator strips the unknown top-level dialect URI before invoking the draft-04 validator, instead of raisingJSON::Schema::SchemaError)tools/listJSON-RPC response includes the 2020-12$schemaon bothinputSchemaandoutputSchema(transport-boundary assertion)bundle exec rake testandbundle exec rake rubocopboth pass.Breaking Changes
Additive change. Tolerant consumers of the
tools/listpayload are unaffected. Consumers that strictly assert hash equality on the emittedinputSchema/outputSchemaneed to account for the new$schemakey, but no schema semantics change.Schemas using 2020-12-only keywords (e.g.
prefixItems, nested$schemaon subschemas) are still rejected by the draft-04 metaschema validator, as before. Lifting that restriction depends on adopting a 2020-12-capable validator and is out of scope for this change.Types of changes
Checklist
Additional context