3434import org .springframework .ai .mcp .util .Assert ;
3535
3636/**
37- * Factory class providing static methods for creating Model Context Protocol (MCP)
38- * clients. This class serves as the main entry point for establishing connections with
39- * MCP servers, offering both synchronous and asynchronous client implementations.
37+ * Factory class for creating Model Context Protocol (MCP) clients. MCP is a protocol that enables
38+ * AI models to interact with external tools and resources through a standardized interface.
39+ *
40+ * <p>This class serves as the main entry point for establishing connections with MCP servers,
41+ * implementing the client-side of the MCP specification. The protocol follows a client-server
42+ * architecture where:
43+ * <ul>
44+ * <li>The client (this implementation) initiates connections and sends requests
45+ * <li>The server responds to requests and provides access to tools and resources
46+ * <li>Communication occurs through a transport layer (e.g., stdio, SSE) using JSON-RPC 2.0
47+ * </ul>
4048 *
41- * <p>
42- * The class provides factory methods to create either:
49+ * <p>The class provides factory methods to create either:
4350 * <ul>
44- * <li>{@link McpAsyncClient} for non-blocking operations
45- * <li>{@link McpSyncClient} for blocking operations
51+ * <li>{@link McpAsyncClient} for non-blocking operations with CompletableFuture responses
52+ * <li>{@link McpSyncClient} for blocking operations with direct responses
4653 * </ul>
4754 *
48- * <p>
49- * Use the builder pattern for flexible client configuration:
55+ * <p>Example of creating a basic client:
56+ * <pre>{@code
57+ * McpClient.using(transport)
58+ * .requestTimeout(Duration.ofSeconds(5))
59+ * .sync(); // or .async()
60+ * }</pre>
5061 *
62+ * <p>Example with advanced configuration:
5163 * <pre>{@code
5264 * McpClient.using(transport)
53- * .requestTimeout(Duration.ofSeconds(5))
54- * .sync(); // or .async()
65+ * .requestTimeout(Duration.ofSeconds(10))
66+ * .capabilities(new ClientCapabilities(...))
67+ * .clientInfo(new Implementation("My Client", "1.0.0"))
68+ * .roots(new Root("file://workspace", "Workspace Files"))
69+ * .toolsChangeConsumer(tools -> System.out.println("Tools updated: " + tools))
70+ * .async();
5571 * }</pre>
5672 *
73+ * <p>The client supports:
74+ * <ul>
75+ * <li>Tool discovery and invocation
76+ * <li>Resource access and management
77+ * <li>Prompt template handling
78+ * <li>Real-time updates through change consumers
79+ * <li>Custom sampling strategies
80+ * </ul>
81+ *
5782 * @author Christian Tzolov
5883 * @author Dariusz Jędrzejczyk
84+ * @see McpAsyncClient
85+ * @see McpSyncClient
86+ * @see McpTransport
5987 */
6088public interface McpClient {
6189
6290 /**
63- * Start building an MCP client with the specified transport.
64- * @param transport The transport layer implementation for MCP communication
65- * @return A new builder instance
91+ * Start building an MCP client with the specified transport layer.
92+ * The transport layer handles the low-level communication between
93+ * client and server using protocols like stdio or Server-Sent Events (SSE).
94+ *
95+ * @param transport The transport layer implementation for MCP communication.
96+ * Common implementations include {@code StdioClientTransport}
97+ * for stdio-based communication and {@code SseClientTransport}
98+ * for SSE-based communication.
99+ * @return A new builder instance for configuring the client
100+ * @throws IllegalArgumentException if transport is null
66101 */
67102 public static Builder using (McpTransport transport ) {
68103 return new Builder (transport );
69104 }
70105
71106 /**
72- * Builder class for creating MCP clients with custom configuration.
107+ * Builder class for creating and configuring MCP clients. This class follows
108+ * the builder pattern to provide a fluent API for setting up clients with
109+ * custom configurations.
110+ *
111+ * <p>The builder supports configuration of:
112+ * <ul>
113+ * <li>Transport layer for client-server communication
114+ * <li>Request timeouts for operation boundaries
115+ * <li>Client capabilities for feature negotiation
116+ * <li>Client implementation details for version tracking
117+ * <li>Root URIs for resource access
118+ * <li>Change notification handlers for tools, resources, and prompts
119+ * <li>Custom message sampling logic
120+ * </ul>
73121 */
74122 public static class Builder {
75123
@@ -79,7 +127,7 @@ public static class Builder {
79127
80128 private ClientCapabilities capabilities ;
81129
82- private Implementation clientInfo = new Implementation ("Spring AI MCP Client" , "0.3.0 " );
130+ private Implementation clientInfo = new Implementation ("Spring AI MCP Client" , "0.3.1 " );
83131
84132 private Map <String , Root > roots = new HashMap <>();
85133
@@ -97,28 +145,61 @@ private Builder(McpTransport transport) {
97145 }
98146
99147 /**
100- * Set the request timeout duration.
101- * @param requestTimeout The duration to wait before timing out requests
102- * @return This builder instance
148+ * Sets the duration to wait for server responses before timing out requests.
149+ * This timeout applies to all requests made through the client, including
150+ * tool calls, resource access, and prompt operations.
151+ *
152+ * @param requestTimeout The duration to wait before timing out requests.
153+ * Must not be null.
154+ * @return This builder instance for method chaining
155+ * @throws IllegalArgumentException if requestTimeout is null
103156 */
104157 public Builder requestTimeout (Duration requestTimeout ) {
105158 Assert .notNull (requestTimeout , "Request timeout must not be null" );
106159 this .requestTimeout = requestTimeout ;
107160 return this ;
108161 }
109162
163+ /**
164+ * Sets the client capabilities that will be advertised to the server during
165+ * connection initialization. Capabilities define what features the client supports,
166+ * such as tool execution, resource access, and prompt handling.
167+ *
168+ * @param capabilities The client capabilities configuration. Must not be null.
169+ * @return This builder instance for method chaining
170+ * @throws IllegalArgumentException if capabilities is null
171+ */
110172 public Builder capabilities (ClientCapabilities capabilities ) {
111173 Assert .notNull (capabilities , "Capabilities must not be null" );
112174 this .capabilities = capabilities ;
113175 return this ;
114176 }
115177
178+ /**
179+ * Sets the client implementation information that will be shared with the server
180+ * during connection initialization. This helps with version compatibility and
181+ * debugging.
182+ *
183+ * @param clientInfo The client implementation details including name and version.
184+ * Must not be null.
185+ * @return This builder instance for method chaining
186+ * @throws IllegalArgumentException if clientInfo is null
187+ */
116188 public Builder clientInfo (Implementation clientInfo ) {
117189 Assert .notNull (clientInfo , "Client info must not be null" );
118190 this .clientInfo = clientInfo ;
119191 return this ;
120192 }
121193
194+ /**
195+ * Sets the root URIs that this client can access. Roots define the base URIs
196+ * for resources that the client can request from the server. For example,
197+ * a root might be "file://workspace" for accessing workspace files.
198+ *
199+ * @param roots A list of root definitions. Must not be null.
200+ * @return This builder instance for method chaining
201+ * @throws IllegalArgumentException if roots is null
202+ */
122203 public Builder roots (List <Root > roots ) {
123204 Assert .notNull (roots , "Roots must not be null" );
124205 for (Root root : roots ) {
@@ -127,6 +208,15 @@ public Builder roots(List<Root> roots) {
127208 return this ;
128209 }
129210
211+ /**
212+ * Sets the root URIs that this client can access, using a varargs parameter
213+ * for convenience. This is an alternative to {@link #roots(List)}.
214+ *
215+ * @param roots An array of root definitions. Must not be null.
216+ * @return This builder instance for method chaining
217+ * @throws IllegalArgumentException if roots is null
218+ * @see #roots(List)
219+ */
130220 public Builder roots (Root ... roots ) {
131221 Assert .notNull (roots , "Roots must not be null" );
132222 for (Root root : roots ) {
@@ -135,41 +225,90 @@ public Builder roots(Root... roots) {
135225 return this ;
136226 }
137227
228+ /**
229+ * Sets a custom sampling handler for processing message creation requests.
230+ * The sampling handler can modify or validate messages before they are sent
231+ * to the server, enabling custom processing logic.
232+ *
233+ * @param samplingHandler A function that processes message requests and returns
234+ * results. Must not be null.
235+ * @return This builder instance for method chaining
236+ * @throws IllegalArgumentException if samplingHandler is null
237+ */
138238 public Builder sampling (Function <CreateMessageRequest , CreateMessageResult > samplingHandler ) {
139239 Assert .notNull (samplingHandler , "Sampling handler must not be null" );
140240 this .samplingHandler = samplingHandler ;
141241 return this ;
142242 }
143243
244+ /**
245+ * Adds a consumer to be notified when the available tools change. This allows
246+ * the client to react to changes in the server's tool capabilities, such as
247+ * tools being added or removed.
248+ *
249+ * @param toolsChangeConsumer A consumer that receives the updated list of
250+ * available tools. Must not be null.
251+ * @return This builder instance for method chaining
252+ * @throws IllegalArgumentException if toolsChangeConsumer is null
253+ */
144254 public Builder toolsChangeConsumer (Consumer <List <McpSchema .Tool >> toolsChangeConsumer ) {
145255 Assert .notNull (toolsChangeConsumer , "Tools change consumer must not be null" );
146256 this .toolsChangeConsumers .add (toolsChangeConsumer );
147257 return this ;
148258 }
149259
260+ /**
261+ * Adds a consumer to be notified when the available resources change. This allows
262+ * the client to react to changes in the server's resource availability, such as
263+ * files being added or removed.
264+ *
265+ * @param resourcesChangeConsumer A consumer that receives the updated list of
266+ * available resources. Must not be null.
267+ * @return This builder instance for method chaining
268+ * @throws IllegalArgumentException if resourcesChangeConsumer is null
269+ */
150270 public Builder resourcesChangeConsumer (Consumer <List <McpSchema .Resource >> resourcesChangeConsumer ) {
151271 Assert .notNull (resourcesChangeConsumer , "Resources change consumer must not be null" );
152272 this .resourcesChangeConsumers .add (resourcesChangeConsumer );
153273 return this ;
154274 }
155275
276+ /**
277+ * Adds a consumer to be notified when the available prompts change. This allows
278+ * the client to react to changes in the server's prompt templates, such as
279+ * new templates being added or existing ones being modified.
280+ *
281+ * @param promptsChangeConsumer A consumer that receives the updated list of
282+ * available prompts. Must not be null.
283+ * @return This builder instance for method chaining
284+ * @throws IllegalArgumentException if promptsChangeConsumer is null
285+ */
156286 public Builder promptsChangeConsumer (Consumer <List <McpSchema .Prompt >> promptsChangeConsumer ) {
157287 Assert .notNull (promptsChangeConsumer , "Prompts change consumer must not be null" );
158288 this .promptsChangeConsumers .add (promptsChangeConsumer );
159289 return this ;
160290 }
161291
162292 /**
163- * Build a synchronous MCP client.
164- * @return A new instance of {@link McpSyncClient}
293+ * Builds a synchronous MCP client that provides blocking operations.
294+ * Synchronous clients wait for each operation to complete before returning,
295+ * making them simpler to use but potentially less performant for
296+ * concurrent operations.
297+ *
298+ * @return A new instance of {@link McpSyncClient} configured with this
299+ * builder's settings
165300 */
166301 public McpSyncClient sync () {
167302 return new McpSyncClient (async ());
168303 }
169304
170305 /**
171- * Build an asynchronous MCP client.
172- * @return A new instance of {@link McpAsyncClient}
306+ * Builds an asynchronous MCP client that provides non-blocking operations.
307+ * Asynchronous clients return CompletableFuture objects immediately,
308+ * allowing for concurrent operations and reactive programming patterns.
309+ *
310+ * @return A new instance of {@link McpAsyncClient} configured with this
311+ * builder's settings
173312 */
174313 public McpAsyncClient async () {
175314 return new McpAsyncClient (transport , requestTimeout , clientInfo , capabilities , roots , toolsChangeConsumers ,
0 commit comments