Skip to content

Python: [Bug]: _build_pydantic_model_from_json_schema does not handle anyOf — all optional/union MCP tool parameters collapse to str #4253

@lukasz-cledar

Description

@lukasz-cledar

Description

What happened:
When using MCPStreamableHTTPTool (or any MCP tool integration), any MCP tool parameter whose JSON Schema uses anyOf — which is how Pydantic represents Optional[X], X | None, or any union type — is incorrectly resolved to str by _build_pydantic_model_from_json_schema().

What I expected to happen:
Parameters with anyOf schemas (e.g. list[str] | None, int | None) should be resolved to the correct Python union type

Steps to reproduce:

  1. Create an MCP server with a tool that has an optional list parameter (e.g. columns: list[str] | None = None)
  2. Connect to it using MCPStreamableHTTPTool
  3. Have the LLM call the tool with that parameter
  4. Observe that the LLM sends a string instead of an array, and the MCP server rejects it

Code Sample

# Reproducing the bug directly with the internal function
from agent_framework._tools import _build_pydantic_model_from_json_schema
import json

schema = {
    "properties": {
        "required_id": {"type": "string", "description": "Some required ID."},
        "start": {
            "anyOf": [{"type": "integer"}, {"type": "null"}],
            "default": None,
            "description": "Start index."
        },
        "columns": {
            "anyOf": [
                {"items": {"type": "string"}, "type": "array"},
                {"type": "null"}
            ],
            "default": None,
            "description": "List of columns."
        },
    },
    "required": ["required_id"],
}

Model = _build_pydantic_model_from_json_schema("my_tool", schema)
print(json.dumps(Model.model_json_schema(), indent=2))
# All anyOf fields become "type": "string" — start and columns are both str

# String is accepted (WRONG — should require list):
m = Model.model_validate({"required_id": "abc", "columns": "name"})
print(type(m.columns))  # <class 'str'>

# Actual list is REJECTED:
m = Model.model_validate({"required_id": "abc", "columns": ["name"]})
# ValidationError: Input should be a valid string

Error Messages / Stack Traces

Error: Argument parsing failed.

Package Versions

agent-framework: 1.0.0b260130

Python Version

Python: 3.13.2

Additional Context

No response

Metadata

Metadata

Labels

bugSomething isn't workingpython

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions