@@ -7,7 +7,12 @@ import { ToolUse } from "../../../shared/tools"
77// Mock dependencies
88vi . mock ( "../../prompts/responses" , ( ) => ( {
99 formatResponse : {
10- toolResult : vi . fn ( ( result : string ) => `Tool result: ${ result } ` ) ,
10+ toolResult : vi . fn ( ( result : string , images ?: string [ ] ) => {
11+ if ( images && images . length > 0 ) {
12+ return `Tool result: ${ result } [with ${ images . length } image(s)]`
13+ }
14+ return `Tool result: ${ result } `
15+ } ) ,
1116 toolError : vi . fn ( ( error : string ) => `Tool error: ${ error } ` ) ,
1217 invalidMcpToolArgumentError : vi . fn ( ( server : string , tool : string ) => `Invalid args for ${ server } :${ tool } ` ) ,
1318 unknownMcpToolError : vi . fn ( ( server : string , tool : string , availableTools : string [ ] ) => {
@@ -245,7 +250,7 @@ describe("useMcpToolTool", () => {
245250 expect ( mockTask . consecutiveMistakeCount ) . toBe ( 0 )
246251 expect ( mockAskApproval ) . toHaveBeenCalled ( )
247252 expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
248- expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Tool executed successfully" )
253+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Tool executed successfully" , [ ] )
249254 expect ( mockPushToolResult ) . toHaveBeenCalledWith ( "Tool result: Tool executed successfully" )
250255 } )
251256
@@ -483,7 +488,7 @@ describe("useMcpToolTool", () => {
483488 expect ( mockTask . consecutiveMistakeCount ) . toBe ( 0 )
484489 expect ( mockTask . recordToolError ) . not . toHaveBeenCalled ( )
485490 expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
486- expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Tool executed successfully" )
491+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Tool executed successfully" , [ ] )
487492 } )
488493
489494 it ( "should reject unknown server names with available servers listed" , async ( ) => {
@@ -578,4 +583,240 @@ describe("useMcpToolTool", () => {
578583 expect ( mockAskApproval ) . not . toHaveBeenCalled ( )
579584 } )
580585 } )
586+
587+ describe ( "image handling" , ( ) => {
588+ it ( "should handle tool response with image content" , async ( ) => {
589+ const block : ToolUse = {
590+ type : "tool_use" ,
591+ name : "use_mcp_tool" ,
592+ params : {
593+ server_name : "figma-server" ,
594+ tool_name : "get_screenshot" ,
595+ arguments : '{"nodeId": "123"}' ,
596+ } ,
597+ nativeArgs : {
598+ server_name : "figma-server" ,
599+ tool_name : "get_screenshot" ,
600+ arguments : { nodeId : "123" } ,
601+ } ,
602+ partial : false ,
603+ }
604+
605+ mockAskApproval . mockResolvedValue ( true )
606+
607+ const mockToolResult = {
608+ content : [
609+ {
610+ type : "image" ,
611+ mimeType : "image/png" ,
612+ data : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ" ,
613+ } ,
614+ ] ,
615+ isError : false ,
616+ }
617+
618+ mockProviderRef . deref . mockReturnValue ( {
619+ getMcpHub : ( ) => ( {
620+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
621+ getAllServers : vi
622+ . fn ( )
623+ . mockReturnValue ( [
624+ {
625+ name : "figma-server" ,
626+ tools : [ { name : "get_screenshot" , description : "Get screenshot" } ] ,
627+ } ,
628+ ] ) ,
629+ } ) ,
630+ postMessageToWebview : vi . fn ( ) ,
631+ } )
632+
633+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
634+ askApproval : mockAskApproval ,
635+ handleError : mockHandleError ,
636+ pushToolResult : mockPushToolResult ,
637+ } )
638+
639+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
640+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "[1 image(s) received]" , [
641+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ" ,
642+ ] )
643+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "with 1 image(s)" ) )
644+ } )
645+
646+ it ( "should handle tool response with both text and image content" , async ( ) => {
647+ const block : ToolUse = {
648+ type : "tool_use" ,
649+ name : "use_mcp_tool" ,
650+ params : {
651+ server_name : "figma-server" ,
652+ tool_name : "get_node_info" ,
653+ arguments : '{"nodeId": "123"}' ,
654+ } ,
655+ nativeArgs : {
656+ server_name : "figma-server" ,
657+ tool_name : "get_node_info" ,
658+ arguments : { nodeId : "123" } ,
659+ } ,
660+ partial : false ,
661+ }
662+
663+ mockAskApproval . mockResolvedValue ( true )
664+
665+ const mockToolResult = {
666+ content : [
667+ { type : "text" , text : "Node name: Button" } ,
668+ {
669+ type : "image" ,
670+ mimeType : "image/png" ,
671+ data : "base64imagedata" ,
672+ } ,
673+ ] ,
674+ isError : false ,
675+ }
676+
677+ mockProviderRef . deref . mockReturnValue ( {
678+ getMcpHub : ( ) => ( {
679+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
680+ getAllServers : vi
681+ . fn ( )
682+ . mockReturnValue ( [
683+ { name : "figma-server" , tools : [ { name : "get_node_info" , description : "Get node info" } ] } ,
684+ ] ) ,
685+ } ) ,
686+ postMessageToWebview : vi . fn ( ) ,
687+ } )
688+
689+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
690+ askApproval : mockAskApproval ,
691+ handleError : mockHandleError ,
692+ pushToolResult : mockPushToolResult ,
693+ } )
694+
695+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
696+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Node name: Button" , [
697+ "data:image/png;base64,base64imagedata" ,
698+ ] )
699+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "with 1 image(s)" ) )
700+ } )
701+
702+ it ( "should handle image with data URL already formatted" , async ( ) => {
703+ const block : ToolUse = {
704+ type : "tool_use" ,
705+ name : "use_mcp_tool" ,
706+ params : {
707+ server_name : "figma-server" ,
708+ tool_name : "get_screenshot" ,
709+ arguments : '{"nodeId": "123"}' ,
710+ } ,
711+ nativeArgs : {
712+ server_name : "figma-server" ,
713+ tool_name : "get_screenshot" ,
714+ arguments : { nodeId : "123" } ,
715+ } ,
716+ partial : false ,
717+ }
718+
719+ mockAskApproval . mockResolvedValue ( true )
720+
721+ const mockToolResult = {
722+ content : [
723+ {
724+ type : "image" ,
725+ mimeType : "image/jpeg" ,
726+ data : "data:image/jpeg;base64,/9j/4AAQSkZJRg==" ,
727+ } ,
728+ ] ,
729+ isError : false ,
730+ }
731+
732+ mockProviderRef . deref . mockReturnValue ( {
733+ getMcpHub : ( ) => ( {
734+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
735+ getAllServers : vi
736+ . fn ( )
737+ . mockReturnValue ( [
738+ {
739+ name : "figma-server" ,
740+ tools : [ { name : "get_screenshot" , description : "Get screenshot" } ] ,
741+ } ,
742+ ] ) ,
743+ } ) ,
744+ postMessageToWebview : vi . fn ( ) ,
745+ } )
746+
747+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
748+ askApproval : mockAskApproval ,
749+ handleError : mockHandleError ,
750+ pushToolResult : mockPushToolResult ,
751+ } )
752+
753+ // Should not double-prefix the data URL
754+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "[1 image(s) received]" , [
755+ "data:image/jpeg;base64,/9j/4AAQSkZJRg==" ,
756+ ] )
757+ } )
758+
759+ it ( "should handle multiple images in response" , async ( ) => {
760+ const block : ToolUse = {
761+ type : "tool_use" ,
762+ name : "use_mcp_tool" ,
763+ params : {
764+ server_name : "figma-server" ,
765+ tool_name : "get_screenshots" ,
766+ arguments : '{"nodeIds": ["1", "2"]}' ,
767+ } ,
768+ nativeArgs : {
769+ server_name : "figma-server" ,
770+ tool_name : "get_screenshots" ,
771+ arguments : { nodeIds : [ "1" , "2" ] } ,
772+ } ,
773+ partial : false ,
774+ }
775+
776+ mockAskApproval . mockResolvedValue ( true )
777+
778+ const mockToolResult = {
779+ content : [
780+ {
781+ type : "image" ,
782+ mimeType : "image/png" ,
783+ data : "image1data" ,
784+ } ,
785+ {
786+ type : "image" ,
787+ mimeType : "image/png" ,
788+ data : "image2data" ,
789+ } ,
790+ ] ,
791+ isError : false ,
792+ }
793+
794+ mockProviderRef . deref . mockReturnValue ( {
795+ getMcpHub : ( ) => ( {
796+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
797+ getAllServers : vi
798+ . fn ( )
799+ . mockReturnValue ( [
800+ {
801+ name : "figma-server" ,
802+ tools : [ { name : "get_screenshots" , description : "Get screenshots" } ] ,
803+ } ,
804+ ] ) ,
805+ } ) ,
806+ postMessageToWebview : vi . fn ( ) ,
807+ } )
808+
809+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
810+ askApproval : mockAskApproval ,
811+ handleError : mockHandleError ,
812+ pushToolResult : mockPushToolResult ,
813+ } )
814+
815+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "[2 image(s) received]" , [
816+ "data:image/png;base64,image1data" ,
817+ "data:image/png;base64,image2data" ,
818+ ] )
819+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "with 2 image(s)" ) )
820+ } )
821+ } )
581822} )
0 commit comments