Skip to content

fix: report MCP isError as ToolFailure on the external URL path - #7643

Open
BlueX888 wants to merge 2 commits into
crewAIInc:mainfrom
BlueX888:fix/prep-mcp-external-iserror-reported-as-success
Open

BlueX888 wants to merge 2 commits into
crewAIInc:mainfrom
BlueX888:fix/prep-mcp-external-iserror-reported-as-success

Conversation

@BlueX888

Copy link
Copy Markdown
Contributor

Summary

MCPToolWrapper (the external HTTPS URL resolution path used by mcp/tool_resolver.py::_resolve_external) returned the response text unconditionally from _execute_tool and never inspected the isError flag an MCP server sets on an otherwise successful tools/call response (lib/crewai/src/crewai/tools/mcp_tool_wrapper.py:185-187 on main). The error text reached the framework as a plain str, so the call was recorded as a success: no ToolFailureDetectedEvent and ToolOutput.has_tool_failures stayed false. MCPNativeTool already handles the same server answer by returning ToolFailure(reason=MCP_ERROR) (lib/crewai/src/crewai/tools/mcp_native_tool.py:135-145).

Changes

_execute_tool now checks result.isError after extracting the content and returns ToolFailure(message=content, reason=ToolFailureReason.MCP_ERROR, details={"server": ..., "tool": ...}), matching MCPNativeTool. Signatures along the retry path are widened to str | ToolFailure. Successful calls are unchanged.

Verification

  • Tests added or updated for the changed behavior

  • Relevant tests and quality checks pass locally

  • python -m pytest tests/tools/test_mcp_tool_wrapper.py -p no:randomly -q (from lib/crewai) — 2 passed

  • With the source change reverted (tests only), the new test fails with AssertionError: assert False + where False = isinstance('Error: file not found', ToolFailure), confirming the old code reported the server error as a success

  • python -m pytest tests/tools/ tests/mcp/ -p no:randomly -q — 326 passed

  • ruff check lib/crewai/src/crewai/tools/mcp_tool_wrapper.py lib/crewai/tests/tools/test_mcp_tool_wrapper.py — All checks passed

  • mypy lib/crewai/src/crewai/tools/mcp_tool_wrapper.py — Success: no issues found in 1 source file

Additional context

This PR was authored by an AI coding agent. Per .github/CONTRIBUTING.md it should carry the llm-generated label; I don't have permission to apply labels, so a maintainer would need to add it.

MCPToolWrapper returned the error text as a plain str when a server answered tools/call with isError=true, so the framework recorded the call as a success: no ToolFailureDetectedEvent, no ToolOutput.has_tool_failures. MCPNativeTool already reported the same server answer as ToolFailure(reason=MCP_ERROR).
@coderabbitai

coderabbitai Bot commented Sep 20, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 3c532ff0-d892-45f8-951f-8634fc5d65bc

📥 Commits

Reviewing files that changed from the base of the PR and between 0374c63 and 74a1d99.

📒 Files selected for processing (2)
  • lib/crewai/src/crewai/tools/mcp_tool_wrapper.py
  • lib/crewai/tests/tools/test_mcp_tool_wrapper.py

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

MCPToolWrapper now returns structured ToolFailure objects for MCP error responses. Successful responses still return text. Execution and retry helpers now propagate the wider return type, with tests covering both outcomes.

Changes

MCP error handling

Layer / File(s) Summary
ToolFailure return propagation
lib/crewai/src/crewai/tools/mcp_tool_wrapper.py
Execution, retry, timeout, and MCP call methods now accept and return str | ToolFailure.
MCP result conversion and validation
lib/crewai/src/crewai/tools/mcp_tool_wrapper.py, lib/crewai/tests/tools/test_mcp_tool_wrapper.py
MCP results now extract content before checking isError. Error results become ToolFailure objects with MCP_ERROR, message content, and server/tool details. Tests cover error and successful responses.

Sequence Diagram(s)

sequenceDiagram
  participant MCPToolWrapper
  participant MCPServer
  participant ToolFailure
  MCPToolWrapper->>MCPServer: call_tool
  MCPServer-->>MCPToolWrapper: CallToolResult with content and isError
  MCPToolWrapper->>ToolFailure: create MCP_ERROR failure when isError is true
  ToolFailure-->>MCPToolWrapper: structured failure
Loading

Priority: ⬇️ Low

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description clearly explains the problem, solution, tests, and quality checks. However, it omits the required Related issue section and does not provide an issue reference. Add the Related issue section with a valid linked open issue, for example: "Fixes #123". If no issue applies, confirm the repository policy with a maintainer before merging.
Docstring Coverage ⚠️ Warning Docstring coverage is 38.89% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 18 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: reporting MCP isError responses as ToolFailure on the external URL path.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant