@@ -333,6 +333,135 @@ describe("useMcpToolTool", () => {
333333 expect ( mockPushToolResult ) . toHaveBeenCalledWith ( "Tool result: (with 1 images)" )
334334 } )
335335
336+ it ( "should handle corrupted base64 image data gracefully" , async ( ) => {
337+ const block : ToolUse = {
338+ type : "tool_use" ,
339+ name : "use_mcp_tool" ,
340+ params : {
341+ server_name : "test_server" ,
342+ tool_name : "test_tool" ,
343+ arguments : '{"param": "value"}' ,
344+ } ,
345+ partial : false ,
346+ }
347+
348+ mockAskApproval . mockResolvedValue ( true )
349+
350+ const mockToolResult = {
351+ content : [
352+ { type : "text" , text : "Generated content with images:" } ,
353+ {
354+ type : "image" ,
355+ data : "invalid@base64@data" , // Invalid base64 characters
356+ mimeType : "image/png" ,
357+ } ,
358+ {
359+ type : "image" ,
360+ data : "" , // Empty base64 data
361+ mimeType : "image/png" ,
362+ } ,
363+ {
364+ type : "image" ,
365+ data : "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChAI9jU" , // Valid base64
366+ mimeType : "image/png" ,
367+ } ,
368+ ] ,
369+ isError : false ,
370+ }
371+
372+ mockProviderRef . deref . mockReturnValue ( {
373+ getMcpHub : ( ) => ( {
374+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
375+ } ) ,
376+ postMessageToWebview : vi . fn ( ) ,
377+ } )
378+
379+ // Spy on console.warn to verify error logging
380+ const consoleSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
381+
382+ await useMcpToolTool (
383+ mockTask as Task ,
384+ block ,
385+ mockAskApproval ,
386+ mockHandleError ,
387+ mockPushToolResult ,
388+ mockRemoveClosingTag ,
389+ )
390+
391+ // Should continue processing despite corrupted images
392+ expect ( mockTask . consecutiveMistakeCount ) . toBe ( 0 )
393+ expect ( mockAskApproval ) . toHaveBeenCalled ( )
394+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_request_started" )
395+
396+ // Should only include the valid image, not the corrupted ones
397+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Generated content with images:" , [
398+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPhfDwAChAI9jU" ,
399+ ] )
400+ expect ( mockPushToolResult ) . toHaveBeenCalledWith (
401+ "Tool result: Generated content with images: (with 1 images)" ,
402+ )
403+
404+ // Should log warnings for corrupted images
405+ expect ( consoleSpy ) . toHaveBeenCalledWith ( "Invalid MCP ImageContent: base64 data contains invalid characters" )
406+ expect ( consoleSpy ) . toHaveBeenCalledWith ( "Invalid MCP ImageContent: base64 data is not a valid string" )
407+
408+ consoleSpy . mockRestore ( )
409+ } )
410+
411+ it ( "should handle non-string base64 data" , async ( ) => {
412+ const block : ToolUse = {
413+ type : "tool_use" ,
414+ name : "use_mcp_tool" ,
415+ params : {
416+ server_name : "test_server" ,
417+ tool_name : "test_tool" ,
418+ arguments : '{"param": "value"}' ,
419+ } ,
420+ partial : false ,
421+ }
422+
423+ mockAskApproval . mockResolvedValue ( true )
424+
425+ const mockToolResult = {
426+ content : [
427+ { type : "text" , text : "Some text" } ,
428+ {
429+ type : "image" ,
430+ data : 12345 , // Non-string data
431+ mimeType : "image/png" ,
432+ } ,
433+ ] ,
434+ isError : false ,
435+ }
436+
437+ mockProviderRef . deref . mockReturnValue ( {
438+ getMcpHub : ( ) => ( {
439+ callTool : vi . fn ( ) . mockResolvedValue ( mockToolResult ) ,
440+ } ) ,
441+ postMessageToWebview : vi . fn ( ) ,
442+ } )
443+
444+ const consoleSpy = vi . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } )
445+
446+ await useMcpToolTool (
447+ mockTask as Task ,
448+ block ,
449+ mockAskApproval ,
450+ mockHandleError ,
451+ mockPushToolResult ,
452+ mockRemoveClosingTag ,
453+ )
454+
455+ // Should process text content normally
456+ expect ( mockTask . say ) . toHaveBeenCalledWith ( "mcp_server_response" , "Some text" , [ ] )
457+ expect ( mockPushToolResult ) . toHaveBeenCalledWith ( "Tool result: Some text" )
458+
459+ // Should log warning for invalid data type
460+ expect ( consoleSpy ) . toHaveBeenCalledWith ( "Invalid MCP ImageContent: base64 data is not a valid string" )
461+
462+ consoleSpy . mockRestore ( )
463+ } )
464+
336465 it ( "should handle user rejection" , async ( ) => {
337466 const block : ToolUse = {
338467 type : "tool_use" ,
0 commit comments