Skip to content

AnthropicLlm sends failed MCP tool results to Claude with is_error=False聽#7664

Closed

Description

@AkshayShah03

馃敶 Required Information

Describe the Bug:
When an MCP tool call fails, Claude is told it succeeded. The MCP server returns a CallToolResult with isError: true, and McpTool passes that result on as the function response. AnthropicLlm then builds the tool_result block with is_error=False hardcoded (_part_to_message_block in src/google/adk/models/anthropic_llm.py). Claude receives the error text as a successful result, so it may treat the error message as data instead of recovering from the failure.

McpTool._detect_error_in_response already reads the same flag (both isError and is_error) for telemetry, so ADK knows the call failed; only the Anthropic request loses it.

Steps to Reproduce:

  1. pip install google-adk==2.11.0 anthropic
  2. Run the snippet below. It calls the conversion function directly, so no API key is needed.

Expected Behavior:

'file not found: notes.txt' is_error = True

Observed Behavior:

'file not found: notes.txt' is_error = False

Environment Details:

  • ADK Library Version: 2.11.0 (also reproduced on main at d324744)
  • Desktop OS: macOS
  • Python Version: 3.12.13

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: Claude via AnthropicLlm / Claude

馃煛 Optional Information

Minimal Reproduction Code:

from google.adk.models.anthropic_llm import part_to_message_block
from google.genai import types

# What McpTool returns when an MCP server reports a failed call.
part = types.Part.from_function_response(
    name="read_file",
    response={
        "content": [{"type": "text", "text": "file not found: notes.txt"}],
        "isError": True,
    },
)
part.function_response.id = "toolu_1"

block = part_to_message_block(part)
print(repr(block["content"]), "is_error =", block["is_error"])

How often has this issue occurred?:

  • Always (100%)

Proposed fix: Set is_error from the response's isError (or is_error) flag instead of hardcoding False. I have a small PR ready with unit tests.

A related question (not part of that PR): when a tool result has a content key, _part_to_message_block sends only that value and drops every other key. That seems intended for load_skill_resource (there is a test asserting its skill_name and file_path are dropped). For other tools it loses data, for example {"content": ["a", "b"], "next_page_token": "tok2"} reaches Claude as "a\nb", without the pagination token. Would you like that narrowed (for example, only take the shortcut for MCP results and load_skill_resource, and JSON-encode everything else, as the result branch does since #7073)? I'm happy to file it separately if so.

Activity

  1. added
    models[Component] This issue is related to model support
    mcp[Component] This issues is related to MCP support
    on Oct 22, 2026
  2. added a commit that references this issue on Oct 22, 2026
    37b1ab3
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

mcp[Component] This issues is related to MCP supportmodels[Component] This issue is related to model support

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions