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 f40fd90435a Harden shared fixture boundaries (#38852)
f40fd90435a is described below

commit f40fd90435ac28ce6eca996ebe7c29cbb3973673
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Jun 16 09:12:22 2026 +0800

    Harden shared fixture boundaries (#38852)
    
    * Expose storage unit metadata resources
    
    Expose Proxy-backed storage unit and single table metadata through MCP 
resources,
    search metadata, completion targets, and recovery guidance.
    
    Add contract and Proxy-backed E2E coverage to verify that MCP clients can 
read
    storage unit information from a logical database.
    
    * Expose storage unit metadata resources
    
    Expose Proxy-backed storage unit and single table metadata through MCP 
resources,
    search metadata, completion targets, and recovery guidance.
    
    Add contract and Proxy-backed E2E coverage to verify that MCP clients can 
read
    storage unit information from a logical database.
    
    * Expose storage unit metadata resources
    
    Expose Proxy-backed storage unit and single table metadata through MCP 
resources,
    search metadata, completion targets, and recovery guidance.
    
    Add contract and Proxy-backed E2E coverage to verify that MCP clients can 
read
    storage unit information from a logical database.
    
    * Expose storage unit metadata resources
    
    Expose Proxy-backed storage unit and single table metadata through MCP 
resources,
    search metadata, completion targets, and recovery guidance.
    
    Add contract and Proxy-backed E2E coverage to verify that MCP clients can 
read
    storage unit information from a logical database.
    
    * Expose storage unit metadata resources
    
    Expose Proxy-backed storage unit and single table metadata through MCP 
resources,
    search metadata, completion targets, and recovery guidance.
    
    Add contract and Proxy-backed E2E coverage to verify that MCP clients can 
read
    storage unit information from a logical database.
    
    * Expose storage unit metadata resources
    
    Expose Proxy-backed storage unit and single table metadata through MCP 
resources,
    search metadata, completion targets, and recovery guidance.
    
    Add contract and Proxy-backed E2E coverage to verify that MCP clients can 
read
    storage unit information from a logical database.
    
    * Harden shared fixture boundaries
    
    - Use transport-specific reusable homes for packaged distribution tests
    - Rename Proxy shared fixture opt-in to make read-only scope explicit
    - Keep shared fixture boundary decisions in test code and verification 
evidence
---
 .../e2e/mcp/llm/suite/smoke/LLMSmokeE2ETest.java   |   8 +-
 .../suite/usability/LLMUsabilitySuiteE2ETest.java  |  22 +++-
 .../AbstractProductionMySQLRuntimeE2ETest.java     | 116 ++++++++++++++++++---
 .../AbstractProductionProxyWorkflowE2ETest.java    |  42 ++++++--
 ...sportParameterizedProductionRuntimeE2ETest.java |   6 ++
 .../HttpProductionProxyEncryptWorkflowE2ETest.java |   1 +
 ...ductionProxyFeatureWorkflowContractE2ETest.java |   1 +
 .../HttpProductionProxyMaskWorkflowE2ETest.java    |   1 +
 .../production/PackagedDistributionE2ETest.java    |  24 +++--
 .../production/ProductionMySQLRuntimeE2ETest.java  |  33 +++---
 .../ProductionMySQLSQLRuntimeE2ETest.java          |  46 ++++----
 .../ProductionRuntimeTransportSmokeE2ETest.java    |  53 ++++++++++
 .../AbstractHttpProgrammaticRuntimeE2ETest.java    |  86 ++++++++++++---
 ...t.java => AbstractHttpProtocolOnlyE2ETest.java} |  99 ++++++------------
 ...tractSharedHttpProgrammaticRuntimeE2ETest.java} |  24 ++---
 .../FeatureWorkflowContractE2ETest.java            |   2 +-
 .../HttpTransportApprovalSafetyE2ETest.java        |   2 +-
 .../HttpTransportBaselineContractE2ETest.java      |   2 +-
 .../HttpTransportCompletionE2ETest.java            |   2 +-
 .../programmatic/HttpTransportContractE2ETest.java |   2 +-
 .../HttpTransportProtocolContractE2ETest.java      |   9 +-
 .../programmatic/HttpTransportRecoveryE2ETest.java |   2 +-
 .../programmatic/HttpTransportSecurityE2ETest.java |   9 +-
 .../HttpTransportSessionLifecycleE2ETest.java      |   9 +-
 .../programmatic/MetadataDiscoveryE2ETest.java     |   8 +-
 .../PackagedDistributionTestSupport.java           |  26 +++++
 26 files changed, 434 insertions(+), 201 deletions(-)

diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/smoke/LLMSmokeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/smoke/LLMSmokeE2ETest.java
index e16872f461e..01cf010c4d3 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/smoke/LLMSmokeE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/smoke/LLMSmokeE2ETest.java
@@ -33,6 +33,7 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Tag;
+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;
@@ -48,6 +49,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @Tag("llm-e2e")
 @EnabledIf("isEnabled")
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
 class LLMSmokeE2ETest extends AbstractConfigBackedRuntimeE2ETest {
     
     private static final String DATABASE_NAME = "logic_db";
@@ -86,12 +88,16 @@ class LLMSmokeE2ETest extends 
AbstractConfigBackedRuntimeE2ETest {
         }
     }
     
