fix: route MCP tool errors as failed ToolReturnParts instead of raising ModelRetry (#5217)
- Closes #5217
Description
Replaces the rejected implementation from PR #5293 to align with maintainer feedback.
Previously, when a FastMCP or MCP tool encountered an error (isError=True), the framework raised a ToolError or ModelRetry. This forced the agent into an infinite retry loop for non-retryable tool failures (e.g., trying to read a missing file).
This PR alters the behavior so that tool errors are treated as informational context rather than framework crashes:
mcp.py&fastmcp.py: Intercepts the error and returns a standard dictionary containing the error message, flagged internally with_tool_error=True.fastmcp.pynow correctly honors thetool_error_behaviorconfiguration._agent_graph.py: Detects the internal_tool_errorflag on the rawtool_result. It extracts the error message to keep the prompt clean, and constructs theToolReturnPartwithoutcome='failed'.
This allows the LLM to receive the failure message directly in the conversation history, allowing it to adapt its strategy rather than triggering a framework-level retry loop.
Type Safety
Maintained strict mypy compliance by returning standard dicts that satisfy the Any return type on direct_call_tool. outcome='failed' aligns with the allowed literal values for BaseToolReturnPart.
Checklist
- Any AI generated code has been reviewed line-by-line by the human PR author, who stands by it.
- No breaking changes in accordance with the version policy.
- PR title is fit for the release changelog.