Skip to content

McpError raised in tool handlers is swallowed as isError:true instead of propagating as JSON-RPC error #2770

Description

@mengyunxie

Bug

When a tool handler raises McpError, the call_tool handler in src/mcp/server/lowlevel/server.py catches it via except Exception as e and wraps it as CallToolResult(isError=True). This loses the structured error code on the wire.

The existing UrlElicitationRequiredError (a subclass of McpError) already has a raise bypass for exactly this reason, but the parent McpError class does not.

Note: The v2 high-level API (src/mcp/server/mcpserver/server.py on main) already handles this correctly with except MCPError: raise.
This issue is specific to the v1.x decorator-based low-level server.

Expected behavior

McpError raised in a tool handler should propagate to the transport layer's _handle_request, which converts it to a JSON-RPC error response with the structured error code preserved — the same behavior as UrlElicitationRequiredError.

Reproduction

  from mcp.shared.exceptions import McpError
  
  @server.call_tool()
  async def handle_call_tool(name, arguments):
      raise McpError(code=-32000, message="server fault")
      # Actual: client sees CallToolResult(isError=True, content="server fault")
      # Expected: client sees JSON-RPC error with code=-32000

Proposed fix

In src/mcp/server/lowlevel/server.py, replace the tool call handler's exception chain:

  # Before:
  except UrlElicitationRequiredError:
      raise
  except Exception as e:
      return self._make_error_result(str(e))
  # After:
  except McpError:
      raise
  except Exception as e:
      return self._make_error_result(str(e))

This subsumes the existing except UrlElicitationRequiredError: raise since it's a subclass of McpError.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions