Default dialect: 2020-12 (SEP-1613)
Omitting $schema means 2020-12 — the modern, more expressive vocabulary. Need legacy? Set $schema to draft-07 explicitly.
Default (2020-12)
{ "type": "object", "properties": { ... } }
Explicit draft-07
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object" }
PrimitiveSchemaDefinition (for elicitation)
Elicitation forms restrict properties to primitives — keeping form UIs tractable. The union:
| Type | Notable fields |
|---|---|
| StringSchema | minLength, maxLength, format ("uri" | "email" | "date" | "date-time"), default |
| NumberSchema | minimum, maximum, integer vs number, default |
| BooleanSchema | default |
| EnumSchema | enum, items.enum (multi-select), default, minItems/maxItems |
EnumSchema variants (SEP-1330)
Untitled single-select
{ "type": "string", "enum": ["small", "medium", "large"] }
Untitled multi-select
{ "type": "array", "items": { "type": "string", "enum": ["a","b"] }, "minItems": 1 }
Tool input/output schemas
Tool inputSchema and outputSchema are full JSON Schema — nested objects, arrays, refs, conditional logic all allowed. The constraint to primitives only applies to elicitation.
{
"name": "create_invoice",
"inputSchema": {
"type": "object",
"properties": {
"customer": { "type": "object", "properties": { "id": {"type": "string"} }, "required": ["id"] },
"lines": {
"type": "array",
"items": {
"type": "object",
"properties": { "description": {"type": "string"}, "amount": {"type": "number"} },
"required": ["description", "amount"]
},
"minItems": 1
}
},
"required": ["customer", "lines"]
}
}
Validation errors as tool errors (SEP-1303)
When inputs fail validation, return isError: true in CallToolResult with a helpful message. The LLM can read it and retry with corrected arguments — far better UX than a JSON-RPC error.
Quick summary
- Default dialect: JSON Schema 2020-12; opt out to draft-07 if you must
- Elicitation properties are limited to primitives (string, number, boolean, enum)
- Tool schemas are full JSON Schema — go nuts
- Validation failures belong in
isError, not JSON-RPC errors