This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new 0471919824c Refactor MCP E2E HTTP support contracts (#39007)
0471919824c is described below
commit 0471919824c2e5b0c0b9048065b54080ca847dfe
Author: Liang Zhang <[email protected]>
AuthorDate: Sun Jul 5 19:58:49 2026 +0800
Refactor MCP E2E HTTP support contracts (#39007)
- centralize raw HTTP JSON-RPC request helpers in
MCPHttpTransportTestSupport
- derive official E2E tool names from registered MCP tool descriptors
- cover HTTP request helper and official tool-name contract
---
.../AbstractHttpProgrammaticRuntimeE2ETest.java | 32 ++------
.../AbstractHttpProtocolOnlyE2ETest.java | 33 ++------
.../test/e2e/mcp/support/OfficialMCPToolNames.java | 25 +-----
.../e2e/mcp/support/OfficialMCPToolNamesTest.java | 33 ++++++++
.../client/MCPHttpTransportTestSupport.java | 90 ++++++++++++++++++++++
.../client/MCPHttpTransportTestSupportTest.java | 69 +++++++++++++++++
6 files changed, 209 insertions(+), 73 deletions(-)
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProgrammaticRuntimeE2ETest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProgrammaticRuntimeE2ETest.java
index 5bc0b1caff0..af22a66d697 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProgrammaticRuntimeE2ETest.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProgrammaticRuntimeE2ETest.java
@@ -30,10 +30,8 @@ import org.testcontainers.containers.GenericContainer;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.sql.SQLException;
-import java.util.LinkedHashMap;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -85,7 +83,7 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest extends
AbstractConfigBack
protected final HttpResponse<String> sendInitializeRequest(final
HttpClient httpClient, final Map<String, String> headers,
final
Map<String, Object> initializeRequestParams) throws IOException,
InterruptedException {
- return sendJsonRpcRequest(httpClient, headers, "init-1", "initialize",
initializeRequestParams);
+ return MCPHttpTransportTestSupport.sendJsonRpcRequest(httpClient,
getEndpointUri(), headers, "init-1", "initialize", initializeRequestParams);
}
protected final HttpResponse<String> sendInitializedNotification(final
HttpClient httpClient, final String sessionId) throws IOException,
InterruptedException {
@@ -95,26 +93,22 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest
extends AbstractConfigBack
protected final HttpResponse<String> sendToolCallRequest(final HttpClient
httpClient, final String sessionId,
final String
toolName, final Map<String, Object> arguments) throws IOException,
InterruptedException {
- return sendJsonRpcRequest(httpClient, createSessionHeaders(sessionId),
toolName + "-1", "tools/call", Map.of("name", toolName, "arguments",
arguments));
+ return MCPHttpTransportTestSupport.sendJsonRpcRequest(httpClient,
getEndpointUri(), createSessionHeaders(sessionId), toolName + "-1",
"tools/call",
+ Map.of("name", toolName, "arguments", arguments));
}
protected final HttpResponse<String> sendResourceReadRequest(final
HttpClient httpClient, final String sessionId,
final String
resourceUri) throws IOException, InterruptedException {
- return sendJsonRpcRequest(httpClient, createSessionHeaders(sessionId),
"resource-1", "resources/read", Map.of("uri", resourceUri));
+ return MCPHttpTransportTestSupport.sendJsonRpcRequest(httpClient,
getEndpointUri(), createSessionHeaders(sessionId), "resource-1",
"resources/read", Map.of("uri", resourceUri));
}
protected final HttpResponse<String> sendDeleteRequest(final HttpClient
httpClient, final Map<String, String> headers) throws IOException,
InterruptedException {
- HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder(getEndpointUri()).DELETE();
- applyHeaders(requestBuilder, headers);
- return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ return MCPHttpTransportTestSupport.sendDeleteRequest(httpClient,
getEndpointUri(), headers);
}
protected final HttpResponse<String> sendRawPostRequest(final HttpClient
httpClient, final Map<String, String> headers,
final String
requestBody) throws IOException, InterruptedException {
- HttpRequest.Builder requestBuilder =
MCPHttpTransportTestSupport.createJsonRequestBuilder(getEndpointUri())
- .POST(HttpRequest.BodyPublishers.ofString(requestBody));
- applyHeaders(requestBuilder, headers);
- return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ return MCPHttpTransportTestSupport.sendRawPostRequest(httpClient,
getEndpointUri(), headers, requestBody);
}
protected final Map<String, Object> getStructuredContent(final String
responseBody) {
@@ -166,10 +160,7 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest
extends AbstractConfigBack
}
protected final Map<String, String> createSessionHeaders(final String
sessionId) {
- Map<String, String> result = new LinkedHashMap<>(2, 1F);
- result.put("MCP-Session-Id", sessionId);
- result.put("MCP-Protocol-Version", getProtocolVersion());
- return result;
+ return MCPHttpTransportTestSupport.createSessionHeaders(sessionId,
getProtocolVersion());
}
@Override
@@ -233,15 +224,6 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest
extends AbstractConfigBack
}
}
- private HttpResponse<String> sendJsonRpcRequest(final HttpClient
httpClient, final Map<String, String> headers, final String requestId,
- final String method, final
Map<String, Object> params) throws IOException, InterruptedException {
- return sendRawPostRequest(httpClient, headers,
MCPHttpTransportTestSupport.createJsonRpcRequestBody(requestId, method,
params));
- }
-
- private void applyHeaders(final HttpRequest.Builder requestBuilder, final
Map<String, String> headers) {
- headers.forEach(requestBuilder::setHeader);
- }
-
private static final class ProgrammaticRuntimeFixture implements
AutoCloseable {
private final GenericContainer<?> container;
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProtocolOnlyE2ETest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProtocolOnlyE2ETest.java
index 2dc53a275bd..261e3bd5354 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProtocolOnlyE2ETest.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProtocolOnlyE2ETest.java
@@ -29,10 +29,8 @@ import org.junit.jupiter.api.AfterEach;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
-import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Collections;
-import java.util.LinkedHashMap;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
@@ -82,7 +80,7 @@ abstract class AbstractHttpProtocolOnlyE2ETest {
protected final HttpResponse<String> sendInitializeRequest(final
HttpClient httpClient, final Map<String, String> headers,
final
Map<String, Object> initializeRequestParams) throws IOException,
InterruptedException {
- return sendJsonRpcRequest(httpClient, headers, "init-1", "initialize",
initializeRequestParams);
+ return MCPHttpTransportTestSupport.sendJsonRpcRequest(httpClient,
getEndpointUri(), headers, "init-1", "initialize", initializeRequestParams);
}
protected final HttpResponse<String> sendInitializedNotification(final
HttpClient httpClient, final String sessionId) throws IOException,
InterruptedException {
@@ -91,27 +89,20 @@ abstract class AbstractHttpProtocolOnlyE2ETest {
}
protected final HttpResponse<String> sendCapabilitiesRequest(final
HttpClient httpClient, final Map<String, String> headers) throws IOException,
InterruptedException {
- return sendJsonRpcRequest(httpClient, headers, "resource-1",
"resources/read", Map.of("uri", "shardingsphere://capabilities"));
+ return MCPHttpTransportTestSupport.sendJsonRpcRequest(httpClient,
getEndpointUri(), headers, "resource-1", "resources/read", Map.of("uri",
"shardingsphere://capabilities"));
}
protected final HttpResponse<String> sendDeleteRequest(final HttpClient
httpClient, final Map<String, String> headers) throws IOException,
InterruptedException {
- HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder(getEndpointUri()).DELETE();
- applyHeaders(requestBuilder, headers);
- return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ return MCPHttpTransportTestSupport.sendDeleteRequest(httpClient,
getEndpointUri(), headers);
}
protected final HttpResponse<String> sendRawPostRequest(final HttpClient
httpClient, final Map<String, String> headers,
final String
requestBody) throws IOException, InterruptedException {
- HttpRequest.Builder requestBuilder =
MCPHttpTransportTestSupport.createJsonRequestBuilder(getEndpointUri())
- .POST(HttpRequest.BodyPublishers.ofString(requestBody));
- applyHeaders(requestBuilder, headers);
- return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ return MCPHttpTransportTestSupport.sendRawPostRequest(httpClient,
getEndpointUri(), headers, requestBody);
}
protected final HttpResponse<String> openEventStream(final HttpClient
httpClient, final Map<String, String> headers) throws IOException,
InterruptedException {
- HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder(getEndpointUri()).GET();
- applyHeaders(requestBuilder, headers);
- return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ return MCPHttpTransportTestSupport.openEventStream(httpClient,
getEndpointUri(), headers);
}
protected final Map<String, Object> parseJsonBody(final String
responseBody) {
@@ -134,10 +125,7 @@ abstract class AbstractHttpProtocolOnlyE2ETest {
}
protected final Map<String, String> createSessionHeaders(final String
sessionId) {
- Map<String, String> result = new LinkedHashMap<>(2, 1F);
- result.put("MCP-Session-Id", sessionId);
- result.put("MCP-Protocol-Version", getProtocolVersion());
- return result;
+ return MCPHttpTransportTestSupport.createSessionHeaders(sessionId,
getProtocolVersion());
}
protected HttpTransportConfiguration createHttpTransportConfiguration() {
@@ -148,15 +136,6 @@ abstract class AbstractHttpProtocolOnlyE2ETest {
return ENDPOINT_PATH;
}
- private HttpResponse<String> sendJsonRpcRequest(final HttpClient
httpClient, final Map<String, String> headers, final String requestId,
- final String method, final
Map<String, Object> params) throws IOException, InterruptedException {
- return sendRawPostRequest(httpClient, headers,
MCPHttpTransportTestSupport.createJsonRpcRequestBody(requestId, method,
params));
- }
-
- private void applyHeaders(final HttpRequest.Builder requestBuilder, final
Map<String, String> headers) {
- headers.forEach(requestBuilder::setHeader);
- }
-
private MCPRuntimeContext createRuntimeContext() {
return new MCPRuntimeContext(new
MCPSessionManager(Collections.emptyMap()), new
MCPDatabaseCapabilityProvider(Collections.emptyMap()), "http");
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNames.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNames.java
index d31004a48ab..81b950b73ea 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNames.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNames.java
@@ -17,6 +17,9 @@
package org.apache.shardingsphere.test.e2e.mcp.support;
+import org.apache.shardingsphere.mcp.api.tool.descriptor.MCPToolDescriptor;
+import org.apache.shardingsphere.mcp.core.tool.handler.ToolDefinitionRegistry;
+
import java.util.List;
/**
@@ -24,27 +27,7 @@ import java.util.List;
*/
public final class OfficialMCPToolNames {
- private static final List<String> ALL = List.of(
- "database_gateway_search_metadata",
- "database_gateway_validate_runtime_database",
- "database_gateway_execute_query",
- "database_gateway_execute_update",
- "database_gateway_apply_workflow",
- "database_gateway_validate_workflow",
- "database_gateway_plan_encrypt_rule",
- "database_gateway_plan_mask_rule",
- "database_gateway_plan_broadcast_rule",
- "database_gateway_plan_readwrite_splitting_rule",
- "database_gateway_plan_readwrite_splitting_status",
- "database_gateway_plan_shadow_rule",
- "database_gateway_plan_default_shadow_algorithm",
- "database_gateway_plan_shadow_algorithm_cleanup",
- "database_gateway_plan_sharding_table_rule",
- "database_gateway_plan_sharding_table_reference_rule",
- "database_gateway_plan_sharding_default_strategy",
- "database_gateway_plan_sharding_key_generator",
- "database_gateway_plan_sharding_key_generate_strategy",
- "database_gateway_plan_sharding_rule_component_cleanup");
+ private static final List<String> ALL =
ToolDefinitionRegistry.getSupportedToolDescriptors().stream().map(MCPToolDescriptor::getName).toList();
private OfficialMCPToolNames() {
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNamesTest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNamesTest.java
new file mode 100644
index 00000000000..1800eeb9b1a
--- /dev/null
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/OfficialMCPToolNamesTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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 org.apache.shardingsphere.test.e2e.mcp.support;
+
+import org.apache.shardingsphere.mcp.api.tool.descriptor.MCPToolDescriptor;
+import org.apache.shardingsphere.mcp.core.tool.handler.ToolDefinitionRegistry;
+import org.junit.jupiter.api.Test;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+class OfficialMCPToolNamesTest {
+
+ @Test
+ void assertGetAll() {
+ assertThat(OfficialMCPToolNames.getAll(),
is(ToolDefinitionRegistry.getSupportedToolDescriptors().stream().map(MCPToolDescriptor::getName).toList()));
+ }
+}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupport.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupport.java
index 72f9e276f01..9de3c8c2b43 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupport.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupport.java
@@ -21,8 +21,12 @@ import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionProtocolSupport;
+import java.io.IOException;
import java.net.URI;
+import java.net.http.HttpClient;
import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.LinkedHashMap;
import java.util.Map;
/**
@@ -63,6 +67,88 @@ public final class MCPHttpTransportTestSupport {
.header("MCP-Protocol-Version", protocolVersion);
}
+ /**
+ * Create session headers.
+ *
+ * @param sessionId MCP session identifier
+ * @param protocolVersion MCP protocol version
+ * @return session headers
+ */
+ public static Map<String, String> createSessionHeaders(final String
sessionId, final String protocolVersion) {
+ Map<String, String> result = new LinkedHashMap<>(2, 1F);
+ result.put("MCP-Session-Id", sessionId);
+ result.put("MCP-Protocol-Version", protocolVersion);
+ return result;
+ }
+
+ /**
+ * Send a DELETE request.
+ *
+ * @param httpClient HTTP client
+ * @param endpointUri MCP endpoint URI
+ * @param headers request headers
+ * @return HTTP response
+ * @throws IOException I/O exception
+ * @throws InterruptedException interrupted exception
+ */
+ public static HttpResponse<String> sendDeleteRequest(final HttpClient
httpClient, final URI endpointUri, final Map<String, String> headers) throws
IOException, InterruptedException {
+ HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder(endpointUri).DELETE();
+ applyHeaders(requestBuilder, headers);
+ return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ }
+
+ /**
+ * Send a raw POST request.
+ *
+ * @param httpClient HTTP client
+ * @param endpointUri MCP endpoint URI
+ * @param headers request headers
+ * @param requestBody request body
+ * @return HTTP response
+ * @throws IOException I/O exception
+ * @throws InterruptedException interrupted exception
+ */
+ public static HttpResponse<String> sendRawPostRequest(final HttpClient
httpClient, final URI endpointUri, final Map<String, String> headers,
+ final String
requestBody) throws IOException, InterruptedException {
+ HttpRequest.Builder requestBuilder =
createJsonRequestBuilder(endpointUri).POST(HttpRequest.BodyPublishers.ofString(requestBody));
+ applyHeaders(requestBuilder, headers);
+ return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ }
+
+ /**
+ * Open an event stream.
+ *
+ * @param httpClient HTTP client
+ * @param endpointUri MCP endpoint URI
+ * @param headers request headers
+ * @return HTTP response
+ * @throws IOException I/O exception
+ * @throws InterruptedException interrupted exception
+ */
+ public static HttpResponse<String> openEventStream(final HttpClient
httpClient, final URI endpointUri, final Map<String, String> headers) throws
IOException, InterruptedException {
+ HttpRequest.Builder requestBuilder =
HttpRequest.newBuilder(endpointUri).GET();
+ applyHeaders(requestBuilder, headers);
+ return httpClient.send(requestBuilder.build(),
HttpResponse.BodyHandlers.ofString());
+ }
+
+ /**
+ * Send a JSON-RPC request.
+ *
+ * @param httpClient HTTP client
+ * @param endpointUri MCP endpoint URI
+ * @param headers request headers
+ * @param requestId request id
+ * @param method method name
+ * @param params request parameters
+ * @return HTTP response
+ * @throws IOException I/O exception
+ * @throws InterruptedException interrupted exception
+ */
+ public static HttpResponse<String> sendJsonRpcRequest(final HttpClient
httpClient, final URI endpointUri, final Map<String, String> headers, final
String requestId,
+ final String method,
final Map<String, Object> params) throws IOException, InterruptedException {
+ return sendRawPostRequest(httpClient, endpointUri, headers,
createJsonRpcRequestBody(requestId, method, params));
+ }
+
/**
* Create initialize request parameters.
*
@@ -95,4 +181,8 @@ public final class MCPHttpTransportTestSupport {
public static String createJsonRpcNotificationBody(final String method,
final Map<String, Object> params) {
return
MCPInteractionProtocolSupport.createJsonRpcNotificationBody(method, params);
}
+
+ private static void applyHeaders(final HttpRequest.Builder requestBuilder,
final Map<String, String> headers) {
+ headers.forEach(requestBuilder::setHeader);
+ }
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupportTest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupportTest.java
index 20bcf5f39d9..646b34bba68 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupportTest.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupportTest.java
@@ -20,13 +20,20 @@ package
org.apache.shardingsphere.test.e2e.mcp.support.transport.client;
import
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionPayloads;
import
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionProtocolSupport;
import org.junit.jupiter.api.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.ArgumentMatchers;
+import java.io.IOException;
import java.net.URI;
+import java.net.http.HttpClient;
import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
class MCPHttpTransportTestSupportTest {
@@ -45,6 +52,57 @@ class MCPHttpTransportTestSupportTest {
assertThat(actual.headers().firstValue("MCP-Protocol-Version").orElse(""),
is("protocol"));
}
+ @Test
+ void assertCreateSessionHeaders() {
+ assertThat(MCPHttpTransportTestSupport.createSessionHeaders("session",
"protocol"), is(Map.of("MCP-Session-Id", "session", "MCP-Protocol-Version",
"protocol")));
+ }
+
+ @Test
+ void assertSendDeleteRequest() throws IOException, InterruptedException {
+ ArgumentCaptor<HttpRequest> requestCaptor =
ArgumentCaptor.forClass(HttpRequest.class);
+ HttpResponse<String> expected = mockHttpResponse();
+ HttpClient httpClient = mockHttpClient(expected, requestCaptor);
+ HttpResponse<String> actual =
MCPHttpTransportTestSupport.sendDeleteRequest(httpClient,
URI.create("http://127.0.0.1:8080/mcp"), Map.of("MCP-Session-Id", "session"));
+ assertThat(actual, is(expected));
+ assertThat(requestCaptor.getValue().method(), is("DELETE"));
+
assertThat(requestCaptor.getValue().headers().firstValue("MCP-Session-Id").orElse(""),
is("session"));
+ }
+
+ @Test
+ void assertSendRawPostRequest() throws IOException, InterruptedException {
+ ArgumentCaptor<HttpRequest> requestCaptor =
ArgumentCaptor.forClass(HttpRequest.class);
+ HttpResponse<String> expected = mockHttpResponse();
+ HttpClient httpClient = mockHttpClient(expected, requestCaptor);
+ HttpResponse<String> actual =
MCPHttpTransportTestSupport.sendRawPostRequest(httpClient,
URI.create("http://127.0.0.1:8080/mcp"), Map.of("MCP-Session-Id", "session"),
"{}");
+ assertThat(actual, is(expected));
+ assertThat(requestCaptor.getValue().method(), is("POST"));
+
assertThat(requestCaptor.getValue().headers().firstValue("Content-Type").orElse(""),
is("application/json"));
+
assertThat(requestCaptor.getValue().headers().firstValue("MCP-Session-Id").orElse(""),
is("session"));
+ }
+
+ @Test
+ void assertOpenEventStream() throws IOException, InterruptedException {
+ ArgumentCaptor<HttpRequest> requestCaptor =
ArgumentCaptor.forClass(HttpRequest.class);
+ HttpResponse<String> expected = mockHttpResponse();
+ HttpClient httpClient = mockHttpClient(expected, requestCaptor);
+ HttpResponse<String> actual =
MCPHttpTransportTestSupport.openEventStream(httpClient,
URI.create("http://127.0.0.1:8080/mcp"), Map.of("MCP-Session-Id", "session"));
+ assertThat(actual, is(expected));
+ assertThat(requestCaptor.getValue().method(), is("GET"));
+
assertThat(requestCaptor.getValue().headers().firstValue("MCP-Session-Id").orElse(""),
is("session"));
+ }
+
+ @Test
+ void assertSendJsonRpcRequest() throws IOException, InterruptedException {
+ ArgumentCaptor<HttpRequest> requestCaptor =
ArgumentCaptor.forClass(HttpRequest.class);
+ HttpResponse<String> expected = mockHttpResponse();
+ HttpClient httpClient = mockHttpClient(expected, requestCaptor);
+ HttpResponse<String> actual =
MCPHttpTransportTestSupport.sendJsonRpcRequest(
+ httpClient, URI.create("http://127.0.0.1:8080/mcp"),
Map.of("MCP-Session-Id", "session"), "id", "tools/list", Map.of());
+ assertThat(actual, is(expected));
+ assertThat(requestCaptor.getValue().method(), is("POST"));
+
assertThat(requestCaptor.getValue().headers().firstValue("Accept").orElse(""),
is("application/json, text/event-stream"));
+ }
+
@Test
void assertCreateInitializeRequestParams() {
assertThat(MCPHttpTransportTestSupport.createInitializeRequestParams("client"),
@@ -62,4 +120,15 @@ class MCPHttpTransportTestSupportTest {
assertThat(MCPInteractionPayloads.parseJsonPayload(MCPHttpTransportTestSupport.createJsonRpcNotificationBody("notifications/initialized",
Map.of())),
is(Map.of("jsonrpc", "2.0", "method",
"notifications/initialized", "params", Map.of())));
}
+
+ private HttpClient mockHttpClient(final HttpResponse<String> response,
final ArgumentCaptor<HttpRequest> requestCaptor) throws IOException,
InterruptedException {
+ HttpClient result = mock(HttpClient.class);
+ when(result.send(requestCaptor.capture(),
ArgumentMatchers.<HttpResponse.BodyHandler<String>>any())).thenReturn(response);
+ return result;
+ }
+
+ @SuppressWarnings("unchecked")
+ private HttpResponse<String> mockHttpResponse() {
+ return mock(HttpResponse.class);
+ }
}