The Anthropic spelling
input_schema is camelCased inputSchema in MCP, and the client reads a tool with no schema at all
{
"name": "read_file",
"input_schema": {
"type": "object",
"properties": { "path": { "type": "string" } }
}
} Paste an MCP tool's inputSchema, or the whole tool object. Get the structural errors, the $refs that will not resolve, and the JSON Schema keywords that are accepted and then silently not applied.
Or drop a file anywhere on this panel. Nothing is uploaded: the analysis runs in this tab.
The answer appears here
Paste on the left and press Validate. Nothing leaves this tab.
Nothing else to flag.
No formatting problems, and nothing the rules object to. Worth remembering what that covers: this reads the file you pasted, not the account or cluster it will be applied to.
No finding matches that filter.
Real input you can load into the tool above. Each one shows a different thing going wrong, because that is what the tool is for.
input_schema is camelCased inputSchema in MCP, and the client reads a tool with no schema at all
{
"name": "read_file",
"input_schema": {
"type": "object",
"properties": { "path": { "type": "string" } }
}
}maximum and maxLength are accepted and then not applied, so your tool receives values that violate them
{
"type": "object",
"properties": {
"name": { "type": "string", "description": "The name.", "maxLength": 40 },
"count": { "type": "integer", "description": "How many.", "maximum": 100 }
},
"required": ["name"]
}Fine where the schema is advisory, and rejected outright under strict structured output
{
"type": "object",
"properties": {
"value": { "type": "string", "description": "This node." },
"child": { "$ref": "#" }
},
"required": ["value"]
}These are the ones that fail silently. The config is accepted, nothing raises an error, and the consequence arrives later.
MCP uses `inputSchema`. Under the other spelling the client sees a tool with no schema, tells the model it takes no arguments, and every call arrives empty. Nothing in the error mentions a field name.
Instead:Rename it. The two protocols are close enough that this survives review.
These keywords are frequently accepted and then not applied, so the model produces a violating value and your tool receives it. Under a strict mode the same keywords are rejected outright instead.
Instead:Validate in the tool, and put the bound in the description as well. "between 1 and 100" changes behaviour where the keyword does not.
The description is the only thing telling the model what a parameter means. A property called `id` could be a row, a user, a session or a request, and the model picks one.
Instead:A sentence each, naming the format when it is not obvious: "ISO 8601 date, for example 2026-07-30".
An inputSchema is JSON Schema, and only part of JSON Schema survives the trip to a model. The keywords that do not survive are not rejected. They are ignored, which is a much quieter failure.
Write maximum: 100 and the model may still send 500. Nothing warns you, nothing rejects the request, and your tool receives the value. The constraint existed in the document and was never applied. Validate in the tool as well, and put the bound in the description too, because that part the model does read: "between 1 and 100" changes behaviour where a maximum keyword does not.
Which is better, because it fails at request time rather than at call time. Strict modes typically refuse numeric bounds, string length bounds, and recursive schemas outright, and require additionalProperties: false on every object. A schema that is merely advisory in one mode is a 400 in the other, so the same tool definition behaves differently depending on how it is being consumed.
Tool arguments are a named set. A root of type string or array has no property names for the model to fill in; clients either reject the tool or drop it from the list without reporting it, so the tool simply does not appear.
MCP is camelCase. The Anthropic Messages API uses input_schema, and a tool copied from one to the other keeps the wrong spelling. The client then sees a tool with no schema at all and tells the model it takes no arguments, so every call arrives empty and the tool reports missing required fields. Nothing in the chain mentions the field name.
The description on each property is the only thing telling the model what the parameter means. A property called `id` with no description could be a row, a user, a session or a request; the model picks one. Naming the format saves an entire failed round trip: "ISO 8601 date, for example 2026-07-30" is worth more than any keyword.
Which subset your specific client and model actually enforce, because that varies and is not published as a single list. The weak-keyword warnings here name the keywords that are commonly dropped; on some paths they are honoured. It also cannot tell you whether the schema describes what the tool really accepts, only whether the document is well-formed and portable. This runs on the pasted text in your browser and fetches nothing, so a $ref to a remote schema is reported as unresolvable rather than followed.