ax-check rule

AXC-D018: Required property not defined

The schema marks a property as required but never defines it, or the required list is malformed.

ax-check is a checker being prepared for release. This page documents the rule ahead of that release; see all 50 rules.

Severityerror
KindConformance. A finding is a fact about the input.
Modeax-check lint
Applies toMCP tool lists, OpenAPI
Pattern tagsschema-enum, error-recovery
Fix in one lineDefine every required property under "properties", or remove it from "required".

The input schema marks a property as required but never defines it, or its required list is malformed. In a closed schema, a required property that is not defined cannot be sent at all, so no call can ever be valid. An agent that follows the schema gets an error it has no way to fix.

What it checks

For each MCP tool’s inputSchema and each OpenAPI operation’s JSON request body schema, ax-check checks the top-level required keyword:

  • required must be an array. A value such as "required": true or "required": "email" is reported.
  • Every entry in the array must be a string. A number or object in the list is reported.
  • No property may be listed twice.
  • In a closed schema ("additionalProperties": false), every required property must appear under properties.

These checks mirror four checks in the audit_agent_path tool on agentexperience.tech: catalog.malformed_required_array, catalog.malformed_required_entry, catalog.duplicate_required_property and catalog.required_property_not_defined.

Why it matters

An agent builds its arguments from the schema. When the schema requires customer_id but properties only defines customerId, and unknown properties are rejected, the agent has two choices and both fail: leave customer_id out and break the required rule, or send it and break the closed object rule. The agent sees an error that it cannot recover from by reading the schema again.

Malformed required values are a common leftover from other schema dialects, where required: true sat on each property. Different validators may handle these values differently, so the same tool can behave one way in one client and another way in the next.

How to fix

  • Define every required property under properties, with the exact same spelling.
  • Or remove the name from required if callers should not send it.
  • Make required an array of unique strings, or remove it when nothing is required.

Example

Before

{
  "name": "create_invoice",
  "inputSchema": {
    "type": "object",
    "properties": {
      "customerId": { "type": "string", "description": "The customer's ID, for example cus_123." },
      "amount": { "type": "number", "description": "Total in the invoice currency." }
    },
    "required": ["customer_id", "amount", "amount"],
    "additionalProperties": false
  }
}

After

{
  "name": "create_invoice",
  "inputSchema": {
    "type": "object",
    "properties": {
      "customer_id": { "type": "string", "description": "The customer's ID, for example cus_123." },
      "amount": { "type": "number", "description": "Total in the invoice currency." }
    },
    "required": ["customer_id", "amount"],
    "additionalProperties": false
  }
}

How ax-check detects it

ax-check reads the top-level required keyword of the input schema and reports each problem at its exact position (for example /tools/0/inputSchema/required/0).

A required property that is missing from properties is reported only when the schema is closed: additionalProperties is false and the schema uses none of $ref, oneOf, anyOf, allOf, not, if, then, else, patternProperties or a list of types, either at the top level or directly on a property. One exception: a top-level anyOf whose branches only list required (the usual way to say “send at least one of these fields”) is allowed. In an open schema, the property may still be allowed through additionalProperties, a pattern or composition, so this is not a proven contradiction. Like the agentexperience.tech audit, ax-check does not report a required property that is missing from an open schema. (The audit lists that case as inconclusive; ax-check stays silent.)

Known false negatives:

  • Only the top-level input schema is checked. A required list inside a nested object is not.
  • For OpenAPI, only the JSON request body schema is checked. The required flag on path, query and header parameters is a separate field and is not part of this rule.
  • Open schemas are never reported for missing properties, as described above.

If the finding does not apply, silence it with --disable AXC-D018.

Sources

  • Specification: Model Context Protocol, Tools, revision 2026-07-28. https://modelcontextprotocol.io/specification/2026-07-28/server/tools. A tool’s inputSchema is the JSON Schema clients use to build and check arguments.
  • Specification: OpenAPI Specification v3.1.0, OpenAPI Initiative, 15 February 2021. https://spec.openapis.org/oas/v3.1.0. Request bodies are described with JSON Schema objects.
  • Guide: Write tool descriptions an agent can act on, agentexperience.tech, retrieved 2026-10-08. https://agentexperience.tech/insights/tool-descriptions/. Put closed sets in the schema and set additionalProperties to false.
  • Related check: the agentexperience.tech audit_agent_path tool reports the same defects as catalog.malformed_required_array, catalog.malformed_required_entry, catalog.duplicate_required_property and catalog.required_property_not_defined.

Records in the AX evidence register that share a pattern tag with this rule. A shared tag means the record is about the same pattern, not that it tests this rule. Read the evidence class before the number.