feat: validate embedded JSON Schema documents against 2020-12 meta-schema (SEP-1613) (#949)

MCP embeds JSON Schema documents in three places — Tool.inputSchema,
Tool.outputSchema, and ElicitRequest.requestedSchema — and SEP-1613
mandates that these documents conform to JSON Schema 2020-12 by default.

Servers now reject malformed schemas at both build time (McpServer.build())
and runtime (McpAsyncServer/McpStatelessAsyncServer.addTool()), returning
an IllegalArgumentException that identifies the offending field and
references SEP-1613.  Elicitation requests whose requestedSchema violates
the meta-schema are rejected before being sent to the client.

Schemas that explicitly declare a different dialect via $schema are accepted
without meta-schema validation, since 2020-12 is the default, not the only
permitted dialect.

Refine meta-schema loading and deprecate orphan JsonSchemaValidator

Resolves #700

Signed-off-by: Dariusz Jędrzejczyk <2554306+chemicL@users.noreply.github.com>
This commit is contained in:
Dariusz Jędrzejczyk 2026-05-07 14:14:53 +02:00 • committed by GitHub
commit 87e2c7d4de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -9,6 +9,7 @@ import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.server.transport.DefaultServerTransportSecurityValidator;
import io.modelcontextprotocol.server.transport.HttpServletStreamableServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.AudioContent;
import io.modelcontextprotocol.spec.McpSchema.BlobResourceContents;
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
@ -402,6 +403,29 @@ public class ConformanceServlet {
})
.build(),
// json_schema_2020_12_tool - SEP-1613 dialect/keyword preservation
McpServerFeatures.SyncToolSpecification.builder()
.tool(Tool
.builder("json_schema_2020_12_tool", Map.of("$schema", McpSchema.JSON_SCHEMA_DIALECT_2020_12,
"type", "object", "$defs",
Map.of("address",
Map.of("type", "object", "properties",
Map.of("street", Map.of("type", "string"), "city",
Map.of("type", "string")))),
"properties",
Map.of("name", Map.of("type", "string"), "address", Map.of("$ref", "#/$defs/address")),
"additionalProperties", false))
.description("Tool with JSON Schema 2020-12 features (SEP-1613)")
.build())
.callHandler((exchange, request) -> {
logger.info("Tool 'json_schema_2020_12_tool' called");
return CallToolResult.builder()
.content(List.of(TextContent.builder("ok").build()))
.isError(false)
.build();
})
.build(),
// test_elicitation_sep1330_enums - Tool with enum schema improvements
McpServerFeatures.SyncToolSpecification.builder()
.tool(Tool.builder("test_elicitation_sep1330_enums", EMPTY_JSON_SCHEMA)