@@ -391,6 +391,141 @@ async def test_callback(client_session: ClientSession) -> CallToolResult:
391391 assert result .structuredContent == {"sentiment" : "positive" , "confidence" : 0.95 }
392392
393393
394+ @pytest .mark .anyio
395+ async def test_tool_call_result_without_output_schema ():
396+ """Test returning ToolCallResult when no outputSchema is defined."""
397+ tools = [
398+ Tool (
399+ name = "get_info" ,
400+ description = "Get structured information" ,
401+ inputSchema = {
402+ "type" : "object" ,
403+ "properties" : {},
404+ },
405+ # No outputSchema defined
406+ )
407+ ]
408+
409+ async def call_tool_handler (name : str , arguments : dict [str , Any ]) -> CallToolResult :
410+ if name == "get_info" :
411+ return CallToolResult (
412+ content = [TextContent (type = "text" , text = "Results calculated" )],
413+ structuredContent = {"status" : "ok" , "data" : {"value" : 42 }},
414+ _meta = {"some" : "metadata" },
415+ )
416+ else :
417+ raise ValueError (f"Unknown tool: { name } " )
418+
419+ async def test_callback (client_session : ClientSession ) -> CallToolResult :
420+ return await client_session .call_tool ("get_info" , {})
421+
422+ result = await run_tool_test (tools , call_tool_handler , test_callback )
423+
424+ # Verify results
425+ assert result is not None
426+ assert not result .isError
427+ assert len (result .content ) == 1
428+ assert result .content [0 ].type == "text"
429+ assert result .content [0 ].text == "Results calculated"
430+ assert isinstance (result .content [0 ], TextContent )
431+ assert result .structuredContent == {"status" : "ok" , "data" : {"value" : 42 }}
432+ assert result .meta == {"some" : "metadata" }
433+
434+
435+ @pytest .mark .anyio
436+ async def test_valid_tool_call_result_with_output_schema ():
437+ """Test returning ToolCallResult when no outputSchema is defined."""
438+ tools = [
439+ Tool (
440+ name = "get_info" ,
441+ description = "Get structured information" ,
442+ inputSchema = {
443+ "type" : "object" ,
444+ "properties" : {},
445+ },
446+ outputSchema = {
447+ "type" : "object" ,
448+ "properties" : {
449+ "name" : {"type" : "string" },
450+ "number" : {"type" : "integer" },
451+ },
452+ "required" : ["name" , "number" ],
453+ },
454+ )
455+ ]
456+
457+ async def call_tool_handler (name : str , arguments : dict [str , Any ]) -> CallToolResult :
458+ if name == "get_info" :
459+ return CallToolResult (
460+ content = [TextContent (type = "text" , text = "Results calculated" )],
461+ structuredContent = {"name" : "Brandon" , "number" : 29 },
462+ _meta = {"some" : "metadata" },
463+ )
464+ else :
465+ raise ValueError (f"Unknown tool: { name } " )
466+
467+ async def test_callback (client_session : ClientSession ) -> CallToolResult :
468+ return await client_session .call_tool ("get_info" , {})
469+
470+ result = await run_tool_test (tools , call_tool_handler , test_callback )
471+
472+ # Verify results
473+ assert result is not None
474+ assert not result .isError
475+ assert len (result .content ) == 1
476+ assert result .content [0 ].type == "text"
477+ assert result .content [0 ].text == "Results calculated"
478+ assert isinstance (result .content [0 ], TextContent )
479+ assert result .structuredContent == {"name" : "Brandon" , "number" : 29 }
480+ assert result .meta == {"some" : "metadata" }
481+
482+
483+ @pytest .mark .anyio
484+ async def test_invalid_tool_call_result_with_output_schema ():
485+ """Test returning ToolCallResult when no outputSchema is defined."""
486+ tools = [
487+ Tool (
488+ name = "get_info" ,
489+ description = "Get structured information" ,
490+ inputSchema = {
491+ "type" : "object" ,
492+ "properties" : {},
493+ },
494+ outputSchema = {
495+ "type" : "object" ,
496+ "properties" : {
497+ "name" : {"type" : "string" },
498+ "number" : {"type" : "integer" },
499+ },
500+ "required" : ["name" , "number" ],
501+ },
502+ )
503+ ]
504+
505+ async def call_tool_handler (name : str , arguments : dict [str , Any ]) -> CallToolResult :
506+ if name == "get_info" :
507+ return CallToolResult (
508+ content = [TextContent (type = "text" , text = "Results calculated" )],
509+ structuredContent = {"name" : "Brandon" },
510+ _meta = {"some" : "metadata" },
511+ )
512+ else :
513+ raise ValueError (f"Unknown tool: { name } " )
514+
515+ async def test_callback (client_session : ClientSession ) -> CallToolResult :
516+ return await client_session .call_tool ("get_info" , {})
517+
518+ result = await run_tool_test (tools , call_tool_handler , test_callback )
519+
520+ assert result is not None
521+ assert result .isError
522+ assert len (result .content ) == 1
523+ assert result .content [0 ].type == "text"
524+ assert isinstance (result .content [0 ], TextContent )
525+ assert "Output validation error:" in result .content [0 ].text
526+ assert "'number' is a required property" in result .content [0 ].text
527+
528+
394529@pytest .mark .anyio
395530async def test_output_schema_type_validation ():
396531 """Test outputSchema validates types correctly."""
0 commit comments