Repository navigation
Fastmcp tool parameter parsing type error #381
Copy link
Copy link
Closed as not planned
Labels
P1Significant bug affecting many users, highly requested featureSignificant bug affecting many users, highly requested featurebugSomething isn't workingSomething isn't workingready for workEnough information for someone to start working onEnough information for someone to start working on
Milestone
Description
When I define the tool parameter as string, the parameter parsing function of fastmcp parses the numeric string I pass in into a numeric value.
- mcp/server/fastmcp/utilities/func_metadata.py
def pre_parse_json(self, data: dict[str, Any]) -> dict[str, Any]:
"""Pre-parse data from JSON.
Return a dict with same keys as input but with values parsed from JSON
if appropriate.
This is to handle cases like `["a", "b", "c"]` being passed in as JSON inside
a string rather than an actual list. Claude desktop is prone to this - in fact
it seems incapable of NOT doing this. For sub-models, it tends to pass
dicts (JSON objects) as JSON strings, which can be pre-parsed here.
"""
new_data = data.copy() # Shallow copy
for field_name, field_info in self.arg_model.model_fields.items():
import logging
logging.info((field_name, field_info))
logging.info("before parse: ", new_data)
if field_name not in data.keys():
continue
if isinstance(data[field_name], str):
try:
pre_parsed = json.loads(data[field_name])
except json.JSONDecodeError:
continue # Not JSON - skip
if isinstance(pre_parsed, str):
# This is likely that the raw value is e.g. `"hello"` which we
# Should really be parsed as '"hello"' in Python - but if we parse
# it as JSON it'll turn into just 'hello'. So we skip it.
continue
new_data[field_name] = pre_parsed
logging.info("after parse: ", new_data)
assert new_data.keys() == data.keys()
return new_data
test output:
video-1 | ('cid', FieldInfo(annotation=str, required=True, description='xxx.'))
video-1 | before parse: {'cid': '1.2'}
video-1 | after parse: {'cid': 1.2}
video-1 | Error calling tool: Error executing tool getinfo: 1 validation error for getinfoArguments
video-1 | cid
video-1 | Input should be a valid string [type=string_type, input_value=1.2, input_type=float]
video-1 | For further information visit https://errors.pydantic.dev/2.10/v/string_type
Here, json.loads will parse the incoming string "1.2" into the floating point number 1.2
So, when I use pydantic to define parameters in tool, a validation error occurs
from pydantic import validate_call, Field
@server.tool(description="xxx")
@validate_call
async def getinfo(
cid: str = Field(..., description="xxx."),
) -> bool | None:
Is my understanding correct?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
P1Significant bug affecting many users, highly requested featureSignificant bug affecting many users, highly requested featurebugSomething isn't workingSomething isn't workingready for workEnough information for someone to start working onEnough information for someone to start working on
Activity
msamon-nrg commentedon Mar 27, 2025
I experienced this same issue with this function signature:
It was resolved once I updated it to
def tool(account_id: int). I think you've identified the origin of the bug correctly. I believe what's happening is thejson.loads(data[field_name])is converting number strings to numbers in cases wheredata[field_name]is a number string. This is expected behavior of thejson.loadsmethod. For example:dsp-ant commentedon Mar 27, 2025
Can you add more information, such as the version of the SDK?
weester-yan commentedon Mar 28, 2025
I'm using version 1.3.0, but I saw that the latest version seems to have fixed this problem.
Thank you very much for your reply.
davidlin2k commentedon Mar 30, 2025
I suspect the problem is coming from this, I've also encountered similar problem
https://docs.pydantic.dev/latest/concepts/strict_mode/
davidlin2k commentedon Mar 30, 2025
Seems like there is a PR trying to address this
#350
0kenx commentedon Apr 1, 2025
I can confirm the same bug. When client tries to call a functon of arg
strand with a valid JSON string, it produces error:timesler commentedon Apr 8, 2025
We are seeing the same issue as @0kenx with JSON strings being converted to dicts when they need to stay as strings. Currently, the only workaround we can think of is to prepend something to the argument that makes it unparsable by
json.loadsand then remove that in the MCP server code (we are seeing this in a server we also developed, so this is possible)timesler commentedon Apr 19, 2025
I believe this would be fixed with #350. @dsp-ant would it be possible for that PR to get a look from maintainers?
0kenx commentedon May 20, 2025
Is anyone maintaining this repo? @ihrpr
ksafonov commentedon Dec 22, 2025
Same here using version 1.10.1.
maxisbey commentedon Dec 31, 2025
Hi, PR #1113 (merged July 2025) should have fixed this for simple
strannotations. Could you provide a minimal reproduction with your exact type annotation and SDK version? This will help us identify if there are edge cases we missed.AI Disclaimer
Nuclear2 commentedon Jan 8, 2026
Still in sdk 1.21.0,tool definition in server is:
When invoking this tool with a valid json string value for the argument c, the function receives c as a dict instead of a str, resulting in a validation error.
This appears to happen whenever an argument is annotated with a union type—such as Optional[str] (from typing) or str | None. In these cases, the MCP framework seems to interpret the parameter as a Union or types.Optional type, which it then incorrectly deserializes as a dictionary rather than handling it as a nullable string.
It might be better to handle this as follows:
Then replace the
field_info.annotation is not strcheck with_is_string_like_type(annotation).maxisbey commentedon Jul 24, 2026
Thanks for the report. Tracking this in #1873 instead. Closing this as part of a wider backlog cleanup around the v2 release. If it's still relevant, feel free to reopen.
AI Disclaimer