@@ -241,8 +241,12 @@ private Publisher<Void> createDelete(String sessionId) {
241241 var transportContext = ctx .getOrDefault (McpTransportContext .KEY , McpTransportContext .EMPTY );
242242 return Mono .from (this .httpRequestCustomizer .customize (builder , "DELETE" , uri , null , transportContext ));
243243 })
244- .flatMap (requestBuilder -> Mono .fromFuture (() -> this .httpClient .sendAsync (requestBuilder .build (),
245- ResponseSubscribers .boundedStringBodyHandler (this .maxResponseSize ))))
244+ .flatMap (requestBuilder -> Mono .fromFuture (
245+ () -> this .httpClient .sendAsync (requestBuilder .build (), HttpResponse .BodyHandlers .ofPublisher ()))
246+ // The response is not inspected, but the body still has to be consumed
247+ // to release the connection.
248+ .flatMapMany (response -> ResponseSubscribers .drain (response .body (), this .maxResponseSize ))
249+ .then ())
246250 .then ();
247251 }
248252
@@ -282,7 +286,7 @@ public Mono<Void> closeGracefully() {
282286 private Flux <McpSchema .JSONRPCMessage > consumeSseStream (
283287 java .util .concurrent .Flow .Publisher <List <java .nio .ByteBuffer >> body ,
284288 McpTransportStream <Disposable > existingStream , Runnable onFirstMessage ) {
285- Flux <String > lines = ResponseSubscribers .decodeLines (body );
289+ Flux <String > lines = ResponseSubscribers .decodeLines (body , this . maxResponseSize );
286290 return ResponseSubscribers .decodeSseResponse (lines , this .maxResponseSize ).flatMap (sseEvent -> {
287291 if (!isMessageEvent (sseEvent .event ())) {
288292 logger .debug ("Received SSE event with type: {}" , sseEvent );
@@ -372,8 +376,7 @@ private Mono<Disposable> reconnect(McpTransportStream<Disposable> stream) {
372376 Optional <String > maybeSessionId = request .headers ().firstValue (HttpHeaders .MCP_SESSION_ID );
373377
374378 return Mono
375- .fromFuture (() -> this .httpClient .sendAsync (request ,
376- ResponseSubscribers .boundedPublisherBodyHandler (this .maxResponseSize )))
379+ .fromFuture (() -> this .httpClient .sendAsync (request , HttpResponse .BodyHandlers .ofPublisher ()))
377380 .flatMapMany (httpResponse -> {
378381 int statusCode = httpResponse .statusCode ();
379382 Exception exception = null ;
@@ -430,8 +433,10 @@ else if (statusCode >= 200 && statusCode < 300) {
430433 }
431434
432435 return proceed ? consumeSseStream (httpResponse .body (), stream , null )
433- : exception != null ? ResponseSubscribers .drainThenError (httpResponse .body (), exception )
434- : ResponseSubscribers .drain (httpResponse .body ());
436+ : exception != null
437+ ? ResponseSubscribers .drainThenError (httpResponse .body (), this .maxResponseSize ,
438+ exception )
439+ : ResponseSubscribers .drain (httpResponse .body (), this .maxResponseSize );
435440 });
436441 })
437442 .retryWhen (authorizationErrorRetrySpec ())
@@ -540,7 +545,7 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sentMessage) {
540545 })
541546 .flatMapMany (requestBuilder -> Mono
542547 .fromFuture (() -> this .httpClient .sendAsync (requestBuilder .build (),
543- ResponseSubscribers . boundedPublisherBodyHandler ( this . maxResponseSize )))
548+ HttpResponse . BodyHandlers . ofPublisher ( )))
544549 .flatMapMany (httpResponse -> {
545550 int statusCode = httpResponse .statusCode ();
546551 Optional <String > maybeSessionId = transportSession == null ? Optional .empty ()
@@ -550,7 +555,7 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sentMessage) {
550555 var request = requestBuilder .build ();
551556 var requestSnapshot = new HttpRequestSnapshot (request .uri (), request .method (),
552557 request .headers ());
553- return ResponseSubscribers .drainThenError (httpResponse .body (),
558+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
554559 new McpHttpClientTransportAuthorizationException (
555560 "Authorization error when sending message" , requestSnapshot ,
556561 toResponseInfo (httpResponse )));
@@ -575,7 +580,7 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sentMessage) {
575580 if (contentType .isBlank () || "0" .equals (contentLength ) || statusCode == 202 ) {
576581 logger .debug ("No body returned for POST in session {}" , sessionRepresentation );
577582 deliveredSink .success ();
578- return ResponseSubscribers .drain (httpResponse .body ());
583+ return ResponseSubscribers .drain (httpResponse .body (), this . maxResponseSize );
579584 }
580585 else if (contentType .contains (TEXT_EVENT_STREAM )) {
581586 AtomicBoolean delivered = new AtomicBoolean ();
@@ -607,34 +612,34 @@ else if (contentType.contains(APPLICATION_JSON)) {
607612
608613 logger .warn ("Unknown media type {} returned for POST in session {}" , contentType ,
609614 sessionRepresentation );
610- return ResponseSubscribers .drainThenError (httpResponse .body (),
615+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
611616 new RuntimeException ("Unknown media type returned: " + contentType ));
612617 }
613618 else if (statusCode == NOT_FOUND ) {
614619 if (maybeSessionId .isPresent ()) {
615620 logger .debug ("Session not found for session ID: {}" , sessionRepresentation );
616- return ResponseSubscribers .drainThenError (httpResponse .body (),
621+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
617622 new McpTransportSessionNotFoundException (
618623 "Session not found for session ID: " + sessionRepresentation ));
619624 }
620- return ResponseSubscribers .drainThenError (httpResponse .body (),
625+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
621626 new McpTransportException ("Server Not Found. Status code:" + statusCode ));
622627 }
623628 else if (statusCode == BAD_REQUEST ) {
624629 if (maybeSessionId .isPresent ()) {
625- return ResponseSubscribers .drainThenError (httpResponse .body (),
630+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
626631 new McpTransportSessionNotFoundException (
627632 "Session not found for session ID: " + sessionRepresentation ));
628633 }
629- return ResponseSubscribers .drainThenError (httpResponse .body (),
634+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
630635 new McpTransportException ("Bad Request. Status code:" + statusCode ));
631636 }
632637 else if (statusCode >= 400 && statusCode < 500 ) {
633- return ResponseSubscribers .drainThenError (httpResponse .body (),
638+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
634639 new McpTransportException ("Invalid request. Status code: " + statusCode ));
635640 }
636641
637- return ResponseSubscribers .drainThenError (httpResponse .body (),
642+ return ResponseSubscribers .drainThenError (httpResponse .body (), this . maxResponseSize ,
638643 new RuntimeException ("Failed to send message, status code: " + statusCode ));
639644 })
640645 .onErrorMap (CompletionException .class , Throwable ::getCause ))
0 commit comments