diff --git a/core/src/main/java/com/google/adk/tools/mcp/AbstractMcpTool.java b/core/src/main/java/com/google/adk/tools/mcp/AbstractMcpTool.java index 0fcb74846..99d9eb282 100644 --- a/core/src/main/java/com/google/adk/tools/mcp/AbstractMcpTool.java +++ b/core/src/main/java/com/google/adk/tools/mcp/AbstractMcpTool.java @@ -22,6 +22,7 @@ import com.google.adk.tools.BaseTool; import com.google.adk.tools.mcp.McpToolException.McpToolDeclarationException; import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.genai.types.FunctionDeclaration; import io.modelcontextprotocol.spec.McpSchema.CallToolResult; @@ -31,6 +32,7 @@ import io.modelcontextprotocol.spec.McpSchema.Tool; import io.modelcontextprotocol.spec.McpSchema.ToolAnnotations; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -145,11 +147,14 @@ protected static Map wrapCallResult( } if (textOutputs.isEmpty()) { - return ImmutableMap.of( - "error", - "Tool '" + mcpToolName + "' returned content that is not TextContent.", - "content_details", - contents.toString()); + Map result = new HashMap<>(); + result.put("text_output", ImmutableList.of()); + result.put("content", contents); + result.put("isError", Boolean.FALSE); + if (callResult.structuredContent() != null) { + result.put("structuredContent", callResult.structuredContent()); + } + return result; } List> resultMaps = new ArrayList<>(); @@ -161,6 +166,13 @@ protected static Map wrapCallResult( resultMaps.add(ImmutableMap.of("text", textOutput)); } } - return ImmutableMap.of("text_output", resultMaps); + Map result = new HashMap<>(); + result.put("text_output", resultMaps); + result.put("content", contents); + result.put("isError", Boolean.FALSE); + if (callResult.structuredContent() != null) { + result.put("structuredContent", callResult.structuredContent()); + } + return result; } } diff --git a/core/src/test/java/com/google/adk/tools/mcp/AbstractMcpToolTest.java b/core/src/test/java/com/google/adk/tools/mcp/AbstractMcpToolTest.java index 4c633c660..4859512eb 100644 --- a/core/src/test/java/com/google/adk/tools/mcp/AbstractMcpToolTest.java +++ b/core/src/test/java/com/google/adk/tools/mcp/AbstractMcpToolTest.java @@ -25,6 +25,7 @@ import io.modelcontextprotocol.client.McpSyncClient; import io.modelcontextprotocol.spec.McpSchema; import io.modelcontextprotocol.spec.McpSchema.CallToolResult; +import io.modelcontextprotocol.spec.McpSchema.ImageContent; import io.modelcontextprotocol.spec.McpSchema.TextContent; import java.util.List; import java.util.Map; @@ -61,6 +62,43 @@ public void testWrapCallResult_success() { assertThat(contentItem).containsEntry("text", "success"); } + @Test + public void testWrapCallResult_preservesCompleteSuccessfulResult() { + Map structuredContent = Map.of("count", 2); + CallToolResult result = + CallToolResult.builder() + .content( + ImmutableList.of( + new TextContent("first"), + new ImageContent("aW1hZ2U=", "image/png"))) + .structuredContent(structuredContent) + .isError(false) + .build(); + + Map map = AbstractMcpTool.wrapCallResult(objectMapper, "my_tool", result); + + assertThat(map).containsEntry("isError", false); + assertThat(map).containsEntry("structuredContent", structuredContent); + assertThat((List) map.get("content")).hasSize(2); + assertThat(map).containsKey("text_output"); + } + + @Test + public void testWrapCallResult_preservesSuccessfulNonTextResult() { + CallToolResult result = + CallToolResult.builder() + .content(ImmutableList.of(new ImageContent("aW1hZ2U=", "image/png"))) + .isError(false) + .build(); + + Map map = AbstractMcpTool.wrapCallResult(objectMapper, "my_tool", result); + + assertThat(map).containsEntry("isError", false); + assertThat((List) map.get("content")).hasSize(1); + assertThat((List) map.get("text_output")).isEmpty(); + assertThat(map).doesNotContainKey("error"); + } + @Test public void instantiateWithToolBuilder_nullDescription_succeeds() { McpSyncClient sessionMock = mock(McpSyncClient.class);