diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index ca868198c..1457bb3e8 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -101,7 +101,7 @@ class Tool(FastMCPBaseModel, ABC): tool: Tool, transform_fn: Callable[..., Any] | None = None, name: str | None = None, - transform_args: dict[str, str | ArgTransform | None] | None = None, + transform_args: dict[str, ArgTransform] | None = None, description: str | None = None, tags: set[str] | None = None, annotations: ToolAnnotations | None = None, diff --git a/src/fastmcp/tools/tool_transform.py b/src/fastmcp/tools/tool_transform.py index 11d3338a3..b193d4906 100644 --- a/src/fastmcp/tools/tool_transform.py +++ b/src/fastmcp/tools/tool_transform.py @@ -168,6 +168,11 @@ class ArgTransform: "Hidden parameters cannot be required since clients cannot provide them." ) + if self.required is False: + raise ValueError( + "Cannot specify 'required=False'. Set a default value instead." + ) + class TransformedTool(Tool): """A tool that is transformed from another tool. diff --git a/tests/tools/test_tool_transform.py b/tests/tools/test_tool_transform.py index cb5af15b4..017ebdcf6 100644 --- a/tests/tools/test_tool_transform.py +++ b/tests/tools/test_tool_transform.py @@ -858,23 +858,14 @@ async def test_arg_transform_required_false(): def base_tool(required_param: int) -> str: return f"value: {required_param}" - # Make the required parameter optional with a default - new_tool = Tool.from_tool( - base_tool, - transform_args={"required_param": ArgTransform(required=False, default=99)}, - ) - - # Parameter should now be optional (not in required list, has default) - assert "required_param" not in new_tool.parameters["required"] - assert new_tool.parameters["properties"]["required_param"]["default"] == 99 - - # Should work when parameter is not provided (uses default) - result = await new_tool.run(arguments={}) - assert result[0].text == "value: 99" # type: ignore - - # Should work when parameter is provided - result = await new_tool.run(arguments={"required_param": 123}) - assert result[0].text == "value: 123" # type: ignore + with pytest.raises( + ValueError, + match="Cannot specify 'required=False'. Set a default value instead.", + ): + Tool.from_tool( + base_tool, + transform_args={"required_param": ArgTransform(required=False, default=99)}, # type: ignore + ) async def test_arg_transform_required_with_rename():