diff --git a/mcp/src/main/java/org/springframework/ai/mcp/client/McpAsyncClient.java b/mcp/src/main/java/org/springframework/ai/mcp/client/McpAsyncClient.java index 5b50266..add1ad6 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/client/McpAsyncClient.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/client/McpAsyncClient.java @@ -84,8 +84,8 @@ public class McpAsyncClient { private final ConcurrentHashMap roots; /** - * MCP provides a standardized way for servers to request LLM sampling (“completions” - * or “generations”) from language models via clients. This flow allows clients to + * MCP provides a standardized way for servers to request LLM sampling ("completions" + * or "generations") from language models via clients. This flow allows clients to * maintain control over model access, selection, and permissions while enabling * servers to leverage AI capabilities—with no server API keys necessary. Servers can * request text or image-based interactions and optionally include context from MCP @@ -108,10 +108,13 @@ public class McpAsyncClient { * timeout. * @param transport the transport to use. * @param requestTimeout the session request-response timeout. - * @param rootsListProviders the list of suppliers that provide the list of roots - * backing the roots list request. - * @param rootsListChangedNotification whether the client supports roots/list_changed - * notification. + * @param clientInfo the client implementation information. + * @param clientCapabilities the client capabilities. + * @param roots the roots. + * @param toolsChangeConsumers the tools change consumers. + * @param resourcesChangeConsumers the resources change consumers. + * @param promptsChangeConsumers the prompts change consumers. + * @param samplingHandler the sampling handler. */ public McpAsyncClient(McpTransport transport, Duration requestTimeout, Implementation clientInfo, ClientCapabilities clientCapabilities, Map roots, @@ -215,9 +218,9 @@ public class McpAsyncClient { */ public Mono initialize() { McpSchema.InitializeRequest initializeRequest = new McpSchema.InitializeRequest(// @formatter:off - McpSchema.LATEST_PROTOCOL_VERSION, - this.clientCapabilities, - this.clientInfo); // @formatter:on + McpSchema.LATEST_PROTOCOL_VERSION, + this.clientCapabilities, + this.clientInfo); // @formatter:on Mono result = this.mcpSession.sendRequest("initialize", initializeRequest, new TypeReference() { @@ -239,10 +242,17 @@ public class McpAsyncClient { }); } + /** + * Closes the client connection immediately. + */ public void close() { this.mcpSession.close(); } + /** + * Gracefully closes the client connection. + * @return A Mono that completes when the connection is closed + */ public Mono closeGracefully() { return this.mcpSession.closeGracefully(); } @@ -252,7 +262,8 @@ public class McpAsyncClient { // -------------------------- /** - * Send a synchronous ping request. + * Sends a ping request to the server. + * @return A Mono that completes with the server's ping response */ public Mono ping() { return this.mcpSession.sendRequest("ping", null, new TypeReference() { @@ -262,6 +273,11 @@ public class McpAsyncClient { // -------------------------- // Roots // -------------------------- + /** + * Adds a new root to the client's root list. + * @param root The root to add + * @return A Mono that completes when the root is added and notifications are sent + */ public Mono addRoot(Root root) { if (root == null) { @@ -286,6 +302,11 @@ public class McpAsyncClient { return Mono.empty(); } + /** + * Removes a root from the client's root list. + * @param rootUri The URI of the root to remove + * @return A Mono that completes when the root is removed and notifications are sent + */ public Mono removeRoot(String rootUri) { if (rootUri == null) { @@ -309,8 +330,9 @@ public class McpAsyncClient { } /** - * Manually, send a roots/list_changed notification. The addRoot and removeRoot + * Manually sends a roots/list_changed notification. The addRoot and removeRoot * methods automatically send the roots/list_changed notification. + * @return A Mono that completes when the notification is sent */ public Mono rootsListChangedNotification() { return this.mcpSession.sendNotification("notifications/roots/list_changed"); @@ -436,7 +458,7 @@ public class McpAsyncClient { /** * Send a resources/list request. - * @return the list of resources result. + * @return A Mono that completes with the list of resources result */ public Mono listResources() { return this.listResources(null); @@ -444,8 +466,8 @@ public class McpAsyncClient { /** * Send a resources/list request. - * @param cursor the cursor - * @return the list of resources result. + * @param cursor the cursor for pagination + * @return A Mono that completes with the list of resources result */ public Mono listResources(String cursor) { return this.mcpSession.sendRequest("resources/list", new McpSchema.PaginatedRequest(cursor), @@ -455,7 +477,7 @@ public class McpAsyncClient { /** * Send a resources/read request. * @param resource the resource to read - * @return the resource content. + * @return A Mono that completes with the resource content */ public Mono readResource(McpSchema.Resource resource) { return this.readResource(new McpSchema.ReadResourceRequest(resource.uri())); @@ -463,8 +485,8 @@ public class McpAsyncClient { /** * Send a resources/read request. - * @param readResourceRequest the read resource request. - * @return the resource content. + * @param readResourceRequest the read resource request + * @return A Mono that completes with the resource content */ public Mono readResource(McpSchema.ReadResourceRequest readResourceRequest) { return this.mcpSession.sendRequest("resources/read", readResourceRequest, READ_RESOURCE_RESULT_TYPE_REF); @@ -475,7 +497,7 @@ public class McpAsyncClient { * templates. Arguments may be auto-completed through the completion API. * * Request a list of resource templates the server has. - * @return the list of resource templates result. + * @return A Mono that completes with the list of resource templates result */ public Mono listResourceTemplates() { return this.listResourceTemplates(null); @@ -486,8 +508,8 @@ public class McpAsyncClient { * templates. Arguments may be auto-completed through the completion API. * * Request a list of resource templates the server has. - * @param cursor the cursor - * @return the list of resource templates result. + * @param cursor the cursor for pagination + * @return A Mono that completes with the list of resource templates result */ public Mono listResourceTemplates(String cursor) { return this.mcpSession.sendRequest("resources/templates/list", new McpSchema.PaginatedRequest(cursor), @@ -496,7 +518,8 @@ public class McpAsyncClient { /** * List Changed Notification. When the list of available resources changes, servers - * that declared the listChanged capability SHOULD send a notification: + * that declared the listChanged capability SHOULD send a notification. + * @return A Mono that completes when the notification is sent */ public Mono sendResourcesListChanged() { return this.mcpSession.sendNotification("notifications/resources/list_changed"); @@ -509,7 +532,8 @@ public class McpAsyncClient { * * Send a resources/subscribe request. * @param subscribeRequest the subscribe request contains the uri of the resource to - * subscribe to. + * subscribe to + * @return A Mono that completes when the subscription is complete */ public Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest) { return this.mcpSession.sendRequest("resources/subscribe", subscribeRequest, VOID_TYPE_REFERENCE); @@ -518,7 +542,8 @@ public class McpAsyncClient { /** * Send a resources/unsubscribe request. * @param unsubscribeRequest the unsubscribe request contains the uri of the resource - * to unsubscribe from. + * to unsubscribe from + * @return A Mono that completes when the unsubscription is complete */ public Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest) { return this.mcpSession.sendRequest("resources/unsubscribe", unsubscribeRequest, VOID_TYPE_REFERENCE); @@ -554,7 +579,7 @@ public class McpAsyncClient { /** * List all available prompts. - * @return the list of prompts result. + * @return A Mono that completes with the list of prompts result */ public Mono listPrompts() { return this.listPrompts(null); @@ -562,8 +587,8 @@ public class McpAsyncClient { /** * List all available prompts. - * @param cursor the cursor - * @return the list of prompts result. + * @param cursor the cursor for pagination + * @return A Mono that completes with the list of prompts result */ public Mono listPrompts(String cursor) { return this.mcpSession.sendRequest("prompts/list", new PaginatedRequest(cursor), LIST_PROMPTS_RESULT_TYPE_REF); @@ -571,8 +596,8 @@ public class McpAsyncClient { /** * Get a prompt by its id. - * @param getPromptRequest the get prompt request. - * @return the get prompt result. + * @param getPromptRequest the get prompt request + * @return A Mono that completes with the get prompt result */ public Mono getPrompt(GetPromptRequest getPromptRequest) { return this.mcpSession.sendRequest("prompts/get", getPromptRequest, GET_PROMPT_RESULT_TYPE_REF); @@ -582,6 +607,7 @@ public class McpAsyncClient { * (Server) An optional notification from the server to the client, informing it that * the list of prompts it offers has changed. This may be issued by servers without * any previous subscription from the client. + * @return A Mono that completes when the notification is sent */ public Mono promptListChangedNotification() { return this.mcpSession.sendNotification("notifications/prompts/list_changed"); diff --git a/mcp/src/main/java/org/springframework/ai/mcp/client/McpSyncClient.java b/mcp/src/main/java/org/springframework/ai/mcp/client/McpSyncClient.java index 54fed7b..88b87e0 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/client/McpSyncClient.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/client/McpSyncClient.java @@ -28,6 +28,8 @@ import org.springframework.ai.mcp.spec.McpSchema.ListPromptsResult; import org.springframework.ai.mcp.util.Assert; /** + * A synchronous client for the Model Context Protocol (MCP). + * * @author Dariusz Jędrzejczyk * @author Christian Tzolov */ diff --git a/mcp/src/main/java/org/springframework/ai/mcp/client/transport/SseClientTransport.java b/mcp/src/main/java/org/springframework/ai/mcp/client/transport/SseClientTransport.java index 8438958..a77528b 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/client/transport/SseClientTransport.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/client/transport/SseClientTransport.java @@ -60,8 +60,8 @@ import org.springframework.web.reactive.function.client.WebClient; *
    *
  1. The client establishes an SSE connection to the server's /sse endpoint
  2. *
  3. The server sends an 'endpoint' event containing the URI for sending messages
  4. - * - *

    + *

+ * * This implementation handles automatic reconnection for transient failures and provides * graceful shutdown capabilities. It uses {@link WebClient} for HTTP communications and * supports JSON serialization/deserialization of messages. diff --git a/mcp/src/main/java/org/springframework/ai/mcp/server/McpAsyncServer.java b/mcp/src/main/java/org/springframework/ai/mcp/server/McpAsyncServer.java index fc31c98..7e1d259 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/server/McpAsyncServer.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/server/McpAsyncServer.java @@ -61,10 +61,13 @@ public class McpAsyncServer { /** * Create a new McpAsyncServer with the given transport and capabilities. - * @param transport The transport to use for communication - * @param tools List of tool registrations - * @param resources Map of resource registrations - * @param prompts Map of prompt registrations + * @param mcpTransport The transport layer implementation for MCP communication + * @param serverInfo The server implementation details + * @param serverCapabilities The server capabilities + * @param tools The list of tool registrations + * @param resources The map of resource registrations + * @param resourceTemplates The list of resource templates + * @param prompts The map of prompt registrations */ public McpAsyncServer(McpTransport mcpTransport, McpSchema.Implementation serverInfo, McpSchema.ServerCapabilities serverCapabilities, List tools, @@ -407,28 +410,32 @@ public class McpAsyncServer { } /** - * Notify clients that the list of available tools has changed. + * Notifies clients that the list of available tools has changed. + * @return A Mono that completes when all clients have been notified */ public Mono notifyToolsListChanged() { return this.mcpSession.sendNotification("notifications/tools/list_changed", null); } /** - * Notify clients that the list of available resources has changed. + * Notifies clients that the list of available resources has changed. + * @return A Mono that completes when all clients have been notified */ public Mono notifyResourcesListChanged() { return this.mcpSession.sendNotification("notifications/resources/list_changed", null); } /** - * Notify clients that the list of available prompts has changed. + * Notifies clients that the list of available prompts has changed. + * @return A Mono that completes when all clients have been notified */ public Mono notifyPromptsListChanged() { return this.mcpSession.sendNotification("notifications/prompts/list_changed", null); } /** - * Close the server gracefully. + * Gracefully closes the server, allowing any in-progress operations to complete. + * @return A Mono that completes when the server has been closed */ public Mono closeGracefully() { return this.mcpSession.closeGracefully(); diff --git a/mcp/src/main/java/org/springframework/ai/mcp/spec/McpSchema.java b/mcp/src/main/java/org/springframework/ai/mcp/spec/McpSchema.java index ece13f6..2c466d6 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/spec/McpSchema.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/spec/McpSchema.java @@ -32,7 +32,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; /** * Based on the JSON-RPC 2.0 - * specification and the and the Model * Context Protocol Schema. * @@ -47,16 +47,34 @@ public class McpSchema { // --------------------------- // JSON-RPC Error Codes // --------------------------- + /** + * Standard error codes used in MCP JSON-RPC responses. + */ public final class ErrorCodes { + /** + * Invalid JSON was received by the server. + */ public static final int PARSE_ERROR = -32700; + /** + * The JSON sent is not a valid Request object. + */ public static final int INVALID_REQUEST = -32600; + /** + * The method does not exist / is not available. + */ public static final int METHOD_NOT_FOUND = -32601; + /** + * Invalid method parameter(s). + */ public static final int INVALID_PARAMS = -32602; + /** + * Internal JSON-RPC error. + */ public static final int INTERNAL_ERROR = -32603; } @@ -340,6 +358,9 @@ public class McpSchema { } /** + * Optional annotations for the client. The client can use annotations to inform how + * objects are used or displayed. + * * @param audience Describes who the intended customer of this object or data is. It * can include multiple entries to indicate content useful for multiple audiences * (e.g., `["user", "assistant"]`). @@ -544,6 +565,10 @@ public class McpSchema { /** * The server's response to a prompts/list request from the client. + * + * @param prompts A list of prompts that the server provides. + * @param nextCursor An optional cursor for pagination. If present, indicates there + * are more prompts available. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) public record ListPromptsResult( // @formatter:off @@ -856,6 +881,9 @@ public class McpSchema { * The client's response to a roots/list request from the server. This result contains * an array of Root objects, each representing a root directory or file that the * server can operate on. + * + * @param roots An array of Root objects, each representing a root directory or file + * that the server can operate on. */ @JsonInclude(JsonInclude.Include.NON_ABSENT) public record ListRootsResult( // @formatter:off diff --git a/mcp/src/main/java/org/springframework/ai/mcp/util/Assert.java b/mcp/src/main/java/org/springframework/ai/mcp/util/Assert.java index 256d063..8d4ea23 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/util/Assert.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/util/Assert.java @@ -19,10 +19,15 @@ package org.springframework.ai.mcp.util; import reactor.util.annotation.Nullable; /** + * Assertion utility class that assists in validating arguments. + * * @author Christian Tzolov */ -public class Assert { +/** + * Utility class providing assertion methods for parameter validation. + */ +public final class Assert { /** * Assert that an object is not {@code null}. diff --git a/mcp/src/main/java/org/springframework/ai/mcp/util/Utils.java b/mcp/src/main/java/org/springframework/ai/mcp/util/Utils.java index 7f6850a..47e38c7 100644 --- a/mcp/src/main/java/org/springframework/ai/mcp/util/Utils.java +++ b/mcp/src/main/java/org/springframework/ai/mcp/util/Utils.java @@ -24,10 +24,12 @@ import reactor.util.annotation.Nullable; import org.springframework.lang.Contract; /** + * Miscellaneous utility methods. + * * @author Christian Tzolov */ -public class Utils { +public final class Utils { /** * Check whether the given {@code String} contains actual text.