Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 13 additions & 9 deletions src/mcpadapt/utils/modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,21 @@ def process_schema(name: str, schema_def: Dict[str, Any]) -> Type[BaseModel]:

for field_name, field_schema in properties.items():
field_type, default = get_field_type(field_name, field_schema, required)
field_kwargs = {
"default": default,
"description": field_schema.get("description", ""),
"title": field_schema.get("title", ""),
}
json_schema_extras = {}
for extra_key in ("items", "anyOf", "enum", "properties"):
if extra_key in field_schema:
json_schema_extras[extra_key] = field_schema[extra_key]
if json_schema_extras:
field_kwargs["json_schema_extra"] = json_schema_extras

fields[field_name] = (
field_type,
Field(
default=default,
description=field_schema.get("description", ""),
title=field_schema.get("title", ""),
items=field_schema.get("items", None),
anyOf=field_schema.get("anyOf", []),
enum=field_schema.get("enum", None),
properties=field_schema.get("properties", {}),
),
Field(**field_kwargs),
)

# Create the model
Expand Down
58 changes: 58 additions & 0 deletions tests/utils/test_modeling.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
Tests for the modeling module, specifically focused on JSON Schema handling.
"""

import warnings

from mcpadapt.utils.modeling import create_model_from_json_schema


Expand Down Expand Up @@ -35,3 +37,59 @@ def test_direct_modeling_with_list_type():
# Verify the model works as expected with number
instance = model(multi_type_field=42)
assert instance.multi_type_field == 42


def test_model_creation_does_not_pass_invalid_field_keywords():
"""Field() should not receive JSON-schema-only keys as kwargs."""

schema = {
"type": "object",
"properties": {
"nullable_field": {
"anyOf": [
{"type": "string"},
{"type": "null"},
],
"description": "field allowing strings or null",
},
"array_field": {
"type": "array",
"items": {"type": "string"},
"description": "array of strings",
},
"status": {
"type": "string",
"enum": ["ok", "error", "unknown"],
"description": "status enum",
},
"payload": {
"type": "object",
"properties": {
"value": {"type": "string"},
},
"description": "nested object payload",
},
},
"required": ["status"],
}

with warnings.catch_warnings(record=True) as captured:
warnings.simplefilter("always")
model = create_model_from_json_schema(schema)
model_instance = model(
nullable_field=None,
array_field=["one", "two"],
status="ok",
payload={"value": "x"},
)

deprecation_warnings = [
warning
for warning in captured
if issubclass(warning.category, DeprecationWarning)
and "Field" in str(warning.message)
]
assert not deprecation_warnings
assert model_instance.status == "ok"
assert model_instance.array_field == ["one", "two"]
assert model_instance.payload == {"value": "x"}