fix: include both file paths and raw base64 data in MCP image responses

Pass both source_path and raw base64 data URLs to the LLM in MCP tool
image responses. This ensures the model can analyze images in the current
turn (via base64 data) while still benefiting from path-based persistence
for future context (via source_path).
This commit is contained in:
Roo Code 2026-02-06 20:46:05 +00:00
parent 98bed42dec
commit d4c77b63d5
2 changed files with 20 additions and 9 deletions

View file

@ -325,17 +325,18 @@ export class UseMcpToolTool extends BaseTool<"use_mcp_tool"> {
// Build the result text
let resultText = outputText || ""
// If there are images, save them to temp storage and provide file paths to the LLM
// This avoids passing raw base64 through LLM context which causes corruption and high costs
// If there are images, save them to temp storage and provide both file paths and raw data to the LLM.
// File paths enable efficient persistence for future context, while raw base64 data allows
// the model to analyze images in the current turn.
if (images.length > 0) {
const savedImagePaths = await this.saveImagesToTempStorage(task, images, serverName, toolName)
const imagePathsSection = savedImagePaths
.map(
(imgPath, index) =>
`<image_${index + 1}>\n <source_path>${imgPath}</source_path>\n</image_${index + 1}>`,
`<image_${index + 1}>\n <source_path>${imgPath}</source_path>\n <data>${images[index]}</data>\n</image_${index + 1}>`,
)
.join("\n\n")
const imageInfo = `\n\n[${images.length} image(s) received and saved to temporary storage. Use save_image tool with source_path to save to your desired location.]\n\n${imagePathsSection}`
const imageInfo = `\n\n[${images.length} image(s) received and saved to temporary storage. Use save_image tool with source_path (preferred) or data to save to your desired location.]\n\n${imagePathsSection}`
resultText = resultText ? resultText + imageInfo : imageInfo.trim()
}

View file

@ -658,16 +658,21 @@ describe("useMcpToolTool", () => {
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining(
"[1 image(s) received and saved to temporary storage. Use save_image tool with source_path to save to your desired location.]",
"[1 image(s) received and saved to temporary storage. Use save_image tool with source_path (preferred) or data to save to your desired location.]",
),
["data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJ"],
)
// Text response should contain source_path XML tags, not raw base64
// Text response should contain both source_path and data XML tags
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining("<source_path>"),
expect.anything(),
)
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining("<data>"),
expect.anything(),
)
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("with 1 image(s)"))
})
@ -726,12 +731,17 @@ describe("useMcpToolTool", () => {
expect.stringContaining("Node name: Button"),
["data:image/png;base64,base64imagedata"],
)
// Text response should contain source_path, not raw base64
// Text response should contain both source_path and data XML tags
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining("<source_path>"),
expect.anything(),
)
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining("<data>"),
expect.anything(),
)
expect(mockPushToolResult).toHaveBeenCalledWith(expect.stringContaining("with 1 image(s)"))
})
@ -788,7 +798,7 @@ describe("useMcpToolTool", () => {
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining(
"[1 image(s) received and saved to temporary storage. Use save_image tool with source_path to save to your desired location.]",
"[1 image(s) received and saved to temporary storage. Use save_image tool with source_path (preferred) or data to save to your desired location.]",
),
["data:image/jpeg;base64,/9j/4AAQSkZJRg=="],
)
@ -851,7 +861,7 @@ describe("useMcpToolTool", () => {
expect(mockTask.say).toHaveBeenCalledWith(
"mcp_server_response",
expect.stringContaining(
"[2 image(s) received and saved to temporary storage. Use save_image tool with source_path to save to your desired location.]",
"[2 image(s) received and saved to temporary storage. Use save_image tool with source_path (preferred) or data to save to your desired location.]",
),
["data:image/png;base64,image1data", "data:image/png;base64,image2data"],
)