@@ -139,6 +139,7 @@ pub fn convert_mcp_call_tool_result(value: &serde_json::Value) -> Option<ToolRes
139139 let mime_type = resource
140140 . get ( "mimeType" )
141141 . and_then ( serde_json:: Value :: as_str)
142+ . filter ( |s| !s. is_empty ( ) )
142143 . unwrap_or ( "application/octet-stream" ) ;
143144 let description = resource
144145 . get ( "uri" )
@@ -523,12 +524,130 @@ mod tests {
523524 . expect ( "binary results should be captured" ) ;
524525 assert_eq ! ( binary_results. len( ) , 2 ) ;
525526 assert_eq ! ( binary_results[ 0 ] . r#type, "image" ) ;
527+ assert_eq ! ( binary_results[ 0 ] . data, "aW1n" ) ;
528+ assert_eq ! ( binary_results[ 0 ] . mime_type, "image/png" ) ;
526529 assert_eq ! (
527530 binary_results[ 1 ] . description. as_deref( ) ,
528531 Some ( "file:///tmp/data.bin" )
529532 ) ;
530533 }
531534
535+ #[ test]
536+ fn convert_mcp_call_tool_result_converts_image_content ( ) {
537+ let result = convert_mcp_call_tool_result ( & serde_json:: json!( {
538+ "content" : [
539+ { "type" : "image" , "data" : "aW1hZ2U=" , "mimeType" : "image/jpeg" }
540+ ]
541+ } ) )
542+ . expect ( "valid CallToolResult should convert" ) ;
543+
544+ let ToolResult :: Expanded ( expanded) = result else {
545+ panic ! ( "expected expanded tool result" ) ;
546+ } ;
547+
548+ assert_eq ! ( expanded. text_result_for_llm, "" ) ;
549+ assert_eq ! ( expanded. result_type, "success" ) ;
550+ let binary_results = expanded
551+ . binary_results_for_llm
552+ . expect ( "image result should be captured" ) ;
553+ assert_eq ! ( binary_results. len( ) , 1 ) ;
554+ assert_eq ! ( binary_results[ 0 ] . data, "aW1hZ2U=" ) ;
555+ assert_eq ! ( binary_results[ 0 ] . mime_type, "image/jpeg" ) ;
556+ assert_eq ! ( binary_results[ 0 ] . r#type, "image" ) ;
557+ assert ! ( binary_results[ 0 ] . description. is_none( ) ) ;
558+ }
559+
560+ #[ test]
561+ fn convert_mcp_call_tool_result_converts_resource_blob_content ( ) {
562+ let result = convert_mcp_call_tool_result ( & serde_json:: json!( {
563+ "content" : [
564+ {
565+ "type" : "resource" ,
566+ "resource" : {
567+ "uri" : "file:///tmp/report.pdf" ,
568+ "blob" : "cGRm" ,
569+ "mimeType" : "application/pdf"
570+ }
571+ }
572+ ]
573+ } ) )
574+ . expect ( "valid CallToolResult should convert" ) ;
575+
576+ let ToolResult :: Expanded ( expanded) = result else {
577+ panic ! ( "expected expanded tool result" ) ;
578+ } ;
579+
580+ let binary_results = expanded
581+ . binary_results_for_llm
582+ . expect ( "resource result should be captured" ) ;
583+ assert_eq ! ( binary_results. len( ) , 1 ) ;
584+ assert_eq ! ( binary_results[ 0 ] . data, "cGRm" ) ;
585+ assert_eq ! ( binary_results[ 0 ] . mime_type, "application/pdf" ) ;
586+ assert_eq ! ( binary_results[ 0 ] . r#type, "resource" ) ;
587+ assert_eq ! (
588+ binary_results[ 0 ] . description. as_deref( ) ,
589+ Some ( "file:///tmp/report.pdf" )
590+ ) ;
591+ }
592+
593+ #[ test]
594+ fn convert_mcp_call_tool_result_defaults_resource_blob_mime_type ( ) {
595+ let result = convert_mcp_call_tool_result ( & serde_json:: json!( {
596+ "content" : [
597+ {
598+ "type" : "resource" ,
599+ "resource" : {
600+ "uri" : "file:///tmp/data.bin" ,
601+ "blob" : "Ymlu"
602+ }
603+ } ,
604+ {
605+ "type" : "resource" ,
606+ "resource" : {
607+ "blob" : "YmluMg==" ,
608+ "mimeType" : ""
609+ }
610+ }
611+ ]
612+ } ) )
613+ . expect ( "valid CallToolResult should convert" ) ;
614+
615+ let ToolResult :: Expanded ( expanded) = result else {
616+ panic ! ( "expected expanded tool result" ) ;
617+ } ;
618+
619+ let binary_results = expanded
620+ . binary_results_for_llm
621+ . expect ( "resource blobs should be captured" ) ;
622+ assert_eq ! ( binary_results. len( ) , 2 ) ;
623+ assert_eq ! ( binary_results[ 0 ] . mime_type, "application/octet-stream" ) ;
624+ assert_eq ! ( binary_results[ 1 ] . mime_type, "application/octet-stream" ) ;
625+ }
626+
627+ #[ test]
628+ fn convert_mcp_call_tool_result_omits_binary_results_without_binary_content ( ) {
629+ let result = convert_mcp_call_tool_result ( & serde_json:: json!( {
630+ "content" : [
631+ { "type" : "text" , "text" : "hello" } ,
632+ {
633+ "type" : "resource" ,
634+ "resource" : {
635+ "uri" : "file:///tmp/readme.md" ,
636+ "text" : "resource text"
637+ }
638+ }
639+ ]
640+ } ) )
641+ . expect ( "valid CallToolResult should convert" ) ;
642+
643+ let ToolResult :: Expanded ( expanded) = result else {
644+ panic ! ( "expected expanded tool result" ) ;
645+ } ;
646+
647+ assert_eq ! ( expanded. text_result_for_llm, "hello\n resource text" ) ;
648+ assert ! ( expanded. binary_results_for_llm. is_none( ) ) ;
649+ }
650+
532651 #[ tokio:: test]
533652 async fn tool_handler_call_returns_result ( ) {
534653 let tool = EchoTool ;
0 commit comments