-    @AfterEach
+    @AfterAll
     void closeRuntimeFixture() {
         if (null != currentRuntimeFixture) {
             currentRuntimeFixture.close();
             currentRuntimeFixture = null;
         }
+    }
+    
+    @AfterEach
+    void clearCurrentTransport() {
         currentTransport = null;
     }
     
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/usability/LLMUsabilitySuiteE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/usability/LLMUsabilitySuiteE2ETest.java
index f550e2f9018..6639df93a99 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/usability/LLMUsabilitySuiteE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/suite/usability/LLMUsabilitySuiteE2ETest.java
@@ -32,6 +32,7 @@ import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Tag;
+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;
@@ -44,6 +45,7 @@ import java.util.stream.Stream;
 
 @Tag("llm-e2e")
 @EnabledIf("isEnabled")
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
 class LLMUsabilitySuiteE2ETest extends AbstractConfigBackedRuntimeE2ETest {
     
     private static final String RUNTIME_KIND = "mysql";
@@ -54,6 +56,8 @@ class LLMUsabilitySuiteE2ETest extends 
AbstractConfigBackedRuntimeE2ETest {
     
     private static final String COUNT_ORDERS_SQL = "SELECT COUNT(*) AS 
total_orders FROM orders";
     
+    private static final String FULL_TRANSPORT_MATRIX_PROPERTY = 
"mcp.e2e.llm.full-transport-matrix";
+    
     private static LLMRuntimeSupport.ModelRuntime llmRuntime;
     
     private final LLMRuntimeFixtureFactory runtimeFixtureFactory = new 
LLMRuntimeFixtureFactory();
@@ -79,12 +83,16 @@ class LLMUsabilitySuiteE2ETest extends 
AbstractConfigBackedRuntimeE2ETest {
         }
     }
     
-    @AfterEach
+    @AfterAll
     void closeRuntimeFixture() {
         if (null != currentRuntimeFixture) {
             currentRuntimeFixture.close();
             currentRuntimeFixture = null;
         }
+    }
+    
+    @AfterEach
+    void clearCurrentTransport() {
         currentTransport = null;
     }
     
@@ -93,9 +101,15 @@ class LLMUsabilitySuiteE2ETest extends 
AbstractConfigBackedRuntimeE2ETest {
     }
     
     static Stream<Arguments> getTestCases() {
-        return Stream.of(
-                Arguments.of("llm-usability-mysql-http", 
RuntimeTransport.HTTP),
-                Arguments.of("llm-usability-mysql-stdio", 
RuntimeTransport.STDIO));
+        return isFullTransportMatrixEnabled()
+                ? Stream.of(
+                        Arguments.of("llm-usability-mysql-http", 
RuntimeTransport.HTTP),
+                        Arguments.of("llm-usability-mysql-stdio", 
RuntimeTransport.STDIO))
+                : Stream.of(Arguments.of("llm-usability-mysql-http", 
RuntimeTransport.HTTP));
+    }
+    
+    private static boolean isFullTransportMatrixEnabled() {
+        return 
Boolean.parseBoolean(System.getProperty(FULL_TRANSPORT_MATRIX_PROPERTY, 
"false"));
     }
     
     @ParameterizedTest(name = "{0}")
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionMySQLRuntimeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionMySQLRuntimeE2ETest.java
index 24904c31217..325368d8077 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionMySQLRuntimeE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionMySQLRuntimeE2ETest.java
@@ -17,11 +17,6 @@
 
 package org.apache.shardingsphere.test.e2e.mcp.runtime.production;
 
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.hasItems;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.isA;
-
 import io.modelcontextprotocol.client.McpClient;
 import io.modelcontextprotocol.client.McpSyncClient;
 import 
io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
@@ -42,8 +37,10 @@ import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionPa
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPPayloadAssertions;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPInteractionClient;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPStdioLogbackConfiguration;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.TestInstance;
 import org.junit.jupiter.api.condition.EnabledIf;
 import org.junit.jupiter.params.provider.Arguments;
 import org.testcontainers.containers.GenericContainer;
@@ -59,9 +56,14 @@ import java.util.Map;
 import java.util.stream.Stream;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isA;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
 @EnabledIf("isEnabled")
 abstract class AbstractProductionMySQLRuntimeE2ETest extends 
AbstractTransportParameterizedProductionRuntimeE2ETest {
     
@@ -77,6 +79,8 @@ abstract class AbstractProductionMySQLRuntimeE2ETest extends 
AbstractTransportPa
     
     private String physicalSchemaName;
     
+    private MySQLRuntimeFixture sharedRuntimeFixture;
+    
     protected GenericContainer<?> getContainer() {
         return container;
     }
@@ -87,6 +91,11 @@ abstract class AbstractProductionMySQLRuntimeE2ETest extends 
AbstractTransportPa
     
     @AfterEach
     void tearDownContainer() {
+        if (useSharedRuntimeFixture()) {
+            container = null;
+            physicalSchemaName = null;
+            return;
+        }
         if (null != container) {
             container.stop();
             container = null;
@@ -94,21 +103,59 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
         physicalSchemaName = null;
     }
     
+    @AfterAll
+    void tearDownSharedContainer() {
+        if (null != sharedRuntimeFixture) {
+            sharedRuntimeFixture.close();
+            sharedRuntimeFixture = null;
+        }
+    }
+    
     @Override
     protected void prepareRuntimeFixture() throws IOException {
         Assumptions.assumeTrue(MySQLRuntimeTestSupport.isDockerAvailable(),
                 () -> 
MySQLRuntimeTestSupport.createDockerRequiredMessage("Docker is required for the 
MySQL-backed production runtime E2E test."));
-        container = MySQLRuntimeTestSupport.createContainer();
-        container.start();
+        if (useSharedRuntimeFixture()) {
+            prepareSharedRuntimeFixture();
+            return;
+        }
+        applyRuntimeFixture(createRuntimeFixture());
+    }
+    
+    private void prepareSharedRuntimeFixture() throws IOException {
+        if (null == sharedRuntimeFixture) {
+            sharedRuntimeFixture = createRuntimeFixture();
+        }
+        applyRuntimeFixture(sharedRuntimeFixture);
+    }
+    
+    private MySQLRuntimeFixture createRuntimeFixture() throws IOException {
+        GenericContainer<?> result = MySQLRuntimeTestSupport.createContainer();
+        boolean success = false;
         try {
-            MySQLRuntimeTestSupport.initializeDatabase(container);
-            String detectedSchemaName = 
MySQLRuntimeTestSupport.detectSchema(container);
-            physicalSchemaName = detectedSchemaName.isEmpty() ? 
PHYSICAL_DATABASE_NAME : detectedSchemaName;
+            result.start();
+            MySQLRuntimeTestSupport.initializeDatabase(result);
+            String detectedSchemaName = 
MySQLRuntimeTestSupport.detectSchema(result);
+            success = true;
+            return new MySQLRuntimeFixture(result, 
detectedSchemaName.isEmpty() ? PHYSICAL_DATABASE_NAME : detectedSchemaName);
         } catch (final SQLException ex) {
             throw new IOException(ex);
+        } finally {
+            if (!success) {
+                result.stop();
+            }
         }
     }
     
+    private void applyRuntimeFixture(final MySQLRuntimeFixture fixture) {
+        container = fixture.container();
+        physicalSchemaName = fixture.physicalSchemaName();
+    }
+    
+    protected boolean useSharedRuntimeFixture() {
+        return false;
+    }
+    
     @Override
     protected Map<String, RuntimeDatabaseConfiguration> getRuntimeDatabases() {
         return MySQLRuntimeTestSupport.createRuntimeDatabases(container, 
LOGICAL_DATABASE_NAME);
@@ -130,8 +177,16 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
         return runtimeTransports().map(each -> 
Arguments.of(getTransportName(each), each));
     }
     
+    protected static Stream<Arguments> dualTransports() {
+        return transports();
+    }
+    
+    protected static Stream<Arguments> semanticPrimaryTransport() {
+        return semanticPrimaryRuntimeTransports().map(each -> 
Arguments.of(getTransportName(each), each));
+    }
+    
     protected static Stream<Arguments> assertReadSingleMetadataResourceCases() 
{
-        return runtimeTransports().flatMap(each -> Stream.of(
+        return semanticPrimaryRuntimeTransports().flatMap(each -> Stream.of(
                 Arguments.of(getTransportName(each) + " database detail", 
each, "shardingsphere://databases/logic_db", "database", LOGICAL_DATABASE_NAME),
                 Arguments.of(getTransportName(each) + " schema detail", each, 
"shardingsphere://databases/logic_db/schemas/logic_db", "schema", 
LOGICAL_DATABASE_NAME),
                 Arguments.of(getTransportName(each) + " table column detail", 
each,
@@ -144,7 +199,7 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
     }
     
     protected static Stream<Arguments> 
assertReadCollectionMetadataResourceCases() {
-        return runtimeTransports().flatMap(each -> Stream.of(
+        return semanticPrimaryRuntimeTransports().flatMap(each -> Stream.of(
                 Arguments.of(getTransportName(each) + " schemas list", each, 
"shardingsphere://databases/logic_db/schemas", "schema", 
List.of(LOGICAL_DATABASE_NAME)),
                 Arguments.of(getTransportName(each) + " tables list", each,
                         
"shardingsphere://databases/logic_db/schemas/logic_db/tables", "table", 
List.of("order_items", "orders")),
@@ -158,6 +213,10 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
         return Stream.of(RuntimeTransport.HTTP, RuntimeTransport.STDIO);
     }
     
+    private static Stream<RuntimeTransport> semanticPrimaryRuntimeTransports() 
{
+        return Stream.of(RuntimeTransport.HTTP);
+    }
+    
     protected static String getTransportName(final RuntimeTransport transport) 
{
         return RuntimeTransport.HTTP == transport ? "http" : "stdio";
     }
@@ -274,7 +333,7 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
         assertFalse((Boolean) actual.get("would_execute"));
         List<Map<String, Object>> nextActions = 
getMapList(actual.get("next_actions"));
         assertThat(nextActions.stream().map(each -> 
String.valueOf(each.get("type"))).toList(), is(List.of("tool_call")));
-        assertFalse(nextActions.get(0).containsKey("requires_user_approval"));
+        
assertFalse(nextActions.getFirst().containsKey("requires_user_approval"));
     }
     
     protected void assertAiNativeSqlResult(final MCPInteractionClient 
interactionClient) throws IOException, InterruptedException {
@@ -284,7 +343,7 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
         assertThat(String.valueOf(actual.get("row_object_status")), 
is("available"));
         assertThat(((List<?>) actual.get("row_objects")).size(), is(1));
         assertThat(String.valueOf(actual.get("truncated")), is("true"));
-        
assertThat(String.valueOf(getMapList(actual.get("next_actions")).get(0).get("type")),
 is("ask_user"));
+        
assertThat(String.valueOf(getMapList(actual.get("next_actions")).getFirst().get("type")),
 is("ask_user"));
     }
     
     protected McpSyncClient createElicitationClient(final RuntimeTransport 
transport, final List<McpSchema.ElicitRequest> elicitationRequests) throws 
IOException {
@@ -322,13 +381,13 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
         elicitationRequests.add(request);
         List<String> requiredFields = 
getStringList(request.requestedSchema().get("required"));
         return new 
McpSchema.ElicitResult(McpSchema.ElicitResult.Action.ACCEPT, Map.of(
-                requiredFields.get(0), "1",
+                requiredFields.getFirst(), "1",
                 requiredFields.get(1), "3"));
     }
     
     protected void assertElicitationRequest(final 
List<McpSchema.ElicitRequest> actualRequests) {
         assertThat(actualRequests.size(), is(1));
-        McpSchema.ElicitRequest actual = actualRequests.get(0);
+        McpSchema.ElicitRequest actual = actualRequests.getFirst();
         assertThat(actual.meta().get(MCPShardingSphereMetadataKeys.TOOL), 
is(MASK_PLAN_TOOL_NAME));
         
assertFalse(String.valueOf(actual.meta().get(MCPShardingSphereMetadataKeys.PLAN_ID)).isBlank());
         Map<String, Object> actualRequestedSchema = actual.requestedSchema();
@@ -376,4 +435,29 @@ abstract class AbstractProductionMySQLRuntimeE2ETest 
extends AbstractTransportPa
             return List.of(ProtocolVersions.MCP_2025_06_18, 
ProtocolVersions.MCP_2025_11_25);
         }
     }
+    
+    private static final class MySQLRuntimeFixture implements AutoCloseable {
+        
+        private final GenericContainer<?> container;
+        
+        private final String physicalSchemaName;
+        
+        private MySQLRuntimeFixture(final GenericContainer<?> container, final 
String physicalSchemaName) {
+            this.container = container;
+            this.physicalSchemaName = physicalSchemaName;
+        }
+        
+        private GenericContainer<?> container() {
+            return container;
+        }
+        
+        private String physicalSchemaName() {
+            return physicalSchemaName;
+        }
+        
+        @Override
+        public void close() {
+            container.stop();
+        }
+    }
 }
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionProxyWorkflowE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionProxyWorkflowE2ETest.java
index cd369e42afe..93a1d77d458 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionProxyWorkflowE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractProductionProxyWorkflowE2ETest.java
@@ -22,8 +22,10 @@ import 
org.apache.shardingsphere.test.e2e.mcp.support.runtime.MySQLRuntimeTestSu
 import 
org.apache.shardingsphere.test.e2e.mcp.support.runtime.ProxyEncryptWorkflowRuntimeTestSupport;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.runtime.ProxyEncryptWorkflowRuntimeTestSupport.ProxyEncryptWorkflowRuntimeFixture;
 import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assumptions;
+import org.junit.jupiter.api.TestInstance;
 
 import java.io.IOException;
 import java.sql.SQLException;
@@ -33,18 +35,36 @@ import java.util.Map;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
 abstract class AbstractProductionProxyWorkflowE2ETest extends 
AbstractProductionRuntimeE2ETest {
     
     private ProxyEncryptWorkflowRuntimeFixture runtimeFixture;
     
+    private ProxyEncryptWorkflowRuntimeFixture sharedRuntimeFixture;
+    
+    private boolean sharedRuntimeFixtureSelected;
+    
     @AfterEach
     void tearDownFixture() {
+        if (sharedRuntimeFixtureSelected) {
+            runtimeFixture = null;
+            sharedRuntimeFixtureSelected = false;
+            return;
+        }
         if (null != runtimeFixture) {
             runtimeFixture.close();
             runtimeFixture = null;
         }
     }
     
+    @AfterAll
+    void tearDownSharedFixture() {
+        if (null != sharedRuntimeFixture) {
+            sharedRuntimeFixture.close();
+            sharedRuntimeFixture = null;
+        }
+    }
+    
     @Override
     protected final RuntimeTransport getTransport() {
         return RuntimeTransport.HTTP;
@@ -55,12 +75,23 @@ abstract class AbstractProductionProxyWorkflowE2ETest 
extends AbstractProduction
         Assumptions.assumeTrue(MySQLRuntimeTestSupport.isDockerAvailable(),
                 () -> 
MySQLRuntimeTestSupport.createDockerRequiredMessage("Docker is required for the 
Proxy-backed workflow E2E tests."));
         try {
+            if (sharedRuntimeFixtureSelected) {
+                prepareSharedRuntimeFixture();
+                return;
+            }
             runtimeFixture = 
ProxyEncryptWorkflowRuntimeTestSupport.createFixture();
         } catch (final SQLException ex) {
             throw new IOException(ex);
         }
     }
     
+    private void prepareSharedRuntimeFixture() throws SQLException {
+        if (null == sharedRuntimeFixture) {
+            sharedRuntimeFixture = 
ProxyEncryptWorkflowRuntimeTestSupport.createFixture();
+        }
+        runtimeFixture = sharedRuntimeFixture;
+    }
+    
     @Override
     protected final Map<String, RuntimeDatabaseConfiguration> 
getRuntimeDatabases() {
         return runtimeFixture.getRuntimeDatabases();
@@ -70,10 +101,8 @@ abstract class AbstractProductionProxyWorkflowE2ETest 
extends AbstractProduction
         return runtimeFixture.getLogicalDatabaseName();
     }
     
-    protected final int countPhysicalColumn(final String columnName) throws 
SQLException {
-        return 
MySQLRuntimeTestSupport.querySingleInt(runtimeFixture.getStorageContainer(), 
String.format(
-                "SELECT COUNT(*) FROM information_schema.columns WHERE 
table_schema = '%s' AND table_name = 'orders' AND column_name = '%s'",
-                runtimeFixture.getPhysicalDatabaseName(), columnName));
+    protected final void useSharedReadOnlyRuntimeFixture() {
+        sharedRuntimeFixtureSelected = true;
     }
     
     protected final void assertValidationPassed(final Map<String, Object> 
actualValidationResponse) {
@@ -83,11 +112,6 @@ abstract class AbstractProductionProxyWorkflowE2ETest 
extends AbstractProduction
         assertThat(actualValidationResponse.toString(), 
getMapList(actualValidationResponse.get("mismatches")).size(), is(0));
     }
     
-    protected final void assertValidationFailed(final Map<String, Object> 
actualValidationResponse) {
-        assertThat(actualValidationResponse.toString(), 
String.valueOf(actualValidationResponse.get("status")), is("failed"));
-        assertThat(actualValidationResponse.toString(), 
String.valueOf(actualValidationResponse.get("overall_status")), is("failed"));
-    }
-    
     protected final void assertApplyCompleted(final Map<String, Object> 
actualApplyResponse) {
         assertThat(actualApplyResponse.toString(), 
String.valueOf(actualApplyResponse.get("status")), is("completed"));
     }
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
index 7b6b66a1ebf..09c4245c98d 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
@@ -18,6 +18,7 @@
 package org.apache.shardingsphere.test.e2e.mcp.runtime.production;
 
 import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
+import org.junit.jupiter.api.AfterEach;
 
 abstract class AbstractTransportParameterizedProductionRuntimeE2ETest extends 
AbstractProductionRuntimeE2ETest {
     
@@ -27,6 +28,11 @@ abstract class 
AbstractTransportParameterizedProductionRuntimeE2ETest extends Ab
         this.transport = transport;
     }
     
+    @AfterEach
+    void clearTransport() {
+        transport = null;
+    }
+    
     @Override
     protected final RuntimeTransport getTransport() {
         if (null == transport) {
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyEncryptWorkflowE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyEncryptWorkflowE2ETest.java
index d103a343556..76943ad51b0 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyEncryptWorkflowE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyEncryptWorkflowE2ETest.java
@@ -63,6 +63,7 @@ class HttpProductionProxyEncryptWorkflowE2ETest extends 
AbstractProductionProxyW
     
     @Test
     void assertCompleteEncryptAlgorithmThroughProxy() throws IOException, 
InterruptedException {
+        useSharedReadOnlyRuntimeFixture();
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
             Map<String, Object> actual = 
interactionClient.complete(Map.of("type", "ref/prompt", "name", 
PLAN_PROMPT_NAME), "algorithm_type", "AE", Map.of());
             
assertThat(getStringList(getMap(actual.get("completion")).get("values")), 
hasItem("AES"));
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyFeatureWorkflowContractE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyFeatureWorkflowContractE2ETest.java
index 515ea25116c..15f3246bcc6 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyFeatureWorkflowContractE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyFeatureWorkflowContractE2ETest.java
@@ -86,6 +86,7 @@ class HttpProductionProxyFeatureWorkflowContractE2ETest 
extends AbstractProducti
     
     @Test
     void assertReadStorageUnitsThroughProxy() throws IOException, 
InterruptedException {
+        useSharedReadOnlyRuntimeFixture();
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
             List<Map<String, Object>> actualStorageUnits = 
getPayloadItems(interactionClient.readResource(
                     
String.format("shardingsphere://databases/%s/storage-units", 
getLogicalDatabaseName())));
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyMaskWorkflowE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyMaskWorkflowE2ETest.java
index 1ef2ac6ae24..68279ef4a99 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyMaskWorkflowE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/HttpProductionProxyMaskWorkflowE2ETest.java
@@ -57,6 +57,7 @@ class HttpProductionProxyMaskWorkflowE2ETest extends 
AbstractProductionProxyWork
     
     @Test
     void assertCompleteMaskAlgorithmThroughProxy() throws IOException, 
InterruptedException {
+        useSharedReadOnlyRuntimeFixture();
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
             Map<String, Object> actual = 
interactionClient.complete(Map.of("type", "ref/prompt", "name", 
PLAN_PROMPT_NAME), "algorithm_type", "KEEP", Map.of());
             
assertThat(getStringList(getMap(actual.get("completion")).get("values")), 
hasItem("KEEP_FIRST_N_LAST_M"));
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/PackagedDistributionE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/PackagedDistributionE2ETest.java
index 2120d3144f6..17073afad68 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/PackagedDistributionE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/PackagedDistributionE2ETest.java
@@ -17,10 +17,6 @@
 
 package org.apache.shardingsphere.test.e2e.mcp.runtime.production;
 
-import static org.hamcrest.Matchers.containsInAnyOrder;
-import static org.hamcrest.Matchers.hasItems;
-import static org.hamcrest.Matchers.is;
-
 import 
org.apache.shardingsphere.test.e2e.env.runtime.EnvironmentPropertiesLoader;
 import org.apache.shardingsphere.test.e2e.mcp.env.MCPE2ECondition;
 import org.apache.shardingsphere.test.e2e.mcp.support.OfficialMCPToolNames;
@@ -50,10 +46,14 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.sql.SQLException;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.stream.Stream;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.hasItems;
+import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -105,7 +105,7 @@ class PackagedDistributionE2ETest {
     
     @Test
     void assertLaunchPackagedDistributionOverHttp() throws IOException, 
InterruptedException, SQLException {
-        PreparedPackagedDistribution distribution = 
preparePackagedDistribution("http", RuntimeTransport.HTTP);
+        PreparedPackagedDistribution distribution = 
prepareReusableOfficialPackagedDistribution(RuntimeTransport.HTTP);
         try (
                 PackagedDistributionHttpRuntime runtime = new 
PackagedDistributionHttpRuntime(distribution);
                 MCPInteractionClient interactionClient = 
runtime.openInteractionClient()) {
@@ -117,7 +117,7 @@ class PackagedDistributionE2ETest {
     
     @Test
     void assertLaunchPackagedDistributionOverStdio() throws IOException, 
InterruptedException, SQLException {
-        PreparedPackagedDistribution distribution = 
preparePackagedDistribution("stdio", RuntimeTransport.STDIO);
+        PreparedPackagedDistribution distribution = 
prepareReusableOfficialPackagedDistribution(RuntimeTransport.STDIO);
         try (MCPInteractionClient interactionClient = new 
PackagedDistributionStdioInteractionClient(distribution.home(), 
distribution.configFile())) {
             interactionClient.open();
             assertOfficialRuntime(distribution.home(), RuntimeTransport.STDIO, 
interactionClient);
@@ -174,9 +174,15 @@ class PackagedDistributionE2ETest {
                 MySQLRuntimeTestSupport.createRuntimeDatabases(mysqlContainer, 
LOGICAL_DATABASE_NAME));
     }
     
+    private PreparedPackagedDistribution 
prepareReusableOfficialPackagedDistribution(final RuntimeTransport transport) 
throws IOException, SQLException {
+        prepareMySQLContainer();
+        return 
PackagedDistributionTestSupport.prepareReusable(tempDir.resolve("official-distribution-home-"
 + transport.name().toLowerCase(Locale.ENGLISH)), transport,
+                MySQLRuntimeTestSupport.createRuntimeDatabases(mysqlContainer, 
LOGICAL_DATABASE_NAME));
+    }
+    
     private Path createDockerConfigurationFile(final RuntimeTransport 
transport) throws IOException, SQLException {
         prepareMySQLContainer();
-        return 
PackagedDistributionTestSupport.createDockerConfigurationFile(tempDir.resolve("container-"
 + transport.name().toLowerCase() + ".yaml"), transport,
+        return 
PackagedDistributionTestSupport.createDockerConfigurationFile(tempDir.resolve("container-"
 + transport.name().toLowerCase(Locale.ENGLISH) + ".yaml"), transport,
                 
MySQLRuntimeTestSupport.createDockerHostRuntimeDatabases(mysqlContainer, 
LOGICAL_DATABASE_NAME));
     }
     
@@ -307,8 +313,8 @@ class PackagedDistributionE2ETest {
     private void assertFixtureResource(final Map<String, Object> payload) {
         List<Map<String, Object>> actualItems = 
MCPInteractionPayloads.castToList(payload.get("items"));
         assertThat(actualItems.size(), is(1));
-        assertThat(actualItems.get(0).get("feature"), is("test-fixture"));
-        assertThat(actualItems.get(0).get("status"), is("ready"));
+        assertThat(actualItems.getFirst().get("feature"), is("test-fixture"));
+        assertThat(actualItems.getFirst().get("status"), is("ready"));
     }
     
     private void assertCapabilities(final Map<String, Object> payload) {
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLRuntimeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLRuntimeE2ETest.java
index 165bcf7f0e0..f9ae572a6ba 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLRuntimeE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLRuntimeE2ETest.java
@@ -40,8 +40,13 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 @EnabledIf("isEnabled")
 class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETest {
     
+    @Override
+    protected boolean useSharedRuntimeFixture() {
+        return true;
+    }
+    
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertReadCapabilitiesWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -52,7 +57,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertReadDatabasesResourceWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -61,7 +66,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertServiceCapabilitiesResourceWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -70,7 +75,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertListToolsWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -84,7 +89,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertListResourcesWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -93,7 +98,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertListResourceTemplatesWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -106,7 +111,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectUnsupportedResourceUriWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -119,7 +124,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectUnsupportedToolNameWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -131,7 +136,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertInitializeExposesMarkdownInstructionsWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -143,7 +148,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertServerInstructionsAreNotListedAsResourceWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -173,7 +178,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertReadTableDetailWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -188,7 +193,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertSearchMetadataTablesAndViewsWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -199,7 +204,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertReadViewsWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -211,7 +216,7 @@ class ProductionMySQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETes
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertReadIndexesWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLSQLRuntimeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLSQLRuntimeE2ETest.java
index f3b1f79528f..a25269bb910 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLSQLRuntimeE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionMySQLSQLRuntimeE2ETest.java
@@ -46,7 +46,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETest {
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteSelectWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -57,7 +57,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteSelectWithTruncationWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -70,7 +70,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteExplainAnalyzeSelectWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -83,7 +83,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteQueryTimeoutWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -94,7 +94,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectExecuteMultiStatementWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -105,7 +105,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertRejectExplainAnalyzeUpdateFromReadOnlyToolWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -119,7 +119,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectLockingReadFromReadOnlyToolWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -130,7 +130,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectLockingReadFromUpdateToolWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -141,7 +141,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("dualTransports")
     void assertElicitMaskPlanningWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws IOException {
         useTransport(transport);
         List<McpSchema.ElicitRequest> actualElicitationRequests = new 
CopyOnWriteArrayList<>();
@@ -170,7 +170,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteUpdateWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws SQLException, IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -183,7 +183,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertExecuteUpdateWithoutApprovalArgumentWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -195,7 +195,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectSequenceResourceWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -207,7 +207,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteRollbackWithActualMySQLBackend(final String name, final 
RuntimeTransport transport) throws SQLException, IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -222,7 +222,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertRejectBlankSavepointNameWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -232,7 +232,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteSavepointFlowWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws SQLException, IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -252,7 +252,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteReleaseSavepointWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -267,7 +267,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertExecuteDdlRefreshesMetadataWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -281,7 +281,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void assertCloseRollsBackPendingTransactionWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws SQLException, 
IOException, InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -294,7 +294,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertAiNativeDeterministicInteractionLoopWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
@@ -313,7 +313,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertListDatabasesWithMultipleRuntimeDatabasesWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient(createPreparedProgrammaticRuntimeDatabases())) {
@@ -324,7 +324,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertRefreshMetadataVisibleForTargetDatabaseOnlyWithActualMySQLBackend(final 
String name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient firstInteractionClient = 
createOpenedInteractionClient(createPreparedProgrammaticRuntimeDatabases())) {
@@ -343,7 +343,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("semanticPrimaryTransport")
     void 
assertRejectCrossDatabaseTransactionSwitchWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) throws IOException, 
InterruptedException {
         useTransport(transport);
         try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient(createPreparedProgrammaticRuntimeDatabases())) {
@@ -355,7 +355,7 @@ class ProductionMySQLSQLRuntimeE2ETest extends 
AbstractProductionMySQLRuntimeE2E
     }
     
     @ParameterizedTest(name = "{0}")
-    @MethodSource("transports")
+    @MethodSource("dualTransports")
     void assertRejectMismatchedDatabaseTypeWithActualMySQLBackend(final String 
name, final RuntimeTransport transport) {
         useTransport(transport);
         if (RuntimeTransport.HTTP == transport) {
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionRuntimeTransportSmokeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionRuntimeTransportSmokeE2ETest.java
new file mode 100644
index 00000000000..11f3920d6b5
--- /dev/null
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/ProductionRuntimeTransportSmokeE2ETest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.runtime.production;
+
+import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
+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.condition.EnabledIf;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import java.io.IOException;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+
+@EnabledIf("isEnabled")
+class ProductionRuntimeTransportSmokeE2ETest extends 
AbstractProductionMySQLRuntimeE2ETest {
+    
+    @Override
+    protected boolean useSharedRuntimeFixture() {
+        return true;
+    }
+    
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("dualTransports")
+    void assertTransportLifecycleWithActualMySQLBackend(final String name, 
final RuntimeTransport transport) throws IOException, InterruptedException {
+        useTransport(transport);
+        try (MCPInteractionClient interactionClient = 
createOpenedInteractionClient()) {
+            
assertOfficialToolNames(interactionClient.listTools().stream().map(each -> 
String.valueOf(each.get("name"))).toList());
+            
MCPPayloadAssertions.assertSingleItemValue(interactionClient.readResource("shardingsphere://databases"),
 "database", LOGICAL_DATABASE_NAME);
+            Map<String, Object> actual = 
interactionClient.call("database_gateway_execute_query",
+                    Map.of("database", LOGICAL_DATABASE_NAME, "schema", 
LOGICAL_DATABASE_NAME, "sql", "SELECT status FROM orders WHERE order_id = 1", 
"max_rows", 1));
+            assertThat(String.valueOf(actual.get("result_kind")), 
is("result_set"));
+        }
+    }
+}
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 f7584ad3eca..b73b2efc603 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
@@ -47,8 +47,15 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
     
     private Map<String, RuntimeDatabaseConfiguration> runtimeDatabases;
     
+    private ProgrammaticRuntimeFixture sharedRuntimeFixture;
+    
     @AfterEach
     void tearDownContainer() {
+        if (useSharedDatabaseBackedRuntime()) {
+            container = null;
+            runtimeDatabases = null;
+            return;
+        }
         if (null != container) {
             container.stop();
             container = null;
@@ -96,10 +103,6 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
         return sendJsonRpcRequest(httpClient, createSessionHeaders(sessionId), 
"resource-1", "resources/read", Map.of("uri", resourceUri));
     }
     
-    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"));
-    }
-    
     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);
@@ -114,12 +117,6 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
         return httpClient.send(requestBuilder.build(), 
HttpResponse.BodyHandlers.ofString());
     }
     
-    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());
-    }
-    
     protected final Map<String, Object> getStructuredContent(final String 
responseBody) {
         Map<String, Object> payload = 
MCPInteractionPayloads.parseJsonPayload(responseBody);
         return MCPInteractionPayloads.hasJsonRpcError(payload) ? 
MCPInteractionPayloads.getJsonRpcErrorPayload(payload) : 
MCPInteractionPayloads.getStructuredContent(payload);
@@ -174,12 +171,50 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
     protected final void prepareRuntimeFixture() throws IOException {
         Assumptions.assumeTrue(MySQLRuntimeTestSupport.isDockerAvailable(),
                 () -> 
MySQLRuntimeTestSupport.createDockerRequiredMessage("Docker is required for the 
MySQL-backed MCP programmatic contract E2E test."));
-        container = MySQLRuntimeTestSupport.createContainer();
-        container.start();
+        if (useSharedDatabaseBackedRuntime()) {
+            prepareSharedDatabaseBackedRuntime();
+            return;
+        }
+        applyRuntimeFixture(createRuntimeFixture());
+    }
+    
+    private void prepareSharedDatabaseBackedRuntime() throws IOException {
+        if (null == sharedRuntimeFixture) {
+            sharedRuntimeFixture = createRuntimeFixture();
+        }
+        applyRuntimeFixture(sharedRuntimeFixture);
+    }
+    
+    private ProgrammaticRuntimeFixture createRuntimeFixture() throws 
IOException {
+        GenericContainer<?> result = MySQLRuntimeTestSupport.createContainer();
+        boolean success = false;
         try {
-            runtimeDatabases = 
MySQLRuntimeTestSupport.createPreparedProgrammaticRuntimeDatabases(container);
+            result.start();
+            Map<String, RuntimeDatabaseConfiguration> actualRuntimeDatabases = 
MySQLRuntimeTestSupport.createPreparedProgrammaticRuntimeDatabases(result);
+            success = true;
+            return new ProgrammaticRuntimeFixture(result, 
actualRuntimeDatabases);
         } catch (final SQLException ex) {
             throw new IOException("Failed to initialize MCP E2E runtime 
databases.", ex);
+        } finally {
+            if (!success) {
+                result.stop();
+            }
+        }
+    }
+    
+    private void applyRuntimeFixture(final ProgrammaticRuntimeFixture fixture) 
{
+        container = fixture.container();
+        runtimeDatabases = fixture.runtimeDatabases();
+    }
+    
+    protected boolean useSharedDatabaseBackedRuntime() {
+        return false;
+    }
+    
+    protected void closeSharedDatabaseBackedRuntime() {
+        if (null != sharedRuntimeFixture) {
+            sharedRuntimeFixture.close();
+            sharedRuntimeFixture = null;
         }
     }
     
@@ -191,4 +226,29 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
     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;
+        
+        private final Map<String, RuntimeDatabaseConfiguration> 
runtimeDatabases;
+        
+        private ProgrammaticRuntimeFixture(final GenericContainer<?> 
container, final Map<String, RuntimeDatabaseConfiguration> runtimeDatabases) {
+            this.container = container;
+            this.runtimeDatabases = runtimeDatabases;
+        }
+        
+        private GenericContainer<?> container() {
+            return container;
+        }
+        
+        private Map<String, RuntimeDatabaseConfiguration> runtimeDatabases() {
+            return runtimeDatabases;
+        }
+        
+        @Override
+        public void close() {
+            container.stop();
+        }
+    }
 }
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/AbstractHttpProtocolOnlyE2ETest.java
similarity index 62%
copy from 
test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProgrammaticRuntimeE2ETest.java
copy to 
test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractHttpProtocolOnlyE2ETest.java
index f7584ad3eca..2dc53a275bd 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/AbstractHttpProtocolOnlyE2ETest.java
@@ -17,47 +17,51 @@
 
 package org.apache.shardingsphere.test.e2e.mcp.runtime.programmatic;
 
-import 
org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
-import 
org.apache.shardingsphere.test.e2e.mcp.support.runtime.AbstractConfigBackedRuntimeE2ETest;
-import 
org.apache.shardingsphere.test.e2e.mcp.support.runtime.MySQLRuntimeTestSupport;
-import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
+import 
org.apache.shardingsphere.mcp.bootstrap.config.HttpTransportConfiguration;
+import 
org.apache.shardingsphere.mcp.bootstrap.transport.server.http.StreamableHttpMCPServer;
+import org.apache.shardingsphere.mcp.core.context.MCPRuntimeContext;
+import org.apache.shardingsphere.mcp.core.session.MCPSessionManager;
+import 
org.apache.shardingsphere.mcp.support.database.capability.MCPDatabaseCapabilityProvider;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionPayloads;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPHttpTransportTestSupport;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Assumptions;
-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.Collections;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
-abstract class AbstractHttpProgrammaticRuntimeE2ETest extends 
AbstractConfigBackedRuntimeE2ETest {
+abstract class AbstractHttpProtocolOnlyE2ETest {
     
-    private static final String CLIENT_NAME = "mcp-e2e-programmatic";
+    private static final String LOOPBACK_BIND_HOST = "127.0.0.1";
+    
+    private static final String ENDPOINT_PATH = "/gateway";
     
-    private GenericContainer<?> container;
+    private static final String CLIENT_NAME = "mcp-e2e-programmatic";
     
-    private Map<String, RuntimeDatabaseConfiguration> runtimeDatabases;
+    private StreamableHttpMCPServer httpServer;
     
     @AfterEach
-    void tearDownContainer() {
-        if (null != container) {
-            container.stop();
-            container = null;
+    void tearDownHttpServer() {
+        if (null != httpServer) {
+            httpServer.stop();
+            httpServer = null;
         }
-        runtimeDatabases = null;
     }
     
     protected final void launchHttpTransport() throws IOException {
-        prepareRuntime();
+        if (null != httpServer) {
+            return;
+        }
+        httpServer = new 
StreamableHttpMCPServer(createHttpTransportConfiguration(), 
createRuntimeContext());
+        httpServer.start();
     }
     
     protected final String initializeSession(final HttpClient httpClient) 
throws IOException, InterruptedException {
@@ -86,16 +90,6 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
                 
MCPHttpTransportTestSupport.createJsonRpcNotificationBody("notifications/initialized",
 Map.of()));
     }
     
-    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));
-    }
-    
-    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));
-    }
-    
     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"));
     }
@@ -120,16 +114,6 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
         return httpClient.send(requestBuilder.build(), 
HttpResponse.BodyHandlers.ofString());
     }
     
-    protected final Map<String, Object> getStructuredContent(final String 
responseBody) {
-        Map<String, Object> payload = 
MCPInteractionPayloads.parseJsonPayload(responseBody);
-        return MCPInteractionPayloads.hasJsonRpcError(payload) ? 
MCPInteractionPayloads.getJsonRpcErrorPayload(payload) : 
MCPInteractionPayloads.getStructuredContent(payload);
-    }
-    
-    protected final Map<String, Object> getFirstResourcePayload(final String 
responseBody) {
-        Map<String, Object> payload = 
MCPInteractionPayloads.parseJsonPayload(responseBody);
-        return MCPInteractionPayloads.hasJsonRpcError(payload) ? 
MCPInteractionPayloads.getJsonRpcErrorPayload(payload) : 
MCPInteractionPayloads.getFirstResourcePayload(payload);
-    }
-    
     protected final Map<String, Object> parseJsonBody(final String 
responseBody) {
         return MCPInteractionPayloads.parseJsonPayload(responseBody);
     }
@@ -138,15 +122,11 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
         return MCPInteractionPayloads.castToMap(value);
     }
     
-    protected final Map<String, Object> getRecoveryPayload(final Map<String, 
Object> payload, final String expectedRecoveryCategory) {
-        assertThat(String.valueOf(payload.get("response_mode")), 
is("recovery"));
-        Map<String, Object> result = castToMap(payload.get("recovery"));
-        assertThat(String.valueOf(result.get("recovery_category")), 
is(expectedRecoveryCategory));
-        return result;
-    }
-    
-    protected final URI getEndpointUri() throws IOException {
-        return getHttpEndpointUri();
+    protected final URI getEndpointUri() {
+        if (null == httpServer) {
+            throw new IllegalStateException("HTTP transport is not enabled for 
current protocol E2E test.");
+        }
+        return URI.create(String.format("http://%s:%d%s";, LOOPBACK_BIND_HOST, 
httpServer.getLocalPort(), getHttpEndpointPath()));
     }
     
     protected final String getProtocolVersion() {
@@ -160,27 +140,12 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
         return result;
     }
     
-    @Override
-    protected final RuntimeTransport getTransport() {
-        return RuntimeTransport.HTTP;
+    protected HttpTransportConfiguration createHttpTransportConfiguration() {
+        return new HttpTransportConfiguration(LOOPBACK_BIND_HOST, 0, 
getHttpEndpointPath());
     }
     
-    @Override
-    protected final Map<String, RuntimeDatabaseConfiguration> 
getRuntimeDatabases() {
-        return runtimeDatabases;
-    }
-    
-    @Override
-    protected final void prepareRuntimeFixture() throws IOException {
-        Assumptions.assumeTrue(MySQLRuntimeTestSupport.isDockerAvailable(),
-                () -> 
MySQLRuntimeTestSupport.createDockerRequiredMessage("Docker is required for the 
MySQL-backed MCP programmatic contract E2E test."));
-        container = MySQLRuntimeTestSupport.createContainer();
-        container.start();
-        try {
-            runtimeDatabases = 
MySQLRuntimeTestSupport.createPreparedProgrammaticRuntimeDatabases(container);
-        } catch (final SQLException ex) {
-            throw new IOException("Failed to initialize MCP E2E runtime 
databases.", ex);
-        }
+    protected String getHttpEndpointPath() {
+        return ENDPOINT_PATH;
     }
     
     private HttpResponse<String> sendJsonRpcRequest(final HttpClient 
httpClient, final Map<String, String> headers, final String requestId,
@@ -191,4 +156,8 @@ abstract class AbstractHttpProgrammaticRuntimeE2ETest 
extends AbstractConfigBack
     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/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractSharedHttpProgrammaticRuntimeE2ETest.java
similarity index 56%
copy from 
test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
copy to 
test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractSharedHttpProgrammaticRuntimeE2ETest.java
index 7b6b66a1ebf..a2728e221a5 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/production/AbstractTransportParameterizedProductionRuntimeE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/AbstractSharedHttpProgrammaticRuntimeE2ETest.java
@@ -15,23 +15,21 @@
  * limitations under the License.
  */
 
-package org.apache.shardingsphere.test.e2e.mcp.runtime.production;
+package org.apache.shardingsphere.test.e2e.mcp.runtime.programmatic;
 
-import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.TestInstance;
 
-abstract class AbstractTransportParameterizedProductionRuntimeE2ETest extends 
AbstractProductionRuntimeE2ETest {
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+abstract class AbstractSharedHttpProgrammaticRuntimeE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
     
-    private RuntimeTransport transport;
-    
-    protected final void useTransport(final RuntimeTransport transport) {
-        this.transport = transport;
+    @Override
+    protected boolean useSharedDatabaseBackedRuntime() {
+        return true;
     }
     
-    @Override
-    protected final RuntimeTransport getTransport() {
-        if (null == transport) {
-            throw new IllegalStateException("Runtime transport is not selected 
for current production E2E test.");
-        }
-        return transport;
+    @AfterAll
+    void tearDownSharedDatabaseBackedRuntime() {
+        closeSharedDatabaseBackedRuntime();
     }
 }
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/FeatureWorkflowContractE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/FeatureWorkflowContractE2ETest.java
index 8a59e4faae2..91513ca75c0 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/FeatureWorkflowContractE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/FeatureWorkflowContractE2ETest.java
@@ -38,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @EnabledIf("isEnabled")
-class FeatureWorkflowContractE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class FeatureWorkflowContractE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static final List<String> FORBIDDEN_ARTIFACT_TOKENS = List.of(
             "create table", "alter table", "drop table", "create index", "drop 
index", "migrate", "migration", "backfill", "data probe", "physical metadata",
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportApprovalSafetyE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportApprovalSafetyE2ETest.java
index 1020d66662d..2b97d688b4b 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportApprovalSafetyE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportApprovalSafetyE2ETest.java
@@ -35,7 +35,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
 @EnabledIf("isEnabled")
-class HttpTransportApprovalSafetyE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class HttpTransportApprovalSafetyE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static boolean isEnabled() {
         return MCPE2ECondition.isDockerEnabled();
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportBaselineContractE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportBaselineContractE2ETest.java
index fef006781dd..469d5e2322d 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportBaselineContractE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportBaselineContractE2ETest.java
@@ -35,7 +35,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
 @EnabledIf("isEnabled")
-class HttpTransportBaselineContractE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class HttpTransportBaselineContractE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static final String BASELINE_RESOURCE_PATH = 
"baseline-contract/model-contract/";
     
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
index 55ef7d8cadc..038284dcf3e 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
@@ -36,7 +36,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @EnabledIf("isEnabled")
-class HttpTransportCompletionE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class HttpTransportCompletionE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static final String PLAN_MASK_PROMPT_NAME = "plan_mask_rule";
     
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportContractE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportContractE2ETest.java
index 341749ca36c..9c6dcc7282a 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportContractE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportContractE2ETest.java
@@ -41,7 +41,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @EnabledIf("isEnabled")
-class HttpTransportContractE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class HttpTransportContractE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static final List<String> OFFICIAL_TOOL_NAMES = 
OfficialMCPToolNames.getAll();
     
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportProtocolContractE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportProtocolContractE2ETest.java
index 10f27c01995..05db95835de 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportProtocolContractE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportProtocolContractE2ETest.java
@@ -17,10 +17,8 @@
 
 package org.apache.shardingsphere.test.e2e.mcp.runtime.programmatic;
 
-import org.apache.shardingsphere.test.e2e.mcp.env.MCPE2ECondition;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPHttpTransportTestSupport;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
 
 import java.io.IOException;
 import java.net.http.HttpClient;
@@ -34,12 +32,7 @@ import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
-@EnabledIf("isEnabled")
-class HttpTransportProtocolContractE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
-    
-    private static boolean isEnabled() {
-        return MCPE2ECondition.isDockerEnabled();
-    }
+class HttpTransportProtocolContractE2ETest extends 
AbstractHttpProtocolOnlyE2ETest {
     
     @Test
     void assertInitializeSessionAndProtocolHeaders() throws IOException, 
InterruptedException {
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportRecoveryE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportRecoveryE2ETest.java
index 833e7776d83..b5b1d10603d 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportRecoveryE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportRecoveryE2ETest.java
@@ -38,7 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 @EnabledIf("isEnabled")
-class HttpTransportRecoveryE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class HttpTransportRecoveryE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static final String RECOVERY_SECRET = "recovery-secret-value";
     
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSecurityE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSecurityE2ETest.java
index 1f5124d3481..9d02d1fcb85 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSecurityE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSecurityE2ETest.java
@@ -18,10 +18,8 @@
 package org.apache.shardingsphere.test.e2e.mcp.runtime.programmatic;
 
 import 
org.apache.shardingsphere.mcp.bootstrap.config.HttpTransportConfiguration;
-import org.apache.shardingsphere.test.e2e.mcp.env.MCPE2ECondition;
 import 
org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPHttpTransportTestSupport;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
 
 import java.io.IOException;
 import java.net.http.HttpClient;
@@ -33,15 +31,10 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 
-@EnabledIf("isEnabled")
-class HttpTransportSecurityE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
+class HttpTransportSecurityE2ETest extends AbstractHttpProtocolOnlyE2ETest {
     
     private boolean remoteBinding;
     
-    private static boolean isEnabled() {
-        return MCPE2ECondition.isDockerEnabled();
-    }
-    
     @Override
     protected HttpTransportConfiguration createHttpTransportConfiguration() {
         return remoteBinding ? new HttpTransportConfiguration("0.0.0.0", 0, 
getHttpEndpointPath()) : super.createHttpTransportConfiguration();
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSessionLifecycleE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSessionLifecycleE2ETest.java
index ff41ec73476..86671d5cf54 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSessionLifecycleE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportSessionLifecycleE2ETest.java
@@ -17,9 +17,7 @@
 
 package org.apache.shardingsphere.test.e2e.mcp.runtime.programmatic;
 
-import org.apache.shardingsphere.test.e2e.mcp.env.MCPE2ECondition;
 import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.condition.EnabledIf;
 
 import java.io.IOException;
 import java.net.http.HttpClient;
@@ -29,12 +27,7 @@ import java.util.Map;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 
-@EnabledIf("isEnabled")
-class HttpTransportSessionLifecycleE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
-    
-    private static boolean isEnabled() {
-        return MCPE2ECondition.isDockerEnabled();
-    }
+class HttpTransportSessionLifecycleE2ETest extends 
AbstractHttpProtocolOnlyE2ETest {
     
     @Test
     void assertRejectOpenStreamAfterDelete() throws IOException, 
InterruptedException {
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/MetadataDiscoveryE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/MetadataDiscoveryE2ETest.java
index 85654d7847b..bb6a2e84005 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/MetadataDiscoveryE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/MetadataDiscoveryE2ETest.java
@@ -33,7 +33,7 @@ import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 
 @EnabledIf("isEnabled")
-class MetadataDiscoveryE2ETest extends AbstractHttpProgrammaticRuntimeE2ETest {
+class MetadataDiscoveryE2ETest extends 
AbstractSharedHttpProgrammaticRuntimeE2ETest {
     
     private static boolean isEnabled() {
         return MCPE2ECondition.isDockerEnabled();
@@ -61,7 +61,7 @@ class MetadataDiscoveryE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
                         
"shardingsphere://databases/logic_db/schemas/logic_db/tables/orders/indexes")));
         HttpResponse<String> tableResource = 
sendResourceReadRequest(httpClient, sessionId, 
String.valueOf(actualResource.get("uri")));
         assertThat(tableResource.statusCode(), is(200));
-        
assertThat(String.valueOf(MCPInteractionPayloads.castToList(getFirstResourcePayload(tableResource.body()).get("items")).get(0).get("table")),
 is("orders"));
+        
assertThat(String.valueOf(MCPInteractionPayloads.castToList(getFirstResourcePayload(tableResource.body()).get("items")).getFirst().get("table")),
 is("orders"));
     }
     
     @Test
@@ -96,8 +96,8 @@ class MetadataDiscoveryE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ETest {
         assertThat(actual.statusCode(), is(200));
         List<Map<String, Object>> actualItems = 
MCPInteractionPayloads.castToList(getFirstResourcePayload(actual.body()).get("items"));
         assertThat(actualItems.size(), is(1));
-        assertThat(String.valueOf(actualItems.get(0).get("table")), 
is("facts"));
-        assertThat(String.valueOf(actualItems.get(0).get("index")), 
is("PRIMARY"));
+        assertThat(String.valueOf(actualItems.getFirst().get("table")), 
is("facts"));
+        assertThat(String.valueOf(actualItems.getFirst().get("index")), 
is("PRIMARY"));
     }
     
     @Test
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 0b00365e19a..95343e05c36 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
@@ -89,6 +89,23 @@ public final class PackagedDistributionTestSupport {
         return new PreparedPackagedDistribution(workingHome, configFile, 
transport, httpPort);
     }
     
+    /**
+     * Prepare a reusable packaged MCP distribution home with supplied runtime 
databases.
+     *
+     * @param workingHome reusable working home
+     * @param transport runtime transport
+     * @param runtimeDatabases runtime databases
+     * @return prepared packaged distribution
+     * @throws IOException I/O exception
+     */
+    public static PreparedPackagedDistribution prepareReusable(final Path 
workingHome, final RuntimeTransport transport,
+                                                               final 
Map<String, RuntimeDatabaseConfiguration> runtimeDatabases) throws IOException {
+        Path actualWorkingHome = prepareReusableWorkingHome(workingHome);
+        int httpPort = resolveHttpPort(transport);
+        Path configFile = rewriteConfiguration(actualWorkingHome, transport, 
httpPort, runtimeDatabases);
+        return new PreparedPackagedDistribution(actualWorkingHome, configFile, 
transport, httpPort);
+    }
+    
     /**
      * Create a mounted configuration file for a Dockerized MCP distribution.
      *
@@ -130,6 +147,15 @@ public final class PackagedDistributionTestSupport {
         return workingHome;
     }
     
+    private static Path prepareReusableWorkingHome(final Path workingHome) 
throws IOException {
+        if (!Files.exists(workingHome)) {
+            copyDistributionHome(findRequiredDistributionHome(), workingHome);
+        }
+        resetRuntimeDirectories(workingHome);
+        makeStartScriptExecutable(workingHome);
+        return workingHome;
+    }
+    
     private static Path findRequiredDistributionHome() throws IOException {
         return 
findDistributionHome().orElseThrow(PackagedDistributionTestSupport::createMissingDistributionHomeException);
     }


Reply via email to