From 54ff61d966ab8c53d76f867ab881867693475f30 Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:24:27 +0800
Subject: [PATCH 1/7] .
Signed-off-by: He-Pin
---
.../client/{McpAsyncClient.java => DefaultMcpAsyncClient.java} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename mcp-core/src/main/java/io/modelcontextprotocol/client/{McpAsyncClient.java => DefaultMcpAsyncClient.java} (100%)
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
similarity index 100%
rename from mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
From f02e46a1145b1b7787c135762d89ea0df91734d5 Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:26:01 +0800
Subject: [PATCH 2/7] .
Signed-off-by: He-Pin
---
.../modelcontextprotocol/client/DefaultMcpAsyncClient.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
index 2d1f4b43c..20816fb6d 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
@@ -81,9 +81,9 @@
* @see McpClientSession
* @see McpClientTransport
*/
-public class McpAsyncClient {
+public class DefaultMcpAsyncClient {
- private static final Logger logger = LoggerFactory.getLogger(McpAsyncClient.class);
+ private static final Logger logger = LoggerFactory.getLogger(DefaultMcpAsyncClient.class);
private static final TypeRef VOID_TYPE_REFERENCE = new TypeRef<>() {
};
@@ -178,7 +178,7 @@ public class McpAsyncClient {
* @param features the MCP Client supported features. responses against output
* schemas.
*/
- McpAsyncClient(McpClientTransport transport, Duration requestTimeout, Duration initializationTimeout,
+ DefaultMcpAsyncClient(McpClientTransport transport, Duration requestTimeout, Duration initializationTimeout,
JsonSchemaValidator jsonSchemaValidator, McpClientFeatures.Async features) {
Assert.notNull(transport, "Transport must not be null");
From 78389c47e16a8a123a6254f7e537e3156391caad Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:26:53 +0800
Subject: [PATCH 3/7] .
Signed-off-by: He-Pin
---
.../client/McpAsyncClient.java | 348 ++++++++++++++++++
1 file changed, 348 insertions(+)
create mode 100644 mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
new file mode 100644
index 000000000..50a14f31e
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
@@ -0,0 +1,348 @@
+package io.modelcontextprotocol.client;
+
+import io.modelcontextprotocol.spec.McpClientSession;
+import io.modelcontextprotocol.spec.McpClientTransport;
+import io.modelcontextprotocol.spec.McpSchema;
+import reactor.core.publisher.Mono;
+
+/**
+ * The Model Context Protocol (MCP) client implementation that provides asynchronous
+ * communication with MCP servers using Project Reactor's Mono and Flux types.
+ *
+ *
+ * This client implements the MCP specification, enabling AI models to interact with
+ * external tools and resources through a standardized interface. Key features include:
+ *
+ * Asynchronous communication using reactive programming patterns
+ * Tool discovery and invocation for server-provided functionality
+ * Resource access and management with URI-based addressing
+ * Prompt template handling for standardized AI interactions
+ * Real-time notifications for tools, resources, and prompts changes
+ * Structured logging with configurable severity levels
+ * Message sampling for AI model interactions
+ *
+ *
+ *
+ * The client follows a lifecycle:
+ *
+ * Initialization - Establishes connection and negotiates capabilities
+ * Normal Operation - Handles requests and notifications
+ * Graceful Shutdown - Ensures clean connection termination
+ *
+ *
+ *
+ * This implementation uses Project Reactor for non-blocking operations, making it
+ * suitable for high-throughput scenarios and reactive applications. All operations return
+ * Mono or Flux types that can be composed into reactive pipelines.
+ *
+ * @author Dariusz Jędrzejczyk
+ * @author Christian Tzolov
+ * @author Jihoon Kim
+ * @author Anurag Pant
+ * @see McpClient
+ * @see McpSchema
+ * @see McpClientSession
+ * @see McpClientTransport
+ */
+public interface McpAsyncClient {
+ /**
+ * Get the current initialization result.
+ * @return the initialization result.
+ */
+ McpSchema.InitializeResult getCurrentInitializationResult();
+
+ /**
+ * Get the server capabilities that define the supported features and functionality.
+ * @return The server capabilities
+ */
+ McpSchema.ServerCapabilities getServerCapabilities();
+
+ /**
+ * Get the server instructions that provide guidance to the client on how to interact
+ * with this server.
+ * @return The server instructions
+ */
+ String getServerInstructions();
+
+ /**
+ * Get the server implementation information.
+ * @return The server implementation details
+ */
+ McpSchema.Implementation getServerInfo();
+
+ /**
+ * Check if the client-server connection is initialized.
+ * @return true if the client-server connection is initialized
+ */
+ boolean isInitialized();
+
+ /**
+ * Get the client capabilities that define the supported features and functionality.
+ * @return The client capabilities
+ */
+ McpSchema.ClientCapabilities getClientCapabilities();
+
+ /**
+ * Get the client implementation information.
+ * @return The client implementation details
+ */
+ McpSchema.Implementation getClientInfo();
+
+ /**
+ * Closes the client connection immediately.
+ */
+ void close();
+
+ /**
+ * Gracefully closes the client connection.
+ * @return A Mono that completes when the connection is closed
+ */
+ Mono closeGracefully();
+
+ // --------------------------
+ // Initialization
+ // --------------------------
+
+ /**
+ * The initialization phase should be the first interaction between client and server.
+ * The client will ensure it happens in case it has not been explicitly called and in
+ * case of transport session invalidation.
+ *
+ * During this phase, the client and server:
+ *
+ * Establish protocol version compatibility
+ * Exchange and negotiate capabilities
+ * Share implementation details
+ *
+ *
+ * The client MUST initiate this phase by sending an initialize request containing:
+ * The protocol version the client supports, client's capabilities and clients
+ * implementation information.
+ *
+ * The server MUST respond with its own capabilities and information.
+ *
+ * After successful initialization, the client MUST send an initialized notification
+ * to indicate it is ready to begin normal operations.
+ * @return the initialize result.
+ * @see MCP
+ * Initialization Spec
+ *
+ */
+ Mono initialize();
+
+ // --------------------------
+ // Basic Utilities
+ // --------------------------
+
+ /**
+ * Sends a ping request to the server.
+ * @return A Mono that completes with the server's ping response
+ */
+ Mono ping();
+
+
+ // --------------------------
+ // 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.
+ */
+ Mono addRoot(McpSchema.Root root);
+
+ /**
+ * 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.
+ */
+ Mono removeRoot(String rootUri);
+
+ /**
+ * Manually sends a roots/list_changed notification. The addRoot and removeRoot
+ * methods automatically send the roots/list_changed notification if the client is in
+ * an initialized state.
+ * @return A Mono that completes when the notification is sent.
+ */
+ Mono rootsListChangedNotification();
+
+ // --------------------------
+ // Tools
+ // --------------------------
+
+ /**
+ * Calls a tool provided by the server. Tools enable servers to expose executable
+ * functionality that can interact with external systems, perform computations, and
+ * take actions in the real world.
+ * @param callToolRequest The request containing the tool name and input parameters.
+ * @return A Mono that emits the result of the tool call, including the output and any
+ * errors.
+ * @see McpSchema.CallToolRequest
+ * @see McpSchema.CallToolResult
+ * @see #listTools()
+ */
+ Mono callTool(McpSchema.CallToolRequest callToolRequest);
+
+ /**
+ * Retrieves the list of all tools provided by the server.
+ * @return A Mono that emits the list of all tools result
+ */
+ Mono listTools();
+
+ /**
+ * Retrieves a paginated list of tools provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return A Mono that emits the list of tools result
+ */
+ Mono listTools(String cursor);
+
+ // --------------------------
+ // Resources
+ // --------------------------
+
+ /**
+ * Retrieves the list of all resources provided by the server. Resources represent any
+ * kind of UTF-8 encoded data that an MCP server makes available to clients, such as
+ * database records, API responses, log files, and more.
+ * @return A Mono that completes with the list of all resources result
+ * @see McpSchema.ListResourcesResult
+ * @see #readResource(McpSchema.Resource)
+ */
+ Mono listResources();
+
+ /**
+ * Retrieves a paginated list of resources provided by the server. Resources represent
+ * any kind of UTF-8 encoded data that an MCP server makes available to clients, such
+ * as database records, API responses, log files, and more.
+ * @param cursor Optional pagination cursor from a previous list request.
+ * @return A Mono that completes with the list of resources result.
+ * @see McpSchema.ListResourcesResult
+ * @see #readResource(McpSchema.Resource)
+ */
+ Mono listResources(String cursor);
+
+ /**
+ * Reads the content of a specific resource identified by the provided Resource
+ * object. This method fetches the actual data that the resource represents.
+ * @param resource The resource to read, containing the URI that identifies the
+ * resource.
+ * @return A Mono that completes with the resource content.
+ * @see McpSchema.Resource
+ * @see McpSchema.ReadResourceResult
+ */
+ Mono readResource(McpSchema.Resource resource);
+
+ /**
+ * Reads the content of a specific resource identified by the provided request. This
+ * method fetches the actual data that the resource represents.
+ * @param readResourceRequest The request containing the URI of the resource to read
+ * @return A Mono that completes with the resource content.
+ * @see McpSchema.ReadResourceRequest
+ * @see McpSchema.ReadResourceResult
+ */
+ Mono readResource(McpSchema.ReadResourceRequest readResourceRequest);
+
+ /**
+ * Retrieves the list of all resource templates provided by the server. Resource
+ * templates allow servers to expose parameterized resources using URI templates,
+ * enabling dynamic resource access based on variable parameters.
+ * @return A Mono that completes with the list of all resource templates result
+ * @see McpSchema.ListResourceTemplatesResult
+ */
+ Mono listResourceTemplates();
+
+ /**
+ * Retrieves a paginated list of resource templates provided by the server. Resource
+ * templates allow servers to expose parameterized resources using URI templates,
+ * enabling dynamic resource access based on variable parameters.
+ * @param cursor Optional pagination cursor from a previous list request.
+ * @return A Mono that completes with the list of resource templates result.
+ * @see McpSchema.ListResourceTemplatesResult
+ */
+ Mono listResourceTemplates(String cursor);
+
+ /**
+ * Subscribes to changes in a specific resource. When the resource changes on the
+ * server, the client will receive notifications through the resources change
+ * notification handler.
+ * @param subscribeRequest The subscribe request containing the URI of the resource.
+ * @return A Mono that completes when the subscription is complete.
+ * @see McpSchema.SubscribeRequest
+ * @see #unsubscribeResource(McpSchema.UnsubscribeRequest)
+ */
+ Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest);
+
+ /**
+ * Cancels an existing subscription to a resource. After unsubscribing, the client
+ * will no longer receive notifications when the resource changes.
+ * @param unsubscribeRequest The unsubscribe request containing the URI of the
+ * resource.
+ * @return A Mono that completes when the unsubscription is complete.
+ * @see McpSchema.UnsubscribeRequest
+ * @see #subscribeResource(McpSchema.SubscribeRequest)
+ */
+ Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest);
+
+ // --------------------------
+ // Prompts
+ // --------------------------
+
+ /**
+ * Retrieves the list of all prompts provided by the server.
+ * @return A Mono that completes with the list of all prompts result.
+ * @see McpSchema.ListPromptsResult
+ * @see #getPrompt(McpSchema.GetPromptRequest)
+ */
+ Mono listPrompts();
+
+ /**
+ * Retrieves a paginated list of prompts provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return A Mono that completes with the list of prompts result.
+ * @see McpSchema.ListPromptsResult
+ * @see #getPrompt(McpSchema.GetPromptRequest)
+ */
+ Mono listPrompts(String cursor);
+
+ /**
+ * Retrieves a specific prompt by its ID. This provides the complete prompt template
+ * including all parameters and instructions for generating AI content.
+ * @param getPromptRequest The request containing the ID of the prompt to retrieve.
+ * @return A Mono that completes with the prompt result.
+ * @see McpSchema.GetPromptRequest
+ * @see McpSchema.GetPromptResult
+ * @see #listPrompts()
+ */
+ Mono getPrompt(McpSchema.GetPromptRequest getPromptRequest);
+
+ // --------------------------
+ // Logging
+ // --------------------------
+
+ /**
+ * Sets the minimum logging level for messages received from the server. The client
+ * will only receive log messages at or above the specified severity level.
+ * @param loggingLevel The minimum logging level to receive.
+ * @return A Mono that completes when the logging level is set.
+ * @see McpSchema.LoggingLevel
+ */
+ Mono setLoggingLevel(McpSchema.LoggingLevel loggingLevel);
+
+ // --------------------------
+ // Completions
+ // --------------------------
+ /**
+ * Sends a completion/complete request to generate value suggestions based on a given
+ * reference and argument. This is typically used to provide auto-completion options
+ * for user input fields.
+ * @param completeRequest The request containing the prompt or resource reference and
+ * argument for which to generate completions.
+ * @return A Mono that completes with the result containing completion suggestions.
+ * @see McpSchema.CompleteRequest
+ * @see McpSchema.CompleteResult
+ */
+ Mono completeCompletion(McpSchema.CompleteRequest completeRequest);
+
+}
From 7b6511bd9215e30766f8606bc3227d066ea0a6b4 Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:31:21 +0800
Subject: [PATCH 4/7] .
Signed-off-by: He-Pin
---
.../client/DefaultMcpAsyncClient.java | 244 +++---------------
.../client/LifecycleInitializer.java | 2 +-
.../client/McpClient.java | 4 +-
.../client/McpClientProtocolVersionTests.java | 4 +-
4 files changed, 38 insertions(+), 216 deletions(-)
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
index 20816fb6d..94daf4af2 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
@@ -81,7 +81,7 @@
* @see McpClientSession
* @see McpClientTransport
*/
-public class DefaultMcpAsyncClient {
+public class DefaultMcpAsyncClient implements McpAsyncClient {
private static final Logger logger = LoggerFactory.getLogger(DefaultMcpAsyncClient.class);
@@ -321,79 +321,52 @@ public class DefaultMcpAsyncClient {
this.transport.setExceptionHandler(this.initializer::handleException);
}
- /**
- * Get the current initialization result.
- * @return the initialization result.
- */
+ @Override
public McpSchema.InitializeResult getCurrentInitializationResult() {
return this.initializer.currentInitializationResult();
}
- /**
- * Get the server capabilities that define the supported features and functionality.
- * @return The server capabilities
- */
+ @Override
public McpSchema.ServerCapabilities getServerCapabilities() {
McpSchema.InitializeResult initializeResult = this.initializer.currentInitializationResult();
return initializeResult != null ? initializeResult.capabilities() : null;
}
- /**
- * Get the server instructions that provide guidance to the client on how to interact
- * with this server.
- * @return The server instructions
- */
+ @Override
public String getServerInstructions() {
McpSchema.InitializeResult initializeResult = this.initializer.currentInitializationResult();
return initializeResult != null ? initializeResult.instructions() : null;
}
- /**
- * Get the server implementation information.
- * @return The server implementation details
- */
+ @Override
public McpSchema.Implementation getServerInfo() {
McpSchema.InitializeResult initializeResult = this.initializer.currentInitializationResult();
return initializeResult != null ? initializeResult.serverInfo() : null;
}
- /**
- * Check if the client-server connection is initialized.
- * @return true if the client-server connection is initialized
- */
+ @Override
public boolean isInitialized() {
return this.initializer.isInitialized();
}
- /**
- * Get the client capabilities that define the supported features and functionality.
- * @return The client capabilities
- */
+ @Override
public ClientCapabilities getClientCapabilities() {
return this.clientCapabilities;
}
- /**
- * Get the client implementation information.
- * @return The client implementation details
- */
+ @Override
public McpSchema.Implementation getClientInfo() {
return this.clientInfo;
}
- /**
- * Closes the client connection immediately.
- */
+ @Override
public void close() {
this.initializer.close();
this.transport.close();
}
- /**
- * Gracefully closes the client connection.
- * @return A Mono that completes when the connection is closed
- */
- public Mono closeGracefully() {
+ @Override
+ public Mono closeGracefully() {
return Mono.defer(() -> {
return this.initializer.closeGracefully().then(transport.closeGracefully());
});
@@ -403,33 +376,8 @@ public Mono closeGracefully() {
// Initialization
// --------------------------
- /**
- * The initialization phase should be the first interaction between client and server.
- * The client will ensure it happens in case it has not been explicitly called and in
- * case of transport session invalidation.
- *
- * During this phase, the client and server:
- *
- * Establish protocol version compatibility
- * Exchange and negotiate capabilities
- * Share implementation details
- *
- *
- * The client MUST initiate this phase by sending an initialize request containing:
- * The protocol version the client supports, client's capabilities and clients
- * implementation information.
- *
- * The server MUST respond with its own capabilities and information.
- *
- * After successful initialization, the client MUST send an initialized notification
- * to indicate it is ready to begin normal operations.
- * @return the initialize result.
- * @see MCP
- * Initialization Spec
- *
- */
- public Mono initialize() {
+ @Override
+ public Mono initialize() {
return this.initializer.withInitialization("by explicit API call", init -> Mono.just(init.initializeResult()));
}
@@ -437,10 +385,7 @@ public Mono initialize() {
// Basic Utilities
// --------------------------
- /**
- * Sends a ping request to the server.
- * @return A Mono that completes with the server's ping response
- */
+ @Override
public Mono ping() {
return this.initializer.withInitialization("pinging the server",
init -> init.mcpSession().sendRequest(McpSchema.METHOD_PING, null, OBJECT_TYPE_REF));
@@ -450,11 +395,7 @@ public Mono ping() {
// 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.
- */
+ @Override
public Mono addRoot(Root root) {
if (root == null) {
@@ -484,11 +425,7 @@ public Mono addRoot(Root root) {
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.
- */
+ @Override
public Mono removeRoot(String rootUri) {
if (rootUri == null) {
@@ -517,12 +454,7 @@ public Mono removeRoot(String rootUri) {
return Mono.error(new IllegalStateException("Root with uri '" + rootUri + "' not found"));
}
- /**
- * Manually sends a roots/list_changed notification. The addRoot and removeRoot
- * methods automatically send the roots/list_changed notification if the client is in
- * an initialized state.
- * @return A Mono that completes when the notification is sent.
- */
+ @Override
public Mono rootsListChangedNotification() {
return this.initializer.withInitialization("sending roots list changed notification",
init -> init.mcpSession().sendNotification(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED));
@@ -571,17 +503,7 @@ private RequestHandler elicitationCreateHandler() {
private static final TypeRef LIST_TOOLS_RESULT_TYPE_REF = new TypeRef<>() {
};
- /**
- * Calls a tool provided by the server. Tools enable servers to expose executable
- * functionality that can interact with external systems, perform computations, and
- * take actions in the real world.
- * @param callToolRequest The request containing the tool name and input parameters.
- * @return A Mono that emits the result of the tool call, including the output and any
- * errors.
- * @see McpSchema.CallToolRequest
- * @see McpSchema.CallToolResult
- * @see #listTools()
- */
+ @Override
public Mono callTool(McpSchema.CallToolRequest callToolRequest) {
return this.initializer.withInitialization("calling tool", init -> {
if (init.initializeResult().capabilities().tools() == null) {
@@ -622,10 +544,7 @@ private McpSchema.CallToolResult validateToolResult(String toolName, McpSchema.C
return result;
}
- /**
- * Retrieves the list of all tools provided by the server.
- * @return A Mono that emits the list of all tools result
- */
+ @Override
public Mono listTools() {
return this.listTools(McpSchema.FIRST_PAGE).expand(result -> {
String next = result.nextCursor();
@@ -636,11 +555,7 @@ public Mono listTools() {
}).map(result -> new McpSchema.ListToolsResult(Collections.unmodifiableList(result.tools()), null));
}
- /**
- * Retrieves a paginated list of tools provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return A Mono that emits the list of tools result
- */
+ @Override
public Mono listTools(String cursor) {
return this.initializer.withInitialization("listing tools", init -> this.listToolsInternal(init, cursor));
}
@@ -690,14 +605,7 @@ private NotificationHandler asyncToolsChangeNotificationHandler(
private static final TypeRef LIST_RESOURCE_TEMPLATES_RESULT_TYPE_REF = new TypeRef<>() {
};
- /**
- * Retrieves the list of all resources provided by the server. Resources represent any
- * kind of UTF-8 encoded data that an MCP server makes available to clients, such as
- * database records, API responses, log files, and more.
- * @return A Mono that completes with the list of all resources result
- * @see McpSchema.ListResourcesResult
- * @see #readResource(McpSchema.Resource)
- */
+ @Override
public Mono listResources() {
return this.listResources(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listResources(result.nextCursor()) : Mono.empty())
@@ -708,15 +616,7 @@ public Mono listResources() {
.map(result -> new McpSchema.ListResourcesResult(Collections.unmodifiableList(result.resources()), null));
}
- /**
- * Retrieves a paginated list of resources provided by the server. Resources represent
- * any kind of UTF-8 encoded data that an MCP server makes available to clients, such
- * as database records, API responses, log files, and more.
- * @param cursor Optional pagination cursor from a previous list request.
- * @return A Mono that completes with the list of resources result.
- * @see McpSchema.ListResourcesResult
- * @see #readResource(McpSchema.Resource)
- */
+ @Override
public Mono listResources(String cursor) {
return this.initializer.withInitialization("listing resources", init -> {
if (init.initializeResult().capabilities().resources() == null) {
@@ -728,27 +628,12 @@ public Mono listResources(String cursor) {
});
}
- /**
- * Reads the content of a specific resource identified by the provided Resource
- * object. This method fetches the actual data that the resource represents.
- * @param resource The resource to read, containing the URI that identifies the
- * resource.
- * @return A Mono that completes with the resource content.
- * @see McpSchema.Resource
- * @see McpSchema.ReadResourceResult
- */
+ @Override
public Mono readResource(McpSchema.Resource resource) {
return this.readResource(new McpSchema.ReadResourceRequest(resource.uri()));
}
- /**
- * Reads the content of a specific resource identified by the provided request. This
- * method fetches the actual data that the resource represents.
- * @param readResourceRequest The request containing the URI of the resource to read
- * @return A Mono that completes with the resource content.
- * @see McpSchema.ReadResourceRequest
- * @see McpSchema.ReadResourceResult
- */
+ @Override
public Mono readResource(McpSchema.ReadResourceRequest readResourceRequest) {
return this.initializer.withInitialization("reading resources", init -> {
if (init.initializeResult().capabilities().resources() == null) {
@@ -759,13 +644,7 @@ public Mono readResource(McpSchema.ReadResourceReq
});
}
- /**
- * Retrieves the list of all resource templates provided by the server. Resource
- * templates allow servers to expose parameterized resources using URI templates,
- * enabling dynamic resource access based on variable parameters.
- * @return A Mono that completes with the list of all resource templates result
- * @see McpSchema.ListResourceTemplatesResult
- */
+ @Override
public Mono listResourceTemplates() {
return this.listResourceTemplates(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listResourceTemplates(result.nextCursor())
@@ -779,14 +658,7 @@ public Mono listResourceTemplates() {
Collections.unmodifiableList(result.resourceTemplates()), null));
}
- /**
- * Retrieves a paginated list of resource templates provided by the server. Resource
- * templates allow servers to expose parameterized resources using URI templates,
- * enabling dynamic resource access based on variable parameters.
- * @param cursor Optional pagination cursor from a previous list request.
- * @return A Mono that completes with the list of resource templates result.
- * @see McpSchema.ListResourceTemplatesResult
- */
+ @Override
public Mono listResourceTemplates(String cursor) {
return this.initializer.withInitialization("listing resource templates", init -> {
if (init.initializeResult().capabilities().resources() == null) {
@@ -798,29 +670,13 @@ public Mono listResourceTemplates(String
});
}
- /**
- * Subscribes to changes in a specific resource. When the resource changes on the
- * server, the client will receive notifications through the resources change
- * notification handler.
- * @param subscribeRequest The subscribe request containing the URI of the resource.
- * @return A Mono that completes when the subscription is complete.
- * @see McpSchema.SubscribeRequest
- * @see #unsubscribeResource(McpSchema.UnsubscribeRequest)
- */
+ @Override
public Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest) {
return this.initializer.withInitialization("subscribing to resources", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_RESOURCES_SUBSCRIBE, subscribeRequest, VOID_TYPE_REFERENCE));
}
- /**
- * Cancels an existing subscription to a resource. After unsubscribing, the client
- * will no longer receive notifications when the resource changes.
- * @param unsubscribeRequest The unsubscribe request containing the URI of the
- * resource.
- * @return A Mono that completes when the unsubscription is complete.
- * @see McpSchema.UnsubscribeRequest
- * @see #subscribeResource(McpSchema.SubscribeRequest)
- */
+ @Override
public Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest) {
return this.initializer.withInitialization("unsubscribing from resources", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_RESOURCES_UNSUBSCRIBE, unsubscribeRequest, VOID_TYPE_REFERENCE));
@@ -864,12 +720,7 @@ private NotificationHandler asyncResourcesUpdatedNotificationHandler(
private static final TypeRef GET_PROMPT_RESULT_TYPE_REF = new TypeRef<>() {
};
- /**
- * Retrieves the list of all prompts provided by the server.
- * @return A Mono that completes with the list of all prompts result.
- * @see McpSchema.ListPromptsResult
- * @see #getPrompt(GetPromptRequest)
- */
+ @Override
public Mono listPrompts() {
return this.listPrompts(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listPrompts(result.nextCursor()) : Mono.empty())
@@ -880,27 +731,13 @@ public Mono listPrompts() {
.map(result -> new McpSchema.ListPromptsResult(Collections.unmodifiableList(result.prompts()), null));
}
- /**
- * Retrieves a paginated list of prompts provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return A Mono that completes with the list of prompts result.
- * @see McpSchema.ListPromptsResult
- * @see #getPrompt(GetPromptRequest)
- */
+ @Override
public Mono listPrompts(String cursor) {
return this.initializer.withInitialization("listing prompts", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_PROMPT_LIST, new PaginatedRequest(cursor), LIST_PROMPTS_RESULT_TYPE_REF));
}
- /**
- * Retrieves a specific prompt by its ID. This provides the complete prompt template
- * including all parameters and instructions for generating AI content.
- * @param getPromptRequest The request containing the ID of the prompt to retrieve.
- * @return A Mono that completes with the prompt result.
- * @see McpSchema.GetPromptRequest
- * @see McpSchema.GetPromptResult
- * @see #listPrompts()
- */
+ @Override
public Mono getPrompt(GetPromptRequest getPromptRequest) {
return this.initializer.withInitialization("getting prompts", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_PROMPT_GET, getPromptRequest, GET_PROMPT_RESULT_TYPE_REF));
@@ -933,13 +770,7 @@ private NotificationHandler asyncLoggingNotificationHandler(
};
}
- /**
- * Sets the minimum logging level for messages received from the server. The client
- * will only receive log messages at or above the specified severity level.
- * @param loggingLevel The minimum logging level to receive.
- * @return A Mono that completes when the logging level is set.
- * @see McpSchema.LoggingLevel
- */
+ @Override
public Mono setLoggingLevel(LoggingLevel loggingLevel) {
if (loggingLevel == null) {
return Mono.error(new IllegalArgumentException("Logging level must not be null"));
@@ -982,16 +813,7 @@ void setProtocolVersions(List protocolVersions) {
private static final TypeRef COMPLETION_COMPLETE_RESULT_TYPE_REF = new TypeRef<>() {
};
- /**
- * Sends a completion/complete request to generate value suggestions based on a given
- * reference and argument. This is typically used to provide auto-completion options
- * for user input fields.
- * @param completeRequest The request containing the prompt or resource reference and
- * argument for which to generate completions.
- * @return A Mono that completes with the result containing completion suggestions.
- * @see McpSchema.CompleteRequest
- * @see McpSchema.CompleteResult
- */
+ @Override
public Mono completeCompletion(McpSchema.CompleteRequest completeRequest) {
return this.initializer.withInitialization("complete completions", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_COMPLETION_COMPLETE, completeRequest, COMPLETION_COMPLETE_RESULT_TYPE_REF));
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java
index f56c79a6d..85b3fd743 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java
@@ -304,7 +304,7 @@ private Mono doInitialize(DefaultInitialization init
this.clientCapabilities, this.clientInfo);
Mono result = mcpClientSession.sendRequest(McpSchema.METHOD_INITIALIZE,
- initializeRequest, McpAsyncClient.INITIALIZE_RESULT_TYPE_REF);
+ initializeRequest, DefaultMcpAsyncClient.INITIALIZE_RESULT_TYPE_REF);
return result.flatMap(initializeResult -> {
logger.info("Server response with Protocol: {}, Capabilities: {}, Info: {} and Instructions {}",
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
index 421f2fc7f..1c176680f 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
@@ -474,7 +474,7 @@ public McpSyncClient build() {
McpClientFeatures.Async asyncFeatures = McpClientFeatures.Async.fromSync(syncFeatures);
- return new McpSyncClient(new McpAsyncClient(transport, this.requestTimeout, this.initializationTimeout,
+ return new McpSyncClient(new DefaultMcpAsyncClient(transport, this.requestTimeout, this.initializationTimeout,
jsonSchemaValidator != null ? jsonSchemaValidator : JsonSchemaValidator.getDefault(),
asyncFeatures), this.contextProvider);
}
@@ -810,7 +810,7 @@ public AsyncSpec enableCallToolSchemaCaching(boolean enableCallToolSchemaCaching
public McpAsyncClient build() {
var jsonSchemaValidator = (this.jsonSchemaValidator != null) ? this.jsonSchemaValidator
: JsonSchemaValidator.getDefault();
- return new McpAsyncClient(this.transport, this.requestTimeout, this.initializationTimeout,
+ return new DefaultMcpAsyncClient(this.transport, this.requestTimeout, this.initializationTimeout,
jsonSchemaValidator,
new McpClientFeatures.Async(this.clientInfo, this.capabilities, this.roots,
this.toolsChangeConsumers, this.resourcesChangeConsumers, this.resourcesUpdateConsumers,
diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java b/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java
index a94b9b6a7..c7a829dc5 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java
@@ -68,7 +68,7 @@ void shouldNegotiateSpecificVersion() {
.requestTimeout(REQUEST_TIMEOUT)
.build();
- client.setProtocolVersions(List.of(oldVersion, McpSchema.LATEST_PROTOCOL_VERSION));
+ ((DefaultMcpAsyncClient)client).setProtocolVersions(List.of(oldVersion, McpSchema.LATEST_PROTOCOL_VERSION));
try {
Mono initializeResultMono = client.initialize();
@@ -131,7 +131,7 @@ void shouldUseHighestVersionWhenMultipleSupported() {
.requestTimeout(REQUEST_TIMEOUT)
.build();
- client.setProtocolVersions(List.of(oldVersion, middleVersion, latestVersion));
+ ((DefaultMcpAsyncClient)client).setProtocolVersions(List.of(oldVersion, middleVersion, latestVersion));
try {
Mono initializeResultMono = client.initialize();
From 7ccc191d8059df096f23da0cf4921040edd17274 Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:32:17 +0800
Subject: [PATCH 5/7] .
Signed-off-by: He-Pin
---
.../client/{McpSyncClient.java => DefaultMcpSyncClient.java} | 0
1 file changed, 0 insertions(+), 0 deletions(-)
rename mcp-core/src/main/java/io/modelcontextprotocol/client/{McpSyncClient.java => DefaultMcpSyncClient.java} (100%)
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
similarity index 100%
rename from mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
From 9afc044591b9b4756236f7f4e221356ba12a82b7 Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:32:47 +0800
Subject: [PATCH 6/7] .
Signed-off-by: He-Pin
---
.../modelcontextprotocol/client/DefaultMcpSyncClient.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
index 7fdaa8941..73ee92877 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
@@ -55,9 +55,9 @@
* @see McpAsyncClient
* @see McpSchema
*/
-public class McpSyncClient implements AutoCloseable {
+public class DefaultMcpSyncClient implements AutoCloseable {
- private static final Logger logger = LoggerFactory.getLogger(McpSyncClient.class);
+ private static final Logger logger = LoggerFactory.getLogger(DefaultMcpSyncClient.class);
// TODO: Consider providing a client config to set this properly
// this is currently a concern only because AutoCloseable is used - perhaps it
@@ -75,7 +75,7 @@ public class McpSyncClient implements AutoCloseable {
* @param contextProvider the supplier of context before calling any non-blocking
* operation on underlying delegate
*/
- McpSyncClient(McpAsyncClient delegate, Supplier contextProvider) {
+ DefaultMcpSyncClient(McpAsyncClient delegate, Supplier contextProvider) {
Assert.notNull(delegate, "The delegate can not be null");
Assert.notNull(contextProvider, "The contextProvider can not be null");
this.delegate = delegate;
From d0766542a5db09ae7049e5c805253333835a38e5 Mon Sep 17 00:00:00 2001
From: He-Pin
Date: Wed, 19 Nov 2025 21:48:37 +0800
Subject: [PATCH 7/7] .
Signed-off-by: He-Pin
---
.../client/DefaultMcpAsyncClient.java | 66 +-
.../client/DefaultMcpSyncClient.java | 191 +-----
.../client/McpAsyncClient.java | 607 +++++++++---------
.../client/McpClient.java | 8 +-
.../client/McpSyncClient.java | 278 ++++++++
.../client/McpClientProtocolVersionTests.java | 4 +-
6 files changed, 653 insertions(+), 501 deletions(-)
create mode 100644 mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
index 94daf4af2..ad7c3ebc7 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpAsyncClient.java
@@ -178,7 +178,7 @@ public class DefaultMcpAsyncClient implements McpAsyncClient {
* @param features the MCP Client supported features. responses against output
* schemas.
*/
- DefaultMcpAsyncClient(McpClientTransport transport, Duration requestTimeout, Duration initializationTimeout,
+ DefaultMcpAsyncClient(McpClientTransport transport, Duration requestTimeout, Duration initializationTimeout,
JsonSchemaValidator jsonSchemaValidator, McpClientFeatures.Async features) {
Assert.notNull(transport, "Transport must not be null");
@@ -321,52 +321,52 @@ public class DefaultMcpAsyncClient implements McpAsyncClient {
this.transport.setExceptionHandler(this.initializer::handleException);
}
- @Override
+ @Override
public McpSchema.InitializeResult getCurrentInitializationResult() {
return this.initializer.currentInitializationResult();
}
- @Override
+ @Override
public McpSchema.ServerCapabilities getServerCapabilities() {
McpSchema.InitializeResult initializeResult = this.initializer.currentInitializationResult();
return initializeResult != null ? initializeResult.capabilities() : null;
}
- @Override
+ @Override
public String getServerInstructions() {
McpSchema.InitializeResult initializeResult = this.initializer.currentInitializationResult();
return initializeResult != null ? initializeResult.instructions() : null;
}
- @Override
+ @Override
public McpSchema.Implementation getServerInfo() {
McpSchema.InitializeResult initializeResult = this.initializer.currentInitializationResult();
return initializeResult != null ? initializeResult.serverInfo() : null;
}
- @Override
+ @Override
public boolean isInitialized() {
return this.initializer.isInitialized();
}
- @Override
+ @Override
public ClientCapabilities getClientCapabilities() {
return this.clientCapabilities;
}
- @Override
+ @Override
public McpSchema.Implementation getClientInfo() {
return this.clientInfo;
}
- @Override
+ @Override
public void close() {
this.initializer.close();
this.transport.close();
}
- @Override
- public Mono closeGracefully() {
+ @Override
+ public Mono closeGracefully() {
return Mono.defer(() -> {
return this.initializer.closeGracefully().then(transport.closeGracefully());
});
@@ -376,8 +376,8 @@ public Mono closeGracefully() {
// Initialization
// --------------------------
- @Override
- public Mono initialize() {
+ @Override
+ public Mono initialize() {
return this.initializer.withInitialization("by explicit API call", init -> Mono.just(init.initializeResult()));
}
@@ -385,7 +385,7 @@ public Mono initialize() {
// Basic Utilities
// --------------------------
- @Override
+ @Override
public Mono ping() {
return this.initializer.withInitialization("pinging the server",
init -> init.mcpSession().sendRequest(McpSchema.METHOD_PING, null, OBJECT_TYPE_REF));
@@ -395,7 +395,7 @@ public Mono ping() {
// Roots
// --------------------------
- @Override
+ @Override
public Mono addRoot(Root root) {
if (root == null) {
@@ -425,7 +425,7 @@ public Mono addRoot(Root root) {
return Mono.empty();
}
- @Override
+ @Override
public Mono removeRoot(String rootUri) {
if (rootUri == null) {
@@ -454,7 +454,7 @@ public Mono removeRoot(String rootUri) {
return Mono.error(new IllegalStateException("Root with uri '" + rootUri + "' not found"));
}
- @Override
+ @Override
public Mono rootsListChangedNotification() {
return this.initializer.withInitialization("sending roots list changed notification",
init -> init.mcpSession().sendNotification(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED));
@@ -503,7 +503,7 @@ private RequestHandler elicitationCreateHandler() {
private static final TypeRef LIST_TOOLS_RESULT_TYPE_REF = new TypeRef<>() {
};
- @Override
+ @Override
public Mono callTool(McpSchema.CallToolRequest callToolRequest) {
return this.initializer.withInitialization("calling tool", init -> {
if (init.initializeResult().capabilities().tools() == null) {
@@ -544,7 +544,7 @@ private McpSchema.CallToolResult validateToolResult(String toolName, McpSchema.C
return result;
}
- @Override
+ @Override
public Mono listTools() {
return this.listTools(McpSchema.FIRST_PAGE).expand(result -> {
String next = result.nextCursor();
@@ -555,7 +555,7 @@ public Mono listTools() {
}).map(result -> new McpSchema.ListToolsResult(Collections.unmodifiableList(result.tools()), null));
}
- @Override
+ @Override
public Mono listTools(String cursor) {
return this.initializer.withInitialization("listing tools", init -> this.listToolsInternal(init, cursor));
}
@@ -605,7 +605,7 @@ private NotificationHandler asyncToolsChangeNotificationHandler(
private static final TypeRef LIST_RESOURCE_TEMPLATES_RESULT_TYPE_REF = new TypeRef<>() {
};
- @Override
+ @Override
public Mono listResources() {
return this.listResources(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listResources(result.nextCursor()) : Mono.empty())
@@ -616,7 +616,7 @@ public Mono listResources() {
.map(result -> new McpSchema.ListResourcesResult(Collections.unmodifiableList(result.resources()), null));
}
- @Override
+ @Override
public Mono listResources(String cursor) {
return this.initializer.withInitialization("listing resources", init -> {
if (init.initializeResult().capabilities().resources() == null) {
@@ -628,12 +628,12 @@ public Mono listResources(String cursor) {
});
}
- @Override
+ @Override
public Mono readResource(McpSchema.Resource resource) {
return this.readResource(new McpSchema.ReadResourceRequest(resource.uri()));
}
- @Override
+ @Override
public Mono readResource(McpSchema.ReadResourceRequest readResourceRequest) {
return this.initializer.withInitialization("reading resources", init -> {
if (init.initializeResult().capabilities().resources() == null) {
@@ -644,7 +644,7 @@ public Mono readResource(McpSchema.ReadResourceReq
});
}
- @Override
+ @Override
public Mono listResourceTemplates() {
return this.listResourceTemplates(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listResourceTemplates(result.nextCursor())
@@ -658,7 +658,7 @@ public Mono listResourceTemplates() {
Collections.unmodifiableList(result.resourceTemplates()), null));
}
- @Override
+ @Override
public Mono listResourceTemplates(String cursor) {
return this.initializer.withInitialization("listing resource templates", init -> {
if (init.initializeResult().capabilities().resources() == null) {
@@ -670,13 +670,13 @@ public Mono listResourceTemplates(String
});
}
- @Override
+ @Override
public Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest) {
return this.initializer.withInitialization("subscribing to resources", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_RESOURCES_SUBSCRIBE, subscribeRequest, VOID_TYPE_REFERENCE));
}
- @Override
+ @Override
public Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest) {
return this.initializer.withInitialization("unsubscribing from resources", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_RESOURCES_UNSUBSCRIBE, unsubscribeRequest, VOID_TYPE_REFERENCE));
@@ -720,7 +720,7 @@ private NotificationHandler asyncResourcesUpdatedNotificationHandler(
private static final TypeRef GET_PROMPT_RESULT_TYPE_REF = new TypeRef<>() {
};
- @Override
+ @Override
public Mono listPrompts() {
return this.listPrompts(McpSchema.FIRST_PAGE)
.expand(result -> (result.nextCursor() != null) ? this.listPrompts(result.nextCursor()) : Mono.empty())
@@ -731,13 +731,13 @@ public Mono listPrompts() {
.map(result -> new McpSchema.ListPromptsResult(Collections.unmodifiableList(result.prompts()), null));
}
- @Override
+ @Override
public Mono listPrompts(String cursor) {
return this.initializer.withInitialization("listing prompts", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_PROMPT_LIST, new PaginatedRequest(cursor), LIST_PROMPTS_RESULT_TYPE_REF));
}
- @Override
+ @Override
public Mono getPrompt(GetPromptRequest getPromptRequest) {
return this.initializer.withInitialization("getting prompts", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_PROMPT_GET, getPromptRequest, GET_PROMPT_RESULT_TYPE_REF));
@@ -770,7 +770,7 @@ private NotificationHandler asyncLoggingNotificationHandler(
};
}
- @Override
+ @Override
public Mono setLoggingLevel(LoggingLevel loggingLevel) {
if (loggingLevel == null) {
return Mono.error(new IllegalArgumentException("Logging level must not be null"));
@@ -813,7 +813,7 @@ void setProtocolVersions(List protocolVersions) {
private static final TypeRef COMPLETION_COMPLETE_RESULT_TYPE_REF = new TypeRef<>() {
};
- @Override
+ @Override
public Mono completeCompletion(McpSchema.CompleteRequest completeRequest) {
return this.initializer.withInitialization("complete completions", init -> init.mcpSession()
.sendRequest(McpSchema.METHOD_COMPLETION_COMPLETE, completeRequest, COMPLETION_COMPLETE_RESULT_TYPE_REF));
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
index 73ee92877..2d8e01803 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/DefaultMcpSyncClient.java
@@ -55,7 +55,7 @@
* @see McpAsyncClient
* @see McpSchema
*/
-public class DefaultMcpSyncClient implements AutoCloseable {
+public class DefaultMcpSyncClient implements McpSyncClient {
private static final Logger logger = LoggerFactory.getLogger(DefaultMcpSyncClient.class);
@@ -75,66 +75,44 @@ public class DefaultMcpSyncClient implements AutoCloseable {
* @param contextProvider the supplier of context before calling any non-blocking
* operation on underlying delegate
*/
- DefaultMcpSyncClient(McpAsyncClient delegate, Supplier contextProvider) {
+ DefaultMcpSyncClient(McpAsyncClient delegate, Supplier contextProvider) {
Assert.notNull(delegate, "The delegate can not be null");
Assert.notNull(contextProvider, "The contextProvider can not be null");
this.delegate = delegate;
this.contextProvider = contextProvider;
}
- /**
- * Get the current initialization result.
- * @return the initialization result.
- */
+ @Override
public McpSchema.InitializeResult getCurrentInitializationResult() {
return this.delegate.getCurrentInitializationResult();
}
- /**
- * Get the server capabilities that define the supported features and functionality.
- * @return The server capabilities
- */
+ @Override
public McpSchema.ServerCapabilities getServerCapabilities() {
return this.delegate.getServerCapabilities();
}
- /**
- * Get the server instructions that provide guidance to the client on how to interact
- * with this server.
- * @return The instructions
- */
+ @Override
public String getServerInstructions() {
return this.delegate.getServerInstructions();
}
- /**
- * Get the server implementation information.
- * @return The server implementation details
- */
+ @Override
public McpSchema.Implementation getServerInfo() {
return this.delegate.getServerInfo();
}
- /**
- * Check if the client-server connection is initialized.
- * @return true if the client-server connection is initialized
- */
+ @Override
public boolean isInitialized() {
return this.delegate.isInitialized();
}
- /**
- * Get the client capabilities that define the supported features and functionality.
- * @return The client capabilities
- */
+ @Override
public ClientCapabilities getClientCapabilities() {
return this.delegate.getClientCapabilities();
}
- /**
- * Get the client implementation information.
- * @return The client implementation details
- */
+ @Override
public McpSchema.Implementation getClientInfo() {
return this.delegate.getClientInfo();
}
@@ -144,6 +122,7 @@ public void close() {
this.delegate.close();
}
+ @Override
public boolean closeGracefully() {
try {
this.delegate.closeGracefully().block(Duration.ofMillis(DEFAULT_CLOSE_TIMEOUT_MS));
@@ -155,65 +134,29 @@ public boolean closeGracefully() {
return true;
}
- /**
- * The initialization phase MUST be the first interaction between client and server.
- * During this phase, the client and server:
- *
- * Establish protocol version compatibility
- * Exchange and negotiate capabilities
- * Share implementation details
- *
- *
- * The client MUST initiate this phase by sending an initialize request containing:
- *
- * The protocol version the client supports
- * The client's capabilities
- * Client implementation information
- *
- *
- * The server MUST respond with its own capabilities and information:
- * {@link McpSchema.ServerCapabilities}.
- * After successful initialization, the client MUST send an initialized notification
- * to indicate it is ready to begin normal operations.
- *
- *
- *
- * Initialization
- * Spec
- * @return the initialize result.
- */
+ @Override
public McpSchema.InitializeResult initialize() {
// TODO: block takes no argument here as we assume the async client is
// configured with a requestTimeout at all times
return withProvidedContext(this.delegate.initialize()).block();
}
- /**
- * Send a roots/list_changed notification.
- */
+ @Override
public void rootsListChangedNotification() {
withProvidedContext(this.delegate.rootsListChangedNotification()).block();
}
- /**
- * Add a roots dynamically.
- */
+ @Override
public void addRoot(McpSchema.Root root) {
this.delegate.addRoot(root).block();
}
- /**
- * Remove a root dynamically.
- */
+ @Override
public void removeRoot(String rootUri) {
this.delegate.removeRoot(rootUri).block();
}
- /**
- * Send a synchronous ping request.
- * @return
- */
+ @Override
public Object ping() {
return withProvidedContext(this.delegate.ping()).block();
}
@@ -221,39 +164,18 @@ public Object ping() {
// --------------------------
// Tools
// --------------------------
- /**
- * Calls a tool provided by the server. Tools enable servers to expose executable
- * functionality that can interact with external systems, perform computations, and
- * take actions in the real world.
- * @param callToolRequest The request containing: - name: The name of the tool to call
- * (must match a tool name from tools/list) - arguments: Arguments that conform to the
- * tool's input schema
- * @return The tool execution result containing: - content: List of content items
- * (text, images, or embedded resources) representing the tool's output - isError:
- * Boolean indicating if the execution failed (true) or succeeded (false/absent)
- */
+ @Override
public McpSchema.CallToolResult callTool(McpSchema.CallToolRequest callToolRequest) {
return withProvidedContext(this.delegate.callTool(callToolRequest)).block();
}
- /**
- * Retrieves the list of all tools provided by the server.
- * @return The list of all tools result containing: - tools: List of available tools,
- * each with a name, description, and input schema - nextCursor: Optional cursor for
- * pagination if more tools are available
- */
+ @Override
public McpSchema.ListToolsResult listTools() {
return withProvidedContext(this.delegate.listTools()).block();
}
- /**
- * Retrieves a paginated list of tools provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return The list of tools result containing: - tools: List of available tools, each
- * with a name, description, and input schema - nextCursor: Optional cursor for
- * pagination if more tools are available
- */
+ @Override
public McpSchema.ListToolsResult listTools(String cursor) {
return withProvidedContext(this.delegate.listTools(cursor)).block();
@@ -263,86 +185,49 @@ public McpSchema.ListToolsResult listTools(String cursor) {
// Resources
// --------------------------
- /**
- * Retrieves the list of all resources provided by the server.
- * @return The list of all resources result
- */
+ @Override
public McpSchema.ListResourcesResult listResources() {
return withProvidedContext(this.delegate.listResources()).block();
}
- /**
- * Retrieves a paginated list of resources provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return The list of resources result
- */
+ @Override
public McpSchema.ListResourcesResult listResources(String cursor) {
return withProvidedContext(this.delegate.listResources(cursor)).block();
}
- /**
- * Send a resources/read request.
- * @param resource the resource to read
- * @return the resource content.
- */
+ @Override
public McpSchema.ReadResourceResult readResource(McpSchema.Resource resource) {
return withProvidedContext(this.delegate.readResource(resource)).block();
}
- /**
- * Send a resources/read request.
- * @param readResourceRequest the read resource request.
- * @return the resource content.
- */
+ @Override
public McpSchema.ReadResourceResult readResource(McpSchema.ReadResourceRequest readResourceRequest) {
return withProvidedContext(this.delegate.readResource(readResourceRequest)).block();
}
- /**
- * Retrieves the list of all resource templates provided by the server.
- * @return The list of all resource templates result.
- */
+ @Override
public McpSchema.ListResourceTemplatesResult listResourceTemplates() {
return withProvidedContext(this.delegate.listResourceTemplates()).block();
}
- /**
- * Resource templates allow servers to expose parameterized resources using URI
- * templates. Arguments may be auto-completed through the completion API.
- *
- * Retrieves a paginated list of resource templates provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return The list of resource templates result.
- */
+ @Override
public McpSchema.ListResourceTemplatesResult listResourceTemplates(String cursor) {
return withProvidedContext(this.delegate.listResourceTemplates(cursor)).block();
}
- /**
- * Subscriptions. The protocol supports optional subscriptions to resource changes.
- * Clients can subscribe to specific resources and receive notifications when they
- * change.
- *
- * Send a resources/subscribe request.
- * @param subscribeRequest the subscribe request contains the uri of the resource to
- * subscribe to.
- */
+ @Override
public void subscribeResource(McpSchema.SubscribeRequest subscribeRequest) {
withProvidedContext(this.delegate.subscribeResource(subscribeRequest)).block();
}
- /**
- * Send a resources/unsubscribe request.
- * @param unsubscribeRequest the unsubscribe request contains the uri of the resource
- * to unsubscribe from.
- */
+ @Override
public void unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest) {
withProvidedContext(this.delegate.unsubscribeResource(unsubscribeRequest)).block();
@@ -352,43 +237,29 @@ public void unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest)
// Prompts
// --------------------------
- /**
- * Retrieves the list of all prompts provided by the server.
- * @return The list of all prompts result.
- */
+ @Override
public ListPromptsResult listPrompts() {
return withProvidedContext(this.delegate.listPrompts()).block();
}
- /**
- * Retrieves a paginated list of prompts provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return The list of prompts result.
- */
+ @Override
public ListPromptsResult listPrompts(String cursor) {
return withProvidedContext(this.delegate.listPrompts(cursor)).block();
}
+ @Override
public GetPromptResult getPrompt(GetPromptRequest getPromptRequest) {
return withProvidedContext(this.delegate.getPrompt(getPromptRequest)).block();
}
- /**
- * Client can set the minimum logging level it wants to receive from the server.
- * @param loggingLevel the min logging level
- */
+ @Override
public void setLoggingLevel(McpSchema.LoggingLevel loggingLevel) {
withProvidedContext(this.delegate.setLoggingLevel(loggingLevel)).block();
}
- /**
- * Send a completion/complete request.
- * @param completeRequest the completion request contains the prompt or resource
- * reference and arguments for generating suggestions.
- * @return the completion result containing suggested values.
- */
+ @Override
public McpSchema.CompleteResult completeCompletion(McpSchema.CompleteRequest completeRequest) {
return withProvidedContext(this.delegate.completeCompletion(completeRequest)).block();
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
index 50a14f31e..3ef591aa7 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java
@@ -6,7 +6,7 @@
import reactor.core.publisher.Mono;
/**
- * The Model Context Protocol (MCP) client implementation that provides asynchronous
+ * The Model Context Protocol (MCP) client interface that provides asynchronous
* communication with MCP servers using Project Reactor's Mono and Flux types.
*
*
@@ -31,318 +31,319 @@
*
*
*
- * This implementation uses Project Reactor for non-blocking operations, making it
- * suitable for high-throughput scenarios and reactive applications. All operations return
- * Mono or Flux types that can be composed into reactive pipelines.
+ * This interface uses Project Reactor for non-blocking operations, making it suitable for
+ * high-throughput scenarios and reactive applications. All operations return Mono or Flux
+ * types that can be composed into reactive pipelines.
*
* @author Dariusz Jędrzejczyk
* @author Christian Tzolov
* @author Jihoon Kim
* @author Anurag Pant
+ * @author Pin He
* @see McpClient
* @see McpSchema
* @see McpClientSession
* @see McpClientTransport
*/
public interface McpAsyncClient {
- /**
- * Get the current initialization result.
- * @return the initialization result.
- */
- McpSchema.InitializeResult getCurrentInitializationResult();
-
- /**
- * Get the server capabilities that define the supported features and functionality.
- * @return The server capabilities
- */
- McpSchema.ServerCapabilities getServerCapabilities();
-
- /**
- * Get the server instructions that provide guidance to the client on how to interact
- * with this server.
- * @return The server instructions
- */
- String getServerInstructions();
-
- /**
- * Get the server implementation information.
- * @return The server implementation details
- */
- McpSchema.Implementation getServerInfo();
-
- /**
- * Check if the client-server connection is initialized.
- * @return true if the client-server connection is initialized
- */
- boolean isInitialized();
-
- /**
- * Get the client capabilities that define the supported features and functionality.
- * @return The client capabilities
- */
- McpSchema.ClientCapabilities getClientCapabilities();
-
- /**
- * Get the client implementation information.
- * @return The client implementation details
- */
- McpSchema.Implementation getClientInfo();
-
- /**
- * Closes the client connection immediately.
- */
- void close();
-
- /**
- * Gracefully closes the client connection.
- * @return A Mono that completes when the connection is closed
- */
- Mono closeGracefully();
-
- // --------------------------
- // Initialization
- // --------------------------
-
- /**
- * The initialization phase should be the first interaction between client and server.
- * The client will ensure it happens in case it has not been explicitly called and in
- * case of transport session invalidation.
- *
- * During this phase, the client and server:
- *
- * Establish protocol version compatibility
- * Exchange and negotiate capabilities
- * Share implementation details
- *
- *
- * The client MUST initiate this phase by sending an initialize request containing:
- * The protocol version the client supports, client's capabilities and clients
- * implementation information.
- *
- * The server MUST respond with its own capabilities and information.
- *
- * After successful initialization, the client MUST send an initialized notification
- * to indicate it is ready to begin normal operations.
- * @return the initialize result.
- * @see MCP
- * Initialization Spec
- *
- */
- Mono initialize();
-
- // --------------------------
- // Basic Utilities
- // --------------------------
-
- /**
- * Sends a ping request to the server.
- * @return A Mono that completes with the server's ping response
- */
- Mono ping();
-
-
- // --------------------------
- // 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.
- */
- Mono addRoot(McpSchema.Root root);
-
- /**
- * 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.
- */
- Mono removeRoot(String rootUri);
-
- /**
- * Manually sends a roots/list_changed notification. The addRoot and removeRoot
- * methods automatically send the roots/list_changed notification if the client is in
- * an initialized state.
- * @return A Mono that completes when the notification is sent.
- */
- Mono rootsListChangedNotification();
-
- // --------------------------
- // Tools
- // --------------------------
-
- /**
- * Calls a tool provided by the server. Tools enable servers to expose executable
- * functionality that can interact with external systems, perform computations, and
- * take actions in the real world.
- * @param callToolRequest The request containing the tool name and input parameters.
- * @return A Mono that emits the result of the tool call, including the output and any
- * errors.
- * @see McpSchema.CallToolRequest
- * @see McpSchema.CallToolResult
- * @see #listTools()
- */
- Mono callTool(McpSchema.CallToolRequest callToolRequest);
-
- /**
- * Retrieves the list of all tools provided by the server.
- * @return A Mono that emits the list of all tools result
- */
- Mono listTools();
-
- /**
- * Retrieves a paginated list of tools provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return A Mono that emits the list of tools result
- */
- Mono listTools(String cursor);
-
- // --------------------------
- // Resources
- // --------------------------
-
- /**
- * Retrieves the list of all resources provided by the server. Resources represent any
- * kind of UTF-8 encoded data that an MCP server makes available to clients, such as
- * database records, API responses, log files, and more.
- * @return A Mono that completes with the list of all resources result
- * @see McpSchema.ListResourcesResult
- * @see #readResource(McpSchema.Resource)
- */
- Mono listResources();
-
- /**
- * Retrieves a paginated list of resources provided by the server. Resources represent
- * any kind of UTF-8 encoded data that an MCP server makes available to clients, such
- * as database records, API responses, log files, and more.
- * @param cursor Optional pagination cursor from a previous list request.
- * @return A Mono that completes with the list of resources result.
- * @see McpSchema.ListResourcesResult
- * @see #readResource(McpSchema.Resource)
- */
- Mono listResources(String cursor);
-
- /**
- * Reads the content of a specific resource identified by the provided Resource
- * object. This method fetches the actual data that the resource represents.
- * @param resource The resource to read, containing the URI that identifies the
- * resource.
- * @return A Mono that completes with the resource content.
- * @see McpSchema.Resource
- * @see McpSchema.ReadResourceResult
- */
- Mono readResource(McpSchema.Resource resource);
-
- /**
- * Reads the content of a specific resource identified by the provided request. This
- * method fetches the actual data that the resource represents.
- * @param readResourceRequest The request containing the URI of the resource to read
- * @return A Mono that completes with the resource content.
- * @see McpSchema.ReadResourceRequest
- * @see McpSchema.ReadResourceResult
- */
- Mono readResource(McpSchema.ReadResourceRequest readResourceRequest);
-
- /**
- * Retrieves the list of all resource templates provided by the server. Resource
- * templates allow servers to expose parameterized resources using URI templates,
- * enabling dynamic resource access based on variable parameters.
- * @return A Mono that completes with the list of all resource templates result
- * @see McpSchema.ListResourceTemplatesResult
- */
- Mono listResourceTemplates();
-
- /**
- * Retrieves a paginated list of resource templates provided by the server. Resource
- * templates allow servers to expose parameterized resources using URI templates,
- * enabling dynamic resource access based on variable parameters.
- * @param cursor Optional pagination cursor from a previous list request.
- * @return A Mono that completes with the list of resource templates result.
- * @see McpSchema.ListResourceTemplatesResult
- */
- Mono listResourceTemplates(String cursor);
-
- /**
- * Subscribes to changes in a specific resource. When the resource changes on the
- * server, the client will receive notifications through the resources change
- * notification handler.
- * @param subscribeRequest The subscribe request containing the URI of the resource.
- * @return A Mono that completes when the subscription is complete.
- * @see McpSchema.SubscribeRequest
- * @see #unsubscribeResource(McpSchema.UnsubscribeRequest)
- */
- Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest);
-
- /**
- * Cancels an existing subscription to a resource. After unsubscribing, the client
- * will no longer receive notifications when the resource changes.
- * @param unsubscribeRequest The unsubscribe request containing the URI of the
- * resource.
- * @return A Mono that completes when the unsubscription is complete.
- * @see McpSchema.UnsubscribeRequest
- * @see #subscribeResource(McpSchema.SubscribeRequest)
- */
- Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest);
-
- // --------------------------
- // Prompts
- // --------------------------
-
- /**
- * Retrieves the list of all prompts provided by the server.
- * @return A Mono that completes with the list of all prompts result.
- * @see McpSchema.ListPromptsResult
- * @see #getPrompt(McpSchema.GetPromptRequest)
- */
- Mono listPrompts();
-
- /**
- * Retrieves a paginated list of prompts provided by the server.
- * @param cursor Optional pagination cursor from a previous list request
- * @return A Mono that completes with the list of prompts result.
- * @see McpSchema.ListPromptsResult
- * @see #getPrompt(McpSchema.GetPromptRequest)
- */
- Mono listPrompts(String cursor);
-
- /**
- * Retrieves a specific prompt by its ID. This provides the complete prompt template
- * including all parameters and instructions for generating AI content.
- * @param getPromptRequest The request containing the ID of the prompt to retrieve.
- * @return A Mono that completes with the prompt result.
- * @see McpSchema.GetPromptRequest
- * @see McpSchema.GetPromptResult
- * @see #listPrompts()
- */
- Mono getPrompt(McpSchema.GetPromptRequest getPromptRequest);
-
- // --------------------------
- // Logging
- // --------------------------
-
- /**
- * Sets the minimum logging level for messages received from the server. The client
- * will only receive log messages at or above the specified severity level.
- * @param loggingLevel The minimum logging level to receive.
- * @return A Mono that completes when the logging level is set.
- * @see McpSchema.LoggingLevel
- */
- Mono setLoggingLevel(McpSchema.LoggingLevel loggingLevel);
-
- // --------------------------
- // Completions
- // --------------------------
- /**
- * Sends a completion/complete request to generate value suggestions based on a given
- * reference and argument. This is typically used to provide auto-completion options
- * for user input fields.
- * @param completeRequest The request containing the prompt or resource reference and
- * argument for which to generate completions.
- * @return A Mono that completes with the result containing completion suggestions.
- * @see McpSchema.CompleteRequest
- * @see McpSchema.CompleteResult
- */
- Mono completeCompletion(McpSchema.CompleteRequest completeRequest);
+
+ /**
+ * Get the current initialization result.
+ * @return the initialization result.
+ */
+ McpSchema.InitializeResult getCurrentInitializationResult();
+
+ /**
+ * Get the server capabilities that define the supported features and functionality.
+ * @return The server capabilities
+ */
+ McpSchema.ServerCapabilities getServerCapabilities();
+
+ /**
+ * Get the server instructions that provide guidance to the client on how to interact
+ * with this server.
+ * @return The server instructions
+ */
+ String getServerInstructions();
+
+ /**
+ * Get the server implementation information.
+ * @return The server implementation details
+ */
+ McpSchema.Implementation getServerInfo();
+
+ /**
+ * Check if the client-server connection is initialized.
+ * @return true if the client-server connection is initialized
+ */
+ boolean isInitialized();
+
+ /**
+ * Get the client capabilities that define the supported features and functionality.
+ * @return The client capabilities
+ */
+ McpSchema.ClientCapabilities getClientCapabilities();
+
+ /**
+ * Get the client implementation information.
+ * @return The client implementation details
+ */
+ McpSchema.Implementation getClientInfo();
+
+ /**
+ * Closes the client connection immediately.
+ */
+ void close();
+
+ /**
+ * Gracefully closes the client connection.
+ * @return A Mono that completes when the connection is closed
+ */
+ Mono closeGracefully();
+
+ // --------------------------
+ // Initialization
+ // --------------------------
+
+ /**
+ * The initialization phase should be the first interaction between client and server.
+ * The client will ensure it happens in case it has not been explicitly called and in
+ * case of transport session invalidation.
+ *
+ * During this phase, the client and server:
+ *
+ * Establish protocol version compatibility
+ * Exchange and negotiate capabilities
+ * Share implementation details
+ *
+ *
+ * The client MUST initiate this phase by sending an initialize request containing:
+ * The protocol version the client supports, client's capabilities and clients
+ * implementation information.
+ *
+ * The server MUST respond with its own capabilities and information.
+ *
+ * After successful initialization, the client MUST send an initialized notification
+ * to indicate it is ready to begin normal operations.
+ * @return the initialize result.
+ * @see MCP
+ * Initialization Spec
+ *
+ */
+ Mono initialize();
+
+ // --------------------------
+ // Basic Utilities
+ // --------------------------
+
+ /**
+ * Sends a ping request to the server.
+ * @return A Mono that completes with the server's ping response
+ */
+ Mono ping();
+
+ // --------------------------
+ // 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.
+ */
+ Mono addRoot(McpSchema.Root root);
+
+ /**
+ * 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.
+ */
+ Mono removeRoot(String rootUri);
+
+ /**
+ * Manually sends a roots/list_changed notification. The addRoot and removeRoot
+ * methods automatically send the roots/list_changed notification if the client is in
+ * an initialized state.
+ * @return A Mono that completes when the notification is sent.
+ */
+ Mono rootsListChangedNotification();
+
+ // --------------------------
+ // Tools
+ // --------------------------
+
+ /**
+ * Calls a tool provided by the server. Tools enable servers to expose executable
+ * functionality that can interact with external systems, perform computations, and
+ * take actions in the real world.
+ * @param callToolRequest The request containing the tool name and input parameters.
+ * @return A Mono that emits the result of the tool call, including the output and any
+ * errors.
+ * @see McpSchema.CallToolRequest
+ * @see McpSchema.CallToolResult
+ * @see #listTools()
+ */
+ Mono callTool(McpSchema.CallToolRequest callToolRequest);
+
+ /**
+ * Retrieves the list of all tools provided by the server.
+ * @return A Mono that emits the list of all tools result
+ */
+ Mono listTools();
+
+ /**
+ * Retrieves a paginated list of tools provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return A Mono that emits the list of tools result
+ */
+ Mono listTools(String cursor);
+
+ // --------------------------
+ // Resources
+ // --------------------------
+
+ /**
+ * Retrieves the list of all resources provided by the server. Resources represent any
+ * kind of UTF-8 encoded data that an MCP server makes available to clients, such as
+ * database records, API responses, log files, and more.
+ * @return A Mono that completes with the list of all resources result
+ * @see McpSchema.ListResourcesResult
+ * @see #readResource(McpSchema.Resource)
+ */
+ Mono listResources();
+
+ /**
+ * Retrieves a paginated list of resources provided by the server. Resources represent
+ * any kind of UTF-8 encoded data that an MCP server makes available to clients, such
+ * as database records, API responses, log files, and more.
+ * @param cursor Optional pagination cursor from a previous list request.
+ * @return A Mono that completes with the list of resources result.
+ * @see McpSchema.ListResourcesResult
+ * @see #readResource(McpSchema.Resource)
+ */
+ Mono listResources(String cursor);
+
+ /**
+ * Reads the content of a specific resource identified by the provided Resource
+ * object. This method fetches the actual data that the resource represents.
+ * @param resource The resource to read, containing the URI that identifies the
+ * resource.
+ * @return A Mono that completes with the resource content.
+ * @see McpSchema.Resource
+ * @see McpSchema.ReadResourceResult
+ */
+ Mono readResource(McpSchema.Resource resource);
+
+ /**
+ * Reads the content of a specific resource identified by the provided request. This
+ * method fetches the actual data that the resource represents.
+ * @param readResourceRequest The request containing the URI of the resource to read
+ * @return A Mono that completes with the resource content.
+ * @see McpSchema.ReadResourceRequest
+ * @see McpSchema.ReadResourceResult
+ */
+ Mono readResource(McpSchema.ReadResourceRequest readResourceRequest);
+
+ /**
+ * Retrieves the list of all resource templates provided by the server. Resource
+ * templates allow servers to expose parameterized resources using URI templates,
+ * enabling dynamic resource access based on variable parameters.
+ * @return A Mono that completes with the list of all resource templates result
+ * @see McpSchema.ListResourceTemplatesResult
+ */
+ Mono listResourceTemplates();
+
+ /**
+ * Retrieves a paginated list of resource templates provided by the server. Resource
+ * templates allow servers to expose parameterized resources using URI templates,
+ * enabling dynamic resource access based on variable parameters.
+ * @param cursor Optional pagination cursor from a previous list request.
+ * @return A Mono that completes with the list of resource templates result.
+ * @see McpSchema.ListResourceTemplatesResult
+ */
+ Mono listResourceTemplates(String cursor);
+
+ /**
+ * Subscribes to changes in a specific resource. When the resource changes on the
+ * server, the client will receive notifications through the resources change
+ * notification handler.
+ * @param subscribeRequest The subscribe request containing the URI of the resource.
+ * @return A Mono that completes when the subscription is complete.
+ * @see McpSchema.SubscribeRequest
+ * @see #unsubscribeResource(McpSchema.UnsubscribeRequest)
+ */
+ Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest);
+
+ /**
+ * Cancels an existing subscription to a resource. After unsubscribing, the client
+ * will no longer receive notifications when the resource changes.
+ * @param unsubscribeRequest The unsubscribe request containing the URI of the
+ * resource.
+ * @return A Mono that completes when the unsubscription is complete.
+ * @see McpSchema.UnsubscribeRequest
+ * @see #subscribeResource(McpSchema.SubscribeRequest)
+ */
+ Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest);
+
+ // --------------------------
+ // Prompts
+ // --------------------------
+
+ /**
+ * Retrieves the list of all prompts provided by the server.
+ * @return A Mono that completes with the list of all prompts result.
+ * @see McpSchema.ListPromptsResult
+ * @see #getPrompt(McpSchema.GetPromptRequest)
+ */
+ Mono listPrompts();
+
+ /**
+ * Retrieves a paginated list of prompts provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return A Mono that completes with the list of prompts result.
+ * @see McpSchema.ListPromptsResult
+ * @see #getPrompt(McpSchema.GetPromptRequest)
+ */
+ Mono listPrompts(String cursor);
+
+ /**
+ * Retrieves a specific prompt by its ID. This provides the complete prompt template
+ * including all parameters and instructions for generating AI content.
+ * @param getPromptRequest The request containing the ID of the prompt to retrieve.
+ * @return A Mono that completes with the prompt result.
+ * @see McpSchema.GetPromptRequest
+ * @see McpSchema.GetPromptResult
+ * @see #listPrompts()
+ */
+ Mono getPrompt(McpSchema.GetPromptRequest getPromptRequest);
+
+ // --------------------------
+ // Logging
+ // --------------------------
+
+ /**
+ * Sets the minimum logging level for messages received from the server. The client
+ * will only receive log messages at or above the specified severity level.
+ * @param loggingLevel The minimum logging level to receive.
+ * @return A Mono that completes when the logging level is set.
+ * @see McpSchema.LoggingLevel
+ */
+ Mono setLoggingLevel(McpSchema.LoggingLevel loggingLevel);
+
+ // --------------------------
+ // Completions
+ // --------------------------
+ /**
+ * Sends a completion/complete request to generate value suggestions based on a given
+ * reference and argument. This is typically used to provide auto-completion options
+ * for user input fields.
+ * @param completeRequest The request containing the prompt or resource reference and
+ * argument for which to generate completions.
+ * @return A Mono that completes with the result containing completion suggestions.
+ * @see McpSchema.CompleteRequest
+ * @see McpSchema.CompleteResult
+ */
+ Mono completeCompletion(McpSchema.CompleteRequest completeRequest);
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
index 1c176680f..f162bf2b2 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
@@ -474,9 +474,11 @@ public McpSyncClient build() {
McpClientFeatures.Async asyncFeatures = McpClientFeatures.Async.fromSync(syncFeatures);
- return new McpSyncClient(new DefaultMcpAsyncClient(transport, this.requestTimeout, this.initializationTimeout,
- jsonSchemaValidator != null ? jsonSchemaValidator : JsonSchemaValidator.getDefault(),
- asyncFeatures), this.contextProvider);
+ return new DefaultMcpSyncClient(
+ new DefaultMcpAsyncClient(transport, this.requestTimeout, this.initializationTimeout,
+ jsonSchemaValidator != null ? jsonSchemaValidator : JsonSchemaValidator.getDefault(),
+ asyncFeatures),
+ this.contextProvider);
}
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java
new file mode 100644
index 000000000..4a89d28c1
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpSyncClient.java
@@ -0,0 +1,278 @@
+package io.modelcontextprotocol.client;
+
+import io.modelcontextprotocol.spec.McpSchema;
+
+/**
+ * A synchronous client interface for the Model Context Protocol (MCP) that wraps an
+ * {@link McpAsyncClient} to provide blocking operations.
+ *
+ *
+ * This client interface the MCP specification by delegating to an asynchronous client and
+ * blocking on the results. Key features include:
+ *
+ * Synchronous, blocking API for simpler integration in non-reactive applications
+ * Tool discovery and invocation for server-provided functionality
+ * Resource access and management with URI-based addressing
+ * Prompt template handling for standardized AI interactions
+ * Real-time notifications for tools, resources, and prompts changes
+ * Structured logging with configurable severity levels
+ *
+ *
+ *
+ * The client follows the same lifecycle as its async counterpart:
+ *
+ * Initialization - Establishes connection and negotiates capabilities
+ * Normal Operation - Handles requests and notifications
+ * Graceful Shutdown - Ensures clean connection termination
+ *
+ *
+ *
+ * This implementation interface {@link AutoCloseable} for resource cleanup and provides
+ * both immediate and graceful shutdown options. All operations block until completion or
+ * timeout, making it suitable for traditional synchronous programming models.
+ *
+ * @author Dariusz Jędrzejczyk
+ * @author Christian Tzolov
+ * @author Jihoon Kim
+ * @author Pin He
+ * @see McpClient
+ * @see McpAsyncClient
+ * @see McpSchema
+ */
+public interface McpSyncClient extends AutoCloseable {
+
+ /**
+ * Get the current initialization result.
+ * @return the initialization result.
+ */
+ McpSchema.InitializeResult getCurrentInitializationResult();
+
+ /**
+ * Get the server capabilities that define the supported features and functionality.
+ * @return The server capabilities
+ */
+ McpSchema.ServerCapabilities getServerCapabilities();
+
+ /**
+ * Get the server instructions that provide guidance to the client on how to interact
+ * with this server.
+ * @return The instructions
+ */
+ String getServerInstructions();
+
+ /**
+ * Get the server implementation information.
+ * @return The server implementation details
+ */
+ McpSchema.Implementation getServerInfo();
+
+ /**
+ * Check if the client-server connection is initialized.
+ * @return true if the client-server connection is initialized
+ */
+ boolean isInitialized();
+
+ /**
+ * Get the client capabilities that define the supported features and functionality.
+ * @return The client capabilities
+ */
+ McpSchema.ClientCapabilities getClientCapabilities();
+
+ /**
+ * Get the client implementation information.
+ * @return The client implementation details
+ */
+ McpSchema.Implementation getClientInfo();
+
+ @Override
+ void close();
+
+ /**
+ * Gracefully closes the client connection.
+ * @return true if closed gracefully, false otherwise.
+ */
+ boolean closeGracefully();
+
+ /**
+ * The initialization phase MUST be the first interaction between client and server.
+ * During this phase, the client and server:
+ *
+ * Establish protocol version compatibility
+ * Exchange and negotiate capabilities
+ * Share implementation details
+ *
+ *
+ * The client MUST initiate this phase by sending an initialize request containing:
+ *
+ * The protocol version the client supports
+ * The client's capabilities
+ * Client implementation information
+ *
+ *
+ * The server MUST respond with its own capabilities and information:
+ * {@link McpSchema.ServerCapabilities}.
+ * After successful initialization, the client MUST send an initialized notification
+ * to indicate it is ready to begin normal operations.
+ *
+ *
+ *
+ * Initialization
+ * Spec
+ * @return the initialize result.
+ */
+ McpSchema.InitializeResult initialize();
+
+ /**
+ * Send a roots/list_changed notification.
+ */
+ void rootsListChangedNotification();
+
+ /**
+ * Add a roots dynamically.
+ */
+ void addRoot(McpSchema.Root root);
+
+ /**
+ * Remove a root dynamically.
+ */
+ void removeRoot(String rootUri);
+
+ /**
+ * Send a synchronous ping request.
+ * @return
+ */
+ Object ping();
+
+ // --------------------------
+ // Tools
+ // --------------------------
+ /**
+ * Calls a tool provided by the server. Tools enable servers to expose executable
+ * functionality that can interact with external systems, perform computations, and
+ * take actions in the real world.
+ * @param callToolRequest The request containing: - name: The name of the tool to call
+ * (must match a tool name from tools/list) - arguments: Arguments that conform to the
+ * tool's input schema
+ * @return The tool execution result containing: - content: List of content items
+ * (text, images, or embedded resources) representing the tool's output - isError:
+ * Boolean indicating if the execution failed (true) or succeeded (false/absent)
+ */
+ McpSchema.CallToolResult callTool(McpSchema.CallToolRequest callToolRequest);
+
+ /**
+ * Retrieves the list of all tools provided by the server.
+ * @return The list of all tools result containing: - tools: List of available tools,
+ * each with a name, description, and input schema - nextCursor: Optional cursor for
+ * pagination if more tools are available
+ */
+ McpSchema.ListToolsResult listTools();
+
+ /**
+ * Retrieves a paginated list of tools provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return The list of tools result containing: - tools: List of available tools, each
+ * with a name, description, and input schema - nextCursor: Optional cursor for
+ * pagination if more tools are available
+ */
+ McpSchema.ListToolsResult listTools(String cursor);
+
+ // --------------------------
+ // Resources
+ // --------------------------
+
+ /**
+ * Retrieves the list of all resources provided by the server.
+ * @return The list of all resources result
+ */
+ McpSchema.ListResourcesResult listResources();
+
+ /**
+ * Retrieves a paginated list of resources provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return The list of resources result
+ */
+ McpSchema.ListResourcesResult listResources(String cursor);
+
+ /**
+ * Send a resources/read request.
+ * @param resource the resource to read
+ * @return the resource content.
+ */
+ McpSchema.ReadResourceResult readResource(McpSchema.Resource resource);
+
+ /**
+ * Send a resources/read request.
+ * @param readResourceRequest the read resource request.
+ * @return the resource content.
+ */
+ McpSchema.ReadResourceResult readResource(McpSchema.ReadResourceRequest readResourceRequest);
+
+ /**
+ * Retrieves the list of all resource templates provided by the server.
+ * @return The list of all resource templates result.
+ */
+ McpSchema.ListResourceTemplatesResult listResourceTemplates();
+
+ /**
+ * Resource templates allow servers to expose parameterized resources using URI
+ * templates. Arguments may be auto-completed through the completion API.
+ *
+ * Retrieves a paginated list of resource templates provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return The list of resource templates result.
+ */
+ McpSchema.ListResourceTemplatesResult listResourceTemplates(String cursor);
+
+ /**
+ * Subscriptions. The protocol supports optional subscriptions to resource changes.
+ * Clients can subscribe to specific resources and receive notifications when they
+ * change.
+ *
+ * Send a resources/subscribe request.
+ * @param subscribeRequest the subscribe request contains the uri of the resource to
+ * subscribe to.
+ */
+ void subscribeResource(McpSchema.SubscribeRequest subscribeRequest);
+
+ /**
+ * Send a resources/unsubscribe request.
+ * @param unsubscribeRequest the unsubscribe request contains the uri of the resource
+ * to unsubscribe from.
+ */
+ void unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest);
+
+ // --------------------------
+ // Prompts
+ // --------------------------
+
+ /**
+ * Retrieves the list of all prompts provided by the server.
+ * @return The list of all prompts result.
+ */
+ McpSchema.ListPromptsResult listPrompts();
+
+ /**
+ * Retrieves a paginated list of prompts provided by the server.
+ * @param cursor Optional pagination cursor from a previous list request
+ * @return The list of prompts result.
+ */
+ McpSchema.ListPromptsResult listPrompts(String cursor);
+
+ McpSchema.GetPromptResult getPrompt(McpSchema.GetPromptRequest getPromptRequest);
+
+ /**
+ * Client can set the minimum logging level it wants to receive from the server.
+ * @param loggingLevel the min logging level
+ */
+ void setLoggingLevel(McpSchema.LoggingLevel loggingLevel);
+
+ /**
+ * Send a completion/complete request.
+ * @param completeRequest the completion request contains the prompt or resource
+ * reference and arguments for generating suggestions.
+ * @return the completion result containing suggested values.
+ */
+ McpSchema.CompleteResult completeCompletion(McpSchema.CompleteRequest completeRequest);
+
+}
diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java b/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java
index c7a829dc5..c5011bb0d 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/client/McpClientProtocolVersionTests.java
@@ -68,7 +68,7 @@ void shouldNegotiateSpecificVersion() {
.requestTimeout(REQUEST_TIMEOUT)
.build();
- ((DefaultMcpAsyncClient)client).setProtocolVersions(List.of(oldVersion, McpSchema.LATEST_PROTOCOL_VERSION));
+ ((DefaultMcpAsyncClient) client).setProtocolVersions(List.of(oldVersion, McpSchema.LATEST_PROTOCOL_VERSION));
try {
Mono initializeResultMono = client.initialize();
@@ -131,7 +131,7 @@ void shouldUseHighestVersionWhenMultipleSupported() {
.requestTimeout(REQUEST_TIMEOUT)
.build();
- ((DefaultMcpAsyncClient)client).setProtocolVersions(List.of(oldVersion, middleVersion, latestVersion));
+ ((DefaultMcpAsyncClient) client).setProtocolVersions(List.of(oldVersion, middleVersion, latestVersion));
try {
Mono initializeResultMono = client.initialize();