@@ -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