@@ -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 ( ) => {
@@ -636,4 +641,240 @@ describe("useMcpToolTool", () => {
636641 expect ( callToolMock ) . toHaveBeenCalledWith ( "test-server" , "get-user-profile" , { } )
637642 } )
638643 } )
644+
645+ describe ( "image handling" , ( ) => {
646+ it ( "should handle tool response with 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_screenshot" ,
653+ arguments : '{"nodeId": "123"}' ,
654+ } ,
655+ nativeArgs : {
656+ server_name : "figma-server" ,
657+ tool_name : "get_screenshot" ,
658+ arguments : { nodeId : "123" } ,
659+ } ,
660+ partial : false ,
661+ }
662+
663+ mockAskApproval . mockResolvedValue ( true )
664+
665+ const mockToolResult = {
666+ content : [
667+ {
668+ type : "image" ,
669+ mimeType : "image/png" ,
670+ data : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ" ,
671+ } ,
672+ ] ,
673+ isError : false ,
674+ }
675+
676+ mockProviderRef . deref . mockReturnValue ( {
677+ getMcpHub : ( ) => ( {
678+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
679+ getAllServers : vi
680+ . fn ( )
681+ . mockReturnValue ( [
682+ {
683+ name : "figma-server" ,
684+ tools : [ { name : "get_screenshot" , description : "Get screenshot" } ] ,
685+ } ,
686+ ] ) ,
687+ } ) ,
688+ postMessageToWebview : vi . fn ( ) ,
689+ } )
690+
691+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
692+ askApproval : mockAskApproval ,
693+ handleError : mockHandleError ,
694+ pushToolResult : mockPushToolResult ,
695+ } )
696+
697+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
698+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "[1 image(s) received]" , [
699+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ" ,
700+ ] )
701+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "with 1 image(s)" ) )
702+ } )
703+
704+ it ( "should handle tool response with both text and image content" , async ( ) => {
705+ const block : ToolUse = {
706+ type : "tool_use" ,
707+ name : "use_mcp_tool" ,
708+ params : {
709+ server_name : "figma-server" ,
710+ tool_name : "get_node_info" ,
711+ arguments : '{"nodeId": "123"}' ,
712+ } ,
713+ nativeArgs : {
714+ server_name : "figma-server" ,
715+ tool_name : "get_node_info" ,
716+ arguments : { nodeId : "123" } ,
717+ } ,
718+ partial : false ,
719+ }
720+
721+ mockAskApproval . mockResolvedValue ( true )
722+
723+ const mockToolResult = {
724+ content : [
725+ { type : "text" , text : "Node name: Button" } ,
726+ {
727+ type : "image" ,
728+ mimeType : "image/png" ,
729+ data : "base64imagedata" ,
730+ } ,
731+ ] ,
732+ isError : false ,
733+ }
734+
735+ mockProviderRef . deref . mockReturnValue ( {
736+ getMcpHub : ( ) => ( {
737+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
738+ getAllServers : vi
739+ . fn ( )
740+ . mockReturnValue ( [
741+ { name : "figma-server" , tools : [ { name : "get_node_info" , description : "Get node info" } ] } ,
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+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
754+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Node name: Button" , [
755+ "data:image/png;base64,base64imagedata" ,
756+ ] )
757+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "with 1 image(s)" ) )
758+ } )
759+
760+ it ( "should handle image with data URL already formatted" , async ( ) => {
761+ const block : ToolUse = {
762+ type : "tool_use" ,
763+ name : "use_mcp_tool" ,
764+ params : {
765+ server_name : "figma-server" ,
766+ tool_name : "get_screenshot" ,
767+ arguments : '{"nodeId": "123"}' ,
768+ } ,
769+ nativeArgs : {
770+ server_name : "figma-server" ,
771+ tool_name : "get_screenshot" ,
772+ arguments : { nodeId : "123" } ,
773+ } ,
774+ partial : false ,
775+ }
776+
777+ mockAskApproval . mockResolvedValue ( true )
778+
779+ const mockToolResult = {
780+ content : [
781+ {
782+ type : "image" ,
783+ mimeType : "image/jpeg" ,
784+ data : "data:image/jpeg;base64,/9j/4AAQSkZJRg==" ,
785+ } ,
786+ ] ,
787+ isError : false ,
788+ }
789+
790+ mockProviderRef . deref . mockReturnValue ( {
791+ getMcpHub : ( ) => ( {
792+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
793+ getAllServers : vi
794+ . fn ( )
795+ . mockReturnValue ( [
796+ {
797+ name : "figma-server" ,
798+ tools : [ { name : "get_screenshot" , description : "Get screenshot" } ] ,
799+ } ,
800+ ] ) ,
801+ } ) ,
802+ postMessageToWebview : vi . fn ( ) ,
803+ } )
804+
805+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
806+ askApproval : mockAskApproval ,
807+ handleError : mockHandleError ,
808+ pushToolResult : mockPushToolResult ,
809+ } )
810+
811+ // Should not double-prefix the data URL
812+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "[1 image(s) received]" , [
813+ "data:image/jpeg;base64,/9j/4AAQSkZJRg==" ,
814+ ] )
815+ } )
816+
817+ it ( "should handle multiple images in response" , async ( ) => {
818+ const block : ToolUse = {
819+ type : "tool_use" ,
820+ name : "use_mcp_tool" ,
821+ params : {
822+ server_name : "figma-server" ,
823+ tool_name : "get_screenshots" ,
824+ arguments : '{"nodeIds": ["1", "2"]}' ,
825+ } ,
826+ nativeArgs : {
827+ server_name : "figma-server" ,
828+ tool_name : "get_screenshots" ,
829+ arguments : { nodeIds : [ "1" , "2" ] } ,
830+ } ,
831+ partial : false ,
832+ }
833+
834+ mockAskApproval . mockResolvedValue ( true )
835+
836+ const mockToolResult = {
837+ content : [
838+ {
839+ type : "image" ,
840+ mimeType : "image/png" ,
841+ data : "image1data" ,
842+ } ,
843+ {
844+ type : "image" ,
845+ mimeType : "image/png" ,
846+ data : "image2data" ,
847+ } ,
848+ ] ,
849+ isError : false ,
850+ }
851+
852+ mockProviderRef . deref . mockReturnValue ( {
853+ getMcpHub : ( ) => ( {
854+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
855+ getAllServers : vi
856+ . fn ( )
857+ . mockReturnValue ( [
858+ {
859+ name : "figma-server" ,
860+ tools : [ { name : "get_screenshots" , description : "Get screenshots" } ] ,
861+ } ,
862+ ] ) ,
863+ } ) ,
864+ postMessageToWebview : vi . fn ( ) ,
865+ } )
866+
867+ await useMcpToolTool . handle ( mockTask as Task , block as any , {
868+ askApproval : mockAskApproval ,
869+ handleError : mockHandleError ,
870+ pushToolResult : mockPushToolResult ,
871+ } )
872+
873+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "[2 image(s) received]" , [
874+ "data:image/png;base64,image1data" ,
875+ "data:image/png;base64,image2data" ,
876+ ] )
877+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( expect . stringContaining ( "with 2 image(s)" ) )
878+ } )
879+ } )
639880} )
0 commit comments