Skip to content

Commit bf40f62

Browse files
committed
test: add test cases pinning direct CallToolResult and unstructured content returns
1 parent 23608a3 commit bf40f62

1 file changed

Lines changed: 71 additions & 0 deletions

File tree

tests/server/mcpserver/test_server.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,3 +1556,74 @@ def make_point(x: int, y: int) -> Point:
15561556
assert result.structured_content == {"x": 1, "y": 2}
15571557
assert len(result.content) == 1
15581558
assert isinstance(result.content[0], TextContent)
1559+
1560+
1561+
async def test_handle_call_tool_returns_direct_call_tool_result():
1562+
"""A tool that returns `CallToolResult` directly should be returned unchanged.
1563+
1564+
This pins the `isinstance(result, CallToolResult)` branch of `_handle_call_tool`.
1565+
"""
1566+
1567+
def direct_result_tool() -> CallToolResult:
1568+
return CallToolResult(
1569+
content=[TextContent(type="text", text="Direct content")],
1570+
is_error=False,
1571+
structured_content={"custom": "metadata"},
1572+
)
1573+
1574+
mcp = MCPServer()
1575+
mcp.add_tool(direct_result_tool)
1576+
1577+
request_context = ServerRequestContext(
1578+
session=AsyncMock(),
1579+
lifespan_context=None,
1580+
experimental=Experimental(),
1581+
)
1582+
1583+
result = await mcp._handle_call_tool(
1584+
request_context,
1585+
CallToolRequestParams(name="direct_result_tool", arguments={}),
1586+
)
1587+
1588+
assert isinstance(result, CallToolResult)
1589+
assert result.is_error is False
1590+
assert result.structured_content == {"custom": "metadata"}
1591+
assert len(result.content) == 1
1592+
assert isinstance(result.content[0], TextContent)
1593+
assert result.content[0].text == "Direct content"
1594+
1595+
1596+
async def test_handle_call_tool_returns_unstructured_sequence():
1597+
"""A tool with no output schema returning a sequence of content blocks flows
1598+
1599+
through the fallback branch of `_handle_call_tool` and is wrapped in a CallToolResult.
1600+
"""
1601+
1602+
def unstructured_tool() -> list[ContentBlock]:
1603+
return [
1604+
TextContent(type="text", text="Hello"),
1605+
ImageContent(type="image", data="abc", mime_type="image/png"),
1606+
]
1607+
1608+
mcp = MCPServer()
1609+
mcp.add_tool(unstructured_tool, structured_output=False)
1610+
1611+
request_context = ServerRequestContext(
1612+
session=AsyncMock(),
1613+
lifespan_context=None,
1614+
experimental=Experimental(),
1615+
)
1616+
1617+
result = await mcp._handle_call_tool(
1618+
request_context,
1619+
CallToolRequestParams(name="unstructured_tool", arguments={}),
1620+
)
1621+
1622+
assert isinstance(result, CallToolResult)
1623+
assert result.is_error is False
1624+
assert result.structured_content is None
1625+
assert len(result.content) == 2
1626+
assert isinstance(result.content[0], TextContent)
1627+
assert result.content[0].text == "Hello"
1628+
assert isinstance(result.content[1], ImageContent)
1629+
assert result.content[1].data == "abc"

0 commit comments

Comments
 (0)