From 1b6d6614704f6feae7c7482d187e56997fa8e9dd Mon Sep 17 00:00:00 2001 From: Christian Tzolov Date: Tue, 10 Dec 2024 11:46:58 +0100 Subject: [PATCH] code cleaning --- mcp/README.md | 2 +- mcp/docs/mcp-class-diagram.puml | 14 +-- .../mcp/client/McpAsyncClient.java | 83 +++++++++++------ .../ai/experimental/mcp/client/McpClient.java | 13 ++- .../mcp/client/McpSyncClient.java | 4 + .../mcp/client/stdio/ServerParameters.java | 3 + .../client/stdio/ServerParametersParser.java | 2 +- .../client/stdio/StdioServerTransport.java | 3 + .../mcp/spec/DefaultMcpTransport.java | 6 +- .../mcp/spec/McpAsyncTransport.java | 39 -------- .../{McpAsyncSession.java => McpSession.java} | 14 ++- .../experimental/mcp/spec/McpTransport.java | 91 +++++++++++++++++++ .../mcp/client/McpAsyncClientTests.java | 2 - .../mcp/client/McpSyncClientTests.java | 11 +-- .../mcp/spec/DefaultMcpTransportTests.java | 4 +- 15 files changed, 191 insertions(+), 100 deletions(-) delete mode 100644 mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncTransport.java rename mcp/src/main/java/spring/ai/experimental/mcp/spec/{McpAsyncSession.java => McpSession.java} (90%) create mode 100644 mcp/src/main/java/spring/ai/experimental/mcp/spec/McpTransport.java diff --git a/mcp/README.md b/mcp/README.md index 2e5669f..88e0cc3 100644 --- a/mcp/README.md +++ b/mcp/README.md @@ -101,7 +101,7 @@ The SDK follows a layered architecture: - **McpClient**: Main interface defining the synchronous operations - **McpAsyncClient**: Async implementation using Project Reactor - **McpSyncClient**: Synchronous wrapper around the async client -- **McpAsyncTransport**: Transport layer interface +- **McpTransport**: Transport layer interface - **DefaultMcpTransport**: Base transport implementation - **StdioServerTransport**: Stdio-based server communication diff --git a/mcp/docs/mcp-class-diagram.puml b/mcp/docs/mcp-class-diagram.puml index 18ce099..5c0d939 100644 --- a/mcp/docs/mcp-class-diagram.puml +++ b/mcp/docs/mcp-class-diagram.puml @@ -8,7 +8,7 @@ skinparam class { } ' Interfaces -interface McpAsyncTransport { +interface McpTransport { +start(): void +close(): void +setInboudMessageHandler(Consumer): void @@ -42,16 +42,16 @@ class DefaultMcpTransport { } class McpAsyncClient { - -transport: McpAsyncTransport + -transport: McpTransport -session: McpAsyncSession - +McpAsyncClient(McpAsyncTransport) + +McpAsyncClient(McpTransport) +initialize(): Mono +close(): void } class McpSyncClient { -asyncClient: McpAsyncClient - +McpSyncClient(McpAsyncTransport) + +McpSyncClient(McpTransport) +initialize(): InitializeResult +close(): void } @@ -79,14 +79,14 @@ class Assert { } ' Relationships -McpAsyncTransport <|.. DefaultMcpTransport +McpTransport <|.. DefaultMcpTransport DefaultMcpTransport <|-- StdioServerTransport McpClient <|.. McpSyncClient McpAsyncSession <|.. McpAsyncClient McpSyncClient o-- McpAsyncClient -McpAsyncClient o-- McpAsyncTransport +McpAsyncClient o-- McpTransport McpAsyncClient o-- McpAsyncSession StdioServerTransport o-- ServerParameters @@ -94,7 +94,7 @@ ServerParameters <.. ServerParametersParser : creates ' Package organization package "spring.ai.mcp.spec" { - ' McpAsyncTransport + ' McpTransport ' McpAsyncSession ' DefaultMcpTransport } diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/client/McpAsyncClient.java b/mcp/src/main/java/spring/ai/experimental/mcp/client/McpAsyncClient.java index 7efba72..eae2b56 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/client/McpAsyncClient.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/client/McpAsyncClient.java @@ -5,23 +5,27 @@ import java.time.Duration; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import reactor.core.publisher.Mono; -import spring.ai.experimental.mcp.spec.McpAsyncSession; -import spring.ai.experimental.mcp.spec.McpAsyncTransport; +import spring.ai.experimental.mcp.spec.McpSession; +import spring.ai.experimental.mcp.spec.McpTransport; import spring.ai.experimental.mcp.spec.McpSchema; -public class McpAsyncClient extends McpAsyncSession { +/** + * @author Dariusz Jędrzejczyk + * @author Christian Tzolov + */ +public class McpAsyncClient extends McpSession { - public McpAsyncClient(McpAsyncTransport transport) { + public McpAsyncClient(McpTransport transport) { this(transport, Duration.ofSeconds(10), new ObjectMapper()); } - public McpAsyncClient(McpAsyncTransport transport, Duration requestTimeout, ObjectMapper objectMapper) { + public McpAsyncClient(McpTransport transport, Duration requestTimeout, ObjectMapper objectMapper) { super(requestTimeout, objectMapper, transport); } - /** - * The initialization phase MUST be the first interaction between client and server. + * The initialization phase MUST be the first interaction between client and + * server. * During this phase, the client and server: *
    *
  • Establish protocol version compatibility
  • @@ -29,7 +33,8 @@ public class McpAsyncClient extends McpAsyncSession { *
  • Share implementation details
  • *
*
- * The client MUST initiate this phase by sending an initialize request containing: + * The client MUST initiate this phase by sending an initialize request + * containing: *
    *
  • The protocol version the client supports
  • *
  • The client's capabilities
  • @@ -38,7 +43,8 @@ public class McpAsyncClient extends McpAsyncSession { * * The server MUST respond with its own capabilities and information: * {@link McpSchema.ServerCapabilities}.
    - * After successful initialization, the client MUST send an initialized notification + * After successful initialization, the client MUST send an initialized + * notification * to indicate it is ready to begin normal operations. * *
    @@ -46,6 +52,7 @@ public class McpAsyncClient extends McpAsyncSession { * Initialization * Spec + * * @return the initialize result. */ public Mono initialize() { @@ -54,8 +61,9 @@ public class McpAsyncClient extends McpAsyncSession { new McpSchema.ClientCapabilities(null, new McpSchema.ClientCapabilities.RootCapabilities(true), null), new McpSchema.Implementation("mcp-java-client", "0.0.1")); // @formatter:on - Mono result = - this.sendRequest("initialize", initializeRequest, new TypeReference() {}); + Mono result = this.sendRequest("initialize", initializeRequest, + new TypeReference() { + }); return result.flatMap(initializeResult -> { if (!McpSchema.LATEST_PROTOCOL_VERSION.equals(initializeResult.protocolVersion())) { @@ -64,7 +72,7 @@ public class McpAsyncClient extends McpAsyncSession { + initializeResult.protocolVersion())); } else { return this.sendNotification("notifications/initialized", null) - .thenReturn(initializeResult); + .thenReturn(initializeResult); } }); } @@ -81,7 +89,8 @@ public class McpAsyncClient extends McpAsyncSession { */ public Mono ping() { return this.sendRequest("ping", null, - new TypeReference() {}); + new TypeReference() { + }); } // -------------------------- @@ -89,21 +98,25 @@ public class McpAsyncClient extends McpAsyncSession { // -------------------------- /** * Send a tools/call request. + * * @param callToolRequest the call tool request. * @return the call tool result. */ public Mono callTool(McpSchema.CallToolRequest callToolRequest) { return this.sendRequest("tools/call", callToolRequest, - new TypeReference() {}); + new TypeReference() { + }); } /** * Send a tools/list request. + * * @return the list of tools result. */ public Mono listTools(String cursor) { return this.sendRequest("tools/list", new McpSchema.PaginatedRequest(cursor), - new TypeReference() {}); + new TypeReference() { + }); } // -------------------------- @@ -112,16 +125,19 @@ public class McpAsyncClient extends McpAsyncSession { /** * Send a resources/list request. + * * @param cursor the cursor * @return the list of resources result. */ public Mono listResources(String cursor) { return this.sendRequest("resources/list", new McpSchema.PaginatedRequest(cursor), - new TypeReference() {}); + new TypeReference() { + }); } /** * Send a resources/read request. + * * @param resource the resource to read * @return the resource content. */ @@ -131,12 +147,14 @@ public class McpAsyncClient extends McpAsyncSession { /** * Send a resources/read request. + * * @param readResourceRequest the read resource request. * @return the resource content. */ public Mono readResource(McpSchema.ReadResourceRequest readResourceRequest) { return this.sendRequest("resources/read", readResourceRequest, - new TypeReference() {}); + new TypeReference() { + }); } /** @@ -144,16 +162,19 @@ public class McpAsyncClient extends McpAsyncSession { * templates. Arguments may be auto-completed through the completion API. * * Request a list of resource templates the server has. + * * @param cursor the cursor * @return the list of resource templates result. */ public Mono listResourceTemplates(String cursor) { return this.sendRequest("resources/templates/list", new McpSchema.PaginatedRequest(cursor), - new TypeReference() {}); + new TypeReference() { + }); } /** - * List Changed Notification. When the list of available resources changes, servers + * List Changed Notification. When the list of available resources changes, + * servers * that declared the listChanged capability SHOULD send a notification: */ public Mono sendResourcesListChanged() { @@ -161,26 +182,34 @@ public class McpAsyncClient extends McpAsyncSession { } /** - * Subscriptions. The protocol supports optional subscriptions to resource changes. - * Clients can subscribe to specific resources and receive notifications when they + * 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. + * + * @param subscribeRequest the subscribe request contains the uri of the + * resource to + * subscribe to. */ public Mono subscribeResource(McpSchema.SubscribeRequest subscribeRequest) { return this.sendRequest("resources/subscribe", subscribeRequest, - new TypeReference() {}); + new TypeReference() { + }); } /** * Send a resources/unsubscribe request. - * @param unsubscribeRequest the unsubscribe request contains the uri of the resource - * to unsubscribe from. + * + * @param unsubscribeRequest the unsubscribe request contains the uri of the + * resource + * to unsubscribe from. */ public Mono unsubscribeResource(McpSchema.UnsubscribeRequest unsubscribeRequest) { return this.sendRequest("resources/unsubscribe", unsubscribeRequest, - new TypeReference() {}); + new TypeReference() { + }); } } diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/client/McpClient.java b/mcp/src/main/java/spring/ai/experimental/mcp/client/McpClient.java index 1e7794e..28ce6ce 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/client/McpClient.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/client/McpClient.java @@ -18,15 +18,14 @@ package spring.ai.experimental.mcp.client; import java.time.Duration; import com.fasterxml.jackson.databind.ObjectMapper; -import spring.ai.experimental.mcp.spec.McpAsyncTransport; +import spring.ai.experimental.mcp.spec.McpTransport; /** * The MCP client is the main entry point for interacting with the Model Context Protocol * (MCP) server. * - * * @author Christian Tzolov - * @since 1.0.0 + * @author Dariusz Jędrzejczyk */ public class McpClient { @@ -40,20 +39,20 @@ public class McpClient { // JSONtoPOJOCodec type // .sync(); - public static McpAsyncClient async(McpAsyncTransport transport) { + public static McpAsyncClient async(McpTransport transport) { return new McpAsyncClient(transport); } - public static McpAsyncClient async(McpAsyncTransport transport, Duration requestTimeout, + public static McpAsyncClient async(McpTransport transport, Duration requestTimeout, ObjectMapper objectMapper) { return new McpAsyncClient(transport, requestTimeout, objectMapper); } - public static McpSyncClient sync(McpAsyncTransport transport) { + public static McpSyncClient sync(McpTransport transport) { return new McpSyncClient(async(transport)); } - public static McpSyncClient sync(McpAsyncTransport transport, Duration requestTimeout, + public static McpSyncClient sync(McpTransport transport, Duration requestTimeout, ObjectMapper objectMapper) { return new McpSyncClient(async(transport, requestTimeout, objectMapper)); } diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/client/McpSyncClient.java b/mcp/src/main/java/spring/ai/experimental/mcp/client/McpSyncClient.java index f23ce41..021a13c 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/client/McpSyncClient.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/client/McpSyncClient.java @@ -5,6 +5,10 @@ import java.time.Duration; import spring.ai.experimental.mcp.client.util.Assert; import spring.ai.experimental.mcp.spec.McpSchema; +/** + * @author Dariusz Jędrzejczyk + * @author Christian Tzolov + */ public class McpSyncClient implements AutoCloseable { // TODO: Consider providing a client config to set this properly diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParameters.java b/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParameters.java index 2e0c6c6..f33ba8d 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParameters.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParameters.java @@ -13,6 +13,9 @@ import spring.ai.experimental.mcp.client.util.Assert; /** * Server parameters for stdio client. + * + * @author Christian Tzolov + * @author Dariusz Jędrzejczyk */ @JsonInclude(JsonInclude.Include.NON_ABSENT) public class ServerParameters { diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParametersParser.java b/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParametersParser.java index 91a33ce..577dd15 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParametersParser.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/ServerParametersParser.java @@ -25,7 +25,7 @@ import spring.ai.experimental.mcp.client.stdio.ServerParametersParser.McpServerC /** * @author Christian Tzolov - * @since 1.0.0 + * @author Dariusz Jędrzejczyk */ public class ServerParametersParser { diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/StdioServerTransport.java b/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/StdioServerTransport.java index f6d302e..ee05901 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/StdioServerTransport.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/client/stdio/StdioServerTransport.java @@ -21,6 +21,9 @@ import spring.ai.experimental.mcp.spec.McpSchema.JSONRPCResponse; /** * Stdio client for communicating with a server process. + * + * @author Christian Tzolov + * @author Dariusz Jędrzejczyk */ public class StdioServerTransport extends DefaultMcpTransport { diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/spec/DefaultMcpTransport.java b/mcp/src/main/java/spring/ai/experimental/mcp/spec/DefaultMcpTransport.java index 70ea297..ac93903 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/spec/DefaultMcpTransport.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/spec/DefaultMcpTransport.java @@ -25,9 +25,9 @@ import spring.ai.experimental.mcp.spec.McpSchema.JSONRPCMessage; /** * @author Christian Tzolov - * @since 1.0.0 + * @author Dariusz Jędrzejczyk */ -public class DefaultMcpTransport implements McpAsyncTransport { +public class DefaultMcpTransport implements McpTransport { protected final ObjectMapper objectMapper; @@ -93,7 +93,7 @@ public class DefaultMcpTransport implements McpAsyncTransport { this.inboundMessageHandler = inboundMessageHandler; } - public void setErrorHandler(Consumer errorHandler) { + public void setInboundErrorHandler(Consumer errorHandler) { this.errorHandler = errorHandler; } diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncTransport.java b/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncTransport.java deleted file mode 100644 index 3adcd16..0000000 --- a/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncTransport.java +++ /dev/null @@ -1,39 +0,0 @@ -/* -* Copyright 2024 - 2024 the original author or authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* https://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package spring.ai.experimental.mcp.spec; - -import java.util.function.Consumer; - -import reactor.core.publisher.Mono; -import spring.ai.experimental.mcp.spec.McpSchema.JSONRPCMessage; - -/** - * @author Christian Tzolov - * @since 1.0.0 - */ - -public interface McpAsyncTransport extends AutoCloseable{ - - void start(); - - void close(); - - void setInboudMessageHandler(Consumer messageReader); - - void setErrorHandler(Consumer errorReader); - - Mono sendMessage(JSONRPCMessage message); -} diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncSession.java b/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpSession.java similarity index 90% rename from mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncSession.java rename to mcp/src/main/java/spring/ai/experimental/mcp/spec/McpSession.java index aed36c4..b0faeab 100644 --- a/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpAsyncSession.java +++ b/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpSession.java @@ -11,7 +11,13 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.MonoSink; import spring.ai.experimental.mcp.client.util.Assert; -public class McpAsyncSession { +/** + * Implementation of the MCP client session. + * + * @author Christian Tzolov + * @author Dariusz Jędrzejczyk + */ +public class McpSession { private final ConcurrentHashMap> pendingResponses = new ConcurrentHashMap<>(); @@ -19,9 +25,9 @@ public class McpAsyncSession { private final ObjectMapper objectMapper; - private final McpAsyncTransport transport; + private final McpTransport transport; - public McpAsyncSession(Duration requestTimeout, ObjectMapper objectMapper, McpAsyncTransport transport) { + public McpSession(Duration requestTimeout, ObjectMapper objectMapper, McpTransport transport) { Assert.notNull(objectMapper, "The ObjectMapper can not be null"); Assert.notNull(requestTimeout, "The requstTimeout can not be null"); @@ -50,7 +56,7 @@ public class McpAsyncSession { } }); - this.transport.setErrorHandler(error -> System.out.println("Error received " + error)); + this.transport.setInboundErrorHandler(error -> System.out.println("Error received " + error)); this.transport.start(); } diff --git a/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpTransport.java b/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpTransport.java new file mode 100644 index 0000000..ea06c3f --- /dev/null +++ b/mcp/src/main/java/spring/ai/experimental/mcp/spec/McpTransport.java @@ -0,0 +1,91 @@ +/* + * Copyright 2024 - 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package spring.ai.experimental.mcp.spec; + +import java.util.function.Consumer; + +import reactor.core.publisher.Mono; +import spring.ai.experimental.mcp.spec.McpSchema.JSONRPCMessage; + +/** + * Defines the asynchronous transport layer for the Model Context Protocol (MCP). + * + *

    The McpTransport interface provides the foundation for implementing custom transport + * mechanisms in the Model Context Protocol. It handles the bidirectional communication between + * the client and server components, supporting asynchronous message exchange using JSON-RPC format.

    + * + *

    Implementations of this interface are responsible for:

    + *
      + *
    • Managing the lifecycle of the transport connection
    • + *
    • Handling incoming messages and errors from the server
    • + *
    • Sending outbound messages to the server
    • + *
    + * + *

    The transport layer is designed to be protocol-agnostic, allowing for various implementations + * such as WebSocket, HTTP, or custom protocols.

    + * + * @author Christian Tzolov + * @author Dariusz Jędrzejczyk + */ +public interface McpTransport extends AutoCloseable { + + /** + * Initializes and starts the transport connection. + * + *

    This method should be called before any message exchange can occur. It sets up + * the necessary resources and establishes the connection to the server.

    + */ + void start(); + + /** + * Closes the transport connection and releases any associated resources. + * + *

    This method ensures proper cleanup of resources when the transport is no longer needed. + * It should handle the graceful shutdown of any active connections.

    + */ + void close(); + + /** + * Sets the handler for processing incoming messages from the server. + * + *

    The provided handler will be called whenever a new message is received from the server. + * Messages are expected to follow the JSON-RPC format as defined in the MCP specification.

    + * + * @param inboundMessageHandler a consumer that processes incoming {@link JSONRPCMessage}s + */ + void setInboudMessageHandler(Consumer inboundMessageHandler); + + /** + * Sets the handler for processing transport-level errors. + * + *

    The provided handler will be called when errors occur during transport operations, + * such as connection failures or protocol violations.

    + * + * @param inboundErrorHandler a consumer that processes error messages + */ + void setInboundErrorHandler(Consumer inboundErrorHandler); + + /** + * Sends a message to the server asynchronously. + * + *

    This method handles the transmission of messages to the server in an asynchronous manner. + * Messages are sent in JSON-RPC format as specified by the MCP protocol.

    + * + * @param message the {@link JSONRPCMessage} to be sent to the server + * @return a {@link Mono} that completes when the message has been sent + */ + Mono sendMessage(JSONRPCMessage message); +} diff --git a/mcp/src/test/java/spring/ai/experimental/mcp/client/McpAsyncClientTests.java b/mcp/src/test/java/spring/ai/experimental/mcp/client/McpAsyncClientTests.java index 87c8842..fe78c2d 100644 --- a/mcp/src/test/java/spring/ai/experimental/mcp/client/McpAsyncClientTests.java +++ b/mcp/src/test/java/spring/ai/experimental/mcp/client/McpAsyncClientTests.java @@ -23,8 +23,6 @@ import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; -import spring.ai.experimental.mcp.client.McpAsyncClient; -import spring.ai.experimental.mcp.client.McpClient; import spring.ai.experimental.mcp.client.stdio.ServerParameters; import spring.ai.experimental.mcp.client.stdio.StdioServerTransport; import spring.ai.experimental.mcp.spec.McpSchema.CallToolRequest; diff --git a/mcp/src/test/java/spring/ai/experimental/mcp/client/McpSyncClientTests.java b/mcp/src/test/java/spring/ai/experimental/mcp/client/McpSyncClientTests.java index 907fb4b..70873ec 100644 --- a/mcp/src/test/java/spring/ai/experimental/mcp/client/McpSyncClientTests.java +++ b/mcp/src/test/java/spring/ai/experimental/mcp/client/McpSyncClientTests.java @@ -16,29 +16,26 @@ package spring.ai.experimental.mcp.client; import java.time.Duration; -import java.util.List; import java.util.Map; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; -import spring.ai.experimental.mcp.client.McpClient; -import spring.ai.experimental.mcp.client.McpSyncClient; import spring.ai.experimental.mcp.client.stdio.ServerParameters; import spring.ai.experimental.mcp.client.stdio.StdioServerTransport; import spring.ai.experimental.mcp.spec.McpSchema.CallToolRequest; import spring.ai.experimental.mcp.spec.McpSchema.CallToolResult; -import spring.ai.experimental.mcp.spec.McpSchema.Content; import spring.ai.experimental.mcp.spec.McpSchema.ListResourcesResult; import spring.ai.experimental.mcp.spec.McpSchema.ListToolsResult; import spring.ai.experimental.mcp.spec.McpSchema.Resource; import spring.ai.experimental.mcp.spec.McpSchema.TextContent; import spring.ai.experimental.mcp.spec.McpSchema.Tool; -import static org.assertj.core.api.Assertions.*; - -import com.fasterxml.jackson.databind.ObjectMapper; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatThrownBy; /** * Unit tests for MCP Client Session functionality. diff --git a/mcp/src/test/java/spring/ai/experimental/mcp/spec/DefaultMcpTransportTests.java b/mcp/src/test/java/spring/ai/experimental/mcp/spec/DefaultMcpTransportTests.java index 6f2b797..182edd7 100644 --- a/mcp/src/test/java/spring/ai/experimental/mcp/spec/DefaultMcpTransportTests.java +++ b/mcp/src/test/java/spring/ai/experimental/mcp/spec/DefaultMcpTransportTests.java @@ -107,7 +107,7 @@ class DefaultMcpTransportTests { @Test void customErrorHandlerShouldReceiveErrors() { AtomicReference receivedError = new AtomicReference<>(); - transport.setErrorHandler(receivedError::set); + transport.setInboundErrorHandler(receivedError::set); transport.start(); String errorMessage = "Test error"; @@ -124,7 +124,7 @@ class DefaultMcpTransportTests { AtomicReference receivedError = new AtomicReference<>(); transport.setInboudMessageHandler(receivedMessage::set); - transport.setErrorHandler(receivedError::set); + transport.setInboundErrorHandler(receivedError::set); transport.start(); JSONRPCRequest message = new JSONRPCRequest(