Bug description After the mcp server restarts, the client will return 404.
Environment Client:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>
spring:
ai:
mcp:
client:
name: mcp-client
enabled: true
type: async
request-timeout: 30s
sse:
connections:
music-mcp-server:
url: http://localhost:8083
sse-endpoint: /sse
@Autowired
private final ObjectProvider<List<ToolCallbackProvider>> listObjectProvider;
this.chatClient = builder
.defaultSystem("你是一个智能助手,帮助用户解决相关问题,上下文和历史信息帮助你更好了解用户需求,但记住你不仅可以根据上下文来回答内容,而且你也可以调用工具帮助用户查询,始终遵守用户的指令。")
.defaultAdvisors(
MessageChatMemoryAdvisor.builder(chatMemory).build(),
.defaultToolCallbacks(listObjectProvider.getIfAvailable().toArray(new ToolCallbackProvider[0]))
.build();
Server:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
mcp:
client:
name: mcp-client
enabled: true
type: async
request-timeout: 30s
sse:
connections:
music-mcp-server:
url: http://localhost:8083
sse-endpoint: /sse
Steps to reproduce
MCP server restarts. The client will display:
2025-05-27T10:52:04.339+08:00 ERROR 19032 --- [ai-project] [ient-1-Worker-0] i.m.c.t.WebFluxSseClientTransport : Fatal SSE error, not retrying: 200 OK from GET http://localhost:8083/sse, but response failed with cause: java.io.IOException: chunked transfer encoding, state: READING_LENGTH
2025-05-27T10:52:04.340+08:00 ERROR 19032 --- [ai-project] [ient-1-Worker-0] reactor.core.publisher.Operators : Operator called default onErrorDropped
reactor.core.Exceptions$ErrorCallbackNotImplemented: org.springframework.web.reactive.function.client.WebClientResponseException: 200 OK from GET http://localhost:8083/sse, but response failed with cause: java.io.IOException: chunked transfer encoding, state: READING_LENGTH
Caused by: org.springframework.web.reactive.function.client.WebClientResponseException: 200 OK from GET http://localhost:8083/sse, but response failed with cause: java.io.IOException: chunked transfer encoding, state: READING_LENGTH
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:337) ~[spring-webflux-6.1.12.jar:6.1.12]
at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException$1(DefaultClientResponse.java:214) ~[spring-webflux-6.1.12.jar:6.1.12]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onError(FluxOnErrorReturn.java:199) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onError(FluxDefaultIfEmpty.java:156) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onError(FluxMapFuseable.java:142) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onError(FluxMapFuseable.java:340) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onError(FluxFilterFuseable.java:382) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.MonoCollect$CollectSubscriber.onError(MonoCollect.java:135) ~[reactor-core-3.6.9.jar:3.6.9]
at org.springframework.http.client.reactive.AbstractClientHttpResponse$SingleSubscriberPublisher.subscribe(AbstractClientHttpResponse.java:116) ~[spring-web-6.1.12.jar:6.1.12]
at reactor.core.publisher.FluxSource.subscribe(FluxSource.java:71) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.Mono.subscribe(Mono.java:4576) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onError(FluxOnErrorResume.java:103) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxOnAssembly$OnAssemblySubscriber.onError(FluxOnAssembly.java:544) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.maybeOnError(FluxConcatMapNoPrefetch.java:327) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxConcatMapNoPrefetch$FluxConcatMapNoPrefetchSubscriber.onError(FluxConcatMapNoPrefetch.java:221) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxBufferPredicate$BufferPredicateSubscriber.onError(FluxBufferPredicate.java:346) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableConditionalSubscriber.onError(FluxPeekFuseable.java:553) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onError(FluxMapFuseable.java:340) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxDoFinally$DoFinallySubscriber.onError(FluxDoFinally.java:119) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxConcatArray$ConcatArraySubscriber.onError(FluxConcatArray.java:186) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainAsync(FluxFlattenIterable.java:351) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:724) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onError(FluxFlattenIterable.java:263) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPublish$PublishSubscriber.checkTerminated(FluxPublish.java:625) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPublish$PublishSubscriber.drain(FluxPublish.java:494) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPublish$PublishSubscriber.onError(FluxPublish.java:336) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onError(FluxContextWrite.java:121) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onError(FluxMapFuseable.java:340) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainAsync(FluxFlattenIterable.java:351) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:724) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onError(FluxFlattenIterable.java:263) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.adapter.JdkFlowAdapter$SubscriberToRS.onError(JdkFlowAdapter.java:155) ~[reactor-core-3.6.9.jar:3.6.9]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.complete(ResponseSubscribers.java:960) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.lambda$new$1(ResponseSubscribers.java:886) ~[java.net.http:na]
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2214) ~[na:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.lambda$new$2(ResponseSubscribers.java:886) ~[java.net.http:na]
at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.completeExceptionally(CompletableFuture.java:2194) ~[na:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.signalError(ResponseSubscribers.java:968) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.onError(ResponseSubscribers.java:1044) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.HttpBodySubscriberWrapper.propagateError(HttpBodySubscriberWrapper.java:171) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.HttpBodySubscriberWrapper.complete(HttpBodySubscriberWrapper.java:310) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.HttpBodySubscriberWrapper.onError(HttpBodySubscriberWrapper.java:396) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response.lambda$readBody$1(Http1Response.java:347) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseContent$ChunkedBodyParser.onError(ResponseContent.java:185) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response$BodyReader.onReadError(Http1Response.java:677) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.checkForErrors(Http1AsyncReceiver.java:302) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.flush(Http1AsyncReceiver.java:268) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$LockingRestartableTask.run(SequentialScheduler.java:182) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:149) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:207) ~[java.net.http:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: java.io.IOException: chunked transfer encoding, state: READING_LENGTH
at java.net.http/jdk.internal.net.http.common.Utils.wrapWithExtraDetail(Utils.java:391) ~[java.net.http:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ Body from GET http://localhost:8083/sse [DefaultClientResponse]
Original Stack Trace:
at java.net.http/jdk.internal.net.http.common.Utils.wrapWithExtraDetail(Utils.java:391) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response$BodyReader.onReadError(Http1Response.java:676) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.checkForErrors(Http1AsyncReceiver.java:302) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.flush(Http1AsyncReceiver.java:268) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$LockingRestartableTask.run(SequentialScheduler.java:182) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:149) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:207) ~[java.net.http:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: java.io.EOFException: EOF reached while reading
at java.net.http/jdk.internal.net.http.Http1AsyncReceiver$Http1TubeSubscriber.onComplete(Http1AsyncReceiver.java:601) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$ReadSubscription.signalCompletion(SocketTube.java:648) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.read(SocketTube.java:853) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.SocketTube$SocketFlowTask.run(SocketTube.java:181) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:207) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:280) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler.runOrSchedule(SequentialScheduler.java:233) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$InternalReadSubscription.signalReadable(SocketTube.java:782) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.SocketTube$InternalReadPublisher$ReadEvent.signalEvent(SocketTube.java:965) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.SocketTube$SocketFlowEvent.handle(SocketTube.java:253) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.handleEvent(HttpClientImpl.java:1467) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.lambda$run$3(HttpClientImpl.java:1412) ~[java.net.http:na]
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596) ~[na:na]
at java.net.http/jdk.internal.net.http.HttpClientImpl$SelectorManager.run(HttpClientImpl.java:1412) ~[java.net.http:na]
if you ask some question showed
2025-05-27T10:52:54.416+08:00 ERROR 19032 --- [ai-project] [nio-8082-exec-6] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed: org.springframework.web.reactive.function.client.WebClientResponseException$NotFound: 404 Not Found from POST http://localhost:8083/mcp/message] with root cause
org.springframework.web.reactive.function.client.WebClientResponseException$NotFound: 404 Not Found from POST http://localhost:8083/mcp/message
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:324) ~[spring-webflux-6.1.12.jar:6.1.12]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
*__checkpoint ⇢ 404 NOT_FOUND from POST http://localhost:8083/mcp/message [DefaultWebClient]
Original Stack Trace:
at org.springframework.web.reactive.function.client.WebClientResponseException.create(WebClientResponseException.java:324) ~[spring-webflux-6.1.12.jar:6.1.12]
at org.springframework.web.reactive.function.client.DefaultClientResponse.lambda$createException$1(DefaultClientResponse.java:214) ~[spring-webflux-6.1.12.jar:6.1.12]
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:106) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxOnErrorReturn$ReturnSubscriber.onNext(FluxOnErrorReturn.java:162) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:122) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:129) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onNext(FluxContextWrite.java:107) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onNext(FluxMapFuseable.java:299) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFilterFuseable$FilterFuseableConditionalSubscriber.onNext(FluxFilterFuseable.java:337) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.Operators$BaseFluxToMonoOperator.completePossiblyEmpty(Operators.java:2097) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.MonoCollect$CollectSubscriber.onComplete(MonoCollect.java:145) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPublish$PublishSubscriber.checkTerminated(FluxPublish.java:634) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPublish$PublishSubscriber.drain(FluxPublish.java:494) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxPublish$PublishSubscriber.onComplete(FluxPublish.java:355) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxContextWrite$ContextWriteSubscriber.onComplete(FluxContextWrite.java:126) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxMapFuseable$MapFuseableConditionalSubscriber.onComplete(FluxMapFuseable.java:350) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drainAsync(FluxFlattenIterable.java:371) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.drain(FluxFlattenIterable.java:724) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxFlattenIterable$FlattenIterableSubscriber.onComplete(FluxFlattenIterable.java:273) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.adapter.JdkFlowAdapter$SubscriberToRS.onComplete(JdkFlowAdapter.java:160) ~[reactor-core-3.6.9.jar:3.6.9]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.complete(ResponseSubscribers.java:955) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.lambda$new$1(ResponseSubscribers.java:886) ~[java.net.http:na]
at java.base/java.util.concurrent.CompletableFuture.uniAcceptNow(CompletableFuture.java:757) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.uniAcceptStage(CompletableFuture.java:735) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.thenAccept(CompletableFuture.java:2214) ~[na:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.lambda$new$2(ResponseSubscribers.java:886) ~[java.net.http:na]
at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:863) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:841) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) ~[na:na]
at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2179) ~[na:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.signalComplete(ResponseSubscribers.java:972) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseSubscribers$PublishingBodySubscriber.onComplete(ResponseSubscribers.java:1058) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.HttpBodySubscriberWrapper.complete(HttpBodySubscriberWrapper.java:293) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.HttpBodySubscriberWrapper.onComplete(HttpBodySubscriberWrapper.java:401) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseContent$ChunkedBodyParser.accept(ResponseContent.java:220) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.ResponseContent$ChunkedBodyParser.accept(ResponseContent.java:131) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response$BodyReader.handle(Http1Response.java:707) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response$BodyReader.handle(Http1Response.java:635) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response$Receiver.accept(Http1Response.java:527) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1Response$BodyReader.tryAsyncReceive(Http1Response.java:665) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.Http1AsyncReceiver.flush(Http1AsyncReceiver.java:233) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$LockingRestartableTask.run(SequentialScheduler.java:182) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$CompleteRestartableTask.run(SequentialScheduler.java:149) ~[java.net.http:na]
at java.net.http/jdk.internal.net.http.common.SequentialScheduler$SchedulableTask.run(SequentialScheduler.java:207) ~[java.net.http:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Suppressed: java.lang.Exception: #block terminated with an error
at reactor.core.publisher.BlockingSingleSubscriber.blockingGet(BlockingSingleSubscriber.java:104) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.Mono.block(Mono.java:1779) ~[reactor-core-3.6.9.jar:3.6.9]
at org.springframework.ai.mcp.AsyncMcpToolCallback.call(AsyncMcpToolCallback.java:117) ~[spring-ai-mcp-1.0.0.jar:1.0.0]
at org.springframework.ai.mcp.AsyncMcpToolCallback.call(AsyncMcpToolCallback.java:123) ~[spring-ai-mcp-1.0.0.jar:1.0.0]
at org.springframework.ai.model.tool.DefaultToolCallingManager.lambda$executeToolCall$5(DefaultToolCallingManager.java:224) ~[spring-ai-model-1.0.0.jar:1.0.0]
at io.micrometer.observation.Observation.observe(Observation.java:565) ~[micrometer-observation-1.12.9.jar:1.12.9]
at org.springframework.ai.model.tool.DefaultToolCallingManager.executeToolCall(DefaultToolCallingManager.java:221) ~[spring-ai-model-1.0.0.jar:1.0.0]
at org.springframework.ai.model.tool.DefaultToolCallingManager.executeToolCalls(DefaultToolCallingManager.java:137) ~[spring-ai-model-1.0.0.jar:1.0.0]
at org.springframework.ai.openai.OpenAiChatModel.lambda$internalStream$10(OpenAiChatModel.java:369) ~[spring-ai-openai-1.0.0.jar:1.0.0]
at reactor.core.publisher.FluxDefer.subscribe(FluxDefer.java:46) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84) ~[reactor-core-3.6.9.jar:3.6.9]
at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37) ~[reactor-core-3.6.9.jar:3.6.9]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317) ~[na:na]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[na:na]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Expected behavior Support reconnection. After the mcp server restarts.
Comment From: weicheng113
Just wonder if there is any progress on this issue? This is a serious issue, which I encounter also. Once connection has the issue, it can not be used any more, which will result in system unusable from the point onwards.
@TonyJeans Have you got an workaround yet? I am thinking to recreate the connection at the moment. Thanks.
Comment From: weicheng113
Just to post my current workaround, in case other people also encouter this issue. After the MCP server restarts, the existing session id currently held by MCP Client Session object is no longer valid. That is why the subsequent calls will all fail. At the moment, my workaround is to close the current client and create a new one.
The related classes are io.modelcontextprotocol.spec.McpClientSession, io.modelcontextprotocol.client.transport.HttpClientSseClientTransport, io.modelcontextprotocol.client.transport.WebFluxSseClientTransport.
I will report this issue to MCP repro also, as this might be more to do with that repo.
Comment From: TonyJeans
@weicheng113
See: https://github.com/spring-projects/spring-ai/issues/2740
Currently, the only solution is to rebuild the client or override the inboundRetryHandler in WebClient. It would be great if Spring AI could update to support the streamable HTTP protocol.
Comment From: dberna2
@weicheng113 can you share your workaround?
I tried to recreate the chat client, but always get the same error message 🙁