Skip to content

MCP tool errors lose ErrorData and become HTTP 500 with traceback #336

@M4n5ter

Description

@M4n5ter

Problem

When calling MCP tools through the runtime HTTP API, tool failures are surfaced as a generic HTTP 500 string, and the original MCP ErrorData (especially data) is lost. The error message also includes a full traceback, which is noisy for end users.

This makes it hard for adapters like sandbox_tool_adapter to display the real error cause (e.g., invalid patch: The last line of the patch must be '*** End Patch').

Examples (actual outputs)

Initial error (only HTTP error string):

[{"type": "text", "text": "500 Server Error: Internal Server Error for url: http://localhost:49156/fastapi/mcp/call_tool"}]

After adding custom handling on the client side, we can see more detail, but it is still wrapped in a 500 error + traceback and ErrorData.data is lost:

[{"type": "text", "text": "MCP tool call failed: apply_patch\nstatus=500\nendpoint=http://10.10.2.200:49156/fastapi/mcp/call_tool\ndetail:\ninvalid patch: Traceback (most recent call last):\n  File \"/agentscope_runtime/routers/mcp.py\", line 162, in call_tool\n    result = await server.call_tool(tool_name, arguments)\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/agentscope_runtime/routers/mcp_utils.py\", line 158, in call_tool\n    result = await self.session.call_tool(tool_name, arguments)\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/agentscope_runtime/venv/lib/python3.11/site-packages/mcp/client/session.py\", line 277, in call_tool\n    return await self.send_request(\n           ^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/agentscope_runtime/venv/lib/python3.11/site-packages/mcp/shared/session.py\", line 294, in send_request\n    raise McpError(response_or_error.error)\nmcp.shared.exceptions.McpError: invalid patch\n"}]

Current workaround in our stack (not ideal; just shows we are forced to flatten the error ourselves):

[{"type": "text", "text": "{\"code\":\"INVALID_PARAMS\",\"data\":{\"error\":\"invalid patch: The last line of the patch must be '*** End Patch'\"},\"message\":\"invalid patch\"}"}]

Expected behavior

For MCP tool errors, preserve the original ErrorData (code/message/data) and avoid wrapping it into an HTTP 500 + traceback. Ideally, the runtime should return a normal CallToolResult with isError=true and put the structured error into structuredContent, so client adapters can display meaningful error details without custom hacks.

Suspected locations

  • src/agentscope_runtime/sandbox/box/shared/routers/mcp.py catches all exceptions and raises HTTPException with detail=traceback, which discards ErrorData.data.
  • src/agentscope_runtime/sandbox/client/http_client.py returns only str(e) on non-2xx responses, so the response body is lost even if it contains error details.

Question

Is the intended design to surface tool failures via CallToolResult.isError=true rather than raising HTTP 500? If so, I can prepare a PR to:

  1. Convert McpError to CallToolResult in the runtime router, preserving code/message/data.
  2. Improve the HTTP client to parse error responses when non-2xx.

Would this be acceptable to maintainers?

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions