Skip to content

fix(tools/mcp): preserve inline object properties in create_model_from_json_schema (#22141)#22145

Open
C1-BA-B1-F3 wants to merge 1 commit into
run-llama:mainfrom
C1-BA-B1-F3:fix/mcp-nested-inline-object-22141
Open

fix(tools/mcp): preserve inline object properties in create_model_from_json_schema (#22141)#22145
C1-BA-B1-F3 wants to merge 1 commit into
run-llama:mainfrom
C1-BA-B1-F3:fix/mcp-nested-inline-object-22141

Conversation

@C1-BA-B1-F3

Copy link
Copy Markdown

Description

Inline object schemas ("type": "object" with "properties") in MCP tool input schemas were being silently converted to Dict[str, Any], which discarded the declared properties and their types. This meant the LLM would see a generic dict instead of structured nested fields, making it impossible for the agent to correctly populate nested object parameters.

Root Cause

In _resolve_basic_type(), objects without additionalProperties fell through to the json_type_mapping fallback (objectDict[str, Any]), losing all declared properties.

Changes

tool_spec_mixins.py

  • New _is_object_with_properties() — detects inline object schemas (type=object with properties)
  • New _create_inline_object_model() — creates a Pydantic sub-model for each inline object
  • New _get_inline_model_name() — builds stable, human-readable model names using parent model and field name context
  • Threaded field_name and parent_model_name through _resolve_field_type_resolve_basic_type_create_list_type/_resolve_union_type/_resolve_union_option_create_inline_object_model chain, enabling recursive nested object handling

base.py

  • Pass model_name to _extract_fields() so inline models get meaningful names

Test

  • Added test_create_model_from_json_schema_preserves_nested_inline_object — verifies nested object schemas produce proper Pydantic models with correct types, required fields, and validation

Edge Cases Verified

  • Simple nested inline objects ✅
  • Multiple nested inline fields ✅
  • Inline objects as array items ✅
  • Deeply nested (3 levels) inline objects ✅
  • Optional inline objects (not in required) ✅
  • Inline objects with enum fields ✅
  • Inline objects with descriptions ✅
  • Empty properties schema ✅
  • Non-object properties (string, integer, boolean, number) ✅

Closes #22141

…m_json_schema (run-llama#22141)

Inline object schemas (type: object with properties) were previously
falling through to Dict[str, Any] which discarded the declared
properties and their types. The LLM/agent would then see a generic
dict instead of structured nested fields.

This fix:
- Detects inline objects via _is_object_with_properties()
- Creates Pydantic sub-models for them via _create_inline_object_model()
- Generates stable model names via _get_inline_model_name()
- Threads field_name/parent_model_name through the resolution chain
  so nested models get meaningful names and recursion works

Fixes: run-llama#22141
@dosubot dosubot Bot added the size:M This PR changes 30-99 lines, ignoring generated files. label Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: McpToolSpec.create_model_from_json_schema drops nested inline object properties

1 participant