Skip to content

Fastmcp tool parameter parsing type error #381

@weester-yan

Description

@weester-yan

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1Significant bug affecting many users, highly requested featurebugSomething isn't workingready for workEnough information for someone to start working on

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions