fix: mcp schema generation and non-strict schema validation

Co-authored-by: Jin Peng <jinjpeng@Jins-MacBook-Pro.local>
This commit is contained in:
jnjpng
2025-08-22 15:45:33 -07:00
committed by GitHub
parent c8771d6b80
commit 74029acb0d
8 changed files with 308 additions and 23 deletions

View File

@@ -22,7 +22,7 @@ class TestSchemaValidator:
"additionalProperties": False,
},
},
"required": ["name", "age"],
"required": ["name", "age", "address"], # All properties must be required for strict mode
"additionalProperties": False,
}
@@ -235,22 +235,22 @@ class TestSchemaValidator:
assert status == SchemaHealth.INVALID
assert any("dict" in reason for reason in reasons)
def test_schema_with_defaults_strict_compliant(self):
"""Test that root-level schemas without required field are STRICT_COMPLIANT."""
def test_schema_with_defaults_non_strict(self):
"""Test that root-level schemas without required field are NON_STRICT_ONLY."""
schema = {
"type": "object",
"properties": {"name": {"type": "string"}, "optional": {"type": "string"}},
# Missing "required" field at root level is OK
# Missing "required" field at root level - all properties must be required for strict mode
"additionalProperties": False,
}
status, reasons = validate_complete_json_schema(schema)
# After fix, root level without required should be STRICT_COMPLIANT
assert status == SchemaHealth.STRICT_COMPLIANT
assert reasons == []
# Root level without all properties required should be NON_STRICT_ONLY
assert status == SchemaHealth.NON_STRICT_ONLY
assert any("not in required array" in reason for reason in reasons)
def test_composio_schema_with_optional_root_properties_strict_compliant(self):
"""Test that Composio-like schemas with optional root properties are STRICT_COMPLIANT."""
def test_composio_schema_with_optional_root_properties_non_strict(self):
"""Test that Composio-like schemas with optional root properties are NON_STRICT_ONLY."""
schema = {
"type": "object",
"properties": {
@@ -264,25 +264,25 @@ class TestSchemaValidator:
}
status, reasons = validate_complete_json_schema(schema)
assert status == SchemaHealth.STRICT_COMPLIANT
assert reasons == []
assert status == SchemaHealth.NON_STRICT_ONLY
assert any("not in required array" in reason for reason in reasons)
def test_root_level_without_required_strict_compliant(self):
"""Test that root-level objects without 'required' field are STRICT_COMPLIANT."""
def test_root_level_without_required_non_strict(self):
"""Test that root-level objects without 'required' field are NON_STRICT_ONLY."""
schema = {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer"},
},
# No "required" field at root level
# No "required" field at root level - all properties must be required for strict mode
"additionalProperties": False,
}
status, reasons = validate_complete_json_schema(schema)
# Root level without required should be STRICT_COMPLIANT
assert status == SchemaHealth.STRICT_COMPLIANT
assert reasons == []
# Root level without required should be NON_STRICT_ONLY
assert status == SchemaHealth.NON_STRICT_ONLY
assert any("not in required array" in reason for reason in reasons)
def test_nested_object_without_required_non_strict(self):
"""Test that nested objects without 'required' remain NON_STRICT_ONLY."""
@@ -312,3 +312,35 @@ class TestSchemaValidator:
assert status == SchemaHealth.NON_STRICT_ONLY
# Should have warning about nested preferences object missing 'required'
assert any("required" in reason and "preferences" in reason for reason in reasons)
def test_user_example_schema_non_strict(self):
"""Test the user's example schema with optional properties - should be NON_STRICT_ONLY."""
schema = {
"type": "object",
"properties": {
"a": {"title": "A", "type": "integer"},
"b": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": None, "title": "B"},
},
"required": ["a"], # Only 'a' is required, 'b' is not
"additionalProperties": False,
}
status, reasons = validate_complete_json_schema(schema)
assert status == SchemaHealth.NON_STRICT_ONLY
assert any("property 'b' is not in required array" in reason for reason in reasons)
def test_all_properties_required_strict_compliant(self):
"""Test that schemas with all properties required are STRICT_COMPLIANT."""
schema = {
"type": "object",
"properties": {
"a": {"title": "A", "type": "integer"},
"b": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": None, "title": "B"},
},
"required": ["a", "b"], # All properties are required
"additionalProperties": False,
}
status, reasons = validate_complete_json_schema(schema)
assert status == SchemaHealth.STRICT_COMPLIANT
assert reasons == []