McpTool drops structuredContent and non-text content from CallToolResult
- Dominant language
- Java
- Stars
- 1.7k
- Forks
- 420
- Avg merge
- 4d 12h
- Merged PRs (30d)
- 31
Description
## 🔴 Required Information
**Describe the Bug:**
`AbstractMcpTool.wrapCallResult(...)` silently discards parts of a successful MCP `CallToolResult`.
When the result contains at least one `TextContent`, native `McpTool.runAsync(...)` returns only the legacy `text_output` map. It does not expose:
* `CallToolResult.isError` on successful results
* `CallToolResult.structuredContent`
* non-text `content` entries such as images or embedded resources
* the original ordered content list
This loss is irreversible for callers. An outer `BaseTool` decorator sees only the already-reduced map and cannot recover the discarded fields without bypassing native `McpTool` and invoking `McpSyncClient` itself.
**Steps to Reproduce:**
1. Use `com.google.adk:google-adk:1.7.1`.
2. Construct a native `McpToolset` over a streamable-HTTP MCP server.
3. Have the server advertise a zero-argument tool.
4. Return this successful `tools/call` result:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{"type": "text", "text": "first"},
{"type": "text", "text": "second"},
{
"type": "image",
"data": "aW1hZ2U=",
"mimeType": "image/png"
}
],
"structuredContent": {"count": 2},
"isError": false
}
}
```
5. Call the discovered native tool through `BaseTool.runAsync(...)`.
**Expected Behavior:**
Native MCP tools should preserve the complete semantic `CallToolResult`, including structured content and non-text content, without breaking callers that consume the existing `text_output` field.
A compatible resolution could be either:
1. An additive envelope that retains `text_output` unchanged while also exposing `content`, `structuredContent`, `isError`, and metadata.
2. A supported result-mapper/adapter hook on `McpToolset` or `McpTool` that receives the raw `CallToolResult` before reduction.
**Observed Behavior:**
The returned map contains only:
```text
{text_output=[{text=first}, {text=second}]}
```
`structuredContent`, image data and MIME type, the original content parts, and explicit non-error state are absent.
The loss is silent. No exception or warning indicates that valid MCP response data was discarded.
**Environment Details:**
* ADK Library Version (see maven dependency): `1.7.1`
* MCP Java SDK resolved by ADK: `1.1.2`
* MCP transport: streamable HTTP
* Java: 21
## 🟡 Optional Information
**Regression:**
No
**Additional Context:**
PR #1078 changed `wrapCallResult` to serialize the complete `CallToolResult`, but PR #1090 reverted that change to preserve backward compatibility with `text_output`.
The requested fix is therefore not to remove `text_output`. It is to preserve compatibility without silently losing the remaining MCP result fields.
This blocks replacing a custom MCP bridge with native `McpToolset`: the custom implementation currently preserves text, `structuredContent`, non-text content parts, and error state, while native `McpTool` does not.
**Minimal Reproduction Code:**
N/A. The issue can be reproduced using the MCP response above and a native `McpToolset` over a streamable-HTTP MCP server.
**How often has this issue occurred?:**
* Always (100%)
Contributor guide
Assessment
This issue has not been assessed yet.