Skip to content

Commit a202f69

Browse files
baekgolbaekgol
authored and
baekgol
committed
[FEAT] dynamic stdio connection for mcp client
Signed-off-by: Changue Lim <[email protected]>
1 parent 8f20aab commit a202f69

File tree

1 file changed

+147
-0
lines changed
  • auto-configurations/mcp/spring-ai-autoconfigure-mcp-client/src/main/java/org/springframework/ai/mcp/client/autoconfigure

1 file changed

+147
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright 2025-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.ai.mcp.client.autoconfigure;
18+
19+
import io.modelcontextprotocol.client.McpAsyncClient;
20+
import io.modelcontextprotocol.client.McpClient;
21+
import io.modelcontextprotocol.client.McpSyncClient;
22+
import io.modelcontextprotocol.client.transport.ServerParameters;
23+
import io.modelcontextprotocol.client.transport.StdioClientTransport;
24+
import io.modelcontextprotocol.spec.McpSchema;
25+
import org.springframework.ai.mcp.client.autoconfigure.properties.McpClientCommonProperties;
26+
27+
import java.util.List;
28+
29+
/**
30+
* Utility class for managing MCP (Model Context Protocol) clients using stdio transports.
31+
* <p>
32+
* This utility class provides methods to dynamically create and add MCP clients to existing
33+
* client collections at runtime. It supports both synchronous and asynchronous client creation
34+
* through the appropriate helper methods.
35+
* <p>
36+
* Key features:
37+
* <ul>
38+
* <li>Dynamic creation of MCP clients with stdio transport</li>
39+
* <li>Support for both synchronous and asynchronous client types</li>
40+
* <li>Consistent configuration using common properties</li>
41+
* <li>Runtime management of client connections</li>
42+
* </ul>
43+
* <p>
44+
* Example usage: <pre>{@code
45+
* // Obtain common properties and client lists
46+
* McpClientCommonProperties properties = // obtain properties
47+
* List<McpSyncClient> syncClients = // obtain sync client list
48+
*
49+
* // Add a new stdio connection
50+
* McpStdioUtils.addConnectionSync(properties, syncClients,
51+
* "search-service",
52+
* "/path/to/executable",
53+
* "--arg1", "--arg2");
54+
* }</pre>
55+
*
56+
* @author Changue Lim
57+
* @see McpSyncClient
58+
* @see McpAsyncClient
59+
* @see StdioClientTransport
60+
* @see ServerParameters
61+
*/
62+
public class McpClientStdioUtils {
63+
/**
64+
* Adds a new MCP Sync Client connection to the existing list of clients.
65+
* This method dynamically creates and configures a synchronous MCP client
66+
* using a stdio transport, making it possible to add new connections at runtime.
67+
*
68+
* <p>The newly created client is configured with:
69+
* <ul>
70+
* <li>A stdio transport using the specified command and arguments</li>
71+
* <li>Client information derived from common properties and the connection name</li>
72+
* <li>Request timeout from common properties</li>
73+
* </ul>
74+
*
75+
* <p>If initialization is enabled in the common properties, the client will be initialized
76+
* immediately before being added to the client list.
77+
*
78+
* @param mcpClientCommonProperties common MCP client configuration properties
79+
* used for timeout, name, version, and initialization settings
80+
* @param mcpSyncClients the list of existing clients to which the new client will be added
81+
* @param name a unique identifier for this connection (used as part of the client info name)
82+
* @param command the command to execute for the stdio transport (e.g., path to executable)
83+
* @param args variable number of command-line arguments to pass to the command
84+
*
85+
* @see McpSyncClient
86+
* @see StdioClientTransport
87+
* @see ServerParameters
88+
*/
89+
private static void addConnectionSync(McpClientCommonProperties mcpClientCommonProperties,
90+
List<McpSyncClient> mcpSyncClients,
91+
String name,
92+
String command,
93+
String... args) {
94+
final McpSyncClient syncClient = McpClient.sync(new StdioClientTransport(ServerParameters.builder(command).args(args).build()))
95+
.clientInfo(new McpSchema.Implementation(mcpClientCommonProperties.getName() + "-" + name, mcpClientCommonProperties.getVersion()))
96+
.requestTimeout(mcpClientCommonProperties.getRequestTimeout())
97+
.build();
98+
99+
if(mcpClientCommonProperties.isInitialized())
100+
syncClient.initialize();
101+
102+
mcpSyncClients.add(syncClient);
103+
}
104+
105+
/**
106+
* Adds a new MCP Async Client connection to the existing list of clients.
107+
* This method dynamically creates and configures an asynchronous MCP client
108+
* using a stdio transport, making it possible to add new connections at runtime.
109+
*
110+
* <p>The newly created client is configured with:
111+
* <ul>
112+
* <li>A stdio transport using the specified command and arguments</li>
113+
* <li>Client information derived from common properties and the connection name</li>
114+
* <li>Request timeout from common properties</li>
115+
* </ul>
116+
*
117+
* <p>If initialization is enabled in the common properties, the client will be initialized
118+
* immediately before being added to the client list. For async clients, the initialization
119+
* is performed by blocking on the Mono completion.
120+
*
121+
* @param mcpClientCommonProperties common MCP client configuration properties
122+
* used for timeout, name, version, and initialization settings
123+
* @param mcpAsyncClients the list of existing clients to which the new client will be added
124+
* @param name a unique identifier for this connection (used as part of the client info name)
125+
* @param command the command to execute for the stdio transport (e.g., path to executable)
126+
* @param args variable number of command-line arguments to pass to the command
127+
*
128+
* @see McpAsyncClient
129+
* @see StdioClientTransport
130+
* @see ServerParameters
131+
*/
132+
private static void addConnectionAsync(McpClientCommonProperties mcpClientCommonProperties,
133+
List<McpAsyncClient> mcpAsyncClients,
134+
String name,
135+
String command,
136+
String... args) {
137+
final McpAsyncClient asyncClient = McpClient.async(new StdioClientTransport(ServerParameters.builder(command).args(args).build()))
138+
.clientInfo(new McpSchema.Implementation(mcpClientCommonProperties.getName() + "-" + name, mcpClientCommonProperties.getVersion()))
139+
.requestTimeout(mcpClientCommonProperties.getRequestTimeout())
140+
.build();
141+
142+
if(mcpClientCommonProperties.isInitialized())
143+
asyncClient.initialize().block();
144+
145+
mcpAsyncClients.add(asyncClient);
146+
}
147+
}

0 commit comments

Comments
 (0)