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 451e1a05c56 Remove redundant MCP E2E support code (#39285)
451e1a05c56 is described below
commit 451e1a05c56a06bbe038eaf1ee483a2edae0266b
Author: Liang Zhang <[email protected]>
AuthorDate: Fri Jul 31 11:25:53 2026 +0800
Remove redundant MCP E2E support code (#39285)
* Remove redundant MCP E2E support code
Remove obsolete helper APIs and single-owner test abstractions while
preserving Functionality, Conformance, and LLM scenario coverage.
* Remove redundant MCP E2E support code
Remove obsolete helper APIs and single-owner test abstractions while
preserving Functionality, Conformance, and LLM scenario coverage.
---
.../test/e2e/mcp/env/MCPE2ECondition.java | 28 +++-
.../test/e2e/mcp/env/MCPE2ETestConfiguration.java | 51 -------
.../AbstractPostgreSQLRuntimeE2ETest.java | 83 -----------
.../PostgreSQLDatabaseGatewayE2ETest.java | 60 +++++++-
.../llm/conversation/LLMConversationRunner.java | 8 +-
.../llm/conversation/LLMMCPSafetyValidator.java | 10 +-
.../LLMMCPToolCallValidationFailure.java | 31 ----
.../artifact/LLMConversationArtifactWriter.java | 26 +++-
.../artifact/LLME2ERuntimeEvidenceValidator.java | 47 ------
.../e2e/mcp/llm/fixture/LLMRuntimeSupport.java | 3 +-
.../distribution/DockerImageHttpRuntime.java | 4 +-
.../PackagedDistributionHttpRuntime.java | 2 +-
.../PackagedDistributionProcessSupport.java | 8 +-
.../PackagedDistributionTestSupport.java | 25 +---
.../AbstractConfigBackedRuntimeE2ETest.java | 16 +--
.../support/runtime/MySQLRuntimeTestSupport.java | 7 +-
.../runtime/ProxyWorkflowRuntimeTestSupport.java | 3 +-
.../e2e/mcp/support/runtime/ReadinessProbe.java | 28 +---
.../support/transport/MCPInteractionPayloads.java | 15 +-
.../client/AbstractMCPInteractionClient.java | 16 ---
.../AbstractProcessMCPStdioInteractionClient.java | 10 +-
.../transport/client/MCPHttpInteractionClient.java | 33 +++--
.../client/MCPHttpTransportTestSupport.java | 157 ---------------------
.../transport/client/MCPInteractionClient.java | 38 -----
24 files changed, 159 insertions(+), 550 deletions(-)
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ECondition.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ECondition.java
index 2653f7ec1f9..bd39a0a7ff5 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ECondition.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ECondition.java
@@ -19,15 +19,33 @@ package org.apache.shardingsphere.test.e2e.mcp.env;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
+import
org.apache.shardingsphere.test.e2e.env.runtime.EnvironmentPropertiesLoader;
+
+import java.util.Locale;
+import java.util.Properties;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MCPE2ECondition {
- public static boolean isDockerEnabled() {
- return isDockerEnabled(MCPE2ETestConfiguration.getInstance());
- }
+ private static final Properties PROPS =
EnvironmentPropertiesLoader.loadProperties();
- static boolean isDockerEnabled(final MCPE2ETestConfiguration config) {
- return config.isDockerRunType();
+ /**
+ * Check whether Docker run type is enabled.
+ *
+ * @return whether Docker run type is enabled
+ * @throws IllegalStateException when run type is unsupported
+ */
+ public static boolean isDockerEnabled() {
+ boolean result = false;
+ for (String each : EnvironmentPropertiesLoader.getListValue(PROPS,
"e2e.run.type")) {
+ String runType = each.toUpperCase(Locale.ENGLISH);
+ if (!"DOCKER".equals(runType) && !"NATIVE".equals(runType)) {
+ throw new IllegalStateException(String.format("Unsupported MCP
E2E run type `%s`.", each));
+ }
+ if ("DOCKER".equals(runType)) {
+ result = true;
+ }
+ }
+ return result;
}
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ETestConfiguration.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ETestConfiguration.java
deleted file mode 100644
index e5802803473..00000000000
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/env/MCPE2ETestConfiguration.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.env;
-
-import
org.apache.shardingsphere.test.e2e.env.runtime.EnvironmentPropertiesLoader;
-
-import lombok.RequiredArgsConstructor;
-
-import java.util.Locale;
-import java.util.Properties;
-
-@RequiredArgsConstructor
-final class MCPE2ETestConfiguration {
-
- private static final MCPE2ETestConfiguration INSTANCE = new
MCPE2ETestConfiguration(EnvironmentPropertiesLoader.loadProperties());
-
- private final Properties props;
-
- static MCPE2ETestConfiguration getInstance() {
- return INSTANCE;
- }
-
- boolean isDockerRunType() {
- boolean result = false;
- for (String each : EnvironmentPropertiesLoader.getListValue(props,
"e2e.run.type")) {
- String runType = each.toUpperCase(Locale.ENGLISH);
- if (!"DOCKER".equals(runType) && !"NATIVE".equals(runType)) {
- throw new IllegalStateException(String.format("Unsupported MCP
E2E run type `%s`.", each));
- }
- if ("DOCKER".equals(runType)) {
- result = true;
- }
- }
- return result;
- }
-}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractPostgreSQLRuntimeE2ETest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractPostgreSQLRuntimeE2ETest.java
deleted file mode 100644
index bdfa81fbee0..00000000000
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractPostgreSQLRuntimeE2ETest.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.functionality;
-
-import
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
-import
org.apache.shardingsphere.test.e2e.mcp.support.runtime.PostgreSQLRuntimeTestSupport;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.TestInstance;
-import org.junit.jupiter.params.provider.Arguments;
-import org.testcontainers.containers.GenericContainer;
-
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.Map;
-import java.util.stream.Stream;
-
-@TestInstance(TestInstance.Lifecycle.PER_CLASS)
-abstract class AbstractPostgreSQLRuntimeE2ETest extends
AbstractTransportParameterizedE2ETest {
-
- protected static final String LOGICAL_DATABASE_NAME = "postgres_db";
-
- private GenericContainer<?> container;
-
- @AfterAll
- void tearDownContainer() {
- if (null != container) {
- container.stop();
- container = null;
- }
- }
-
- @Override
- protected void prepareRuntimeFixture() throws IOException {
- if (!PostgreSQLRuntimeTestSupport.isDockerAvailable()) {
- throw new IllegalStateException("Docker is required for the
PostgreSQL-backed MCP Functionality E2E test.");
- }
- if (null != container) {
- return;
- }
- GenericContainer<?> result =
PostgreSQLRuntimeTestSupport.createContainer();
- boolean success = false;
- try {
- result.start();
- PostgreSQLRuntimeTestSupport.initializeDatabase(result);
- container = result;
- success = true;
- } catch (final SQLException ex) {
- throw new IOException("Failed to initialize PostgreSQL runtime
fixture.", ex);
- } finally {
- if (!success) {
- result.stop();
- }
- }
- }
-
- @Override
- protected Map<String, RuntimeDatabaseConfiguration> getRuntimeDatabases() {
- return PostgreSQLRuntimeTestSupport.createRuntimeDatabases(container,
LOGICAL_DATABASE_NAME);
- }
-
- protected static Map<String, Object> createExecuteUpdateArguments(final
String schema, final String sql) {
- return Map.of("database", LOGICAL_DATABASE_NAME, "schema", schema,
"sql", sql, "execution_mode", "execute");
- }
-
- protected static Stream<Arguments> httpTransportCase() {
- return FunctionalityTransportCases.httpTransportCase();
- }
-}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/PostgreSQLDatabaseGatewayE2ETest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/PostgreSQLDatabaseGatewayE2ETest.java
index 7c1c2cc5b7b..5e0d9cdd350 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/PostgreSQLDatabaseGatewayE2ETest.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/PostgreSQLDatabaseGatewayE2ETest.java
@@ -17,18 +17,26 @@
package org.apache.shardingsphere.test.e2e.mcp.functionality;
+import
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
+import
org.apache.shardingsphere.test.e2e.mcp.support.runtime.PostgreSQLRuntimeTestSupport;
import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
import
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionPayloads;
import
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPPayloadAssertions;
import
org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPInteractionClient;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.condition.EnabledIf;
import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import org.testcontainers.containers.GenericContainer;
import java.io.IOException;
+import java.sql.SQLException;
import java.sql.Types;
import java.util.List;
import java.util.Map;
+import java.util.stream.Stream;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
@@ -36,7 +44,49 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@EnabledIf("org.apache.shardingsphere.test.e2e.mcp.env.MCPE2ECondition#isDockerEnabled")
-class PostgreSQLDatabaseGatewayE2ETest extends
AbstractPostgreSQLRuntimeE2ETest {
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+class PostgreSQLDatabaseGatewayE2ETest extends
AbstractTransportParameterizedE2ETest {
+
+ private static final String LOGICAL_DATABASE_NAME = "postgres_db";
+
+ private GenericContainer<?> container;
+
+ @AfterAll
+ void tearDownContainer() {
+ if (null != container) {
+ container.stop();
+ container = null;
+ }
+ }
+
+ @Override
+ protected void prepareRuntimeFixture() throws IOException {
+ if (!PostgreSQLRuntimeTestSupport.isDockerAvailable()) {
+ throw new IllegalStateException("Docker is required for the
PostgreSQL-backed MCP Functionality E2E test.");
+ }
+ if (null != container) {
+ return;
+ }
+ GenericContainer<?> result =
PostgreSQLRuntimeTestSupport.createContainer();
+ boolean success = false;
+ try {
+ result.start();
+ PostgreSQLRuntimeTestSupport.initializeDatabase(result);
+ container = result;
+ success = true;
+ } catch (final SQLException ex) {
+ throw new IOException("Failed to initialize PostgreSQL runtime
fixture.", ex);
+ } finally {
+ if (!success) {
+ result.stop();
+ }
+ }
+ }
+
+ @Override
+ protected Map<String, RuntimeDatabaseConfiguration> getRuntimeDatabases() {
+ return PostgreSQLRuntimeTestSupport.createRuntimeDatabases(container,
LOGICAL_DATABASE_NAME);
+ }
@ParameterizedTest(name = "{0}")
@MethodSource("httpTransportCase")
@@ -105,6 +155,14 @@ class PostgreSQLDatabaseGatewayE2ETest extends
AbstractPostgreSQLRuntimeE2ETest
assertTrue(String.valueOf(actual.get("row_objects")).contains("NEW"));
}
+ private static Map<String, Object> createExecuteUpdateArguments(final
String schema, final String sql) {
+ return Map.of("database", LOGICAL_DATABASE_NAME, "schema", schema,
"sql", sql, "execution_mode", "execute");
+ }
+
+ private static Stream<Arguments> httpTransportCase() {
+ return FunctionalityTransportCases.httpTransportCase();
+ }
+
private Map<String, Object> findNested(final Map<String, Object> payload,
final String collectionName, final String fieldName, final String
expectedValue) {
return ((List<?>) payload.get(collectionName)).stream().map(each ->
MCPInteractionPayloads.getRequiredObjectValue(each, collectionName))
.filter(each ->
expectedValue.equals(each.get(fieldName))).findFirst().orElseThrow();
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
index 1d1c1191116..668aead231d 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
@@ -164,13 +164,13 @@ public final class LLMConversationRunner {
return Optional.of(artifacts.createResult(scenario, modelName,
LLME2EAssertionReport.failure("invalid_tool_arguments", "Model returned invalid
tool arguments JSON.")));
}
- Optional<LLMMCPToolCallValidationFailure> validationFailure =
safetyValidator.validate(each.getName(), arguments);
+ Optional<LLMMCPSafetyValidator.ValidationFailure>
validationFailure = safetyValidator.validate(each.getName(), arguments);
if (validationFailure.isPresent()) {
- LLMMCPToolCallValidationFailure failure =
validationFailure.get();
+ LLMMCPSafetyValidator.ValidationFailure failure =
validationFailure.get();
artifacts.addTrace(MCPInteractionTraceRecord.createInvalidAction(
- artifacts.nextSequence(), modelTurn,
getActionKind(each.getName()), each.getName(), arguments,
failure.getFailureType()));
+ artifacts.nextSequence(), modelTurn,
getActionKind(each.getName()), each.getName(), arguments,
failure.failureType()));
return Optional.of(artifacts.createResult(scenario, modelName,
-
LLME2EAssertionReport.failure(failure.getFailureType(), failure.getMessage())));
+ LLME2EAssertionReport.failure(failure.failureType(),
failure.message())));
}
long startTime = System.currentTimeMillis();
Map<String, Object> response;
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPSafetyValidator.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPSafetyValidator.java
index 76d33bb83ce..788ef064d63 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPSafetyValidator.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPSafetyValidator.java
@@ -25,16 +25,16 @@ final class LLMMCPSafetyValidator {
private static final String EXECUTION_MODE_PREVIEW = "preview";
- Optional<LLMMCPToolCallValidationFailure> validate(final String
actionName, final Map<String, Object> arguments) {
+ Optional<ValidationFailure> validate(final String actionName, final
Map<String, Object> arguments) {
if (LLMConversationRunner.READ_RESOURCE_TOOL_NAME.equals(actionName)
&& Objects.toString(arguments.get("uri"), "").trim().isEmpty()) {
- return Optional.of(new
LLMMCPToolCallValidationFailure("invalid_tool_arguments", "Model returned an
empty resource URI."));
+ return Optional.of(new ValidationFailure("invalid_tool_arguments",
"Model returned an empty resource URI."));
}
if ("database_gateway_execute_query".equals(actionName) &&
isExplain(arguments)) {
- return Optional.of(new
LLMMCPToolCallValidationFailure("invalid_tool_arguments",
+ return Optional.of(new ValidationFailure("invalid_tool_arguments",
"Model routed EXPLAIN SQL to
database_gateway_execute_query instead of
database_gateway_execute_explain_query."));
}
if ("database_gateway_execute_update".equals(actionName) &&
!EXECUTION_MODE_PREVIEW.equals(Objects.toString(arguments.get("execution_mode"),
""))) {
- return Optional.of(new
LLMMCPToolCallValidationFailure("unsafe_sql_execution_attempted",
+ return Optional.of(new
ValidationFailure("unsafe_sql_execution_attempted",
"Model attempted to execute side-effecting SQL in an LLM
E2E scenario."));
}
return Optional.empty();
@@ -46,4 +46,6 @@ final class LLMMCPSafetyValidator {
&& (Character.isWhitespace(sql.charAt(7)) || '(' ==
sql.charAt(7));
}
+ record ValidationFailure(String failureType, String message) {
+ }
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPToolCallValidationFailure.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPToolCallValidationFailure.java
deleted file mode 100644
index c8617d9ecfb..00000000000
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPToolCallValidationFailure.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.llm.conversation;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-
-@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
-@Getter(AccessLevel.PACKAGE)
-final class LLMMCPToolCallValidationFailure {
-
- private final String failureType;
-
- private final String message;
-}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLMConversationArtifactWriter.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLMConversationArtifactWriter.java
index 580f9027263..ab5e0dc4817 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLMConversationArtifactWriter.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLMConversationArtifactWriter.java
@@ -25,6 +25,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
/**
@@ -32,7 +33,10 @@ import java.util.Map;
*/
public final class LLMConversationArtifactWriter {
- private final LLME2ERuntimeEvidenceValidator runtimeEvidenceValidator =
new LLME2ERuntimeEvidenceValidator();
+ private static final List<String> REQUIRED_SCORE_EVIDENCE_KEYS = List.of(
+ "runtimeMode", "dockerOwned", "provider", "serverRuntime",
"serverImage", "serverImageId", "baseServerImage", "baseServerImageDigest",
+ "modelRepository", "modelReference", "servedModelId",
+ "modelQuantization", "modelRevision", "modelFileName",
"modelSha256", "modelPackaging", "contextWindowTokens", "baseUrlOwnedByTest");
/**
* Write one conversation result.
@@ -45,7 +49,7 @@ public final class LLMConversationArtifactWriter {
*/
public void write(final Path artifactDirectory, final Result
conversationResult, final Map<String, Object> runtimeEvidence,
final Collection<String> sensitiveValues) throws
IOException {
- runtimeEvidenceValidator.validate(runtimeEvidence);
+ validateRuntimeEvidence(runtimeEvidence);
writeContent(artifactDirectory.resolve("run-context.json"),
JsonUtils.toJsonString(createRunContext(conversationResult, runtimeEvidence)),
sensitiveValues);
writeContent(artifactDirectory.resolve("system-prompt.md"),
conversationResult.systemPrompt(), sensitiveValues);
writeContent(artifactDirectory.resolve("question.txt"),
conversationResult.scenario().question(), sensitiveValues);
@@ -66,6 +70,24 @@ public final class LLMConversationArtifactWriter {
"failureType",
conversationResult.assertionReport().getFailureType());
}
+ private void validateRuntimeEvidence(final Map<String, Object>
runtimeEvidence) {
+ if (!Boolean.TRUE.equals(runtimeEvidence.get("scoreClosing"))) {
+ return;
+ }
+ for (String each : REQUIRED_SCORE_EVIDENCE_KEYS) {
+ if (isMissingEvidenceValue(runtimeEvidence.get(each))) {
+ throw new IllegalStateException(String.format("Missing
score-closing LLM runtime evidence field `%s`.", each));
+ }
+ }
+ if (!Boolean.TRUE.equals(runtimeEvidence.get("dockerOwned")) ||
!Boolean.TRUE.equals(runtimeEvidence.get("baseUrlOwnedByTest"))) {
+ throw new IllegalStateException("Score-closing LLM runtime
evidence must be Docker-owned and test-owned.");
+ }
+ }
+
+ private boolean isMissingEvidenceValue(final Object value) {
+ return null == value || value instanceof String && ((String)
value).isBlank();
+ }
+
private void writeContent(final Path file, final String content, final
Collection<String> sensitiveValues) throws IOException {
Files.createDirectories(file.getParent());
Files.writeString(file, MCPArtifactUtils.redact(content,
sensitiveValues));
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLME2ERuntimeEvidenceValidator.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLME2ERuntimeEvidenceValidator.java
deleted file mode 100644
index ebe73e970f1..00000000000
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/artifact/LLME2ERuntimeEvidenceValidator.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.llm.conversation.artifact;
-
-import java.util.List;
-import java.util.Map;
-
-final class LLME2ERuntimeEvidenceValidator {
-
- private static final List<String> REQUIRED_SCORE_EVIDENCE_KEYS = List.of(
- "runtimeMode", "dockerOwned", "provider", "serverRuntime",
"serverImage", "serverImageId", "baseServerImage", "baseServerImageDigest",
- "modelRepository", "modelReference", "servedModelId",
- "modelQuantization", "modelRevision", "modelFileName",
"modelSha256", "modelPackaging", "contextWindowTokens", "baseUrlOwnedByTest");
-
- void validate(final Map<String, Object> runtimeEvidence) {
- if (!Boolean.TRUE.equals(runtimeEvidence.get("scoreClosing"))) {
- return;
- }
- for (String each : REQUIRED_SCORE_EVIDENCE_KEYS) {
- if (isMissingEvidenceValue(runtimeEvidence.get(each))) {
- throw new IllegalStateException(String.format("Missing
score-closing LLM runtime evidence field `%s`.", each));
- }
- }
- if (!Boolean.TRUE.equals(runtimeEvidence.get("dockerOwned")) ||
!Boolean.TRUE.equals(runtimeEvidence.get("baseUrlOwnedByTest"))) {
- throw new IllegalStateException("Score-closing LLM runtime
evidence must be Docker-owned and test-owned.");
- }
- }
-
- private boolean isMissingEvidenceValue(final Object value) {
- return null == value || value instanceof String && ((String)
value).isBlank();
- }
-}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
index f8f1e43b88a..95a36024cbf 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
@@ -200,13 +200,14 @@ public final class LLMRuntimeSupport {
* Prepared model runtime.
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
- @Getter
public static final class ModelRuntime implements AutoCloseable {
+ @Getter
private final LLME2EConfiguration configuration;
private final GenericContainer<?> container;
+ @Getter
private final Map<String, Object> evidence;
private static ModelRuntime externalDebug(final LLME2EConfiguration
config) {
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/DockerImageHttpRuntime.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/DockerImageHttpRuntime.java
index 198283acfc3..349ba991206 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/DockerImageHttpRuntime.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/DockerImageHttpRuntime.java
@@ -119,7 +119,7 @@ public final class DockerImageHttpRuntime implements
AutoCloseable {
}
}
- static List<String> createDockerCommand(final String imageName, final Path
configFile, final String containerName) {
+ private static List<String> createDockerCommand(final String imageName,
final Path configFile, final String containerName) {
List<String> result = new LinkedList<>(List.of("docker", "run",
"--rm", "--name", containerName,
"--add-host=host.docker.internal:host-gateway", "-p",
"127.0.0.1::18088", "-e", "SHARDINGSPHERE_MCP_TRANSPORT=http"));
if (null != configFile) {
@@ -185,7 +185,7 @@ public final class DockerImageHttpRuntime implements
AutoCloseable {
}
}
- static OptionalInt parsePublishedPort(final String output) {
+ private static OptionalInt parsePublishedPort(final String output) {
for (String each : output.lines().toList()) {
int separatorIndex = each.lastIndexOf(':');
if (separatorIndex < 0 || separatorIndex == each.length() - 1) {
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionHttpRuntime.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionHttpRuntime.java
index 2f1e4c9bc15..861f528594f 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionHttpRuntime.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionHttpRuntime.java
@@ -96,7 +96,7 @@ public final class PackagedDistributionHttpRuntime implements
AutoCloseable {
}
}
- static Optional<URI> findEndpointUri(final Collection<String>
outputMessages) {
+ private static Optional<URI> findEndpointUri(final Collection<String>
outputMessages) {
for (String each : outputMessages) {
int startIndex = each.indexOf(ENDPOINT_MARKER);
if (startIndex < 0) {
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionProcessSupport.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionProcessSupport.java
index 735c01556a1..3842fa84f7e 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionProcessSupport.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionProcessSupport.java
@@ -79,16 +79,12 @@ public final class PackagedDistributionProcessSupport
implements AutoCloseable {
return result;
}
- static List<String> createCommand(final Path distributionHome, final Path
configFile, final String osName) {
+ private static List<String> createCommand(final Path distributionHome,
final Path configFile, final String osName) {
Path startScript = resolveStartScript(distributionHome, osName);
return isWindows(osName) ? List.of("cmd", "/c",
startScript.toString(), configFile.toString()) :
List.of(startScript.toString(), configFile.toString());
}
- static Path resolveStartScript(final Path distributionHome) {
- return resolveStartScript(distributionHome,
System.getProperty("os.name", ""));
- }
-
- static Path resolveStartScript(final Path distributionHome, final String
osName) {
+ private static Path resolveStartScript(final Path distributionHome, final
String osName) {
return distributionHome.resolve(isWindows(osName) ? "bin/start.bat" :
"bin/start.sh");
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionTestSupport.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionTestSupport.java
index 33aec6f703d..51d39234b57 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionTestSupport.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/distribution/PackagedDistributionTestSupport.java
@@ -58,18 +58,6 @@ public final class PackagedDistributionTestSupport {
private static final String DEFAULT_ENDPOINT_PATH = "/mcp";
- /**
- * Prepare one packaged MCP distribution copy for E2E tests.
- *
- * @param tempDir temporary directory
- * @param transport runtime transport
- * @return prepared packaged distribution
- * @throws IOException I/O exception
- */
- public static PreparedPackagedDistribution prepare(final Path tempDir,
final RuntimeTransport transport) throws IOException {
- return prepare(tempDir, transport, Map.of());
- }
-
/**
* Prepare one packaged MCP distribution copy with supplied runtime
databases.
*
@@ -126,14 +114,7 @@ public final class PackagedDistributionTestSupport {
return targetFile;
}
- /**
- * Find the packaged MCP distribution home.
- *
- * @return packaged MCP distribution home
- * @throws IOException I/O exception
- * @throws IllegalStateException configured distribution home does not
exist
- */
- public static Optional<Path> findDistributionHome() throws IOException {
+ private static Optional<Path> findDistributionHome() throws IOException {
Optional<Path> configuredDistributionHome =
resolveConfiguredDistributionHome();
if (configuredDistributionHome.isPresent()) {
return configuredDistributionHome;
@@ -281,9 +262,5 @@ public final class PackagedDistributionTestSupport {
}
public record PreparedPackagedDistribution(Path home, Path configFile,
RuntimeTransport transport) {
-
- public Path getStartScript() {
- return PackagedDistributionProcessSupport.resolveStartScript(home);
- }
}
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/AbstractConfigBackedRuntimeE2ETest.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/AbstractConfigBackedRuntimeE2ETest.java
index 5c985dedce1..2163fdbdbed 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/AbstractConfigBackedRuntimeE2ETest.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/AbstractConfigBackedRuntimeE2ETest.java
@@ -17,7 +17,6 @@
package org.apache.shardingsphere.test.e2e.mcp.support.runtime;
-import lombok.Getter;
import org.apache.shardingsphere.infra.util.yaml.YamlEngine;
import org.apache.shardingsphere.mcp.bootstrap.MCPRuntimeLauncher;
import
org.apache.shardingsphere.mcp.bootstrap.config.HttpTransportConfiguration;
@@ -55,7 +54,6 @@ public abstract class AbstractConfigBackedRuntimeE2ETest {
SLF4JBridgeHandler.install();
}
- @Getter
@TempDir
private Path tempDir;
@@ -94,7 +92,7 @@ public abstract class AbstractConfigBackedRuntimeE2ETest {
return createInteractionClient(configFile, httpServer);
}
- protected final MCPInteractionClient createInteractionClient(final
Map<String, RuntimeDatabaseConfiguration> runtimeDatabases) throws IOException {
+ private MCPInteractionClient createInteractionClient(final Map<String,
RuntimeDatabaseConfiguration> runtimeDatabases) throws IOException {
prepareRuntimeFixtureIfNeeded();
Path actualConfigFile =
createConfigurationFile(String.format("mcp-custom-%d.yaml",
customConfigurationSequence++), runtimeDatabases);
if (RuntimeTransport.HTTP == getTransport()) {
@@ -172,7 +170,7 @@ public abstract class AbstractConfigBackedRuntimeE2ETest {
}
private URI getEndpointUri(final StreamableHttpMCPServer httpServer) {
- return URI.create(String.format("http://%s:%d%s", LOOPBACK_BIND_HOST,
httpServer.getLocalPort(), getHttpEndpointPath()));
+ return URI.create(String.format("http://%s:%d%s", LOOPBACK_BIND_HOST,
httpServer.getLocalPort(), ENDPOINT_PATH));
}
private Path createConfigurationFile(final String fileName, final
Map<String, RuntimeDatabaseConfiguration> runtimeDatabases) throws IOException {
@@ -185,14 +183,6 @@ public abstract class AbstractConfigBackedRuntimeE2ETest {
RuntimeTransport transport = getTransport();
MCPTransportType transportType = RuntimeTransport.HTTP == transport ?
MCPTransportType.HTTP : MCPTransportType.STDIO;
return YamlEngine.marshal(new
YamlMCPLaunchConfigurationSwapper().swapToYamlConfiguration(
- new MCPLaunchConfiguration(transportType,
createHttpTransportConfiguration(), runtimeDatabases)));
- }
-
- protected HttpTransportConfiguration createHttpTransportConfiguration() {
- return new HttpTransportConfiguration(LOOPBACK_BIND_HOST, 0,
getHttpEndpointPath());
- }
-
- protected String getHttpEndpointPath() {
- return ENDPOINT_PATH;
+ new MCPLaunchConfiguration(transportType, new
HttpTransportConfiguration(LOOPBACK_BIND_HOST, 0, ENDPOINT_PATH),
runtimeDatabases)));
}
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/MySQLRuntimeTestSupport.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/MySQLRuntimeTestSupport.java
index 2a110f03e4d..bfb2bea9d39 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/MySQLRuntimeTestSupport.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/MySQLRuntimeTestSupport.java
@@ -153,7 +153,7 @@ public final class MySQLRuntimeTestSupport {
String jdbcMetadataSchemaName = detectSchema(container);
String resolvedPhysicalSchemaName =
jdbcMetadataSchemaName.isEmpty() ? DATABASE_NAME : jdbcMetadataSchemaName;
int totalOrders = querySingleInt(container,
String.format(COUNT_ORDERS_SQL, resolvedPhysicalSchemaName));
- LLMMySQLRuntimeFixture result = new
LLMMySQLRuntimeFixture(container, logicalDatabase, totalOrders,
createRuntimeDatabases(container, logicalDatabase));
+ LLMMySQLRuntimeFixture result = new
LLMMySQLRuntimeFixture(container, totalOrders,
createRuntimeDatabases(container, logicalDatabase));
startupGuard.complete();
return result;
}
@@ -362,15 +362,14 @@ public final class MySQLRuntimeTestSupport {
}
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
- @Getter
public static final class LLMMySQLRuntimeFixture implements AutoCloseable {
private final GenericContainer<?> container;
- private final String schemaName;
-
+ @Getter
private final int totalOrders;
+ @Getter
private final Map<String, RuntimeDatabaseConfiguration>
runtimeDatabases;
@Override
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ProxyWorkflowRuntimeTestSupport.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ProxyWorkflowRuntimeTestSupport.java
index a1a4a6ec00a..dd21f393666 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ProxyWorkflowRuntimeTestSupport.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ProxyWorkflowRuntimeTestSupport.java
@@ -122,15 +122,16 @@ public final class ProxyWorkflowRuntimeTestSupport {
* Proxy-backed runtime fixture.
*/
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
- @Getter
public static final class ProxyWorkflowRuntimeFixture implements
AutoCloseable {
private final List<GenericContainer<?>> supportingContainers;
private final ShardingSphereProxyEmbeddedContainer proxyContainer;
+ @Getter
private final Map<String, RuntimeDatabaseConfiguration>
runtimeDatabases;
+ @Getter
private final String logicalDatabaseName = LOGICAL_DATABASE_NAME;
@Override
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ReadinessProbe.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ReadinessProbe.java
index 1ea0cf4cd3d..30594488956 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ReadinessProbe.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/runtime/ReadinessProbe.java
@@ -21,8 +21,6 @@ import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
-import java.util.function.LongSupplier;
-
/**
* Readiness retry probe.
*/
@@ -34,21 +32,11 @@ public final class ReadinessProbe {
private final long maxIntervalMillis;
- private final LongSupplier currentTimeMillis;
-
- private final Sleeper sleeper;
-
public ReadinessProbe(final long timeoutMillis, final long
initialIntervalMillis, final long maxIntervalMillis) {
- this(timeoutMillis, initialIntervalMillis, maxIntervalMillis,
System::currentTimeMillis, Thread::sleep);
- }
-
- ReadinessProbe(final long timeoutMillis, final long initialIntervalMillis,
final long maxIntervalMillis, final LongSupplier currentTimeMillis, final
Sleeper sleeper) {
checkArguments(timeoutMillis, initialIntervalMillis,
maxIntervalMillis);
this.timeoutMillis = timeoutMillis;
this.initialIntervalMillis = initialIntervalMillis;
this.maxIntervalMillis = maxIntervalMillis;
- this.currentTimeMillis = currentTimeMillis;
- this.sleeper = sleeper;
}
private void checkArguments(final long timeoutMillis, final long
initialIntervalMillis, final long maxIntervalMillis) {
@@ -75,12 +63,12 @@ public final class ReadinessProbe {
* @throws InterruptedException interrupted exception
*/
public <T, E extends Exception> T waitUntilReady(final ReadinessCheck<T>
readinessCheck, final FailureFactory<E> failureFactory) throws E,
InterruptedException {
- long startTimeMillis = currentTimeMillis.getAsLong();
+ long startTimeMillis = System.currentTimeMillis();
long deadlineMillis = startTimeMillis + timeoutMillis;
long intervalMillis = initialIntervalMillis;
int attemptCount = 0;
Exception lastFailure = null;
- while (currentTimeMillis.getAsLong() < deadlineMillis) {
+ while (System.currentTimeMillis() < deadlineMillis) {
attemptCount++;
ReadinessResult<T> readinessResult = readinessCheck.check();
if (readinessResult.isReady()) {
@@ -98,12 +86,12 @@ public final class ReadinessProbe {
}
private long sleepBeforeRetry(final long deadlineMillis, final long
intervalMillis) throws InterruptedException {
- long remainingMillis = deadlineMillis - currentTimeMillis.getAsLong();
+ long remainingMillis = deadlineMillis - System.currentTimeMillis();
if (0L >= remainingMillis) {
return intervalMillis;
}
try {
- sleeper.sleep(Math.min(intervalMillis, remainingMillis));
+ Thread.sleep(Math.min(intervalMillis, remainingMillis));
return Math.min(maxIntervalMillis, intervalMillis * 2L);
} catch (final InterruptedException ex) {
Thread.currentThread().interrupt();
@@ -112,7 +100,7 @@ public final class ReadinessProbe {
}
private long getElapsedMillis(final long startTimeMillis) {
- return currentTimeMillis.getAsLong() - startTimeMillis;
+ return System.currentTimeMillis() - startTimeMillis;
}
/**
@@ -151,12 +139,6 @@ public final class ReadinessProbe {
E create(Exception cause, int attemptCount, long elapsedMillis);
}
- @FunctionalInterface
- interface Sleeper {
-
- void sleep(long millis) throws InterruptedException;
- }
-
/**
* Readiness result.
*
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/MCPInteractionPayloads.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/MCPInteractionPayloads.java
index 20d21971c5a..8b00866d207 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/MCPInteractionPayloads.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/MCPInteractionPayloads.java
@@ -190,28 +190,15 @@ public final class MCPInteractionPayloads {
*/
@SuppressWarnings("unchecked")
public static List<Map<String, Object>> getRequiredObjectList(final Object
value, final String fieldPath) {
- if (!(value instanceof List)) {
+ if (!(value instanceof final List<?> values)) {
throw new IllegalStateException(String.format("MCP payload field
`%s` must be a list.", fieldPath));
}
- List<?> values = (List<?>) value;
for (int index = 0; index < values.size(); index++) {
getRequiredObjectValue(values.get(index), fieldPath + "[" + index
+ "]");
}
return (List<Map<String, Object>>) values;
}
- /**
- * Get an optional object-list field.
- *
- * @param payload parent payload
- * @param fieldName field name
- * @return object-list field, or an empty list when absent
- * @throws IllegalStateException when the present field is not a list or
contains a non-object value
- */
- public static List<Map<String, Object>> getOptionalObjectList(final
Map<String, Object> payload, final String fieldName) {
- return payload.containsKey(fieldName) ? getRequiredObjectList(payload,
fieldName) : List.of();
- }
-
private static Map<String, Object> parseJsonText(final String value) {
try {
return OBJECT_MAPPER.readValue(value, new TypeReference<>() {
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractMCPInteractionClient.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractMCPInteractionClient.java
index fbfc391562e..cd5ff2269ca 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractMCPInteractionClient.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractMCPInteractionClient.java
@@ -52,22 +52,6 @@ abstract class AbstractMCPInteractionClient implements
MCPInteractionClient {
return
MCPInteractionPayloads.getFirstResourcePayload(sendInitializedRequest("resources-read-1",
"resources/read", Map.of("uri", resourceUri)));
}
- @Override
- public final Map<String, Object> sendRawRequest(final String requestId,
final String method, final Map<String, Object> params) throws IOException,
InterruptedException {
- return sendInitializedRequest(requestId, method, params);
- }
-
- @Override
- public final void sendRawNotification(final String method, final
Map<String, Object> params) throws IOException, InterruptedException {
- ensureOpened();
- sendNotification(method, params);
- }
-
- @Override
- public final Map<String, Object> listPrompts() throws IOException,
InterruptedException {
- return
getObjectListResultOrError(sendInitializedRequest("prompts-list-1",
"prompts/list", Map.of()), "prompts");
- }
-
@Override
public final Map<String, Object> getPrompt(final String promptName, final
Map<String, Object> arguments) throws IOException, InterruptedException {
return
getObjectListResultOrError(sendInitializedRequest("prompts-get-1",
"prompts/get", Map.of("name", promptName, "arguments", arguments)), "messages");
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractProcessMCPStdioInteractionClient.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractProcessMCPStdioInteractionClient.java
index 0e86085c37d..c1b3bc15968 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractProcessMCPStdioInteractionClient.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/AbstractProcessMCPStdioInteractionClient.java
@@ -64,8 +64,6 @@ abstract class AbstractProcessMCPStdioInteractionClient
extends AbstractMCPInter
private BufferedReader reader;
- private Map<String, Object> initializePayload = Map.of();
-
@Override
public final void open() throws IOException, InterruptedException {
if (null != process) {
@@ -117,13 +115,8 @@ abstract class AbstractProcessMCPStdioInteractionClient
extends AbstractMCPInter
return readResponse(requestId);
}
- @Override
- public final Map<String, Object> getInitializePayload() {
- return initializePayload;
- }
-
private void initializeSession() throws IOException, InterruptedException {
- initializePayload = sendRequest(INITIALIZE_REQUEST_ID, "initialize",
+ Map<String, Object> initializePayload =
sendRequest(INITIALIZE_REQUEST_ID, "initialize",
MCPInteractionProtocolSupport.createInitializeRequestParams(getClientName()));
if (MCPInteractionPayloads.hasJsonRpcError(initializePayload)) {
throw createRuntimeFailureException("Failed to initialize STDIO
MCP session: "
@@ -277,7 +270,6 @@ abstract class AbstractProcessMCPStdioInteractionClient
extends AbstractMCPInter
reader = null;
writer = null;
stdErrorCollector = null;
- initializePayload = Map.of();
MCPArtifactUtils.writeRuntimeLogIfConfigured(getClientName() + "-",
stdErrorMessages);
stdErrorMessages.clear();
}
diff --git
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpInteractionClient.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpInteractionClient.java
index 8ec1cc3a931..e22218aa72f 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpInteractionClient.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpInteractionClient.java
@@ -26,6 +26,7 @@ import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
+import java.time.Duration;
import java.util.Map;
/**
@@ -38,6 +39,12 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
private static final String CLIENT_NAME = "mcp-e2e-http";
+ private static final String CONTENT_TYPE = "application/json";
+
+ private static final String ACCEPT = "application/json, text/event-stream";
+
+ private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(30L);
+
private final URI endpointUri;
private final HttpClient httpClient;
@@ -46,14 +53,12 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
private String actualProtocolVersion;
- private Map<String, Object> initializePayload = Map.of();
-
@Override
public void open() throws IOException, InterruptedException {
if (null != sessionId) {
return;
}
- HttpRequest request =
MCPHttpTransportTestSupport.createJsonRequestBuilder(endpointUri)
+ HttpRequest request = createJsonRequestBuilder()
.POST(HttpRequest.BodyPublishers.ofString(MCPInteractionProtocolSupport.createJsonRpcRequestBody(
INITIALIZE_REQUEST_ID, "initialize",
MCPInteractionProtocolSupport.createInitializeRequestParams(CLIENT_NAME))))
.build();
@@ -61,7 +66,7 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
if (200 != response.statusCode()) {
throw new IllegalStateException("Failed to initialize MCP
session.");
}
- initializePayload =
MCPInteractionPayloads.parseJsonPayload(response.body());
+ Map<String, Object> initializePayload =
MCPInteractionPayloads.parseJsonPayload(response.body());
if (MCPInteractionPayloads.hasJsonRpcError(initializePayload)) {
throw new IllegalStateException("Failed to initialize MCP session:
"
+
MCPInteractionPayloads.getJsonRpcErrorPayload(initializePayload).get("message"));
@@ -73,17 +78,12 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
sendNotification("notifications/initialized", Map.of());
}
- @Override
- public Map<String, Object> getInitializePayload() {
- return initializePayload;
- }
-
@Override
public void close() throws IOException, InterruptedException {
if (null == sessionId) {
return;
}
- HttpRequest request =
MCPHttpTransportTestSupport.createJsonRequestBuilder(endpointUri)
+ HttpRequest request = createJsonRequestBuilder()
.header("MCP-Session-Id", sessionId)
.header("MCP-Protocol-Version", actualProtocolVersion)
.DELETE()
@@ -91,7 +91,6 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
sessionId = null;
actualProtocolVersion = null;
- initializePayload = Map.of();
}
@Override
@@ -121,7 +120,16 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
}
private HttpRequest.Builder createSessionRequestBuilder() {
- return
MCPHttpTransportTestSupport.createSessionRequestBuilder(endpointUri, sessionId,
actualProtocolVersion);
+ return createJsonRequestBuilder()
+ .header("MCP-Session-Id", sessionId)
+ .header("MCP-Protocol-Version", actualProtocolVersion);
+ }
+
+ private HttpRequest.Builder createJsonRequestBuilder() {
+ return HttpRequest.newBuilder(endpointUri)
+ .timeout(REQUEST_TIMEOUT)
+ .header("Content-Type", CONTENT_TYPE)
+ .header("Accept", ACCEPT);
}
private HttpResponse<String> sendPostRequest(final String requestId, final
String method, final Map<String, Object> params) throws IOException,
InterruptedException {
@@ -134,5 +142,4 @@ public final class MCPHttpInteractionClient extends
AbstractMCPInteractionClient
}
return response;
}
-
}
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
deleted file mode 100644
index 0da9c879581..00000000000
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPHttpTransportTestSupport.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.transport.client;
-
-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.time.Duration;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * HTTP transport support for MCP E2E tests.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class MCPHttpTransportTestSupport {
-
- private static final String CONTENT_TYPE = "application/json";
-
- private static final String ACCEPT = "application/json, text/event-stream";
-
- private static final Duration REQUEST_TIMEOUT = Duration.ofSeconds(30L);
-
- /**
- * Create a JSON request builder for the given MCP endpoint.
- *
- * @param endpointUri MCP endpoint URI
- * @return JSON request builder
- */
- public static HttpRequest.Builder createJsonRequestBuilder(final URI
endpointUri) {
- return HttpRequest.newBuilder(endpointUri)
- .timeout(REQUEST_TIMEOUT)
- .header("Content-Type", CONTENT_TYPE)
- .header("Accept", ACCEPT);
- }
-
- /**
- * Create a session-bound JSON request builder for the given MCP endpoint.
- *
- * @param endpointUri MCP endpoint URI
- * @param sessionId MCP session id
- * @param protocolVersion MCP protocol version
- * @return session-bound JSON request builder
- */
- public static HttpRequest.Builder createSessionRequestBuilder(final URI
endpointUri, final String sessionId, final String protocolVersion) {
- return createJsonRequestBuilder(endpointUri)
- .header("MCP-Session-Id", sessionId)
- .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 =
createJsonRequestBuilder(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 =
createJsonRequestBuilder(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,
MCPInteractionProtocolSupport.createJsonRpcRequestBody(requestId, 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/MCPInteractionClient.java
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPInteractionClient.java
index d4d2b6155b2..6b6dcf41dd9 100644
---
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPInteractionClient.java
+++
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/support/transport/client/MCPInteractionClient.java
@@ -45,13 +45,6 @@ public interface MCPInteractionClient extends AutoCloseable {
*/
Map<String, Object> call(String actionName, Map<String, Object> arguments)
throws IOException, InterruptedException;
- /**
- * Get initialize payload.
- *
- * @return raw initialize JSON-RPC payload
- */
- Map<String, Object> getInitializePayload();
-
/**
* List tools.
*
@@ -79,15 +72,6 @@ public interface MCPInteractionClient extends AutoCloseable {
*/
Map<String, Object> listResourceTemplates() throws IOException,
InterruptedException;
- /**
- * List prompts.
- *
- * @return MCP prompts payload
- * @throws IOException IO exception
- * @throws InterruptedException interrupted exception
- */
- Map<String, Object> listPrompts() throws IOException, InterruptedException;
-
/**
* Get prompt.
*
@@ -123,28 +107,6 @@ public interface MCPInteractionClient extends
AutoCloseable {
*/
Map<String, Object> readResource(String resourceUri) throws IOException,
InterruptedException;
- /**
- * Send raw JSON-RPC request.
- *
- * @param requestId request id
- * @param method method name
- * @param params request params
- * @return raw JSON-RPC payload
- * @throws IOException IO exception
- * @throws InterruptedException interrupted exception
- */
- Map<String, Object> sendRawRequest(String requestId, String method,
Map<String, Object> params) throws IOException, InterruptedException;
-
- /**
- * Send raw JSON-RPC notification.
- *
- * @param method method name
- * @param params notification params
- * @throws IOException IO exception
- * @throws InterruptedException interrupted exception
- */
- void sendRawNotification(String method, Map<String, Object> params) throws
IOException, InterruptedException;
-
@Override
void close() throws IOException, InterruptedException;
}