fix: mcp schema generation and non-strict schema validation
Co-authored-by: Jin Peng <jinjpeng@Jins-MacBook-Pro.local>
This commit is contained in:
@@ -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 == []
|
||||
|
||||
Reference in New Issue
Block a user