Skip to content

Conversation

dak2
Copy link
Contributor

@dak2 dak2 commented Aug 24, 2025

Motivation and Context

If the server accepts JSON-RPC notifications and responses, it must return an HTTP status code of 202 without a body.

refs

How Has This Been Tested?

  • Check existing and added test cases for this case.
  • Confirm the server returns 202 when the client sends a notification or response.

Breaking Changes

There is a possibility that, if users depend on status code 200.

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

Additional context

Follow up: #111

@atesgoral
Copy link
Contributor

atesgoral commented Aug 29, 2025

On the tests: I don't see anywhere in either the MCP or the JSON-RPC spec where a result or error property is used in a request with an id. These are response properties. Requests have method and params.

…fications and responses

If the server accepts JSON-RPC notifications and responses, it must return an HTTP status code of 202 without a body.

refs
- https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#sending-messages-to-the-server
- https://www.jsonrpc.org/specification

Follow up: modelcontextprotocol#111
@dak2
Copy link
Contributor Author

dak2 commented Sep 1, 2025

@atesgoral
Thanks for your review.

As you pointed out, it seems I misunderstood. I've deleted the test case I added.

Also, I believe this case is already covered by an existing test in test/mcp/server/transports/streamable_http_transport_test.rb (the case where a server returns 202 when a JSON-RPC notification request object is passed, and 200 when a JSON-RPC regular request object is passed), so I haven't added any specific tests.

Could you please review it again?

@koic
Copy link
Member

koic commented Sep 1, 2025

It seems odd that there is no reproduction test. Without a reproduction case for this issue, wouldn't it be difficult to notice if a regression occurs?

@dak2
Copy link
Contributor Author

dak2 commented Sep 1, 2025

@koic

Thanks for your checking!

I believe the following three points need to be verified for this requirement:

  1. When receiving a JSON-RPC notification object, return a 202 status code without a response body.
  2. When receiving a JSON-RPC response object, return a 202 status code without a response body.
  3. Do not return a 202 when receiving a regular JSON-RPC request object.

Regarding the second point, as atesgoral pointed out, since it's a response object, it doesn't get passed as a request in the first place, so I don't believe it needs to be verified in testing.

For case 1, see lines

test "POST notifications/initialized returns 202 with no body" do
# Create a session first (optional for notification, but keep consistent with flow)
init_request = create_rack_request(
"POST",
"/",
{ "CONTENT_TYPE" => "application/json" },
{ jsonrpc: "2.0", method: "initialize", id: "init" }.to_json,
)
init_response = @transport.handle_request(init_request)
session_id = init_response[1]["Mcp-Session-Id"]
notif_request = create_rack_request(
"POST",
"/",
{
"CONTENT_TYPE" => "application/json",
"HTTP_MCP_SESSION_ID" => session_id,
},
{ jsonrpc: "2.0", method: MCP::Methods::NOTIFICATIONS_INITIALIZED }.to_json,
)
response = @transport.handle_request(notif_request)
assert_equal 202, response[0]
assert_empty(response[1])
assert_empty(response[2])
end
, and case 3 is
test "handles POST request with valid JSON-RPC message" do
# First create a session
init_request = create_rack_request(
"POST",
"/",
{ "CONTENT_TYPE" => "application/json" },
{ jsonrpc: "2.0", method: "initialize", id: "init" }.to_json,
)
init_response = @transport.handle_request(init_request)
session_id = init_response[1]["Mcp-Session-Id"]
# Now make the ping request with the session ID
request = create_rack_request(
"POST",
"/",
{
"CONTENT_TYPE" => "application/json",
"HTTP_MCP_SESSION_ID" => session_id,
},
{ jsonrpc: "2.0", method: "ping", id: "123" }.to_json,
)
response = @transport.handle_request(request)
assert_equal 200, response[0]
assert_equal({ "Content-Type" => "application/json" }, response[1])
body = JSON.parse(response[2][0])
assert_equal "2.0", body["jsonrpc"]
assert_equal "123", body["id"]
assert_empty(body["result"])
end

I believe these cases is already covered by above test cases, so I don't think we need to write additional tests.
What do you think about this?

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.

3 participants