diff --git a/lib/mcp/server/transports/streamable_http_transport.rb b/lib/mcp/server/transports/streamable_http_transport.rb index be5404a..06b6323 100644 --- a/lib/mcp/server/transports/streamable_http_transport.rb +++ b/lib/mcp/server/transports/streamable_http_transport.rb @@ -155,8 +155,10 @@ def handle_delete(request) end return missing_session_id_response unless (session_id = request.env["HTTP_MCP_SESSION_ID"]) + return session_not_found_response unless session_exists?(session_id) cleanup_session(session_id) + success_response end diff --git a/test/mcp/server/transports/streamable_http_transport_test.rb b/test/mcp/server/transports/streamable_http_transport_test.rb index abeb2e5..ebc1e1c 100644 --- a/test/mcp/server/transports/streamable_http_transport_test.rb +++ b/test/mcp/server/transports/streamable_http_transport_test.rb @@ -332,6 +332,84 @@ class StreamableHTTPTransportTest < ActiveSupport::TestCase assert body["success"] end + test "handles DELETE request with invalid session ID" do + request = create_rack_request( + "DELETE", + "/", + { "HTTP_MCP_SESSION_ID" => "invalid_id" }, + ) + + response = @transport.handle_request(request) + assert_equal 404, response[0] + assert_equal({ "Content-Type" => "application/json" }, response[1]) + + body = JSON.parse(response[2][0]) + assert_equal "Session not found", body["error"] + end + + test "POST returns 404 after session is deleted" do + 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"] + + delete_request = create_rack_request( + "DELETE", + "/", + { "HTTP_MCP_SESSION_ID" => session_id }, + ) + @transport.handle_request(delete_request) + + post_request = create_rack_request( + "POST", + "/", + { + "CONTENT_TYPE" => "application/json", + "HTTP_MCP_SESSION_ID" => session_id, + }, + { jsonrpc: "2.0", method: "ping", id: "456" }.to_json, + ) + response = @transport.handle_request(post_request) + assert_equal 404, response[0] + + body = JSON.parse(response[2][0]) + assert_equal "Session not found", body["error"] + end + + test "DELETE returns 404 after session is already deleted" do + 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"] + + first_delete = create_rack_request( + "DELETE", + "/", + { "HTTP_MCP_SESSION_ID" => session_id }, + ) + response = @transport.handle_request(first_delete) + assert_equal 200, response[0] + + second_delete = create_rack_request( + "DELETE", + "/", + { "HTTP_MCP_SESSION_ID" => session_id }, + ) + response = @transport.handle_request(second_delete) + assert_equal 404, response[0] + + body = JSON.parse(response[2][0]) + assert_equal "Session not found", body["error"] + end + test "handles DELETE request with missing session ID" do request = create_rack_request( "DELETE",