Skip to content

Accept any 2xx acknowledgement of a notification in the HTTP client - #600

Open
koic wants to merge 1 commit into
modelcontextprotocol:mainfrom
koic:accept_any_2xx_acknowledgement_of_a_notification
Open

koic wants to merge 1 commit into
modelcontextprotocol:mainfrom
koic:accept_any_2xx_acknowledgement_of_a_notification

Conversation

@koic

@koic koic commented Oct 13, 2026

Copy link
Copy Markdown
Member

Motivation and Context

MCP::Client::HTTP treats only 202 Accepted as the acknowledgement of a notification. Any other status goes through the response body resolution, which requires a JSON or SSE content type, so a server that answers notifications/initialized with an empty 200 and no Content-Type fails connect with Unsupported Content-Type: nil (issue #598). The spec has the server answer a notification with 202 and no body, so such a server is out of spec, but a notification awaits no response, and the TypeScript and Python clients check the content type of a response only for a request: any 2xx acknowledges a notification, whatever the body.

The transport now accepts any 2xx without a JSON or SSE body the same way. A notification answered with such a 2xx is acknowledged with nil, and an SSE stream that ends without a response acknowledges it too, with no reconnection, since there is no response to resume for. A JSON or SSE body answering a notification is handed over as before, a 3xx keeps its handling, and a request answered with a 2xx other than 202 and without a JSON or SSE body still fails with unsupported_media_type. send_notification, which MCP::Client#cancel uses, never checked the response; connect keeps sending notifications/initialized through send_request so the 401 and 404 handling applies to it.

Fixes #598.

How Has This Been Tested?

New tests in test/mcp/client/http_test.rb: connect succeeds when the notification is acknowledged with an empty 200, a 204, or a text/plain 200; a notification answered with an SSE stream carrying no response returns nil without reconnecting; a notification answered with a 302 still raises on both paths; a request answered without a JSON or SSE body still raises. Against the previous library the first raises Unsupported Content-Type: nil and the second reconnects.

Breaking Changes

None.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

## Motivation and Context

`MCP::Client::HTTP` treats only `202 Accepted` as the acknowledgement of a notification.
Any other status goes through the response body resolution, which requires a JSON or SSE content type,
so a server that answers `notifications/initialized` with an empty 200 and no `Content-Type` fails `connect` with
`Unsupported Content-Type: nil` (issue modelcontextprotocol#598). The spec has the server answer a notification with 202 and no body,
so such a server is out of spec, but a notification awaits no response, and the TypeScript and Python clients check
the content type of a response only for a request: any 2xx acknowledges a notification, whatever the body.

The transport now accepts any 2xx without a JSON or SSE body the same way. A notification answered with
such a 2xx is acknowledged with `nil`, and an SSE stream that ends without a response acknowledges it too,
with no reconnection, since there is no response to resume for. A JSON or SSE body answering a notification is
handed over as before, a 3xx keeps its handling, and a request answered with a 2xx other than 202 and without
a JSON or SSE body still fails with `unsupported_media_type`. `send_notification`, which `MCP::Client#cancel` uses,
never checked the response; `connect` keeps sending `notifications/initialized` through `send_request`
so the 401 and 404 handling applies to it.

Fixes modelcontextprotocol#598.

## How Has This Been Tested?

New tests in `test/mcp/client/http_test.rb`: `connect` succeeds when the notification is acknowledged with
an empty 200, a 204, or a `text/plain` 200; a notification answered with an SSE stream carrying no response
returns `nil` without reconnecting; a notification answered with a 302 still raises on both paths;
a request answered without a JSON or SSE body still raises.
Against the previous library the first raises `Unsupported Content-Type: nil` and the second reconnects.

## Breaking Changes

None.

@dtjldamien dtjldamien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you!

This branch has not been deployed

No deployments
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.

HTTP client fails connect when the server acknowledges notifications/initialized with an empty 200

2 participants