2626import com .google .genai .types .FunctionDeclaration ;
2727import com .google .genai .types .Schema ;
2828import io .modelcontextprotocol .client .McpAsyncClient ;
29+ import io .modelcontextprotocol .spec .McpSchema ;
2930import io .modelcontextprotocol .spec .McpSchema .CallToolRequest ;
3031import io .modelcontextprotocol .spec .McpSchema .JsonSchema ;
3132import io .modelcontextprotocol .spec .McpSchema .Tool ;
3233import io .reactivex .rxjava3 .core .Maybe ;
3334import io .reactivex .rxjava3 .core .Single ;
3435import java .util .Map ;
3536import java .util .Optional ;
37+ import org .slf4j .Logger ;
38+ import org .slf4j .LoggerFactory ;
3639
3740// TODO(b/413489523): Add support for auth. This is a TODO for Python as well.
3841
4447 */
4548public final class McpAsyncTool extends BaseTool {
4649
50+ private static final Logger logger = LoggerFactory .getLogger (McpAsyncTool .class );
51+
4752 Tool mcpTool ;
48- Single <McpAsyncClient > mcpSession ;
53+ // Volatile ensures write visibility in the asynchronous chain.
54+ volatile McpAsyncClient mcpSession ;
4955 McpSessionManager mcpSessionManager ;
5056 ObjectMapper objectMapper ;
5157
@@ -58,7 +64,7 @@ public final class McpAsyncTool extends BaseTool {
5864 * @throws IllegalArgumentException If mcpTool or mcpSession are null.
5965 */
6066 public McpAsyncTool (
61- Tool mcpTool , Single < McpAsyncClient > mcpSession , McpSessionManager mcpSessionManager ) {
67+ Tool mcpTool , McpAsyncClient mcpSession , McpSessionManager mcpSessionManager ) {
6268 this (mcpTool , mcpSession , mcpSessionManager , JsonBaseModel .getMapper ());
6369 }
6470
@@ -73,7 +79,7 @@ public McpAsyncTool(
7379 */
7480 public McpAsyncTool (
7581 Tool mcpTool ,
76- Single < McpAsyncClient > mcpSession ,
82+ McpAsyncClient mcpSession ,
7783 McpSessionManager mcpSessionManager ,
7884 ObjectMapper objectMapper ) {
7985 super (
@@ -95,16 +101,32 @@ public McpAsyncTool(
95101 this .objectMapper = objectMapper ;
96102 }
97103
98- public Single < McpAsyncClient > getMcpSession () {
104+ public McpAsyncClient getMcpSession () {
99105 return this .mcpSession ;
100106 }
101107
102108 public Schema toGeminiSchema (JsonSchema openApiSchema ) {
103109 return Schema .fromJson (objectMapper .valueToTree (openApiSchema ).toString ());
104110 }
105111
106- private void reintializeSession () {
107- this .mcpSession = this .mcpSessionManager .createAsyncSession ();
112+ private Single <McpSchema .InitializeResult > reintializeSession () {
113+ McpAsyncClient client = this .mcpSessionManager .createAsyncSession ();
114+ return Single .fromCompletionStage (
115+ client
116+ .initialize ()
117+ .doOnSuccess (
118+ initResult -> {
119+ logger .debug ("Initialize McpAsyncClient Result: {}" , initResult );
120+ })
121+ .doOnError (
122+ e -> {
123+ logger .error ("Initialize McpAsyncClient Failed: {}" , e .getMessage (), e );
124+ })
125+ .doOnNext (
126+ _initResult -> {
127+ this .mcpSession = client ;
128+ })
129+ .toFuture ());
108130 }
109131
110132 @ Override
@@ -121,14 +143,10 @@ public Optional<FunctionDeclaration> declaration() {
121143 public Single <Map <String , Object >> runAsync (Map <String , Object > args , ToolContext toolContext ) {
122144 return Single .defer (
123145 () ->
124- this .mcpSession
125- .flatMapMaybe (
126- client ->
127- Maybe .fromCompletionStage (
128- client
129- .callTool (
130- new CallToolRequest (this .name (), ImmutableMap .copyOf (args )))
131- .toFuture ()))
146+ Maybe .fromCompletionStage (
147+ this .mcpSession
148+ .callTool (new CallToolRequest (this .name (), ImmutableMap .copyOf (args )))
149+ .toFuture ())
132150 .map (
133151 callResult ->
134152 McpTool .wrapCallResult (this .objectMapper , this .name (), callResult ))
@@ -141,9 +159,8 @@ public Single<Map<String, Object>> runAsync(Map<String, Object> args, ToolContex
141159 .delay (100 , MILLISECONDS )
142160 .take (3 )
143161 .doOnNext (
144- error -> {
145- System .err .println ("Retrying callTool due to: " + error );
146- reintializeSession ();
147- }));
162+ error ->
163+ logger .error ("Retrying callTool due to: {}" , error .getMessage (), error ))
164+ .flatMapSingle (_ignore -> this .reintializeSession ()));
148165 }
149166}
0 commit comments