fastmcp/tests/deprecated/test_output_schema_false.py

139 lines
5.2 KiB
Python

"""Test deprecated output_schema=False behavior (deprecated in 2.11.4)."""
import warnings
import pytest
from fastmcp import FastMCP
from fastmcp.tools import Tool
class TestDeprecatedOutputSchemaFalse:
"""Test that output_schema=False is deprecated but still works."""
async def test_tool_decorator_output_schema_false_deprecated(self):
"""Test that @mcp.tool(output_schema=False) shows deprecation warning."""
mcp = FastMCP()
with pytest.warns(
DeprecationWarning, match="output_schema=False is deprecated"
):
@mcp.tool(output_schema=False) # type: ignore[arg-type]
def simple_tool() -> int:
"""A simple tool."""
return 42
# Verify the tool was created with None as output_schema
tool = mcp._tool_manager._tools["simple_tool"]
assert tool.output_schema is None
async def test_tool_from_function_output_schema_false_deprecated(self):
"""Test that Tool.from_function(output_schema=False) shows deprecation warning."""
def my_function() -> str:
"""A simple function."""
return "hello"
with pytest.warns(
DeprecationWarning, match="output_schema=False is deprecated"
):
tool = Tool.from_function(my_function, output_schema=False) # type: ignore[arg-type]
# Verify the tool was created with None as output_schema
assert tool.output_schema is None
async def test_tool_from_tool_output_schema_false_deprecated(self):
"""Test that Tool.from_tool(output_schema=False) shows deprecation warning."""
# Create a parent tool
def parent_function() -> dict[str, str]:
"""A parent function."""
return {"status": "ok"}
parent_tool = Tool.from_function(parent_function)
with pytest.warns(
DeprecationWarning, match="output_schema=False is deprecated"
):
transformed_tool = Tool.from_tool(parent_tool, output_schema=False) # type: ignore[arg-type]
# Verify the tool was created with None as output_schema
assert transformed_tool.output_schema is None
async def test_output_schema_false_functionality_preserved(self):
"""Test that output_schema=False still works functionally like output_schema=None."""
mcp = FastMCP()
# Create two tools - one with False, one with None
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
@mcp.tool(output_schema=False) # type: ignore[arg-type]
def tool_with_false() -> dict[str, str]:
"""Tool with output_schema=False."""
return {"result": "false"}
@mcp.tool(output_schema=None)
def tool_with_none() -> dict[str, str]:
"""Tool with output_schema=None."""
return {"result": "none"}
# Both should have None as output_schema
assert mcp._tool_manager._tools["tool_with_false"].output_schema is None
assert mcp._tool_manager._tools["tool_with_none"].output_schema is None
# Both should work the same way
result_false = await mcp._tool_manager._tools["tool_with_false"].run({})
result_none = await mcp._tool_manager._tools["tool_with_none"].run({})
# Both should return structured content for dict-like objects
assert result_false.structured_content == {"result": "false"}
assert result_none.structured_content == {"result": "none"}
async def test_output_schema_false_with_scalar_return(self):
"""Test that output_schema=False works with scalar returns (no structured content)."""
mcp = FastMCP()
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
@mcp.tool(output_schema=False) # type: ignore[arg-type]
def scalar_tool() -> int:
"""Tool returning a scalar."""
return 42
tool = mcp._tool_manager._tools["scalar_tool"]
assert tool.output_schema is None
result = await tool.run({})
# Scalar values don't produce structured content
assert result.structured_content is None
assert len(result.content) == 1
assert result.content[0].text == "42" # type: ignore[attr-defined]
async def test_transform_with_output_schema_false(self):
"""Test that transformation with output_schema=False still works."""
# Create a parent tool
def parent_function(x: int) -> dict[str, int]:
"""A parent function."""
return {"value": x * 2}
parent_tool = Tool.from_function(parent_function)
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
# Transform with output_schema=False
transformed = Tool.from_tool(
parent_tool,
name="doubled",
output_schema=False, # type: ignore[arg-type]
)
assert transformed.output_schema is None
# Tool should still work
result = await transformed.run({"x": 5})
assert result.structured_content == {"value": 10}