Skip to content

JSON-shaped string arguments are coerced into dict/list before validation for str-typed tool params #3931

@cmoski

Description

@cmoski

What happened?

When a tool parameter is annotated as str, passing a string value that happens to contain valid JSON causes validation to fail. Instead of arriving as a Python string, the value is treated as a dict/list, and Pydantic rejects it with a string-type validation error. I expected a string argument to remain a string regardless of its contents.

If the bug reproduces, the call should fail with a validation error indicating content was treated as a dict instead of a str.

Example Code

import asyncio
import json
from fastmcp import FastMCP, Client

mcp = FastMCP("repro")

@mcp.tool()
def echo_type(content: str) -> str:
    return f"type={type(content).__name__} value={content}"

async def demo():
    payload = json.dumps({
        "account_full_name": "Test Data",
        "as_of_date": "2026-04-13",
    })

    async with Client(mcp) as client:
        result = await client.call_tool("echo_type", {"content": payload})
        print(result)

if __name__ == "__main__":
    asyncio.run(demo())

Version Information

fastmcp: 2.10.5
python: 3.13.2 (tags/v3.13.2:4f8bb39, Feb  4 2025, 15:23:48) [MSC v.1942 64 bit (AMD64)]
os: Windows-11-10.0.22631-SP0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working. Reports of errors, unexpected behavior, or broken functionality.serverRelated to FastMCP server implementation or server-side functionality.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions