@@ -213,7 +213,7 @@ private Mono<McpSchema.InitializeResult> await() {
213213
214214 private void complete (McpSchema .InitializeResult initializeResult ) {
215215 // inform all the subscribers waiting for the initialization
216- this .initSink .emitValue (initializeResult , Sinks . EmitFailureHandler . FAIL_FAST );
216+ this .initSink .tryEmitValue (initializeResult );
217217 }
218218
219219 private void cacheResult (McpSchema .InitializeResult initializeResult ) {
@@ -222,14 +222,18 @@ private void cacheResult(McpSchema.InitializeResult initializeResult) {
222222 }
223223
224224 private void error (Throwable t ) {
225- this .initSink .emitError ( t , Sinks . EmitFailureHandler . FAIL_FAST );
225+ this .initSink .tryEmitError ( t );
226226 }
227227
228228 private void close () {
229229 this .mcpSession ().close ();
230230 }
231231
232232 private void terminate (Throwable cause ) {
233+ // Initialization has a single shared outcome. Publish the terminal failure
234+ // even when the session has not been installed yet so that both the owner
235+ // and all concurrent joiners observe it immediately.
236+ this .initSink .tryEmitError (cause );
233237 McpClientSession mcpClientSession = this .mcpSession ();
234238 if (mcpClientSession != null ) {
235239 mcpClientSession .terminate (cause );
@@ -304,8 +308,20 @@ public <T> Mono<T> withInitialization(String actionName, Function<Initialization
304308 boolean needsToInitialize = previous == null ;
305309 logger .debug (needsToInitialize ? "Initialization process started" : "Joining previous initialization" );
306310
307- Mono <McpSchema .InitializeResult > initializationJob = needsToInitialize
308- ? this .doInitialize (newInit , this .postInitializationHook , ctx ) : previous .await ();
311+ Mono <McpSchema .InitializeResult > initializationJob ;
312+ if (needsToInitialize ) {
313+ // The work branch only publishes into the shared sink. Keeping it from
314+ // winning directly makes the owner and all joiners consume the same
315+ // first terminal signal.
316+ Mono <McpSchema .InitializeResult > initializationWork = this
317+ .doInitialize (newInit , this .postInitializationHook , ctx )
318+ .onErrorComplete ()
319+ .then (Mono .never ());
320+ initializationJob = Mono .firstWithSignal (newInit .await (), initializationWork );
321+ }
322+ else {
323+ initializationJob = previous .await ();
324+ }
309325
310326 return initializationJob .map (initializeResult -> this .initializationRef .get ())
311327 .timeout (this .initializationTimeout )
@@ -322,46 +338,45 @@ public <T> Mono<T> withInitialization(String actionName, Function<Initialization
322338 private Mono <McpSchema .InitializeResult > doInitialize (DefaultInitialization initialization ,
323339 Function <Initialization , Mono <Void >> postInitOperation , ContextView ctx ) {
324340
325- initialization .setMcpClientSession (this .sessionSupplier .apply (ctx ));
341+ return Mono .defer (() -> {
342+ initialization .setMcpClientSession (this .sessionSupplier .apply (ctx ));
326343
327- McpClientSession mcpClientSession = initialization .mcpSession ();
328- Throwable terminal = this .terminalFailure .get ();
329- if (terminal != null ) {
330- mcpClientSession .terminate (terminal );
331- return Mono .error (terminal );
332- }
344+ McpClientSession mcpClientSession = initialization .mcpSession ();
345+ Throwable terminal = this .terminalFailure .get ();
346+ if (terminal != null ) {
347+ mcpClientSession .terminate (terminal );
348+ return Mono .error (terminal );
349+ }
333350
334- String latestVersion = this .protocolVersions .get (this .protocolVersions .size () - 1 );
351+ String latestVersion = this .protocolVersions .get (this .protocolVersions .size () - 1 );
335352
336- McpSchema .InitializeRequest initializeRequest = McpSchema .InitializeRequest
337- .builder (latestVersion , this .clientCapabilities , this .clientInfo )
338- .build ();
353+ McpSchema .InitializeRequest initializeRequest = McpSchema .InitializeRequest
354+ .builder (latestVersion , this .clientCapabilities , this .clientInfo )
355+ .build ();
339356
340- Mono <McpSchema .InitializeResult > result = mcpClientSession .sendRequest (McpSchema .METHOD_INITIALIZE ,
341- initializeRequest , McpAsyncClient .INITIALIZE_RESULT_TYPE_REF );
357+ Mono <McpSchema .InitializeResult > result = mcpClientSession .sendRequest (McpSchema .METHOD_INITIALIZE ,
358+ initializeRequest , McpAsyncClient .INITIALIZE_RESULT_TYPE_REF );
342359
343- return result .flatMap (initializeResult -> {
344- logger .info ("Server response with Protocol: {}, Capabilities: {}, Info: {} and Instructions {}" ,
345- initializeResult .protocolVersion (), initializeResult .capabilities (), initializeResult . serverInfo (),
346- initializeResult .instructions ());
360+ return result .flatMap (initializeResult -> {
361+ logger .info ("Server response with Protocol: {}, Capabilities: {}, Info: {} and Instructions {}" ,
362+ initializeResult .protocolVersion (), initializeResult .capabilities (),
363+ initializeResult . serverInfo (), initializeResult .instructions ());
347364
348- if (!this .protocolVersions .contains (initializeResult .protocolVersion ())) {
349- return Mono .error (McpError .builder (-32602 )
350- .message ("Unsupported protocol version" )
351- .data ("Unsupported protocol version from the server: " + initializeResult .protocolVersion ())
352- .build ());
353- }
365+ if (!this .protocolVersions .contains (initializeResult .protocolVersion ())) {
366+ return Mono .error (McpError .builder (-32602 )
367+ .message ("Unsupported protocol version" )
368+ .data ("Unsupported protocol version from the server: " + initializeResult .protocolVersion ())
369+ .build ());
370+ }
354371
355- return mcpClientSession .sendNotification (McpSchema .METHOD_NOTIFICATION_INITIALIZED , null )
356- .contextWrite (
357- c -> c .put (McpAsyncClient .NEGOTIATED_PROTOCOL_VERSION , initializeResult .protocolVersion ()))
358- .thenReturn (initializeResult );
359- }).flatMap (initializeResult -> {
360- initialization .cacheResult (initializeResult );
361- return postInitOperation .apply (initialization ).thenReturn (initializeResult );
362- }).doOnNext (initialization ::complete ).onErrorResume (ex -> {
363- initialization .error (ex );
364- return Mono .error (ex );
372+ return mcpClientSession .sendNotification (McpSchema .METHOD_NOTIFICATION_INITIALIZED , null )
373+ .contextWrite (
374+ c -> c .put (McpAsyncClient .NEGOTIATED_PROTOCOL_VERSION , initializeResult .protocolVersion ()))
375+ .thenReturn (initializeResult );
376+ }).flatMap (initializeResult -> {
377+ initialization .cacheResult (initializeResult );
378+ return postInitOperation .apply (initialization ).thenReturn (initializeResult );
379+ }).doOnNext (initialization ::complete ).doOnError (initialization ::error );
365380 });
366381 }
367382
0 commit comments