Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Http errors are not handled properly by streamable_http #1835

Copy link
Copy link
@yuxiaorun

Description

@yuxiaorun
Issue body actions

Initial Checks

Description

Description

When using Kiro-CLI with a remote fastMCP server, one issue was observed that when the MCP tool call gets a 403 http error, the cli would hang indefinitely instead of showing an error response.

Root Cause

In mcp/client/streamable_http.py, the _handle_post_request() method calls response.raise_for_status() but doesn't catch the resulting httpx.HTTPStatusError exception and convert it to an MCP error response. Without a response message, the client waits indefinitely.

Expected Behavior

HTTP errors should be caught and converted to MCP JSON-RPC error responses so clients can handle them gracefully.

Proposed Fix

Wrap the response.raise_for_status() call in a try/except block that catches httpx.HTTPStatusError and:

  1. Creates a JSONRPCError with appropriate error details
  2. Sends it to the read stream so the client receives the error

The temporary patch that fixs the problem:

@wraps(original_handle_post_request)
    async def _handle_post_request_patched(self, ctx: RequestContext) -> None:  # type: ignore
        """Patched version of _handle_post_request that converts HTTP errors to MCP errors.
        
        This ensures that HTTP errors (like 403 Forbidden) during tool calls are properly
        converted to MCP error messages and sent back to the client, preventing hangs.
        """
        try:
            return await original_handle_post_request(self, ctx)
        except httpx.HTTPStatusError as http_error:
            logger.warning('HTTP error in MCP client: %s %s', http_error.response.status_code, http_error.request.url)
            
            # Extract the request ID if this was a request (not a notification)
            message = ctx.session_message.message
            request_id = None
            if isinstance(message.root, mcp.types.JSONRPCRequest):
                request_id = message.root.id
            
            if request_id is not None:
                # Try to parse the error response as an MCP error
                response = http_error.response
                try:
                    await response.aread()
                    error_body = response.json()
                    error_message = error_body.get('message', f'HTTP {response.status_code} error')
                except Exception:
                    error_message = f'HTTP {response.status_code} error'
                
                # Create an MCP error response
                jsonrpc_error = mcp.types.JSONRPCError(
                    jsonrpc="2.0",
                    id=request_id,
                    error=mcp.types.ErrorData(
                        code=-32603,  # Internal error
                        message=error_message
                    )
                )
                
                # Send the error to the read stream
                session_message = SessionMessage(mcp.types.JSONRPCMessage(jsonrpc_error))
                await ctx.read_stream_writer.send(session_message)
                logger.info('Sent MCP error response for HTTP %s', response.status_code)
            else:
                # For notifications, just log the error
                logger.debug('HTTP error for notification (no response sent): %s', http_error)

    StreamableHTTPTransport._handle_post_request = _handle_post_request_patched
    logger.info('Successfully patched MCP client StreamableHTTPTransport._handle_post_request')

Python & MCP Python SDK

python: 3.10.0
MCP SDK: 1.25.0
Reactions are currently unavailable

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

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.