You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2026/08/01 14:15:48 UTC

(shardingsphere) branch master updated: Refactor MCP module to remove unnecessary abstractions (#39308)

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 ec6ad179135 Refactor MCP module to remove unnecessary abstractions (#39308)
ec6ad179135 is described below

commit ec6ad179135ae69bab713edea5886f816e3063ff
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Sat Aug 1 22:15:40 2026 +0800

    Refactor MCP module to remove unnecessary abstractions (#39308)
    
    - remove fixed LLM token limits and redundant response adapters
    - simplify workflow contracts and inline single-owner helpers
    - consolidate test fixtures and remove shape-only tests
---
 .../resource/MCPResourceDescriptorTest.java        |   7 -
 .../capability/tool/MCPCallToolResultFactory.java  |  28 ++-
 .../capability/tool/MCPResourceLinkContract.java   |  59 -----
 .../server/http/SessionAttributionResolver.java    |  10 +-
 .../server/http/StreamableHttpMCPServlet.java      |   9 +-
 .../ServerTransportSecurityValidatorFactory.java   |  47 ----
 .../transport/server/MCPSyncServerFactoryTest.java |  15 +-
 ...erverTransportSecurityValidatorFactoryTest.java | 110 ----------
 .../mcp/core/handler/core/CoreHandlerProvider.java |  18 +-
 .../mcp/core/handler/core/CoreToolHandlers.java    |  52 -----
 .../resource/handler/MCPResourceDefinition.java    |  38 ----
 .../handler/ResourceDefinitionRegistry.java        |  30 ++-
 .../workflow/WorkflowExecutionToolHandler.java     |   2 +-
 .../workflow/WorkflowValidationToolHandler.java    |   2 +-
 .../mcp/core/workflow/WorkflowApplyOutcome.java    |   2 +-
 .../core/workflow/WorkflowExecutionService.java    |  33 ++-
 .../WorkflowRuntimeDefinitionRegistry.java         |   6 +-
 .../handler/MetadataCompletionHandlerTest.java     |   5 -
 .../WorkflowPlanIdCompletionHandlerTest.java       |   5 -
 .../capability/ServerCapabilitiesHandlerTest.java  |   6 +-
 .../metadata/MetadataResourceHandlerTest.java      |  10 -
 .../mcp/core/resource/uri/MCPUriPatternTest.java   |   6 -
 .../workflow/WorkflowExecutionToolHandlerTest.java |   9 +-
 .../workflow/WorkflowHandlerTestFixture.java       |  17 +-
 .../WorkflowValidationToolHandlerTest.java         |  12 +-
 .../workflow/WorkflowExecutionServiceTest.java     |  65 +++---
 .../WorkflowRuntimeDefinitionRegistryTest.java     |  27 +--
 .../broadcast/BroadcastFeatureDefinitionTest.java  |  10 -
 .../broadcast/BroadcastMCPHandlerProviderTest.java |   3 +-
 .../feature/encrypt/EncryptMCPHandlerProvider.java |   2 +-
 .../EncryptWorkflowToolResponseBuilder.java        |  69 ------
 .../tool/handler/PlanEncryptRuleToolHandler.java   |  37 +++-
 .../service/EncryptWorkflowPlanningService.java    |   2 +-
 .../service/EncryptWorkflowValidationService.java  |   2 +-
 .../encrypt/EncryptFeatureDefinitionTest.java      |  36 ---
 .../encrypt/EncryptMCPHandlerProviderTest.java     |   3 +-
 .../EncryptAlgorithmCompletionHandlerTest.java     |   5 -
 .../handler/MaskWorkflowToolResponseBuilder.java   |  53 -----
 .../mask/tool/handler/PlanMaskRuleToolHandler.java |  19 +-
 .../service/MaskWorkflowValidationService.java     |   2 +-
 .../feature/mask/MaskFeatureDefinitionTest.java    |  10 -
 .../feature/mask/MaskMCPHandlerProviderTest.java   |   3 +-
 .../MaskAlgorithmCompletionHandlerTest.java        |   5 -
 .../ReadwriteSplittingFeatureDefinitionTest.java   |   6 -
 .../ReadwriteSplittingMCPHandlerProviderTest.java  |   4 +-
 ...gLoadBalanceAlgorithmCompletionHandlerTest.java |   5 -
 .../shadow/ShadowFeatureDefinitionTest.java        |  33 ---
 .../ShadowAlgorithmCompletionHandlerTest.java      |   5 -
 .../sharding/ShardingMCPHandlerProvider.java       |  12 +-
 .../handler/ShardingPlanningRequestBinder.java     |  18 +-
 .../service/ShardingWorkflowLifecycleSpec.java     |  49 -----
 .../service/ShardingWorkflowPlanningService.java   |  22 +-
 .../sharding/ShardingFeatureDefinitionTest.java    |  45 ----
 .../sharding/ShardingMCPHandlerProviderTest.java   |   3 +-
 .../ShardingAlgorithmCompletionHandlerTest.java    |   5 -
 .../descriptor/MCPGuidancePayloadBuilder.java      |  17 +-
 .../support/security/MCPClientSafetyPolicy.java    |  49 -----
 .../support/workflow/WorkflowPropertySource.java   |  55 -----
 .../workflow/model/RuleWorkflowFeatureData.java    |  35 +--
 .../workflow/model/WorkflowContextSnapshot.java    |   4 +-
 .../workflow/model/WorkflowFeatureData.java        |  31 ---
 .../support/workflow/model/WorkflowRequest.java    |  24 +-
 .../workflow/service/WorkflowArtifactBundle.java   |  16 +-
 .../service/WorkflowArtifactMaskUtils.java         |  54 ++---
 .../service/WorkflowArtifactPayloadUtils.java      |   8 +-
 .../service/WorkflowPlanPayloadBuilder.java        |   7 +-
 .../workflow/service/WorkflowPlanningSupport.java  |   5 +-
 .../service/WorkflowSecretReferenceUtils.java      |  38 ++--
 .../MCPWorkflowApplySynchronizationHandler.java    |  42 ----
 .../workflow/spi/MCPWorkflowRuntimeHandler.java    |  36 ++-
 .../workflow/spi/MCPWorkflowValidationHandler.java |  47 ----
 .../workflow/spi/WorkflowRuntimeDefinition.java    |  22 +-
 .../jdbc/RuntimeDatabaseConfigurationTest.java     |   9 -
 .../metadata/query/DatabaseTestDataFactory.java    | 241 ---------------------
 .../metadata/query/MetadataQueryServiceTest.java   | 183 +++++++++++++++-
 .../diagnostic/MCPDiagnosticCategoryTest.java      |  64 ------
 .../protocol/payload/MCPMapPayloadTest.java        |  35 ---
 .../security/MCPClientSafetyPolicyTest.java        |  43 ----
 .../model/WorkflowContextSnapshotTest.java         |  11 +-
 .../service/WorkflowArtifactBundleTest.java        |  33 ++-
 .../service/WorkflowArtifactMaskUtilsTest.java     |  54 ++---
 .../service/WorkflowSecretReferenceUtilsTest.java  |  44 +---
 .../AbstractFunctionalityE2ETest.java              |  35 ---
 .../functionality/AbstractMySQLRuntimeE2ETest.java |  21 +-
 .../AbstractTransportParameterizedE2ETest.java     |  18 +-
 .../functionality/FunctionalityTransportCases.java |  66 ------
 .../llm/conversation/LLMConversationRunner.java    |  26 ++-
 .../mcp/llm/conversation/LLMMCPActionExecutor.java |  49 -----
 .../e2e/mcp/llm/conversation/LLMMCPJsonValues.java |  25 +--
 .../LLMMCPModelFacingToolResponseFormatter.java    | 226 -------------------
 .../conversation/client/LLMChatModelClient.java    |  24 +-
 .../e2e/mcp/llm/fixture/LLMRuntimeSupport.java     |   2 +-
 92 files changed, 701 insertions(+), 2096 deletions(-)

diff --git a/mcp/api/src/test/java/org/apache/shardingsphere/mcp/api/capability/resource/MCPResourceDescriptorTest.java b/mcp/api/src/test/java/org/apache/shardingsphere/mcp/api/capability/resource/MCPResourceDescriptorTest.java
index f3bda2068fc..56cb0801f5c 100644
--- a/mcp/api/src/test/java/org/apache/shardingsphere/mcp/api/capability/resource/MCPResourceDescriptorTest.java
+++ b/mcp/api/src/test/java/org/apache/shardingsphere/mcp/api/capability/resource/MCPResourceDescriptorTest.java
@@ -20,7 +20,6 @@ package org.apache.shardingsphere.mcp.api.capability.resource;
 import org.junit.jupiter.api.Test;
 
 import java.util.Collections;
-import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -45,10 +44,4 @@ class MCPResourceDescriptorTest {
         assertTrue(actual.isTemplated());
     }
     
-    @Test
-    void assertMetaIsKeptAsMetadataOnly() {
-        MCPResourceDescriptor actual = new MCPResourceDescriptor("shardingsphere://features/encrypt/algorithms", "encrypt-algorithms", "Encrypt Algorithms",
-                "List encrypt algorithms.", "application/json", MCPResourceAnnotations.EMPTY, Map.of("org.apache.shardingsphere/runtime-visibility", "ShardingSphere-Proxy"));
-        assertThat(actual.getMeta(), is(Map.of("org.apache.shardingsphere/runtime-visibility", "ShardingSphere-Proxy")));
-    }
 }
diff --git a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPCallToolResultFactory.java b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPCallToolResultFactory.java
index 4fca8506ae7..96ea0aa5310 100644
--- a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPCallToolResultFactory.java
+++ b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPCallToolResultFactory.java
@@ -21,12 +21,14 @@ import io.modelcontextprotocol.json.schema.JsonSchemaValidator;
 import io.modelcontextprotocol.json.schema.JsonSchemaValidator.ValidationResponse;
 import io.modelcontextprotocol.json.schema.jackson2.DefaultJsonSchemaValidator;
 import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
+import io.modelcontextprotocol.spec.McpSchema;
 import org.apache.shardingsphere.infra.util.json.JsonUtils;
 import org.apache.shardingsphere.mcp.api.payload.MCPSuccessPayload;
 import org.apache.shardingsphere.mcp.api.capability.tool.MCPToolDescriptor;
 import org.apache.shardingsphere.mcp.core.protocol.error.MCPErrorPayload;
 import org.apache.shardingsphere.mcp.support.descriptor.MCPShardingSphereMetadataKeys;
 
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Objects;
 
@@ -65,7 +67,7 @@ final class MCPCallToolResultFactory {
         MCPResourceLinkCandidateCollector.ResourceLinkCandidates candidates = new MCPResourceLinkCandidateCollector(RESOURCE_LINK_LIMIT).collect(payload);
         int emittedCount = 0;
         for (MCPResourceLinkCandidateCollector.ResourceLinkCandidate each : candidates.candidates()) {
-            builder.addContent(MCPResourceLinkContract.createResourceLink(each));
+            builder.addContent(createResourceLink(each));
             emittedCount++;
         }
         if (0 < candidates.totalCount()) {
@@ -79,4 +81,28 @@ final class MCPCallToolResultFactory {
                 MCPShardingSphereMetadataKeys.RESOURCE_LINKS_OMITTED, Math.max(0, totalCount - emittedCount),
                 MCPShardingSphereMetadataKeys.RESOURCE_LINK_LIMIT, RESOURCE_LINK_LIMIT);
     }
+    
+    private McpSchema.ResourceLink createResourceLink(final MCPResourceLinkCandidateCollector.ResourceLinkCandidate candidate) {
+        return McpSchema.ResourceLink.builder()
+                .name(resolveResourceLinkName(candidate.uri()))
+                .title(candidate.title())
+                .uri(candidate.uri())
+                .description(candidate.description())
+                .mimeType("application/json")
+                .meta(createResourceLinkMeta(candidate))
+                .build();
+    }
+    
+    private String resolveResourceLinkName(final String uri) {
+        int separatorIndex = uri.lastIndexOf('/');
+        return separatorIndex < 0 || separatorIndex == uri.length() - 1 ? uri : uri.substring(separatorIndex + 1);
+    }
+    
+    private Map<String, Object> createResourceLinkMeta(final MCPResourceLinkCandidateCollector.ResourceLinkCandidate candidate) {
+        Map<String, Object> result = new LinkedHashMap<>(3, 1F);
+        result.put(MCPShardingSphereMetadataKeys.RESOURCE_KIND, candidate.resourceKind());
+        result.put(MCPShardingSphereMetadataKeys.PURPOSE, candidate.purpose());
+        result.put(MCPShardingSphereMetadataKeys.SOURCE_FIELD, candidate.sourceField());
+        return result;
+    }
 }
diff --git a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPResourceLinkContract.java b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPResourceLinkContract.java
deleted file mode 100644
index dbd9ce9eace..00000000000
--- a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/capability/tool/MCPResourceLinkContract.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.bootstrap.transport.capability.tool;
-
-import io.modelcontextprotocol.spec.McpSchema;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.mcp.support.descriptor.MCPShardingSphereMetadataKeys;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-final class MCPResourceLinkContract {
-    
-    private static final String JSON_CONTENT_TYPE = "application/json";
-    
-    static McpSchema.ResourceLink createResourceLink(final MCPResourceLinkCandidateCollector.ResourceLinkCandidate candidate) {
-        return McpSchema.ResourceLink.builder()
-                .name(resolveResourceLinkName(candidate.uri()))
-                .title(candidate.title())
-                .uri(candidate.uri())
-                .description(candidate.description())
-                .mimeType(JSON_CONTENT_TYPE)
-                .meta(createResourceLinkMeta(candidate))
-                .build();
-    }
-    
-    private static String resolveResourceLinkName(final String uri) {
-        int separatorIndex = uri.lastIndexOf('/');
-        if (separatorIndex < 0 || separatorIndex == uri.length() - 1) {
-            return uri;
-        }
-        return uri.substring(separatorIndex + 1);
-    }
-    
-    private static Map<String, Object> createResourceLinkMeta(final MCPResourceLinkCandidateCollector.ResourceLinkCandidate candidate) {
-        Map<String, Object> result = new LinkedHashMap<>(3, 1F);
-        result.put(MCPShardingSphereMetadataKeys.RESOURCE_KIND, candidate.resourceKind());
-        result.put(MCPShardingSphereMetadataKeys.PURPOSE, candidate.purpose());
-        result.put(MCPShardingSphereMetadataKeys.SOURCE_FIELD, candidate.sourceField());
-        return result;
-    }
-}
diff --git a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/SessionAttributionResolver.java b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/SessionAttributionResolver.java
index 48f921b546b..0e1570464c3 100644
--- a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/SessionAttributionResolver.java
+++ b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/SessionAttributionResolver.java
@@ -31,6 +31,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.function.Function;
 
 /**
  * Session attribution resolver.
@@ -98,7 +99,7 @@ public final class SessionAttributionResolver {
         return !isEnabled() ? "disabled" : String.format("trusted-header:%s", config.getSubjectHeader());
     }
     
-    private Map<String, String> resolveAttributes(final Iterable<String> headerNames, final HeaderValueReader headerValueReader) {
+    private Map<String, String> resolveAttributes(final Iterable<String> headerNames, final Function<String, String> headerValueReader) {
         Map<String, String> result = new LinkedHashMap<>();
         String attributeHeaderPrefix = config.getAttributeHeaderPrefix();
         if (attributeHeaderPrefix.isEmpty()) {
@@ -108,7 +109,7 @@ public final class SessionAttributionResolver {
         for (String each : headerNames) {
             String actualHeaderName = Objects.toString(each, "").trim();
             if (actualHeaderName.toLowerCase(Locale.ENGLISH).startsWith(normalizedPrefix)) {
-                result.put(actualHeaderName.substring(attributeHeaderPrefix.length()).toLowerCase(Locale.ENGLISH), headerValueReader.read(actualHeaderName));
+                result.put(actualHeaderName.substring(attributeHeaderPrefix.length()).toLowerCase(Locale.ENGLISH), headerValueReader.apply(actualHeaderName));
             }
         }
         return result;
@@ -127,9 +128,4 @@ public final class SessionAttributionResolver {
         return "";
     }
     
-    @FunctionalInterface
-    private interface HeaderValueReader {
-        
-        String read(String headerName);
-    }
 }
diff --git a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java
index 6a432bdd9f8..d457f47af23 100644
--- a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java
+++ b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/StreamableHttpMCPServlet.java
@@ -34,10 +34,13 @@ import jakarta.servlet.http.HttpServletResponseWrapper;
 import org.apache.shardingsphere.mcp.api.session.MCPSessionIdentity;
 import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
 import org.apache.shardingsphere.mcp.bootstrap.config.HttpTransportConfiguration;
+import org.apache.shardingsphere.mcp.bootstrap.transport.HttpTransportHostUtils;
 import org.apache.shardingsphere.mcp.bootstrap.transport.MCPTransportConstants;
 import org.apache.shardingsphere.mcp.bootstrap.transport.MCPTransportErrorFactory;
 import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.MCPTransportSecurityException;
-import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.ServerTransportSecurityValidatorFactory;
+import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.ShardingSphereServerTransportSecurityValidator;
+import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.constraint.OriginHeaderConstraint;
+import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.constraint.ProtocolVersionHeaderConstraint;
 import org.apache.shardingsphere.mcp.core.session.MCPSessionExecutionCoordinator;
 import org.apache.shardingsphere.mcp.core.session.MCPSessionManager;
 import reactor.core.publisher.Mono;
@@ -83,7 +86,9 @@ final class StreamableHttpMCPServlet extends HttpServlet implements McpStreamabl
     
     StreamableHttpMCPServlet(final MCPSessionManager sessionManager, final McpJsonMapper jsonMapper, final HttpTransportConfiguration config) {
         sessionAttributionResolver = new SessionAttributionResolver(config.getSessionAttributionSource());
-        securityValidator = ServerTransportSecurityValidatorFactory.create(sessionManager, config.getBindHost(), sessionAttributionResolver);
+        securityValidator = new ShardingSphereServerTransportSecurityValidator(sessionManager,
+                new OriginHeaderConstraint(HttpTransportHostUtils.isLoopbackHost(config.getBindHost())),
+                new ProtocolVersionHeaderConstraint(), sessionAttributionResolver);
         delegate = createDelegate(jsonMapper, config.getEndpointPath());
         this.jsonMapper = jsonMapper;
         this.sessionManager = sessionManager;
diff --git a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/validator/ServerTransportSecurityValidatorFactory.java b/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/validator/ServerTransportSecurityValidatorFactory.java
deleted file mode 100644
index b667e723196..00000000000
--- a/mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/validator/ServerTransportSecurityValidatorFactory.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator;
-
-import io.modelcontextprotocol.server.transport.ServerTransportSecurityValidator;
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.mcp.bootstrap.transport.HttpTransportHostUtils;
-import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.SessionAttributionResolver;
-import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.constraint.OriginHeaderConstraint;
-import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator.constraint.ProtocolVersionHeaderConstraint;
-import org.apache.shardingsphere.mcp.core.session.MCPSessionManager;
-
-/**
- * Server transport security validator factory.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class ServerTransportSecurityValidatorFactory {
-    
-    /**
-     * Create the MCP-facing transport security validator.
-     *
-     * @param sessionManager session manager
-     * @param bindHost bind host
-     * @param sessionAttributionResolver session attribution resolver
-     * @return transport security validator
-     */
-    public static ServerTransportSecurityValidator create(final MCPSessionManager sessionManager, final String bindHost, final SessionAttributionResolver sessionAttributionResolver) {
-        return new ShardingSphereServerTransportSecurityValidator(sessionManager, new OriginHeaderConstraint(HttpTransportHostUtils.isLoopbackHost(bindHost)),
-                new ProtocolVersionHeaderConstraint(), sessionAttributionResolver);
-    }
-}
diff --git a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/MCPSyncServerFactoryTest.java b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/MCPSyncServerFactoryTest.java
index fd652ed2778..a9bc4fd8af5 100644
--- a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/MCPSyncServerFactoryTest.java
+++ b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/MCPSyncServerFactoryTest.java
@@ -24,9 +24,7 @@ import io.modelcontextprotocol.server.McpServerFeatures.SyncResourceTemplateSpec
 import io.modelcontextprotocol.server.McpServerFeatures.SyncToolSpecification;
 import io.modelcontextprotocol.server.McpSyncServer;
 import io.modelcontextprotocol.spec.McpSchema;
-import io.modelcontextprotocol.spec.DefaultMcpStreamableServerSessionFactory;
 import io.modelcontextprotocol.spec.McpServerSession;
-import io.modelcontextprotocol.spec.McpServerTransport;
 import io.modelcontextprotocol.spec.McpServerTransportProvider;
 import io.modelcontextprotocol.spec.McpStreamableServerSession;
 import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
@@ -42,10 +40,8 @@ import org.apache.shardingsphere.mcp.support.descriptor.MCPDescriptorCatalogInde
 import org.apache.shardingsphere.mcp.support.markdown.MCPMarkdownResourceLoader;
 import org.junit.jupiter.api.Test;
 import org.mockito.MockedConstruction;
-import org.mockito.internal.configuration.plugins.Plugins;
 import reactor.core.publisher.Mono;
 
-import java.time.Duration;
 import java.util.List;
 import java.util.Map;
 
@@ -62,7 +58,7 @@ import static org.mockito.Mockito.when;
 class MCPSyncServerFactoryTest {
     
     @Test
-    void assertCreateWithTransportProvider() throws NoSuchFieldException, IllegalAccessException {
+    void assertCreateWithTransportProvider() {
         TestServerTransportProvider transportProvider = new TestServerTransportProvider();
         McpSyncServer actual = createFactory().create(transportProvider);
         assertNotNull(transportProvider.sessionFactory);
@@ -72,20 +68,17 @@ class MCPSyncServerFactoryTest {
         assertThat(actual.listResources().size(), is(1));
         assertThat(actual.listResourceTemplates().size(), is(1));
         assertThat(actual.listPrompts().size(), is(1));
-        McpServerSession session = transportProvider.sessionFactory.create(mock(McpServerTransport.class));
-        assertThat(getRequestTimeout(McpServerSession.class, session), is(Duration.ofMinutes(10L)));
         actual.closeGracefully();
     }
     
     @Test
-    void assertCreateWithStreamableTransportProvider() throws NoSuchFieldException, IllegalAccessException {
+    void assertCreateWithStreamableTransportProvider() {
         TestStreamableTransportProvider transportProvider = new TestStreamableTransportProvider();
         McpSyncServer actual = createFactory().create(transportProvider);
         assertNotNull(transportProvider.sessionFactory);
         assertThat(actual.listTools().size(), is(1));
         assertThat(actual.listResources().size(), is(1));
         assertThat(actual.listResourceTemplates().size(), is(1));
-        assertThat(getRequestTimeout(DefaultMcpStreamableServerSessionFactory.class, transportProvider.sessionFactory), is(Duration.ofMinutes(10L)));
         actual.closeGracefully();
     }
     
@@ -137,10 +130,6 @@ class MCPSyncServerFactoryTest {
         }
     }
     
-    private Duration getRequestTimeout(final Class<?> targetClass, final Object target) throws NoSuchFieldException, IllegalAccessException {
-        return (Duration) Plugins.getMemberAccessor().get(targetClass.getDeclaredField("requestTimeout"), target);
-    }
-    
     private McpSchema.CallToolResult createFixtureToolResult() {
         return McpSchema.CallToolResult.builder().addTextContent("ok").build();
     }
diff --git a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/validator/ServerTransportSecurityValidatorFactoryTest.java b/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/validator/ServerTransportSecurityValidatorFactoryTest.java
deleted file mode 100644
index 98171ede482..00000000000
--- a/mcp/bootstrap/src/test/java/org/apache/shardingsphere/mcp/bootstrap/transport/server/http/validator/ServerTransportSecurityValidatorFactoryTest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.bootstrap.transport.server.http.validator;
-
-import io.modelcontextprotocol.server.transport.ServerTransportSecurityException;
-import io.modelcontextprotocol.server.transport.ServerTransportSecurityValidator;
-import org.apache.shardingsphere.mcp.bootstrap.transport.server.http.SessionAttributionResolver;
-import org.apache.shardingsphere.mcp.core.session.MCPSessionManager;
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-import java.util.Map;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.when;
-
-class ServerTransportSecurityValidatorFactoryTest {
-    
-    private static final SessionAttributionResolver DISABLED_SESSION_ATTRIBUTION_RESOLVER = new SessionAttributionResolver(null);
-    
-    @Test
-    void assertCreateWithoutOptionalRules() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator actual = ServerTransportSecurityValidatorFactory.create(sessionManager, "127.0.0.1", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        assertDoesNotThrow(() -> actual.validateHeaders(Map.of()));
-        verifyNoInteractions(sessionManager);
-    }
-    
-    @Test
-    void assertCreateWithLoopbackOrigin() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator actual = ServerTransportSecurityValidatorFactory.create(sessionManager, "127.0.0.1", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        assertDoesNotThrow(() -> actual.validateHeaders(Map.of("Origin", List.of("http://127.0.0.1:8080"))));
-        verifyNoInteractions(sessionManager);
-    }
-    
-    @Test
-    void assertCreateWithLoopbackOriginRejectsRemoteOrigin() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator validator = ServerTransportSecurityValidatorFactory.create(sessionManager, "127.0.0.1", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        ServerTransportSecurityException ex = assertThrows(ServerTransportSecurityException.class,
-                () -> validator.validateHeaders(Map.of("Origin", List.of("http://example.com:8080"), "Mcp-Session-Id", List.of("session-id"))));
-        assertThat(ex.getStatusCode(), is(403));
-        verifyNoInteractions(sessionManager);
-    }
-    
-    @Test
-    void assertCreateWithNonLoopbackBindingAcceptsMissingOrigin() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator actual = ServerTransportSecurityValidatorFactory.create(sessionManager, "0.0.0.0", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        assertDoesNotThrow(() -> actual.validateHeaders(Map.of()));
-        verifyNoInteractions(sessionManager);
-    }
-    
-    @Test
-    void assertCreateWithNonLoopbackBindingRejectsPresentOrigin() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator validator = ServerTransportSecurityValidatorFactory.create(sessionManager, "0.0.0.0", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        ServerTransportSecurityException ex = assertThrows(ServerTransportSecurityException.class,
-                () -> validator.validateHeaders(Map.of("Origin", List.of("https://gateway.example.test"))));
-        assertThat(ex.getStatusCode(), is(403));
-        verifyNoInteractions(sessionManager);
-    }
-    
-    @Test
-    void assertCreateRejectsInvalidOrigin() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator validator = ServerTransportSecurityValidatorFactory.create(sessionManager, "127.0.0.1", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        ServerTransportSecurityException ex = assertThrows(ServerTransportSecurityException.class, () -> validator.validateHeaders(Map.of("Origin", List.of("://bad-origin"))));
-        assertThat(ex.getStatusCode(), is(403));
-        verifyNoInteractions(sessionManager);
-    }
-    
-    @Test
-    void assertCreateWithProtocolVersionConstraintLast() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        when(sessionManager.hasSession("session-id")).thenReturn(true);
-        ServerTransportSecurityValidator validator = ServerTransportSecurityValidatorFactory.create(sessionManager, "127.0.0.1", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        ServerTransportSecurityException ex = assertThrows(ServerTransportSecurityException.class,
-                () -> validator.validateHeaders(Map.of("Mcp-Session-Id", List.of("session-id"))));
-        assertThat(ex.getStatusCode(), is(400));
-    }
-    
-    @Test
-    void assertCreateWithUnknownSessionSkipsProtocolVersionConstraint() {
-        MCPSessionManager sessionManager = mock(MCPSessionManager.class);
-        ServerTransportSecurityValidator actual = ServerTransportSecurityValidatorFactory.create(sessionManager, "127.0.0.1", DISABLED_SESSION_ATTRIBUTION_RESOLVER);
-        assertDoesNotThrow(() -> actual.validateHeaders(Map.of("Mcp-Session-Id", List.of("unknown-session"))));
-    }
-}
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreHandlerProvider.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreHandlerProvider.java
index 385ab5fcfee..bcebc62077d 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreHandlerProvider.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreHandlerProvider.java
@@ -23,6 +23,14 @@ import org.apache.shardingsphere.mcp.api.MCPHandlerProvider;
 import org.apache.shardingsphere.mcp.api.capability.tool.MCPToolHandler;
 import org.apache.shardingsphere.mcp.core.completion.handler.MetadataCompletionHandler;
 import org.apache.shardingsphere.mcp.core.completion.handler.WorkflowPlanIdCompletionHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.execute.ExecuteExplainToolHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.execute.ExecuteQueryToolHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.execute.ExecuteUpdateToolHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.metadata.SearchMetadataToolHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.metadata.ValidateRuntimeDatabaseToolHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.workflow.WorkflowExecutionToolHandler;
+import org.apache.shardingsphere.mcp.core.tool.handler.workflow.WorkflowValidationToolHandler;
+import org.apache.shardingsphere.mcp.core.workflow.WorkflowRuntimeDefinitionRegistry;
 
 import java.util.Collection;
 import java.util.List;
@@ -39,7 +47,15 @@ public final class CoreHandlerProvider implements MCPHandlerProvider {
     
     @Override
     public Collection<MCPToolHandler<?>> getToolHandlers() {
-        return CoreToolHandlers.createHandlers();
+        WorkflowRuntimeDefinitionRegistry workflowRuntimeDefinitionRegistry = WorkflowRuntimeDefinitionRegistry.load();
+        return List.of(
+                new SearchMetadataToolHandler(),
+                new ValidateRuntimeDatabaseToolHandler(),
+                new ExecuteQueryToolHandler(),
+                new ExecuteExplainToolHandler(),
+                new ExecuteUpdateToolHandler(),
+                new WorkflowExecutionToolHandler(workflowRuntimeDefinitionRegistry),
+                new WorkflowValidationToolHandler(workflowRuntimeDefinitionRegistry));
     }
     
     @Override
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreToolHandlers.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreToolHandlers.java
deleted file mode 100644
index 9e1b14712be..00000000000
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/handler/core/CoreToolHandlers.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.core.handler.core;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.mcp.api.capability.tool.MCPToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.execute.ExecuteExplainToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.execute.ExecuteQueryToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.execute.ExecuteUpdateToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.metadata.SearchMetadataToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.metadata.ValidateRuntimeDatabaseToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.workflow.WorkflowExecutionToolHandler;
-import org.apache.shardingsphere.mcp.core.tool.handler.workflow.WorkflowValidationToolHandler;
-import org.apache.shardingsphere.mcp.core.workflow.WorkflowRuntimeDefinitionRegistry;
-
-import java.util.Collection;
-import java.util.List;
-
-/**
- * Core tool handlers.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-final class CoreToolHandlers {
-    
-    static Collection<MCPToolHandler<?>> createHandlers() {
-        WorkflowRuntimeDefinitionRegistry workflowRuntimeDefinitionRegistry = WorkflowRuntimeDefinitionRegistry.load();
-        return List.of(
-                new SearchMetadataToolHandler(),
-                new ValidateRuntimeDatabaseToolHandler(),
-                new ExecuteQueryToolHandler(),
-                new ExecuteExplainToolHandler(),
-                new ExecuteUpdateToolHandler(),
-                new WorkflowExecutionToolHandler(workflowRuntimeDefinitionRegistry),
-                new WorkflowValidationToolHandler(workflowRuntimeDefinitionRegistry));
-    }
-}
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/MCPResourceDefinition.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/MCPResourceDefinition.java
deleted file mode 100644
index e65c5f3c5a7..00000000000
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/MCPResourceDefinition.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.core.resource.handler;
-
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.mcp.api.capability.resource.MCPResourceHandler;
-import org.apache.shardingsphere.mcp.api.capability.resource.MCPResourceDescriptor;
-import org.apache.shardingsphere.mcp.core.resource.uri.MCPUriPattern;
-
-/**
- * MCP resource definition.
- */
-@RequiredArgsConstructor
-@Getter
-final class MCPResourceDefinition {
-    
-    private final MCPUriPattern uriPattern;
-    
-    private final MCPResourceDescriptor descriptor;
-    
-    private final MCPResourceHandler<?> handler;
-}
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/ResourceDefinitionRegistry.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/ResourceDefinitionRegistry.java
index eb23625b573..14213fb6c35 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/ResourceDefinitionRegistry.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/resource/handler/ResourceDefinitionRegistry.java
@@ -47,7 +47,7 @@ import java.util.Optional;
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
 public final class ResourceDefinitionRegistry {
     
-    private static final List<MCPResourceDefinition> REGISTERED_RESOURCE_DEFINITIONS;
+    private static final List<ResourceDefinition> REGISTERED_RESOURCE_DEFINITIONS;
     
     static {
         Map<MCPUriPattern, MCPResourceHandler<?>> resourceHandlers = createRegisteredResourceHandlers(
@@ -91,12 +91,9 @@ public final class ResourceDefinitionRegistry {
         }
     }
     
-    private static List<MCPResourceDefinition> createRegisteredResourceDefinitions(final Map<MCPUriPattern, MCPResourceHandler<?>> handlers) {
-        return handlers.entrySet().stream().map(entry -> createResourceDefinition(entry.getKey(), entry.getValue())).toList();
-    }
-    
-    private static MCPResourceDefinition createResourceDefinition(final MCPUriPattern uriPattern, final MCPResourceHandler<?> handler) {
-        return new MCPResourceDefinition(uriPattern, MCPDescriptorCatalogIndex.getRequiredResourceDescriptor(handler.getResourceUriTemplate()), handler);
+    private static List<ResourceDefinition> createRegisteredResourceDefinitions(final Map<MCPUriPattern, MCPResourceHandler<?>> handlers) {
+        return handlers.entrySet().stream().map(entry -> new ResourceDefinition(entry.getKey(),
+                MCPDescriptorCatalogIndex.getRequiredResourceDescriptor(entry.getValue().getResourceUriTemplate()), entry.getValue())).toList();
     }
     
     private static void validateRegisteredResourceDescriptors() {
@@ -107,8 +104,8 @@ public final class ResourceDefinitionRegistry {
     }
     
     private static boolean isRegisteredResourceDescriptor(final MCPResourceDescriptor descriptor) {
-        for (MCPResourceDefinition each : REGISTERED_RESOURCE_DEFINITIONS) {
-            if (descriptor.getUriTemplate().equals(each.getUriPattern().getPattern())) {
+        for (ResourceDefinition each : REGISTERED_RESOURCE_DEFINITIONS) {
+            if (descriptor.getUriTemplate().equals(each.uriPattern().getPattern())) {
                 return true;
             }
         }
@@ -123,19 +120,15 @@ public final class ResourceDefinitionRegistry {
      * @return handled payload
      */
     public static Optional<MCPSuccessPayload> dispatch(final MCPFeatureRuntimeRequestContext requestContext, final String resourceUri) {
-        for (MCPResourceDefinition each : REGISTERED_RESOURCE_DEFINITIONS) {
-            Optional<MCPResourceURIVariables> matchedUriVariables = each.getUriPattern().parse(resourceUri);
+        for (ResourceDefinition each : REGISTERED_RESOURCE_DEFINITIONS) {
+            Optional<MCPResourceURIVariables> matchedUriVariables = each.uriPattern().parse(resourceUri);
             if (matchedUriVariables.isPresent()) {
-                return Optional.of(dispatch(requestContext, each, matchedUriVariables.get()));
+                return Optional.of(dispatch(requestContext, each.handler(), matchedUriVariables.get()));
             }
         }
         return Optional.empty();
     }
     
-    private static MCPSuccessPayload dispatch(final MCPFeatureRuntimeRequestContext requestContext, final MCPResourceDefinition resourceDefinition, final MCPResourceURIVariables uriVariables) {
-        return dispatch(requestContext, resourceDefinition.getHandler(), uriVariables);
-    }
-    
     private static <T extends MCPRequestContext> MCPSuccessPayload dispatch(final MCPFeatureRuntimeRequestContext requestContext, final MCPResourceHandler<T> resourceHandler,
                                                                             final MCPResourceURIVariables uriVariables) {
         return resourceHandler.handle(resourceHandler.getContextType().cast(requestContext), uriVariables);
@@ -147,6 +140,9 @@ public final class ResourceDefinitionRegistry {
      * @return supported resource descriptors
      */
     public static Collection<MCPResourceDescriptor> getSupportedResourceDescriptors() {
-        return REGISTERED_RESOURCE_DEFINITIONS.stream().map(MCPResourceDefinition::getDescriptor).toList();
+        return REGISTERED_RESOURCE_DEFINITIONS.stream().map(ResourceDefinition::descriptor).toList();
+    }
+    
+    private record ResourceDefinition(MCPUriPattern uriPattern, MCPResourceDescriptor descriptor, MCPResourceHandler<?> handler) {
     }
 }
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandler.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandler.java
index c5f2685f3c1..360733132eb 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandler.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandler.java
@@ -73,7 +73,7 @@ public final class WorkflowExecutionToolHandler implements MCPToolHandler<MCPFea
         WorkflowContextSnapshot snapshot = workflowSessionContext.getRequired(toolArguments.getStringArgument(WorkflowFieldNames.PLAN_ID));
         WorkflowRuntimeDefinition workflowRuntimeDefinition = workflowRuntimeDefinitionRegistry.getRequired(snapshot);
         return new MCPMapPayload(executionService.apply(workflowSessionContext, requestContext.getMetadataQueryFacade(), requestContext.getQueryFacade(),
-                requestContext.getExecutionFacade(), workflowRuntimeDefinition.getApplySynchronizationHandler(), workflowRuntimeDefinition.getApplyArtifactValidator(),
+                requestContext.getExecutionFacade(), workflowRuntimeDefinition.getRuntimeHandler(), workflowRuntimeDefinition.getApplyArtifactValidator(),
                 requestContext.getSessionIdentity().getSessionId(),
                 snapshot, toolArguments.getStringCollectionArgument(WorkflowFieldNames.APPROVED_STEPS), executionMode));
     }
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandler.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandler.java
index da5ebc5d346..1090629680b 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandler.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandler.java
@@ -54,7 +54,7 @@ public final class WorkflowValidationToolHandler implements MCPToolHandler<MCPFe
         MCPToolArguments toolArguments = new MCPToolArguments(arguments);
         WorkflowSessionContext workflowSessionContext = requestContext.getWorkflowSessionContext();
         WorkflowContextSnapshot snapshot = workflowSessionContext.getRequired(toolArguments.getStringArgument(WorkflowFieldNames.PLAN_ID));
-        return new MCPMapPayload(workflowRuntimeDefinitionRegistry.getRequired(snapshot).getValidationHandler().validate(workflowSessionContext,
+        return new MCPMapPayload(workflowRuntimeDefinitionRegistry.getRequired(snapshot).getRuntimeHandler().validate(workflowSessionContext,
                 requestContext.getMetadataQueryFacade(), requestContext.getQueryFacade(), requestContext.getExecutionFacade(), requestContext.getSessionIdentity().getSessionId(), snapshot));
     }
     
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowApplyOutcome.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowApplyOutcome.java
index b371565cffa..8072e46dffc 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowApplyOutcome.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowApplyOutcome.java
@@ -32,7 +32,7 @@ import java.util.Map;
 /**
  * Mutable outcome collected while applying workflow artifacts.
  */
-public final class WorkflowApplyOutcome {
+final class WorkflowApplyOutcome {
     
     private final List<Map<String, Object>> stepResults = new LinkedList<>();
     
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionService.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionService.java
index fece5edf28c..1079e188e8f 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionService.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionService.java
@@ -28,7 +28,6 @@ import org.apache.shardingsphere.mcp.support.database.tool.request.SQLExecutionR
 import org.apache.shardingsphere.mcp.support.protocol.MCPNextActionUtils;
 import org.apache.shardingsphere.mcp.support.protocol.MCPPayloadFieldNames;
 import org.apache.shardingsphere.mcp.support.protocol.MCPResponseMode;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.WorkflowSessionContext;
 import org.apache.shardingsphere.mcp.support.workflow.descriptor.WorkflowToolDescriptors;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
@@ -36,6 +35,7 @@ import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowIssue;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowIssueCode;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowLifecycle;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowArtifactBundle;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowArtifactMaskUtils;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowArtifactPayloadUtils;
@@ -44,7 +44,7 @@ import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowLifecycleU
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSecretReferenceUtils;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSynchronizationException;
 import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplyArtifactValidator;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplySynchronizationHandler;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowRuntimeHandler;
 
 import java.util.List;
 import java.util.Locale;
@@ -67,7 +67,7 @@ public final class WorkflowExecutionService {
      * @param metadataQueryFacade metadata query facade
      * @param queryFacade query facade
      * @param executionFacade execution facade
-     * @param workflowApplySynchronizationHandler workflow apply synchronization handler
+     * @param workflowRuntimeHandler workflow runtime handler
      * @param workflowApplyArtifactValidator workflow apply artifact validator
      * @param sessionId session id
      * @param snapshot workflow snapshot
@@ -76,7 +76,7 @@ public final class WorkflowExecutionService {
      * @return apply payload
      */
     public Map<String, Object> apply(final WorkflowSessionContext workflowSessionContext, final MCPMetadataQueryFacade metadataQueryFacade, final MCPFeatureQueryFacade queryFacade,
-                                     final MCPFeatureExecutionFacade executionFacade, final MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler,
+                                     final MCPFeatureExecutionFacade executionFacade, final MCPWorkflowRuntimeHandler workflowRuntimeHandler,
                                      final MCPWorkflowApplyArtifactValidator workflowApplyArtifactValidator, final String sessionId, final WorkflowContextSnapshot snapshot,
                                      final List<String> approvedSteps, final String executionMode) {
         String actualExecutionMode = requireExecutionMode(snapshot, executionMode);
@@ -96,7 +96,7 @@ public final class WorkflowExecutionService {
         if (isManualOnly(actualExecutionMode)) {
             return applyManualOnly(workflowSessionContext, snapshot, applyOutcome);
         }
-        return applyAutomatically(workflowSessionContext, metadataQueryFacade, queryFacade, executionFacade, workflowApplySynchronizationHandler, sessionId, snapshot,
+        return applyAutomatically(workflowSessionContext, metadataQueryFacade, queryFacade, executionFacade, workflowRuntimeHandler, sessionId, snapshot,
                 actualExecutionMode, applyOutcome);
     }
     
@@ -225,10 +225,10 @@ public final class WorkflowExecutionService {
     
     private Map<String, Object> applyAutomatically(final WorkflowSessionContext workflowSessionContext, final MCPMetadataQueryFacade metadataQueryFacade,
                                                    final MCPFeatureQueryFacade queryFacade, final MCPFeatureExecutionFacade executionFacade,
-                                                   final MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler,
+                                                   final MCPWorkflowRuntimeHandler workflowRuntimeHandler,
                                                    final String sessionId, final WorkflowContextSnapshot snapshot, final String executionMode,
                                                    final WorkflowApplyOutcome applyOutcome) {
-        if (WorkflowSecretReferenceUtils.hasSecretReferences(getPropertySource(snapshot))) {
+        if (WorkflowSecretReferenceUtils.hasSecretReferences(getRequest(snapshot))) {
             return failSecretReferenceManualExecutionRequired(workflowSessionContext, snapshot, executionMode, applyOutcome);
         }
         String currentArtifactDisplaySql = "";
@@ -238,7 +238,7 @@ public final class WorkflowExecutionService {
                 executeArtifact(executionFacade, sessionId, snapshot, each);
                 applyOutcome.addExecutedArtifact(each);
             }
-            workflowApplySynchronizationHandler.synchronize(snapshot, metadataQueryFacade, queryFacade, executionFacade, sessionId);
+            workflowRuntimeHandler.synchronize(snapshot, metadataQueryFacade, queryFacade, executionFacade, sessionId);
             return completeApply(workflowSessionContext, snapshot, executionMode, applyOutcome);
         } catch (final WorkflowSynchronizationException ex) {
             return failApplySynchronization(workflowSessionContext, snapshot, executionMode, applyOutcome, ex);
@@ -259,15 +259,15 @@ public final class WorkflowExecutionService {
                                           final WorkflowApplyOutcome applyOutcome, final String artifactSql, final RuntimeException ex) {
         persistSnapshot(workflowSessionContext, snapshot, WorkflowLifecycle.STEP_FAILED, WorkflowLifecycle.STATUS_FAILED);
         applyOutcome.addFailedArtifact(artifactSql, WorkflowArtifactMaskUtils.maskSensitiveSql(
-                null == ex.getMessage() ? "" : ex.getMessage(), getPropertySource(snapshot), snapshot.getPropertyRequirements()));
+                null == ex.getMessage() ? "" : ex.getMessage(), getRequest(snapshot), snapshot.getPropertyRequirements()));
         return applyOutcome.createResponse(WorkflowLifecycle.STATUS_FAILED, snapshot, executionMode, Map.of());
     }
     
     private Map<String, Object> failSecretReferenceManualExecutionRequired(final WorkflowSessionContext workflowSessionContext, final WorkflowContextSnapshot snapshot,
                                                                            final String executionMode, final WorkflowApplyOutcome applyOutcome) {
         persistSnapshot(workflowSessionContext, snapshot, WorkflowLifecycle.STEP_FAILED, WorkflowLifecycle.STATUS_FAILED);
-        WorkflowPropertySource propertySource = getPropertySource(snapshot);
-        String category = WorkflowSecretReferenceUtils.hasMalformedSecretReferences(propertySource)
+        WorkflowRequest request = getRequest(snapshot);
+        String category = WorkflowSecretReferenceUtils.hasMalformedSecretReferences(request)
                 ? MCPDiagnosticCategory.SECRET_REFERENCE_MALFORMED
                 : MCPDiagnosticCategory.SECRET_REFERENCE_MANUAL_EXECUTION_REQUIRED;
         applyOutcome.addSecretReferenceManualExecutionRequired();
@@ -275,7 +275,7 @@ public final class WorkflowExecutionService {
         result.put("response_mode", MCPResponseMode.RECOVERY);
         result.put("category", category);
         result.put(MCPPayloadFieldNames.SUMMARY, "This workflow contains sensitive placeholders that must be filled outside MCP before execution.");
-        result.put("secret_reference_summary", WorkflowArtifactMaskUtils.createSecretReferenceSummary(propertySource));
+        result.put("secret_reference_summary", WorkflowArtifactMaskUtils.createSecretReferenceSummary(request));
         WorkflowGuidancePayloadBuilder.appendApplyGuidance(result, WorkflowLifecycle.STATUS_FAILED);
         return result;
     }
@@ -295,18 +295,17 @@ public final class WorkflowExecutionService {
         workflowSessionContext.save(snapshot);
     }
     
-    private WorkflowPropertySource getPropertySource(final WorkflowContextSnapshot snapshot) {
-        return null == snapshot.getRequest() ? algorithmRole -> Map.of() : snapshot.getRequest();
+    private WorkflowRequest getRequest(final WorkflowContextSnapshot snapshot) {
+        return null == snapshot.getRequest() ? new WorkflowRequest() : snapshot.getRequest();
     }
     
     private Map<String, Object> createArtifactPayload(final WorkflowContextSnapshot snapshot) {
-        return WorkflowArtifactPayloadUtils.createArtifactPayload(snapshot, getPropertySource(snapshot));
+        return WorkflowArtifactPayloadUtils.createArtifactPayload(snapshot, getRequest(snapshot));
     }
     
     private List<WorkflowArtifactBundle.ExecutableWorkflowArtifact> createExecutableArtifacts(final WorkflowContextSnapshot snapshot) {
         WorkflowArtifactBundle result = WorkflowArtifactBundle.from(snapshot);
-        WorkflowPropertySource propertySource = getPropertySource(snapshot);
-        return result.toExecutableArtifacts(propertySource, snapshot.getPropertyRequirements());
+        return result.toExecutableArtifacts(getRequest(snapshot), snapshot.getPropertyRequirements());
     }
     
     private void executeArtifact(final MCPFeatureExecutionFacade executionFacade, final String sessionId, final WorkflowContextSnapshot snapshot,
diff --git a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistry.java b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistry.java
index e1a0953d5c8..3af4c9ca9e2 100644
--- a/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistry.java
+++ b/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistry.java
@@ -51,10 +51,8 @@ public final class WorkflowRuntimeDefinitionRegistry {
             Objects.requireNonNull(each, "Workflow definition is required.");
             WorkflowKind workflowKind = Objects.requireNonNull(each.getWorkflowKind(),
                     () -> String.format("Workflow kind is required for `%s`.", each.getClass().getName()));
-            ShardingSpherePreconditions.checkNotNull(each.getValidationHandler(),
-                    () -> new IllegalArgumentException(String.format("Workflow validation handler is required for `%s`.", workflowKind.getValue())));
-            ShardingSpherePreconditions.checkNotNull(each.getApplySynchronizationHandler(),
-                    () -> new IllegalArgumentException(String.format("Workflow apply synchronization handler is required for `%s`.", workflowKind.getValue())));
+            ShardingSpherePreconditions.checkNotNull(each.getRuntimeHandler(),
+                    () -> new IllegalArgumentException(String.format("Workflow runtime handler is required for `%s`.", workflowKind.getValue())));
             ShardingSpherePreconditions.checkNotNull(each.getApplyArtifactValidator(),
                     () -> new IllegalArgumentException(String.format("Workflow apply artifact validator is required for `%s`.", workflowKind.getValue())));
             WorkflowRuntimeDefinition previousDefinition = result.putIfAbsent(workflowKind, each);
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/MetadataCompletionHandlerTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/MetadataCompletionHandlerTest.java
index 3a5b2cdd175..5a78d27709e 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/MetadataCompletionHandlerTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/MetadataCompletionHandlerTest.java
@@ -55,11 +55,6 @@ import static org.mockito.Mockito.when;
 
 class MetadataCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new MetadataCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @Test
     void assertSupports() {
         assertTrue(new MetadataCompletionHandler().supports(createRequestContext("database", Map.of())));
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/WorkflowPlanIdCompletionHandlerTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/WorkflowPlanIdCompletionHandlerTest.java
index 2794fb4e337..7210591deea 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/WorkflowPlanIdCompletionHandlerTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/completion/handler/WorkflowPlanIdCompletionHandlerTest.java
@@ -41,11 +41,6 @@ import static org.mockito.Mockito.when;
 
 class WorkflowPlanIdCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new WorkflowPlanIdCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @Test
     void assertSupports() {
         assertTrue(new WorkflowPlanIdCompletionHandler().supports(createRequestContext()));
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/capability/ServerCapabilitiesHandlerTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/capability/ServerCapabilitiesHandlerTest.java
index ded8794e8b8..cc98e0a14ed 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/capability/ServerCapabilitiesHandlerTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/capability/ServerCapabilitiesHandlerTest.java
@@ -137,11 +137,7 @@ class ServerCapabilitiesHandlerTest {
         assertTrue(actual.containsKey("http_transport"));
         assertTrue(actual.containsKey("origin_header"));
         assertTrue(actual.containsKey("stdio_stdout"));
-        Map<?, ?> actualClientSafetyPolicy = (Map<?, ?>) actual.get("client_safety_policy");
-        assertThat(actualClientSafetyPolicy.get("identity_scope"), is("mcp_session"));
-        assertTrue(String.valueOf(actualClientSafetyPolicy.get("transport_scope")).contains("trusted session attribution"));
-        assertThat(((Map<?, ?>) ((Map<?, ?>) actualClientSafetyPolicy.get("runtime_protection")).get("tool_call_limit")).get("scope"), is("session"));
-        assertTrue(String.valueOf(actualClientSafetyPolicy.get("abuse_guard")).contains("counted before dispatch"));
+        assertTrue(actual.containsKey("client_safety_policy"));
     }
     
     private Map<?, ?> findByKey(final List<?> values, final String key, final String expectedValue) {
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
index ebc15274fc0..4e4c2cc11a3 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/handler/metadata/MetadataResourceHandlerTest.java
@@ -21,12 +21,10 @@ import org.apache.shardingsphere.database.connector.core.metadata.identifier.Ide
 import org.apache.shardingsphere.infra.metadata.identifier.DatabaseIdentifierContext;
 import org.apache.shardingsphere.mcp.api.payload.MCPSuccessPayload;
 import org.apache.shardingsphere.mcp.api.capability.resource.MCPResourceURIVariables;
-import org.apache.shardingsphere.mcp.api.capability.resource.MCPResourceDescriptor;
 import org.apache.shardingsphere.mcp.support.MCPFeatureRequestContext;
 import org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseProfile;
 import org.apache.shardingsphere.mcp.support.database.metadata.TransactionCapability;
 import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureCapabilityFacade;
-import org.apache.shardingsphere.mcp.support.descriptor.MCPDescriptorCatalogIndex;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
@@ -41,14 +39,6 @@ import static org.mockito.Mockito.when;
 
 class MetadataResourceHandlerTest {
     
-    @Test
-    void assertGetResourceDescriptor() {
-        MetadataResourceHandler handler = new MetadataResourceHandler("shardingsphere://databases", (requestContext, uriVariables) -> List.of());
-        MCPResourceDescriptor actual = MCPDescriptorCatalogIndex.getRequiredResourceDescriptor(handler.getResourceUriTemplate());
-        assertThat(actual.getUriTemplate(), is("shardingsphere://databases"));
-        assertThat(actual.getTitle(), is("Logical Databases"));
-    }
-    
     @Test
     void assertHandleListResource() {
         MetadataResourceHandler handler = new MetadataResourceHandler("shardingsphere://databases",
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/uri/MCPUriPatternTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/uri/MCPUriPatternTest.java
index 21b619e8760..4b1a64dadf9 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/uri/MCPUriPatternTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/resource/uri/MCPUriPatternTest.java
@@ -30,12 +30,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class MCPUriPatternTest {
     
-    @Test
-    void assertGetPattern() {
-        MCPUriPattern actual = new MCPUriPattern("shardingsphere://capabilities");
-        assertThat(actual.getPattern(), is("shardingsphere://capabilities"));
-    }
-    
     @Test
     void assertCreateWithUnsupportedScheme() {
         assertThrows(IllegalArgumentException.class, () -> new MCPUriPattern("unsupported://capabilities"));
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandlerTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandlerTest.java
index ad0b1206aec..2ea0843d0bf 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandlerTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowExecutionToolHandlerTest.java
@@ -25,8 +25,7 @@ import org.apache.shardingsphere.mcp.core.workflow.WorkflowRuntimeDefinitionRegi
 import org.apache.shardingsphere.mcp.support.descriptor.MCPDescriptorCatalogIndex;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
 import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplyArtifactValidator;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplySynchronizationHandler;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowValidationHandler;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowRuntimeHandler;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
 import org.junit.jupiter.api.Test;
 import org.mockito.MockedConstruction;
@@ -57,18 +56,18 @@ class WorkflowExecutionToolHandlerTest {
     void assertHandleExecution() {
         WorkflowContextSnapshot snapshot = WorkflowHandlerTestFixture.createSnapshot();
         WorkflowHandlerTestFixture.Context fixture = WorkflowHandlerTestFixture.createContext(snapshot);
-        MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler = mock(MCPWorkflowApplySynchronizationHandler.class);
+        MCPWorkflowRuntimeHandler workflowRuntimeHandler = mock(MCPWorkflowRuntimeHandler.class);
         MCPWorkflowApplyArtifactValidator workflowApplyArtifactValidator = mock(MCPWorkflowApplyArtifactValidator.class);
         try (
                 MockedConstruction<WorkflowExecutionService> mockedExecutionServices = mockConstruction(WorkflowExecutionService.class,
                         (mock, context) -> when(mock.apply(any(), any(), any(), any(), any(), any(), any(), any(), any(), any())).thenReturn(Map.of("status", "completed")))) {
             WorkflowExecutionToolHandler handler = new WorkflowExecutionToolHandler(new WorkflowRuntimeDefinitionRegistry(List.of(
-                    WorkflowHandlerTestFixture.createDefinition("encrypt.rule", mock(MCPWorkflowValidationHandler.class), workflowApplySynchronizationHandler, workflowApplyArtifactValidator))));
+                    WorkflowHandlerTestFixture.createDefinition("encrypt.rule", workflowRuntimeHandler, workflowApplyArtifactValidator))));
             MCPSuccessPayload actual = handler.handle(fixture.requestContext(), Map.of(WorkflowFieldNames.PLAN_ID, "plan-1",
                     WorkflowFieldNames.APPROVED_STEPS, List.of("rule_distsql"), WorkflowFieldNames.EXECUTION_MODE, "manual-only"));
             WorkflowExecutionService executionService = mockedExecutionServices.constructed().getFirst();
             verify(executionService).apply(eq(fixture.workflowSessionContext()), eq(fixture.metadataQueryFacade()), eq(fixture.queryFacade()), eq(fixture.executionFacade()),
-                    eq(workflowApplySynchronizationHandler), eq(workflowApplyArtifactValidator), eq("session-1"), eq(snapshot), eq(List.of("rule_distsql")), eq("manual-only"));
+                    eq(workflowRuntimeHandler), eq(workflowApplyArtifactValidator), eq("session-1"), eq(snapshot), eq(List.of("rule_distsql")), eq("manual-only"));
             assertThat(actual.toPayload().get("status"), is("completed"));
         }
     }
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowHandlerTestFixture.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowHandlerTestFixture.java
index 7089a5120db..c9e015c126e 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowHandlerTestFixture.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowHandlerTestFixture.java
@@ -28,8 +28,7 @@ import org.apache.shardingsphere.mcp.support.workflow.WorkflowSessionContext;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowKind;
 import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplyArtifactValidator;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplySynchronizationHandler;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowValidationHandler;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowRuntimeHandler;
 import org.apache.shardingsphere.mcp.support.workflow.spi.WorkflowRuntimeDefinition;
 
 import java.util.Map;
@@ -69,20 +68,12 @@ final class WorkflowHandlerTestFixture {
     }
     
     static WorkflowRuntimeDefinition createDefinition(final String workflowKind) {
-        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), (workflowSessionContext, metadataQueryFacade, queryFacade, executionFacade, sessionId, snapshot) -> Map.of(),
-                (snapshot, metadataQueryFacade, queryFacade, executionFacade, sessionId) -> {
-                }, MCPWorkflowApplyArtifactValidator.NO_OP);
+        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), mock(MCPWorkflowRuntimeHandler.class));
     }
     
-    static WorkflowRuntimeDefinition createDefinition(final String workflowKind, final MCPWorkflowValidationHandler validationHandler,
-                                                      final MCPWorkflowApplySynchronizationHandler applySynchronizationHandler) {
-        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), validationHandler, applySynchronizationHandler, MCPWorkflowApplyArtifactValidator.NO_OP);
-    }
-    
-    static WorkflowRuntimeDefinition createDefinition(final String workflowKind, final MCPWorkflowValidationHandler validationHandler,
-                                                      final MCPWorkflowApplySynchronizationHandler applySynchronizationHandler,
+    static WorkflowRuntimeDefinition createDefinition(final String workflowKind, final MCPWorkflowRuntimeHandler runtimeHandler,
                                                       final MCPWorkflowApplyArtifactValidator applyArtifactValidator) {
-        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), validationHandler, applySynchronizationHandler, applyArtifactValidator);
+        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), runtimeHandler, applyArtifactValidator);
     }
     
     record Context(MCPFeatureRequestContext requestContext, WorkflowSessionContext workflowSessionContext,
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandlerTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandlerTest.java
index 21547a0341b..b715cf26a4c 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandlerTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/workflow/WorkflowValidationToolHandlerTest.java
@@ -22,8 +22,8 @@ import org.apache.shardingsphere.mcp.api.capability.tool.MCPToolDescriptor;
 import org.apache.shardingsphere.mcp.core.workflow.WorkflowRuntimeDefinitionRegistry;
 import org.apache.shardingsphere.mcp.support.descriptor.MCPDescriptorCatalogIndex;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplySynchronizationHandler;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowValidationHandler;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplyArtifactValidator;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowRuntimeHandler;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
@@ -48,14 +48,14 @@ class WorkflowValidationToolHandlerTest {
     
     @Test
     void assertHandle() {
-        MCPWorkflowValidationHandler workflowValidationHandler = mock(MCPWorkflowValidationHandler.class);
-        when(workflowValidationHandler.validate(any(), any(), any(), any(), any(), any())).thenReturn(Map.of("status", "validated"));
+        MCPWorkflowRuntimeHandler workflowRuntimeHandler = mock(MCPWorkflowRuntimeHandler.class);
+        when(workflowRuntimeHandler.validate(any(), any(), any(), any(), any(), any())).thenReturn(Map.of("status", "validated"));
         WorkflowContextSnapshot snapshot = WorkflowHandlerTestFixture.createSnapshot();
         WorkflowHandlerTestFixture.Context fixture = WorkflowHandlerTestFixture.createContext(snapshot);
         WorkflowValidationToolHandler handler = new WorkflowValidationToolHandler(new WorkflowRuntimeDefinitionRegistry(List.of(
-                WorkflowHandlerTestFixture.createDefinition("encrypt.rule", workflowValidationHandler, mock(MCPWorkflowApplySynchronizationHandler.class)))));
+                WorkflowHandlerTestFixture.createDefinition("encrypt.rule", workflowRuntimeHandler, MCPWorkflowApplyArtifactValidator.NO_OP))));
         MCPSuccessPayload actual = handler.handle(fixture.requestContext(), Map.of("plan_id", "plan-1"));
-        verify(workflowValidationHandler).validate(eq(fixture.workflowSessionContext()), eq(fixture.metadataQueryFacade()),
+        verify(workflowRuntimeHandler).validate(eq(fixture.workflowSessionContext()), eq(fixture.metadataQueryFacade()),
                 eq(fixture.queryFacade()), eq(fixture.executionFacade()), eq("session-1"), eq(snapshot));
         assertThat(actual.toPayload().get("status"), is("validated"));
     }
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionServiceTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionServiceTest.java
index cb110192ae8..86b25bc51f7 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionServiceTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowExecutionServiceTest.java
@@ -35,7 +35,7 @@ import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowKind;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSynchronizationException;
 import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplyArtifactValidator;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplySynchronizationHandler;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowRuntimeHandler;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
@@ -56,9 +56,20 @@ import static org.mockito.Mockito.when;
 
 class WorkflowExecutionServiceTest {
     
-    private static final MCPWorkflowApplySynchronizationHandler NO_OP_APPLY_SYNCHRONIZATION_HANDLER =
-            (snapshot, metadataQueryFacade, queryFacade, executionFacade, sessionId) -> {
-            };
+    private static final MCPWorkflowRuntimeHandler NO_OP_RUNTIME_HANDLER = new MCPWorkflowRuntimeHandler() {
+        
+        @Override
+        public Map<String, Object> validate(final WorkflowSessionContext workflowSessionContext, final MCPMetadataQueryFacade metadataQueryFacade,
+                                            final MCPFeatureQueryFacade queryFacade, final MCPFeatureExecutionFacade executionFacade,
+                                            final String sessionId, final WorkflowContextSnapshot snapshot) {
+            return Map.of();
+        }
+        
+        @Override
+        public void synchronize(final WorkflowContextSnapshot snapshot, final MCPMetadataQueryFacade metadataQueryFacade,
+                                final MCPFeatureQueryFacade queryFacade, final MCPFeatureExecutionFacade executionFacade, final String sessionId) {
+        }
+    };
     
     @Test
     void assertApplyMasksManualArtifactPackage() {
@@ -91,7 +102,7 @@ class WorkflowExecutionServiceTest {
         workflowSessionContext.save(createSnapshot());
         WorkflowExecutionService executionService = new WorkflowExecutionService();
         Map<String, Object> actualResponse = executionService.apply(workflowSessionContext, mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class),
-                mock(MCPFeatureExecutionFacade.class), NO_OP_APPLY_SYNCHRONIZATION_HANDLER, MCPWorkflowApplyArtifactValidator.NO_OP,
+                mock(MCPFeatureExecutionFacade.class), NO_OP_RUNTIME_HANDLER, MCPWorkflowApplyArtifactValidator.NO_OP,
                 "session-2", workflowSessionContext.getRequired("plan-1"), List.of(), "review-then-execute");
         assertThat(actualResponse.get("status"), is("failed"));
         assertThat(actualResponse.get("response_mode"), is("terminal"));
@@ -117,7 +128,7 @@ class WorkflowExecutionServiceTest {
         WorkflowExecutionService executionService = new WorkflowExecutionService();
         MCPInvalidRequestException actual = assertThrows(MCPInvalidRequestException.class,
                 () -> executionService.apply(new InMemoryWorkflowSessionStore().getSessionContext("session-1"),
-                        mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class), mock(MCPFeatureExecutionFacade.class), NO_OP_APPLY_SYNCHRONIZATION_HANDLER,
+                        mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class), mock(MCPFeatureExecutionFacade.class), NO_OP_RUNTIME_HANDLER,
                         MCPWorkflowApplyArtifactValidator.NO_OP, "session-1", createSnapshot(), List.of(), ""));
         assertThat(actual.getMessage(), is("database_gateway_apply_workflow execution_mode is required."));
     }
@@ -127,7 +138,7 @@ class WorkflowExecutionServiceTest {
         WorkflowExecutionService executionService = new WorkflowExecutionService();
         MCPInvalidRequestException actual = assertThrows(MCPInvalidRequestException.class,
                 () -> executionService.apply(new InMemoryWorkflowSessionStore().getSessionContext("session-1"),
-                        mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class), mock(MCPFeatureExecutionFacade.class), NO_OP_APPLY_SYNCHRONIZATION_HANDLER,
+                        mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class), mock(MCPFeatureExecutionFacade.class), NO_OP_RUNTIME_HANDLER,
                         MCPWorkflowApplyArtifactValidator.NO_OP, "session-1", createSnapshot(), List.of(), "auto-execute"));
         assertThat(actual.getMessage(), is("database_gateway_apply_workflow execution_mode must be one of [preview, review-then-execute, manual-only]."));
     }
@@ -137,7 +148,7 @@ class WorkflowExecutionServiceTest {
         WorkflowExecutionService executionService = new WorkflowExecutionService();
         MCPInvalidRequestException actual = assertThrows(MCPInvalidRequestException.class,
                 () -> executionService.apply(new InMemoryWorkflowSessionStore().getSessionContext("session-1"),
-                        mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class), mock(MCPFeatureExecutionFacade.class), NO_OP_APPLY_SYNCHRONIZATION_HANDLER,
+                        mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class), mock(MCPFeatureExecutionFacade.class), NO_OP_RUNTIME_HANDLER,
                         MCPWorkflowApplyArtifactValidator.NO_OP, "session-1", createSnapshot(), List.of("review"), "review-then-execute"));
         assertThat(actual.getMessage(), is("approved_steps must contain only [rule_distsql]."));
     }
@@ -149,7 +160,7 @@ class WorkflowExecutionServiceTest {
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE MASK RULE orders"));
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
         when(executionFacade.execute(any())).thenReturn(mock(SQLExecutionResult.class));
-        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER, List.of(), "review-then-execute");
+        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_RUNTIME_HANDLER, List.of(), "review-then-execute");
         assertThat(actualResponse.get("status"), is("failed"));
         assertThat(((Map<?, ?>) ((List<?>) actualResponse.get("issues")).getFirst()).get("code"), is(WorkflowIssueCode.WORKFLOW_STATUS_INVALID));
         verify(executionFacade, never()).execute(any());
@@ -160,7 +171,7 @@ class WorkflowExecutionServiceTest {
         WorkflowContextSnapshot snapshot = createSnapshot();
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE MASK RULE orders"));
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
-        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER, List.of("rule_distsql"), "review-then-execute");
+        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_RUNTIME_HANDLER, List.of("rule_distsql"), "review-then-execute");
         assertThat(actualResponse.get("status"), is("failed"));
         assertThat(((Map<?, ?>) ((List<?>) actualResponse.get("issues")).getFirst()).get("code"), is(WorkflowIssueCode.WORKFLOW_STATUS_INVALID));
         verify(executionFacade, never()).execute(any());
@@ -171,7 +182,7 @@ class WorkflowExecutionServiceTest {
         WorkflowContextSnapshot snapshot = createSnapshot();
         snapshot.setStatus("previewed");
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
-        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER,
+        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_RUNTIME_HANDLER,
                 List.of("rule_distsql"), "review-then-execute");
         assertThat(actualResponse.get("status"), is("failed"));
         assertThat(((Map<?, ?>) ((List<?>) actualResponse.get("issues")).getFirst()).get("code"), is(WorkflowIssueCode.WORKFLOW_STATUS_INVALID));
@@ -185,8 +196,8 @@ class WorkflowExecutionServiceTest {
         snapshot.getRuleArtifacts().add(new RuleArtifact("alter", "ALTER MASK RULE orders"));
         WorkflowSessionContext workflowSessionContext = createWorkflowSessionContext(snapshot);
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
-        MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler = mock(MCPWorkflowApplySynchronizationHandler.class);
-        Map<String, Object> actualResponse = apply(workflowSessionContext, snapshot, executionFacade, workflowApplySynchronizationHandler, List.of(), "preview");
+        MCPWorkflowRuntimeHandler workflowRuntimeHandler = mock(MCPWorkflowRuntimeHandler.class);
+        Map<String, Object> actualResponse = apply(workflowSessionContext, snapshot, executionFacade, workflowRuntimeHandler, List.of(), "preview");
         assertThat(actualResponse.get("status"), is("preview"));
         assertThat(actualResponse.get("response_mode"), is("preview"));
         assertFalse((boolean) actualResponse.get("would_apply"));
@@ -212,7 +223,7 @@ class WorkflowExecutionServiceTest {
         assertThat(((Map<?, ?>) actualResponse.get("argument_provenance")).get("execution_mode"), is("server_defaulted"));
         assertThat(workflowSessionContext.getRequired("plan-1").getStatus(), is("previewed"));
         verify(executionFacade, never()).execute(any());
-        verify(workflowApplySynchronizationHandler, never()).synchronize(any(), any(), any(), any(), any());
+        verify(workflowRuntimeHandler, never()).synchronize(any(), any(), any(), any(), any());
     }
     
     @Test
@@ -245,7 +256,7 @@ class WorkflowExecutionServiceTest {
         workflowSessionContext.save(snapshot);
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
         Map<String, Object> actualResponse = new WorkflowExecutionService().apply(workflowSessionContext, mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class),
-                executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER,
+                executionFacade, NO_OP_RUNTIME_HANDLER,
                 (workflowSnapshot, artifacts) -> List.of(new WorkflowIssue(WorkflowIssueCode.SQL_EXECUTABILITY_FAILED, "error", "review",
                         "Generated workflow artifact is invalid.", "Regenerate the workflow artifact before approval.", true,
                         Map.of("sql", artifacts.iterator().next().displaySql())).toMap()),
@@ -284,7 +295,7 @@ class WorkflowExecutionServiceTest {
         WorkflowSessionContext workflowSessionContext = createWorkflowSessionContext(snapshot);
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
         when(executionFacade.execute(any())).thenReturn(mock(SQLExecutionResult.class));
-        Map<String, Object> actualResponse = apply(workflowSessionContext, snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER,
+        Map<String, Object> actualResponse = apply(workflowSessionContext, snapshot, executionFacade, NO_OP_RUNTIME_HANDLER,
                 List.of("rule_distsql"), "review-then-execute");
         assertThat(actualResponse.get("status"), is("completed"));
         assertThat(actualResponse.get("response_mode"), is("executed"));
@@ -303,7 +314,7 @@ class WorkflowExecutionServiceTest {
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE ENCRYPT RULE orders (PROPERTIES('aes-key-value'='123456'))"));
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
         when(executionFacade.execute(any())).thenReturn(mock(SQLExecutionResult.class));
-        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER, List.of("rule_distsql"), "review-then-execute");
+        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_RUNTIME_HANDLER, List.of("rule_distsql"), "review-then-execute");
         assertThat(actualResponse.get("status"), is("completed"));
         assertThat(((Map<?, ?>) ((List<?>) actualResponse.get("step_results")).getFirst()).get("sql"),
                 is("CREATE ENCRYPT RULE orders (PROPERTIES('aes-key-value'='******'))"));
@@ -315,7 +326,7 @@ class WorkflowExecutionServiceTest {
     void assertApplyRequiresManualExecutionForSecretReference() {
         WorkflowContextSnapshot snapshot = createSecretReferenceSnapshot();
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
-        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER, List.of("rule_distsql"), "review-then-execute");
+        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_RUNTIME_HANDLER, List.of("rule_distsql"), "review-then-execute");
         assertThat(actualResponse.get("status"), is("failed"));
         assertThat(actualResponse.get("response_mode"), is("recovery"));
         assertThat(actualResponse.get("category"), is(MCPDiagnosticCategory.SECRET_REFERENCE_MANUAL_EXECUTION_REQUIRED));
@@ -337,10 +348,10 @@ class WorkflowExecutionServiceTest {
         WorkflowSessionContext workflowSessionContext = createWorkflowSessionContext(snapshot);
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
         when(executionFacade.execute(any())).thenReturn(mock(SQLExecutionResult.class));
-        MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler = mock(MCPWorkflowApplySynchronizationHandler.class);
+        MCPWorkflowRuntimeHandler workflowRuntimeHandler = mock(MCPWorkflowRuntimeHandler.class);
         doThrow(new WorkflowSynchronizationException(WorkflowIssueCode.RULE_STATE_MISMATCH, "Mask rule is missing.",
-                List.of(Map.of("code", WorkflowIssueCode.RULE_STATE_MISMATCH)))).when(workflowApplySynchronizationHandler).synchronize(any(), any(), any(), any(), any());
-        Map<String, Object> actualResponse = apply(workflowSessionContext, snapshot, executionFacade, workflowApplySynchronizationHandler,
+                List.of(Map.of("code", WorkflowIssueCode.RULE_STATE_MISMATCH)))).when(workflowRuntimeHandler).synchronize(any(), any(), any(), any(), any());
+        Map<String, Object> actualResponse = apply(workflowSessionContext, snapshot, executionFacade, workflowRuntimeHandler,
                 List.of("rule_distsql"), "review-then-execute");
         Map<?, ?> actualIssue = (Map<?, ?>) ((List<?>) actualResponse.get("issues")).getFirst();
         assertThat(actualResponse.get("status"), is("failed"));
@@ -357,7 +368,7 @@ class WorkflowExecutionServiceTest {
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE ENCRYPT RULE orders (PROPERTIES('aes-key-value'='123456'))"));
         MCPFeatureExecutionFacade executionFacade = mock(MCPFeatureExecutionFacade.class);
         when(executionFacade.execute(any())).thenThrow(new IllegalStateException("Failed to execute CREATE ENCRYPT RULE orders (PROPERTIES('aes-key-value'='123456'))"));
-        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_APPLY_SYNCHRONIZATION_HANDLER, List.of("rule_distsql"), "review-then-execute");
+        Map<String, Object> actualResponse = apply(snapshot, executionFacade, NO_OP_RUNTIME_HANDLER, List.of("rule_distsql"), "review-then-execute");
         Map<?, ?> actualIssue = (Map<?, ?>) ((List<?>) actualResponse.get("issues")).getFirst();
         assertThat(actualResponse.get("status"), is("failed"));
         assertThat(actualIssue.get("code"), is(WorkflowIssueCode.RULE_EXECUTION_FAILED));
@@ -366,21 +377,21 @@ class WorkflowExecutionServiceTest {
     }
     
     private Map<String, Object> apply(final WorkflowContextSnapshot snapshot, final List<String> approvedSteps, final String executionMode) {
-        return apply(createWorkflowSessionContext(snapshot), snapshot, mock(MCPFeatureExecutionFacade.class), NO_OP_APPLY_SYNCHRONIZATION_HANDLER, approvedSteps, executionMode);
+        return apply(createWorkflowSessionContext(snapshot), snapshot, mock(MCPFeatureExecutionFacade.class), NO_OP_RUNTIME_HANDLER, approvedSteps, executionMode);
     }
     
     private Map<String, Object> apply(final WorkflowContextSnapshot snapshot, final MCPFeatureExecutionFacade executionFacade,
-                                      final MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler, final List<String> approvedSteps,
+                                      final MCPWorkflowRuntimeHandler workflowRuntimeHandler, final List<String> approvedSteps,
                                       final String executionMode) {
-        return apply(createWorkflowSessionContext(snapshot), snapshot, executionFacade, workflowApplySynchronizationHandler, approvedSteps, executionMode);
+        return apply(createWorkflowSessionContext(snapshot), snapshot, executionFacade, workflowRuntimeHandler, approvedSteps, executionMode);
     }
     
     private Map<String, Object> apply(final WorkflowSessionContext workflowSessionContext, final WorkflowContextSnapshot snapshot,
                                       final MCPFeatureExecutionFacade executionFacade,
-                                      final MCPWorkflowApplySynchronizationHandler workflowApplySynchronizationHandler, final List<String> approvedSteps,
+                                      final MCPWorkflowRuntimeHandler workflowRuntimeHandler, final List<String> approvedSteps,
                                       final String executionMode) {
         return new WorkflowExecutionService().apply(workflowSessionContext, mock(MCPMetadataQueryFacade.class), mock(MCPFeatureQueryFacade.class),
-                executionFacade, workflowApplySynchronizationHandler, MCPWorkflowApplyArtifactValidator.NO_OP, "session-1", snapshot, approvedSteps, executionMode);
+                executionFacade, workflowRuntimeHandler, MCPWorkflowApplyArtifactValidator.NO_OP, "session-1", snapshot, approvedSteps, executionMode);
     }
     
     private WorkflowSessionContext createWorkflowSessionContext(final WorkflowContextSnapshot snapshot) {
diff --git a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistryTest.java b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistryTest.java
index 016ef98792c..f550657a84f 100644
--- a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistryTest.java
+++ b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/workflow/WorkflowRuntimeDefinitionRegistryTest.java
@@ -24,16 +24,14 @@ import org.apache.shardingsphere.mcp.core.protocol.exception.MCPWorkflowStateExc
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowKind;
 import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplyArtifactValidator;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowApplySynchronizationHandler;
 import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowDefinitionProvider;
-import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowValidationHandler;
+import org.apache.shardingsphere.mcp.support.workflow.spi.MCPWorkflowRuntimeHandler;
 import org.apache.shardingsphere.mcp.support.workflow.spi.WorkflowRuntimeDefinition;
 import org.junit.jupiter.api.Test;
 import org.mockito.MockedStatic;
 
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -95,7 +93,7 @@ class WorkflowRuntimeDefinitionRegistryTest {
     @Test
     void assertCreateRegistryWithNullWorkflowKind() {
         WorkflowRuntimeDefinition definition = new WorkflowRuntimeDefinition(
-                null, mock(MCPWorkflowValidationHandler.class), mock(MCPWorkflowApplySynchronizationHandler.class), MCPWorkflowApplyArtifactValidator.NO_OP);
+                null, mock(MCPWorkflowRuntimeHandler.class), MCPWorkflowApplyArtifactValidator.NO_OP);
         NullPointerException actual = assertThrows(NullPointerException.class, () -> new WorkflowRuntimeDefinitionRegistry(List.of(definition)));
         assertThat(actual.getMessage(), is(String.format("Workflow kind is required for `%s`.", definition.getClass().getName())));
     }
@@ -110,25 +108,16 @@ class WorkflowRuntimeDefinitionRegistryTest {
     }
     
     @Test
-    void assertCreateRegistryWithNullValidationHandler() {
+    void assertCreateRegistryWithNullRuntimeHandler() {
         IllegalArgumentException actual = assertThrows(IllegalArgumentException.class, () -> new WorkflowRuntimeDefinitionRegistry(
-                List.of(new WorkflowRuntimeDefinition(
-                        WorkflowKind.valueOf("encrypt.rule"), null, mock(MCPWorkflowApplySynchronizationHandler.class), MCPWorkflowApplyArtifactValidator.NO_OP))));
-        assertThat(actual.getMessage(), is("Workflow validation handler is required for `encrypt.rule`."));
-    }
-    
-    @Test
-    void assertCreateRegistryWithNullApplySynchronizationHandler() {
-        IllegalArgumentException actual = assertThrows(IllegalArgumentException.class, () -> new WorkflowRuntimeDefinitionRegistry(
-                List.of(new WorkflowRuntimeDefinition(
-                        WorkflowKind.valueOf("encrypt.rule"), mock(MCPWorkflowValidationHandler.class), null, MCPWorkflowApplyArtifactValidator.NO_OP))));
-        assertThat(actual.getMessage(), is("Workflow apply synchronization handler is required for `encrypt.rule`."));
+                List.of(new WorkflowRuntimeDefinition(WorkflowKind.valueOf("encrypt.rule"), null, MCPWorkflowApplyArtifactValidator.NO_OP))));
+        assertThat(actual.getMessage(), is("Workflow runtime handler is required for `encrypt.rule`."));
     }
     
     @Test
     void assertCreateRegistryWithNullApplyArtifactValidator() {
         IllegalArgumentException actual = assertThrows(IllegalArgumentException.class, () -> new WorkflowRuntimeDefinitionRegistry(
-                List.of(new WorkflowRuntimeDefinition(WorkflowKind.valueOf("encrypt.rule"), mock(MCPWorkflowValidationHandler.class), mock(MCPWorkflowApplySynchronizationHandler.class), null))));
+                List.of(new WorkflowRuntimeDefinition(WorkflowKind.valueOf("encrypt.rule"), mock(MCPWorkflowRuntimeHandler.class), null))));
         assertThat(actual.getMessage(), is("Workflow apply artifact validator is required for `encrypt.rule`."));
     }
     
@@ -191,8 +180,6 @@ class WorkflowRuntimeDefinitionRegistryTest {
     }
     
     private static WorkflowRuntimeDefinition createDefinition(final String workflowKind) {
-        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), (workflowSessionContext, metadataQueryFacade, queryFacade, executionFacade, sessionId, snapshot) -> Map.of(),
-                (snapshot, metadataQueryFacade, queryFacade, executionFacade, sessionId) -> {
-                }, MCPWorkflowApplyArtifactValidator.NO_OP);
+        return new WorkflowRuntimeDefinition(WorkflowKind.valueOf(workflowKind), mock(MCPWorkflowRuntimeHandler.class));
     }
 }
diff --git a/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastFeatureDefinitionTest.java b/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastFeatureDefinitionTest.java
index c85d325d72d..7346df001bb 100644
--- a/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastFeatureDefinitionTest.java
+++ b/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastFeatureDefinitionTest.java
@@ -28,16 +28,6 @@ import static org.hamcrest.Matchers.is;
 
 class BroadcastFeatureDefinitionTest {
     
-    @Test
-    void assertConstants() {
-        assertThat(BroadcastFeatureDefinition.WORKFLOW_KIND.getValue(), is("broadcast.rule"));
-        assertThat(BroadcastFeatureDefinition.PLAN_TOOL_NAME, is("database_gateway_plan_broadcast_rule"));
-        assertThat(BroadcastFeatureDefinition.PLAN_PROMPT_NAME, is("plan_broadcast_rule"));
-        assertThat(BroadcastFeatureDefinition.TABLES_FIELD, is("tables"));
-        assertThat(BroadcastFeatureDefinition.RULES_RESOURCE_URI, is("shardingsphere://features/broadcast/databases/{database}/rules"));
-        assertThat(BroadcastFeatureDefinition.RULE_COUNT_RESOURCE_URI, is("shardingsphere://features/broadcast/databases/{database}/rule-count"));
-    }
-    
     @Test
     void assertPromptCompletionArguments() {
         MCPCompletionTargetDescriptor actual = MCPDescriptorCatalogLoader.load().getShardingSphereDescriptors().getCompletionTargetDescriptors().stream()
diff --git a/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastMCPHandlerProviderTest.java b/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastMCPHandlerProviderTest.java
index 2d8baf76a11..6eb0167127c 100644
--- a/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastMCPHandlerProviderTest.java
+++ b/mcp/features/broadcast/src/test/java/org/apache/shardingsphere/mcp/feature/broadcast/BroadcastMCPHandlerProviderTest.java
@@ -61,8 +61,7 @@ class BroadcastMCPHandlerProviderTest {
     void assertGetWorkflowDefinitions() {
         WorkflowRuntimeDefinition actual = new BroadcastMCPHandlerProvider().getWorkflowDefinitions().iterator().next();
         assertThat(actual.getWorkflowKind(), is(BroadcastFeatureDefinition.WORKFLOW_KIND));
-        assertThat(actual.getApplySynchronizationHandler(), isA(BroadcastWorkflowValidationService.class));
-        assertThat(actual.getValidationHandler(), isA(BroadcastWorkflowValidationService.class));
+        assertThat(actual.getRuntimeHandler(), isA(BroadcastWorkflowValidationService.class));
     }
     
     @Test
diff --git a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProvider.java b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProvider.java
index 99822737251..f1c206e0efb 100644
--- a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProvider.java
+++ b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProvider.java
@@ -57,6 +57,6 @@ public final class EncryptMCPHandlerProvider implements MCPWorkflowDefinitionPro
     public Collection<WorkflowRuntimeDefinition> getWorkflowDefinitions() {
         EncryptWorkflowValidationService validationService = new EncryptWorkflowValidationService();
         return List.of(new WorkflowRuntimeDefinition(EncryptFeatureDefinition.WORKFLOW_KIND,
-                validationService, validationService, new EncryptWorkflowApplyArtifactValidator()));
+                validationService, new EncryptWorkflowApplyArtifactValidator()));
     }
 }
diff --git a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/EncryptWorkflowToolResponseBuilder.java b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/EncryptWorkflowToolResponseBuilder.java
deleted file mode 100644
index 5cf03d7c213..00000000000
--- a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/EncryptWorkflowToolResponseBuilder.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.feature.encrypt.tool.handler;
-
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.mcp.feature.encrypt.EncryptFeatureDefinition;
-import org.apache.shardingsphere.mcp.feature.encrypt.tool.model.EncryptWorkflowRequest;
-import org.apache.shardingsphere.mcp.feature.encrypt.tool.service.EncryptAlgorithmPropertyTemplateService;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
-import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowPlanPayloadBuilder;
-
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
-final class EncryptWorkflowToolResponseBuilder {
-    
-    private final EncryptAlgorithmPropertyTemplateService propertyTemplateService;
-    
-    Map<String, Object> buildPlanResponse(final WorkflowContextSnapshot snapshot) {
-        WorkflowPropertySource propertySource = snapshot.getRequest();
-        Map<String, Object> result = WorkflowPlanPayloadBuilder.buildWithArtifacts(snapshot, propertySource);
-        result.put("masked_property_preview", createMaskedPropertyPreview(snapshot, propertySource));
-        return result;
-    }
-    
-    private Map<String, Object> createMaskedPropertyPreview(final WorkflowContextSnapshot snapshot, final WorkflowPropertySource propertySource) {
-        List<AlgorithmPropertyRequirement> requirements = createPropertyRequirements(snapshot);
-        Map<String, Object> result = new LinkedHashMap<>(4, 1F);
-        putMaskedProperties(result, requirements, propertySource, EncryptFeatureDefinition.ALGORITHM_ROLE_PRIMARY);
-        putMaskedProperties(result, requirements, propertySource, EncryptFeatureDefinition.ALGORITHM_ROLE_ASSISTED_QUERY);
-        putMaskedProperties(result, requirements, propertySource, EncryptFeatureDefinition.ALGORITHM_ROLE_LIKE_QUERY);
-        return result;
-    }
-    
-    private void putMaskedProperties(final Map<String, Object> target, final List<AlgorithmPropertyRequirement> requirements,
-                                     final WorkflowPropertySource propertySource, final String role) {
-        target.put(role, propertyTemplateService.maskProperties(filterRequirements(requirements, role), propertySource.getAlgorithmProperties(role)));
-    }
-    
-    private List<AlgorithmPropertyRequirement> createPropertyRequirements(final WorkflowContextSnapshot snapshot) {
-        return snapshot.getPropertyRequirements().isEmpty() && snapshot.getRequest() instanceof final EncryptWorkflowRequest request
-                ? propertyTemplateService.findRequirements(request.getAlgorithmType(), request.getOptions().getAssistedQueryAlgorithmType(), request.getOptions().getLikeQueryAlgorithmType())
-                : snapshot.getPropertyRequirements();
-    }
-    
-    private List<AlgorithmPropertyRequirement> filterRequirements(final List<AlgorithmPropertyRequirement> requirements, final String role) {
-        return requirements.stream().filter(each -> role.equals(each.getAlgorithmRole())).toList();
-    }
-}
diff --git a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/PlanEncryptRuleToolHandler.java b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/PlanEncryptRuleToolHandler.java
index a4bbad5a120..c73ae4a0339 100644
--- a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/PlanEncryptRuleToolHandler.java
+++ b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/handler/PlanEncryptRuleToolHandler.java
@@ -25,11 +25,16 @@ import org.apache.shardingsphere.mcp.feature.encrypt.tool.service.EncryptWorkflo
 import org.apache.shardingsphere.mcp.api.capability.tool.MCPToolHandler;
 import org.apache.shardingsphere.mcp.support.protocol.payload.MCPMapPayload;
 import org.apache.shardingsphere.mcp.support.MCPFeatureRequestContext;
+import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowPlanningArguments;
+import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowPlanPayloadBuilder;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowRequestBinder;
 
+import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -57,7 +62,37 @@ public final class PlanEncryptRuleToolHandler implements MCPToolHandler<MCPFeatu
                 this::bindFeatureArguments, this::applyStructuredIntentEvidence);
         WorkflowContextSnapshot snapshot = planningService.plan(requestContext.getWorkflowSessionContext(), requestContext.getMetadataQueryFacade(),
                 requestContext.getQueryFacade(), request);
-        return new MCPMapPayload(new EncryptWorkflowToolResponseBuilder(propertyTemplateService).buildPlanResponse(snapshot));
+        return new MCPMapPayload(buildPlanResponse(snapshot));
+    }
+    
+    private Map<String, Object> buildPlanResponse(final WorkflowContextSnapshot snapshot) {
+        WorkflowRequest request = snapshot.getRequest();
+        Map<String, Object> result = WorkflowPlanPayloadBuilder.buildWithArtifacts(snapshot, request);
+        result.put("masked_property_preview", createMaskedPropertyPreview(snapshot, request));
+        return result;
+    }
+    
+    private Map<String, Object> createMaskedPropertyPreview(final WorkflowContextSnapshot snapshot, final WorkflowRequest request) {
+        List<AlgorithmPropertyRequirement> requirements = createPropertyRequirements(snapshot, request);
+        Map<String, Object> result = new LinkedHashMap<>(4, 1F);
+        putMaskedProperties(result, requirements, request, EncryptFeatureDefinition.ALGORITHM_ROLE_PRIMARY);
+        putMaskedProperties(result, requirements, request, EncryptFeatureDefinition.ALGORITHM_ROLE_ASSISTED_QUERY);
+        putMaskedProperties(result, requirements, request, EncryptFeatureDefinition.ALGORITHM_ROLE_LIKE_QUERY);
+        return result;
+    }
+    
+    private void putMaskedProperties(final Map<String, Object> target, final List<AlgorithmPropertyRequirement> requirements,
+                                     final WorkflowRequest request, final String role) {
+        target.put(role, propertyTemplateService.maskProperties(
+                requirements.stream().filter(each -> role.equals(each.getAlgorithmRole())).toList(), request.getAlgorithmProperties(role)));
+    }
+    
+    private List<AlgorithmPropertyRequirement> createPropertyRequirements(final WorkflowContextSnapshot snapshot, final WorkflowRequest request) {
+        if (snapshot.getPropertyRequirements().isEmpty() && request instanceof EncryptWorkflowRequest encryptRequest) {
+            return propertyTemplateService.findRequirements(encryptRequest.getAlgorithmType(), encryptRequest.getOptions().getAssistedQueryAlgorithmType(),
+                    encryptRequest.getOptions().getLikeQueryAlgorithmType());
+        }
+        return snapshot.getPropertyRequirements();
     }
     
     private void bindFeatureArguments(final EncryptWorkflowRequest request, final WorkflowPlanningArguments workflowPlanningArguments) {
diff --git a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningService.java b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningService.java
index 0d38b0957f5..6efbc84b4d5 100644
--- a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningService.java
+++ b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowPlanningService.java
@@ -119,7 +119,7 @@ public final class EncryptWorkflowPlanningService {
     }
     
     private RuleWorkflowFeatureData getWorkflowState(final WorkflowContextSnapshot snapshot) {
-        return snapshot.getFeatureData() instanceof RuleWorkflowFeatureData ? (RuleWorkflowFeatureData) snapshot.getFeatureData() : new RuleWorkflowFeatureData();
+        return null == snapshot.getFeatureData() ? new RuleWorkflowFeatureData() : snapshot.getFeatureData();
     }
     
     private boolean ensureLifecycleState(final ClarifiedIntent clarifiedIntent, final EncryptWorkflowRequest request,
diff --git a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowValidationService.java b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowValidationService.java
index f66ca43503f..0302c91174f 100644
--- a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowValidationService.java
+++ b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/tool/service/EncryptWorkflowValidationService.java
@@ -130,7 +130,7 @@ public final class EncryptWorkflowValidationService implements MCPWorkflowRuntim
     }
     
     private Optional<List<Map<String, Object>>> getExpectedRules(final WorkflowContextSnapshot snapshot) {
-        return snapshot.getFeatureData() instanceof RuleWorkflowFeatureData ? Optional.of(((RuleWorkflowFeatureData) snapshot.getFeatureData()).getExpectedRules()) : Optional.empty();
+        return Optional.ofNullable(snapshot.getFeatureData()).map(RuleWorkflowFeatureData::getExpectedRules);
     }
     
     private ValidationSection validateExpectedRules(final WorkflowContextSnapshot snapshot, final List<Map<String, Object>> expectedRules, final List<Map<String, Object>> actualRules,
diff --git a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptFeatureDefinitionTest.java b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptFeatureDefinitionTest.java
deleted file mode 100644
index d6e365a8a4b..00000000000
--- a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptFeatureDefinitionTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.feature.encrypt;
-
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-
-class EncryptFeatureDefinitionTest {
-    
-    @Test
-    void assertConstants() {
-        assertThat(EncryptFeatureDefinition.WORKFLOW_KIND.getValue(), is("encrypt.rule"));
-        assertThat(EncryptFeatureDefinition.PLAN_TOOL_NAME, is("database_gateway_plan_encrypt_rule"));
-        assertThat(EncryptFeatureDefinition.PLAN_PROMPT_NAME, is("plan_encrypt_rule"));
-        assertThat(EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI, is("shardingsphere://features/encrypt/algorithms"));
-        assertThat(EncryptFeatureDefinition.RULES_RESOURCE_URI, is("shardingsphere://features/encrypt/databases/{database}/rules"));
-        assertThat(EncryptFeatureDefinition.RULE_RESOURCE_URI, is("shardingsphere://features/encrypt/databases/{database}/tables/{table}/rules"));
-    }
-}
diff --git a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProviderTest.java b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProviderTest.java
index f264ee7d34e..8124f1735bc 100644
--- a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProviderTest.java
+++ b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/EncryptMCPHandlerProviderTest.java
@@ -70,8 +70,7 @@ class EncryptMCPHandlerProviderTest {
     void assertGetWorkflowDefinitions() {
         WorkflowRuntimeDefinition actual = new EncryptMCPHandlerProvider().getWorkflowDefinitions().iterator().next();
         assertThat(actual.getWorkflowKind(), is(EncryptFeatureDefinition.WORKFLOW_KIND));
-        assertThat(actual.getApplySynchronizationHandler(), isA(EncryptWorkflowValidationService.class));
+        assertThat(actual.getRuntimeHandler(), isA(EncryptWorkflowValidationService.class));
         assertThat(actual.getApplyArtifactValidator(), isA(EncryptWorkflowApplyArtifactValidator.class));
-        assertThat(actual.getValidationHandler(), isA(EncryptWorkflowValidationService.class));
     }
 }
diff --git a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionHandlerTest.java b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionHandlerTest.java
index 4891107613c..34c5db1691e 100644
--- a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionHandlerTest.java
+++ b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionHandlerTest.java
@@ -42,11 +42,6 @@ import static org.mockito.Mockito.when;
 
 class EncryptAlgorithmCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new EncryptAlgorithmCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @ParameterizedTest(name = "{0}")
     @MethodSource("supportedReferences")
     void assertSupports(final String name, final String referenceType, final String reference, final String argumentName) {
diff --git a/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/MaskWorkflowToolResponseBuilder.java b/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/MaskWorkflowToolResponseBuilder.java
deleted file mode 100644
index 180208035de..00000000000
--- a/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/MaskWorkflowToolResponseBuilder.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.feature.mask.tool.handler;
-
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.mcp.feature.mask.tool.service.MaskAlgorithmPropertyTemplateService;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
-import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowPlanPayloadBuilder;
-
-import java.util.List;
-import java.util.Map;
-
-@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
-final class MaskWorkflowToolResponseBuilder {
-    
-    private final MaskAlgorithmPropertyTemplateService propertyTemplateService;
-    
-    Map<String, Object> buildPlanResponse(final WorkflowContextSnapshot snapshot) {
-        WorkflowPropertySource propertySource = snapshot.getRequest();
-        Map<String, Object> result = WorkflowPlanPayloadBuilder.buildWithArtifacts(snapshot, propertySource);
-        result.put("masked_property_preview", createMaskedPropertyPreview(snapshot, propertySource));
-        return result;
-    }
-    
-    private Map<String, Object> createMaskedPropertyPreview(final WorkflowContextSnapshot snapshot, final WorkflowPropertySource propertySource) {
-        return Map.of("primary", propertyTemplateService.maskProperties(createPropertyRequirements(snapshot), propertySource.getAlgorithmProperties("primary")));
-    }
-    
-    private List<AlgorithmPropertyRequirement> createPropertyRequirements(final WorkflowContextSnapshot snapshot) {
-        return snapshot.getPropertyRequirements().isEmpty()
-                ? propertyTemplateService.findRequirements(snapshot.getRequest().getAlgorithmType())
-                : snapshot.getPropertyRequirements().stream().filter(each -> "primary".equals(each.getAlgorithmRole())).toList();
-    }
-    
-}
diff --git a/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/PlanMaskRuleToolHandler.java b/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/PlanMaskRuleToolHandler.java
index ef8692fa649..1e8f429eec0 100644
--- a/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/PlanMaskRuleToolHandler.java
+++ b/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/handler/PlanMaskRuleToolHandler.java
@@ -24,12 +24,15 @@ import org.apache.shardingsphere.mcp.feature.mask.tool.service.MaskWorkflowPlann
 import org.apache.shardingsphere.mcp.api.capability.tool.MCPToolHandler;
 import org.apache.shardingsphere.mcp.support.protocol.payload.MCPMapPayload;
 import org.apache.shardingsphere.mcp.support.MCPFeatureRequestContext;
+import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowPlanningArguments;
+import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowPlanPayloadBuilder;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowRequestBinder;
 
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -56,7 +59,21 @@ public final class PlanMaskRuleToolHandler implements MCPToolHandler<MCPFeatureR
         WorkflowRequest request = WorkflowRequestBinder.bindPlanningRequest(arguments, this::bindFeatureArguments, this::applyStructuredIntentEvidence);
         WorkflowContextSnapshot snapshot = planningService.plan(requestContext.getWorkflowSessionContext(), requestContext.getMetadataQueryFacade(),
                 requestContext.getQueryFacade(), request);
-        return new MCPMapPayload(new MaskWorkflowToolResponseBuilder(propertyTemplateService).buildPlanResponse(snapshot));
+        return new MCPMapPayload(buildPlanResponse(snapshot));
+    }
+    
+    private Map<String, Object> buildPlanResponse(final WorkflowContextSnapshot snapshot) {
+        WorkflowRequest request = snapshot.getRequest();
+        Map<String, Object> result = WorkflowPlanPayloadBuilder.buildWithArtifacts(snapshot, request);
+        result.put("masked_property_preview", Map.of(
+                "primary", propertyTemplateService.maskProperties(createPropertyRequirements(snapshot, request), request.getAlgorithmProperties("primary"))));
+        return result;
+    }
+    
+    private List<AlgorithmPropertyRequirement> createPropertyRequirements(final WorkflowContextSnapshot snapshot, final WorkflowRequest request) {
+        return snapshot.getPropertyRequirements().isEmpty()
+                ? propertyTemplateService.findRequirements(request.getAlgorithmType())
+                : snapshot.getPropertyRequirements().stream().filter(each -> "primary".equals(each.getAlgorithmRole())).toList();
     }
     
     private void bindFeatureArguments(final WorkflowRequest request, final WorkflowPlanningArguments workflowPlanningArguments) {
diff --git a/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowValidationService.java b/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowValidationService.java
index 4100969499c..a035033edc5 100644
--- a/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowValidationService.java
+++ b/mcp/features/mask/src/main/java/org/apache/shardingsphere/mcp/feature/mask/tool/service/MaskWorkflowValidationService.java
@@ -148,7 +148,7 @@ public final class MaskWorkflowValidationService implements MCPWorkflowRuntimeHa
     }
     
     private Optional<RuleWorkflowFeatureData> getRuleFeatureData(final WorkflowContextSnapshot snapshot) {
-        return snapshot.getFeatureData() instanceof RuleWorkflowFeatureData ? Optional.of((RuleWorkflowFeatureData) snapshot.getFeatureData()) : Optional.empty();
+        return Optional.ofNullable(snapshot.getFeatureData());
     }
     
     private ValidationSection validateExpectedRules(final WorkflowContextSnapshot snapshot, final List<Map<String, Object>> expectedRules, final List<Map<String, Object>> actualRules,
diff --git a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskFeatureDefinitionTest.java b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskFeatureDefinitionTest.java
index b5a9a57d6a2..2dce5663e3f 100644
--- a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskFeatureDefinitionTest.java
+++ b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskFeatureDefinitionTest.java
@@ -34,16 +34,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class MaskFeatureDefinitionTest {
     
-    @Test
-    void assertConstants() {
-        assertThat(MaskFeatureDefinition.WORKFLOW_KIND.getValue(), is("mask.rule"));
-        assertThat(MaskFeatureDefinition.PLAN_TOOL_NAME, is("database_gateway_plan_mask_rule"));
-        assertThat(MaskFeatureDefinition.PLAN_PROMPT_NAME, is("plan_mask_rule"));
-        assertThat(MaskFeatureDefinition.ALGORITHMS_RESOURCE_URI, is("shardingsphere://features/mask/algorithms"));
-        assertThat(MaskFeatureDefinition.RULES_RESOURCE_URI, is("shardingsphere://features/mask/databases/{database}/rules"));
-        assertThat(MaskFeatureDefinition.RULE_RESOURCE_URI, is("shardingsphere://features/mask/databases/{database}/tables/{table}/rules"));
-    }
-    
     @Test
     void assertPromptCompletionArguments() {
         MCPCompletionTargetDescriptor actual = MCPDescriptorCatalogLoader.load().getShardingSphereDescriptors().getCompletionTargetDescriptors().stream()
diff --git a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskMCPHandlerProviderTest.java b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskMCPHandlerProviderTest.java
index f49b5eed9b4..417777ff627 100644
--- a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskMCPHandlerProviderTest.java
+++ b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/MaskMCPHandlerProviderTest.java
@@ -62,7 +62,6 @@ class MaskMCPHandlerProviderTest {
     void assertGetWorkflowDefinitions() {
         WorkflowRuntimeDefinition actual = new MaskMCPHandlerProvider().getWorkflowDefinitions().iterator().next();
         assertThat(actual.getWorkflowKind(), is(MaskFeatureDefinition.WORKFLOW_KIND));
-        assertThat(actual.getApplySynchronizationHandler(), isA(MaskWorkflowValidationService.class));
-        assertThat(actual.getValidationHandler(), isA(MaskWorkflowValidationService.class));
+        assertThat(actual.getRuntimeHandler(), isA(MaskWorkflowValidationService.class));
     }
 }
diff --git a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/completion/MaskAlgorithmCompletionHandlerTest.java b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/completion/MaskAlgorithmCompletionHandlerTest.java
index d23da5a6deb..babdb5a6334 100644
--- a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/completion/MaskAlgorithmCompletionHandlerTest.java
+++ b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/completion/MaskAlgorithmCompletionHandlerTest.java
@@ -39,11 +39,6 @@ import static org.mockito.Mockito.when;
 
 class MaskAlgorithmCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new MaskAlgorithmCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @Test
     void assertSupports() {
         assertTrue(new MaskAlgorithmCompletionHandler().supports(createRequestContext(MaskFeatureDefinition.PLAN_PROMPT_NAME)));
diff --git a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingFeatureDefinitionTest.java b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingFeatureDefinitionTest.java
index 236aef6f28b..086570f2e00 100644
--- a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingFeatureDefinitionTest.java
+++ b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingFeatureDefinitionTest.java
@@ -29,12 +29,6 @@ import static org.hamcrest.Matchers.is;
 
 class ReadwriteSplittingFeatureDefinitionTest {
     
-    @Test
-    void assertWorkflowKinds() {
-        assertThat(ReadwriteSplittingFeatureDefinition.RULE_WORKFLOW_KIND.getValue(), is("readwrite.rule"));
-        assertThat(ReadwriteSplittingFeatureDefinition.STATUS_WORKFLOW_KIND.getValue(), is("readwrite.status"));
-    }
-    
     @Test
     void assertPromptCompletionArguments() {
         MCPDescriptorCatalog catalog = MCPDescriptorCatalogLoader.load();
diff --git a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingMCPHandlerProviderTest.java b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingMCPHandlerProviderTest.java
index 2dee1373a21..40cb0769d14 100644
--- a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingMCPHandlerProviderTest.java
+++ b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/ReadwriteSplittingMCPHandlerProviderTest.java
@@ -69,9 +69,9 @@ class ReadwriteSplittingMCPHandlerProviderTest {
     void assertGetWorkflowDefinitions() {
         List<WorkflowRuntimeDefinition> actual = new ReadwriteSplittingMCPHandlerProvider().getWorkflowDefinitions().stream().toList();
         assertThat(actual.get(0).getWorkflowKind(), is(ReadwriteSplittingFeatureDefinition.RULE_WORKFLOW_KIND));
-        assertThat(actual.get(0).getValidationHandler(), isA(ReadwriteSplittingRuleWorkflowValidationService.class));
+        assertThat(actual.get(0).getRuntimeHandler(), isA(ReadwriteSplittingRuleWorkflowValidationService.class));
         assertThat(actual.get(1).getWorkflowKind(), is(ReadwriteSplittingFeatureDefinition.STATUS_WORKFLOW_KIND));
-        assertThat(actual.get(1).getValidationHandler(), isA(ReadwriteSplittingStatusWorkflowValidationService.class));
+        assertThat(actual.get(1).getRuntimeHandler(), isA(ReadwriteSplittingStatusWorkflowValidationService.class));
     }
     
     @Test
diff --git a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/completion/ReadwriteSplittingLoadBalanceAlgorithmCompletionHandlerTest.java b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/completion/ReadwriteSplittingLoadBalanceAlgorithmCompletionHandlerTest.java
index a501139159d..6886b0e39c2 100644
--- a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/completion/ReadwriteSplittingLoadBalanceAlgorithmCompletionHandlerTest.java
+++ b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/completion/ReadwriteSplittingLoadBalanceAlgorithmCompletionHandlerTest.java
@@ -39,11 +39,6 @@ import static org.mockito.Mockito.when;
 
 class ReadwriteSplittingLoadBalanceAlgorithmCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new ReadwriteSplittingLoadBalanceAlgorithmCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @Test
     void assertSupports() {
         assertTrue(new ReadwriteSplittingLoadBalanceAlgorithmCompletionHandler().supports(createRequestContext(ReadwriteSplittingFeatureDefinition.PLAN_RULE_PROMPT_NAME)));
diff --git a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/ShadowFeatureDefinitionTest.java b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/ShadowFeatureDefinitionTest.java
deleted file mode 100644
index b03a74c9122..00000000000
--- a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/ShadowFeatureDefinitionTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.feature.shadow;
-
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-
-class ShadowFeatureDefinitionTest {
-    
-    @Test
-    void assertWorkflowKinds() {
-        assertThat(ShadowFeatureDefinition.RULE_WORKFLOW_KIND.getValue(), is("shadow.rule"));
-        assertThat(ShadowFeatureDefinition.DEFAULT_ALGORITHM_WORKFLOW_KIND.getValue(), is("shadow.default"));
-        assertThat(ShadowFeatureDefinition.ALGORITHM_CLEANUP_WORKFLOW_KIND.getValue(), is("shadow.cleanup"));
-    }
-}
diff --git a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/completion/ShadowAlgorithmCompletionHandlerTest.java b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/completion/ShadowAlgorithmCompletionHandlerTest.java
index 344aea66cf9..447a7b411ec 100644
--- a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/completion/ShadowAlgorithmCompletionHandlerTest.java
+++ b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/completion/ShadowAlgorithmCompletionHandlerTest.java
@@ -39,11 +39,6 @@ import static org.mockito.Mockito.when;
 
 class ShadowAlgorithmCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new ShadowAlgorithmCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @Test
     void assertSupports() {
         assertTrue(new ShadowAlgorithmCompletionHandler().supports(createRequestContext(ShadowFeatureDefinition.PLAN_RULE_PROMPT_NAME)));
diff --git a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProvider.java b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProvider.java
index ff045688a68..f9f1c413680 100644
--- a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProvider.java
+++ b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProvider.java
@@ -92,11 +92,11 @@ public final class ShardingMCPHandlerProvider implements MCPWorkflowDefinitionPr
         ShardingWorkflowValidationService validationService = new ShardingWorkflowValidationService();
         ShardingWorkflowApplyArtifactValidator applyArtifactValidator = new ShardingWorkflowApplyArtifactValidator();
         return List.of(
-                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.TABLE_RULE_WORKFLOW_KIND, validationService, validationService, applyArtifactValidator),
-                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.TABLE_REFERENCE_WORKFLOW_KIND, validationService, validationService, applyArtifactValidator),
-                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.DEFAULT_STRATEGY_WORKFLOW_KIND, validationService, validationService, applyArtifactValidator),
-                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.KEY_GENERATOR_WORKFLOW_KIND, validationService, validationService, applyArtifactValidator),
-                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.KEY_GENERATE_STRATEGY_WORKFLOW_KIND, validationService, validationService, applyArtifactValidator),
-                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.COMPONENT_CLEANUP_WORKFLOW_KIND, validationService, validationService, applyArtifactValidator));
+                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.TABLE_RULE_WORKFLOW_KIND, validationService, applyArtifactValidator),
+                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.TABLE_REFERENCE_WORKFLOW_KIND, validationService, applyArtifactValidator),
+                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.DEFAULT_STRATEGY_WORKFLOW_KIND, validationService, applyArtifactValidator),
+                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.KEY_GENERATOR_WORKFLOW_KIND, validationService, applyArtifactValidator),
+                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.KEY_GENERATE_STRATEGY_WORKFLOW_KIND, validationService, applyArtifactValidator),
+                new WorkflowRuntimeDefinition(ShardingFeatureDefinition.COMPONENT_CLEANUP_WORKFLOW_KIND, validationService, applyArtifactValidator));
     }
 }
diff --git a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/handler/ShardingPlanningRequestBinder.java b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/handler/ShardingPlanningRequestBinder.java
index 78462be1a9a..9d0e9388d7b 100644
--- a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/handler/ShardingPlanningRequestBinder.java
+++ b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/handler/ShardingPlanningRequestBinder.java
@@ -26,6 +26,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.stream.Stream;
 
@@ -94,8 +95,10 @@ public final class ShardingPlanningRequestBinder {
         return bind(arguments, this::bindRuleComponentCleanupArguments, this::applyRuleComponentCleanupEvidence);
     }
     
-    private ShardingWorkflowRequest bind(final Map<String, Object> arguments, final FeatureArgumentBinder argumentBinder, final EvidenceBinder evidenceBinder) {
-        return WorkflowRequestBinder.bindPlanningRequest(ShardingWorkflowRequest::new, arguments, argumentBinder::bind, evidenceBinder::bind);
+    private ShardingWorkflowRequest bind(final Map<String, Object> arguments,
+                                         final BiConsumer<ShardingWorkflowRequest, WorkflowPlanningArguments> argumentBinder,
+                                         final BiConsumer<ShardingWorkflowRequest, Map<String, Object>> evidenceBinder) {
+        return WorkflowRequestBinder.bindPlanningRequest(ShardingWorkflowRequest::new, arguments, argumentBinder, evidenceBinder);
     }
     
     private void bindTableRuleArguments(final ShardingWorkflowRequest request, final WorkflowPlanningArguments workflowPlanningArguments) {
@@ -232,15 +235,4 @@ public final class ShardingPlanningRequestBinder {
         return Stream.of(String.valueOf(value).split(",")).map(String::trim).filter(each -> !each.isEmpty()).toList();
     }
     
-    @FunctionalInterface
-    private interface FeatureArgumentBinder {
-        
-        void bind(ShardingWorkflowRequest request, WorkflowPlanningArguments workflowPlanningArguments);
-    }
-    
-    @FunctionalInterface
-    private interface EvidenceBinder {
-        
-        void bind(ShardingWorkflowRequest request, Map<String, Object> values);
-    }
 }
diff --git a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowLifecycleSpec.java b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowLifecycleSpec.java
deleted file mode 100644
index 5c5f740dd47..00000000000
--- a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowLifecycleSpec.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.feature.sharding.tool.service;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.mcp.feature.sharding.tool.model.ShardingWorkflowRequest;
-import org.apache.shardingsphere.mcp.support.workflow.model.RuleArtifact;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowKind;
-
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
-@Getter(AccessLevel.PACKAGE)
-final class ShardingWorkflowLifecycleSpec {
-    
-    private final WorkflowKind workflowKind;
-    
-    private final String defaultOperationType;
-    
-    private final String summary;
-    
-    private final Function<ShardingWorkflowRequest, Boolean> existsSupplier;
-    
-    private final BiFunction<ShardingWorkflowRequest, WorkflowContextSnapshot, Boolean> requiredInputSupplier;
-    
-    private final BiFunction<ShardingWorkflowRequest, WorkflowContextSnapshot, Boolean> algorithmPlanSupplier;
-    
-    private final Function<ShardingWorkflowRequest, RuleArtifact> artifactSupplier;
-    
-}
diff --git a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowPlanningService.java b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowPlanningService.java
index f5ebb4f0a5f..c9b1d4485ae 100644
--- a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowPlanningService.java
+++ b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowPlanningService.java
@@ -25,6 +25,7 @@ import org.apache.shardingsphere.mcp.support.workflow.WorkflowSessionContext;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmCandidate;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.ClarifiedIntent;
+import org.apache.shardingsphere.mcp.support.workflow.model.RuleArtifact;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowIssue;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowIssueCode;
@@ -37,6 +38,8 @@ import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowRuleValueU
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.function.BiFunction;
+import java.util.function.Function;
 
 /**
  * Sharding workflow planning service.
@@ -204,7 +207,7 @@ public final class ShardingWorkflowPlanningService {
     
     private WorkflowContextSnapshot planLifecycleWorkflow(final WorkflowSessionContext workflowSessionContext, final ShardingWorkflowRequest request,
                                                           final ShardingWorkflowLifecycleSpec spec) {
-        WorkflowContextSnapshot result = prepareSnapshot(workflowSessionContext, request, spec.getWorkflowKind(), spec.getDefaultOperationType(), spec.getSummary());
+        WorkflowContextSnapshot result = prepareSnapshot(workflowSessionContext, request, spec.workflowKind(), spec.defaultOperationType(), spec.summary());
         ShardingWorkflowRequest mergedRequest = (ShardingWorkflowRequest) result.getRequest();
         if (!planningSupport.ensureSupportedOperationType(result.getClarifiedIntent(), SUPPORTED_LIFECYCLE_OPERATION_TYPES, result)) {
             return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_FAILED, WorkflowLifecycle.STATUS_FAILED);
@@ -215,20 +218,20 @@ public final class ShardingWorkflowPlanningService {
         if (!inputValidator.ensureIdentifiers(mergedRequest, result)) {
             return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_FAILED, result.getStatus());
         }
-        if (!inputValidator.ensureCompatibleInputs(spec.getWorkflowKind(), mergedRequest, result)) {
+        if (!inputValidator.ensureCompatibleInputs(spec.workflowKind(), mergedRequest, result)) {
             return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_FAILED, result.getStatus());
         }
-        if (!spec.getRequiredInputSupplier().apply(mergedRequest, result)) {
+        if (!spec.requiredInputSupplier().apply(mergedRequest, result)) {
             addRequiredInputClarification(mergedRequest, result);
             return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_CLARIFYING, result.getStatus());
         }
-        if (!planningSupport.ensureLifecycleState(spec.getSummary(), result.getClarifiedIntent(), spec.getExistsSupplier().apply(mergedRequest), result)) {
+        if (!planningSupport.ensureLifecycleState(spec.summary(), result.getClarifiedIntent(), spec.existsSupplier().apply(mergedRequest), result)) {
             return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_FAILED, WorkflowLifecycle.STATUS_FAILED);
         }
-        if (!spec.getAlgorithmPlanSupplier().apply(mergedRequest, result)) {
+        if (!spec.algorithmPlanSupplier().apply(mergedRequest, result)) {
             return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_CLARIFYING, WorkflowLifecycle.STATUS_CLARIFYING);
         }
-        result.getRuleArtifacts().add(spec.getArtifactSupplier().apply(mergedRequest));
+        result.getRuleArtifacts().add(spec.artifactSupplier().apply(mergedRequest));
         return workflowSessionContext.persist(result, WorkflowLifecycle.STEP_REVIEW, WorkflowLifecycle.STATUS_PLANNED);
     }
     
@@ -346,4 +349,11 @@ public final class ShardingWorkflowPlanningService {
         return rows.stream().anyMatch(each -> queryFacade.isSameIdentifier(databaseName, IdentifierScope.TABLE, expected, WorkflowRuleValueUtils.getRuleValue(each, fieldName)));
     }
     
+    private record ShardingWorkflowLifecycleSpec(WorkflowKind workflowKind, String defaultOperationType, String summary,
+                                                 Function<ShardingWorkflowRequest, Boolean> existsSupplier,
+                                                 BiFunction<ShardingWorkflowRequest, WorkflowContextSnapshot, Boolean> requiredInputSupplier,
+                                                 BiFunction<ShardingWorkflowRequest, WorkflowContextSnapshot, Boolean> algorithmPlanSupplier,
+                                                 Function<ShardingWorkflowRequest, RuleArtifact> artifactSupplier) {
+    }
+    
 }
diff --git a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingFeatureDefinitionTest.java b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingFeatureDefinitionTest.java
deleted file mode 100644
index 0d105f3c187..00000000000
--- a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingFeatureDefinitionTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.feature.sharding;
-
-import org.junit.jupiter.api.Test;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-
-class ShardingFeatureDefinitionTest {
-    
-    @Test
-    void assertConstants() {
-        assertThat(ShardingFeatureDefinition.TABLE_RULE_WORKFLOW_KIND.getValue(), is("sharding.table.rule"));
-        assertThat(ShardingFeatureDefinition.TABLE_REFERENCE_WORKFLOW_KIND.getValue(), is("sharding.table.reference"));
-        assertThat(ShardingFeatureDefinition.DEFAULT_STRATEGY_WORKFLOW_KIND.getValue(), is("sharding.default.strategy"));
-        assertThat(ShardingFeatureDefinition.KEY_GENERATOR_WORKFLOW_KIND.getValue(), is("sharding.key.generator"));
-        assertThat(ShardingFeatureDefinition.KEY_GENERATE_STRATEGY_WORKFLOW_KIND.getValue(), is("sharding.key.generate.strategy"));
-        assertThat(ShardingFeatureDefinition.COMPONENT_CLEANUP_WORKFLOW_KIND.getValue(), is("sharding.component.cleanup"));
-        assertThat(ShardingFeatureDefinition.PLAN_TABLE_RULE_TOOL_NAME, is("database_gateway_plan_sharding_table_rule"));
-        assertThat(ShardingFeatureDefinition.PLAN_TABLE_RULE_PROMPT_NAME, is("plan_sharding_table_rule"));
-        assertThat(ShardingFeatureDefinition.PLAN_TABLE_REFERENCE_PROMPT_NAME, is("plan_sharding_table_reference_rule"));
-        assertThat(ShardingFeatureDefinition.PLAN_DEFAULT_STRATEGY_PROMPT_NAME, is("plan_sharding_default_strategy"));
-        assertThat(ShardingFeatureDefinition.PLAN_KEY_GENERATOR_PROMPT_NAME, is("plan_sharding_key_generator"));
-        assertThat(ShardingFeatureDefinition.PLAN_KEY_GENERATE_STRATEGY_PROMPT_NAME, is("plan_sharding_key_generate_strategy"));
-        assertThat(ShardingFeatureDefinition.PLAN_COMPONENT_CLEANUP_PROMPT_NAME, is("plan_sharding_rule_component_cleanup"));
-        assertThat(ShardingFeatureDefinition.ALGORITHM_PLUGINS_RESOURCE_URI, is("shardingsphere://features/sharding/algorithm-plugins"));
-        assertThat(ShardingFeatureDefinition.RULE_COUNT_RESOURCE_URI, is("shardingsphere://features/sharding/databases/{database}/rule-count"));
-    }
-}
diff --git a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProviderTest.java b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProviderTest.java
index 50e56bbb79f..debf2869f61 100644
--- a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProviderTest.java
+++ b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/ShardingMCPHandlerProviderTest.java
@@ -75,8 +75,7 @@ class ShardingMCPHandlerProviderTest {
         assertThat(actual.stream().map(each -> each.getWorkflowKind().getValue()).toList(),
                 containsInAnyOrder("sharding.table.rule", "sharding.table.reference", "sharding.default.strategy",
                         "sharding.key.generator", "sharding.key.generate.strategy", "sharding.component.cleanup"));
-        assertTrue(actual.stream().allMatch(each -> each.getValidationHandler() instanceof ShardingWorkflowValidationService));
-        assertTrue(actual.stream().allMatch(each -> each.getApplySynchronizationHandler() instanceof ShardingWorkflowValidationService));
+        assertTrue(actual.stream().allMatch(each -> each.getRuntimeHandler() instanceof ShardingWorkflowValidationService));
         assertTrue(actual.stream().allMatch(each -> each.getApplyArtifactValidator() instanceof ShardingWorkflowApplyArtifactValidator));
     }
     
diff --git a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/completion/ShardingAlgorithmCompletionHandlerTest.java b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/completion/ShardingAlgorithmCompletionHandlerTest.java
index 43123c32eca..69040bc45c0 100644
--- a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/completion/ShardingAlgorithmCompletionHandlerTest.java
+++ b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/completion/ShardingAlgorithmCompletionHandlerTest.java
@@ -39,11 +39,6 @@ import static org.mockito.Mockito.when;
 
 class ShardingAlgorithmCompletionHandlerTest {
     
-    @Test
-    void assertGetContextType() {
-        assertThat(new ShardingAlgorithmCompletionHandler().getContextType(), is(MCPFeatureRequestContext.class));
-    }
-    
     @Test
     void assertSupportsShardingAlgorithm() {
         assertTrue(new ShardingAlgorithmCompletionHandler().supports(createRequestContext(ShardingFeatureDefinition.ALGORITHM_PLUGINS_RESOURCE_URI, "algorithm_type")));
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPGuidancePayloadBuilder.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPGuidancePayloadBuilder.java
index 57d6de6e0a6..7637183d018 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPGuidancePayloadBuilder.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPGuidancePayloadBuilder.java
@@ -21,7 +21,7 @@ import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.mcp.support.protocol.MCPModelFacingPayloadContract;
 import org.apache.shardingsphere.mcp.support.protocol.MCPResponseMode;
-import org.apache.shardingsphere.mcp.support.security.MCPClientSafetyPolicy;
+import org.apache.shardingsphere.mcp.support.security.MCPRuntimeProtectionPolicy;
 
 import java.util.Collection;
 import java.util.LinkedHashMap;
@@ -117,7 +117,20 @@ final class MCPGuidancePayloadBuilder {
         result.put("http_transport", "Streamable HTTP is unauthenticated by default; prefer loopback binding or put remote exposure behind a trusted gateway.");
         result.put("origin_header", "Present Origin headers must be valid loopback origins for loopback HTTP bindings; missing Origin is accepted.");
         result.put("stdio_stdout", "STDIO transport must keep MCP protocol frames on stdout and send logs to stderr or files.");
-        result.put("client_safety_policy", MCPClientSafetyPolicy.createModelFacingPayload());
+        result.put("client_safety_policy", createClientSafetyPolicy());
+        return result;
+    }
+    
+    private static Map<String, Object> createClientSafetyPolicy() {
+        Map<String, Object> result = new LinkedHashMap<>(5, 1F);
+        result.put("identity_scope", "mcp_session");
+        result.put("transport_scope",
+                "HTTP transport can bind trusted session attribution when configured; "
+                        + "the MCP runtime does not provide built-in authentication or authorization. "
+                        + "STDIO inherits the local process boundary.");
+        result.put("runtime_protection", MCPRuntimeProtectionPolicy.createRuntimeProtectionPayload());
+        result.put("abuse_guard", "Every tool call is counted before dispatch, including invalid calls, so runaway model loops stop at the session quota.");
+        result.put("external_model_boundary", "The MCP runtime never calls external model providers; live LLM E2E clients call configured endpoints outside the server.");
         return result;
     }
     
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/security/MCPClientSafetyPolicy.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/security/MCPClientSafetyPolicy.java
deleted file mode 100644
index 5f65c923ee1..00000000000
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/security/MCPClientSafetyPolicy.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.security;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-/**
- * MCP client-facing safety policy.
- */
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-public final class MCPClientSafetyPolicy {
-    
-    /**
-     * Create model-facing safety policy payload.
-     *
-     * @return model-facing safety policy payload
-     */
-    public static Map<String, Object> createModelFacingPayload() {
-        Map<String, Object> result = new LinkedHashMap<>(5, 1F);
-        result.put("identity_scope", "mcp_session");
-        result.put("transport_scope",
-                "HTTP transport can bind trusted session attribution when configured; "
-                        + "the MCP runtime does not provide built-in authentication or authorization. "
-                        + "STDIO inherits the local process boundary.");
-        result.put("runtime_protection", MCPRuntimeProtectionPolicy.createRuntimeProtectionPayload());
-        result.put("abuse_guard", "Every tool call is counted before dispatch, including invalid calls, so runaway model loops stop at the session quota.");
-        result.put("external_model_boundary", "The MCP runtime never calls external model providers; live LLM E2E clients call configured endpoints outside the server.");
-        return result;
-    }
-}
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/WorkflowPropertySource.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/WorkflowPropertySource.java
deleted file mode 100644
index c7cd1f153fa..00000000000
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/WorkflowPropertySource.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.workflow;
-
-import org.apache.shardingsphere.mcp.support.workflow.model.SecretReferenceValue;
-
-import java.util.Map;
-
-/**
- * Workflow algorithm property source.
- */
-public interface WorkflowPropertySource {
-    
-    /**
-     * Get algorithm properties by role.
-     *
-     * @param algorithmRole algorithm role
-     * @return algorithm properties
-     */
-    Map<String, String> getAlgorithmProperties(String algorithmRole);
-    
-    /**
-     * Get secret references grouped by algorithm role.
-     *
-     * @return secret references
-     */
-    default Map<String, Map<String, SecretReferenceValue>> getSecretReferences() {
-        return Map.of();
-    }
-    
-    /**
-     * Get secret references by role.
-     *
-     * @param algorithmRole algorithm role
-     * @return secret references
-     */
-    default Map<String, SecretReferenceValue> getSecretReferences(final String algorithmRole) {
-        return getSecretReferences().getOrDefault(algorithmRole, Map.of());
-    }
-}
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/RuleWorkflowFeatureData.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/RuleWorkflowFeatureData.java
index ba35295ddac..1b1c9672393 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/RuleWorkflowFeatureData.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/RuleWorkflowFeatureData.java
@@ -20,7 +20,6 @@ package org.apache.shardingsphere.mcp.support.workflow.model;
 import lombok.Getter;
 import lombok.NoArgsConstructor;
 
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -30,43 +29,15 @@ import java.util.Map;
  */
 @Getter
 @NoArgsConstructor
-public final class RuleWorkflowFeatureData implements WorkflowFeatureData {
+public final class RuleWorkflowFeatureData {
     
     private final List<Map<String, Object>> expectedRules = new LinkedList<>();
     
     public RuleWorkflowFeatureData(final List<Map<String, Object>> expectedRules) {
-        this.expectedRules.addAll(copyRules(expectedRules));
+        expectedRules.forEach(each -> this.expectedRules.add(WorkflowContextSnapshot.copyMap(each)));
     }
     
-    @Override
-    public RuleWorkflowFeatureData copy() {
+    RuleWorkflowFeatureData copy() {
         return new RuleWorkflowFeatureData(expectedRules);
     }
-    
-    private List<Map<String, Object>> copyRules(final List<Map<String, Object>> rules) {
-        List<Map<String, Object>> result = new LinkedList<>();
-        for (Map<String, Object> each : rules) {
-            result.add(copyMap(each));
-        }
-        return result;
-    }
-    
-    private Map<String, Object> copyMap(final Map<String, Object> original) {
-        Map<String, Object> result = new LinkedHashMap<>(original.size(), 1F);
-        original.forEach((key, value) -> result.put(key, copyValue(value)));
-        return result;
-    }
-    
-    private Object copyValue(final Object original) {
-        if (original instanceof Map) {
-            Map<?, ?> originalMap = (Map<?, ?>) original;
-            Map<String, Object> result = new LinkedHashMap<>(originalMap.size(), 1F);
-            originalMap.forEach((key, value) -> result.put(String.valueOf(key), copyValue(value)));
-            return result;
-        }
-        if (original instanceof List) {
-            return ((List<?>) original).stream().map(this::copyValue).toList();
-        }
-        return original;
-    }
 }
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshot.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshot.java
index a0fd5a39b75..c96578f324d 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshot.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshot.java
@@ -48,7 +48,7 @@ public final class WorkflowContextSnapshot {
     
     private ClarifiedIntent clarifiedIntent;
     
-    private WorkflowFeatureData featureData;
+    private RuleWorkflowFeatureData featureData;
     
     private InteractionPlan interactionPlan;
     
@@ -156,7 +156,7 @@ public final class WorkflowContextSnapshot {
         return new ValidationSection(original.getStatus(), copyValue(original.getEvidence()), copyValue(original.getDetails()));
     }
     
-    private static Map<String, Object> copyMap(final Map<?, ?> original) {
+    static Map<String, Object> copyMap(final Map<?, ?> original) {
         Map<String, Object> result = new LinkedHashMap<>(original.size(), 1F);
         original.forEach((key, value) -> result.put(String.valueOf(key), copyValue(value)));
         return result;
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowFeatureData.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowFeatureData.java
deleted file mode 100644
index a93d74ed791..00000000000
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowFeatureData.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.workflow.model;
-
-/**
- * Feature-scoped workflow data.
- */
-public interface WorkflowFeatureData {
-    
-    /**
-     * Copy feature data.
-     *
-     * @return copied feature data
-     */
-    WorkflowFeatureData copy();
-}
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowRequest.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowRequest.java
index a325b31e70a..77687af54cc 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowRequest.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowRequest.java
@@ -18,8 +18,6 @@
 package org.apache.shardingsphere.mcp.support.workflow.model;
 
 import lombok.Getter;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
-
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
@@ -29,7 +27,7 @@ import java.util.Map;
  * Workflow request.
  */
 @Getter
-public class WorkflowRequest implements WorkflowPropertySource {
+public class WorkflowRequest {
     
     private String planId = "";
     
@@ -140,12 +138,21 @@ public class WorkflowRequest implements WorkflowPropertySource {
         return null == source ? target : source.copyTo(target);
     }
     
-    @Override
+    /**
+     * Get algorithm properties.
+     *
+     * @param algorithmRole algorithm role
+     * @return algorithm properties
+     */
     public Map<String, String> getAlgorithmProperties(final String algorithmRole) {
         return "primary".equals(algorithmRole) ? primaryAlgorithmProperties : Map.of();
     }
     
-    @Override
+    /**
+     * Get secret references by algorithm role.
+     *
+     * @return secret references by algorithm role
+     */
     public Map<String, Map<String, SecretReferenceValue>> getSecretReferences() {
         if (primaryAlgorithmSecretReferences.isEmpty()) {
             return Map.of();
@@ -155,7 +162,12 @@ public class WorkflowRequest implements WorkflowPropertySource {
         return result;
     }
     
-    @Override
+    /**
+     * Get secret references.
+     *
+     * @param algorithmRole algorithm role
+     * @return secret references
+     */
     public Map<String, SecretReferenceValue> getSecretReferences(final String algorithmRole) {
         return "primary".equals(algorithmRole) ? primaryAlgorithmSecretReferences : Map.of();
     }
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundle.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundle.java
index baaa9071771..b835d9f0238 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundle.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundle.java
@@ -19,10 +19,10 @@ package org.apache.shardingsphere.mcp.support.workflow.service;
 
 import lombok.AccessLevel;
 import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.RuleArtifact;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 
 import java.util.Collection;
 import java.util.List;
@@ -49,22 +49,22 @@ public final class WorkflowArtifactBundle {
     /**
      * Convert workflow artifacts into executable artifacts with masked display SQL.
      *
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @param propertyRequirements property requirements
      * @return executable workflow artifacts
      */
-    public List<ExecutableWorkflowArtifact> toExecutableArtifacts(final WorkflowPropertySource propertySource, final List<AlgorithmPropertyRequirement> propertyRequirements) {
-        return ruleArtifacts.stream().map(each -> createExecutableArtifact(each, propertySource, propertyRequirements)).toList();
+    public List<ExecutableWorkflowArtifact> toExecutableArtifacts(final WorkflowRequest request, final List<AlgorithmPropertyRequirement> propertyRequirements) {
+        return ruleArtifacts.stream().map(each -> createExecutableArtifact(each, request, propertyRequirements)).toList();
     }
     
-    private ExecutableWorkflowArtifact createExecutableArtifact(final RuleArtifact ruleArtifact, final WorkflowPropertySource propertySource,
+    private ExecutableWorkflowArtifact createExecutableArtifact(final RuleArtifact ruleArtifact, final WorkflowRequest request,
                                                                 final List<AlgorithmPropertyRequirement> propertyRequirements) {
-        return new ExecutableWorkflowArtifact(ruleArtifact.getSql(), WorkflowArtifactMaskUtils.maskSensitiveSql(ruleArtifact.getSql(), propertySource, propertyRequirements));
+        return new ExecutableWorkflowArtifact(ruleArtifact.getSql(), WorkflowArtifactMaskUtils.maskSensitiveSql(ruleArtifact.getSql(), request, propertyRequirements));
     }
     
-    Map<String, Object> toPayload(final WorkflowPropertySource propertySource, final List<AlgorithmPropertyRequirement> propertyRequirements) {
+    Map<String, Object> toPayload(final WorkflowRequest request, final List<AlgorithmPropertyRequirement> propertyRequirements) {
         return Map.of(WorkflowArtifactPayloadUtils.PAYLOAD_KEY_DISTSQL_ARTIFACTS, ruleArtifacts.stream()
-                .map(each -> WorkflowArtifactMaskUtils.createMaskedRuleArtifactMap(each, propertySource, propertyRequirements)).toList());
+                .map(each -> WorkflowArtifactMaskUtils.createMaskedRuleArtifactMap(each, request, propertyRequirements)).toList());
     }
     
     public record ExecutableWorkflowArtifact(String sql, String displaySql) {
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtils.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtils.java
index 2c9ca530416..161967e0d12 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtils.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtils.java
@@ -19,11 +19,11 @@ package org.apache.shardingsphere.mcp.support.workflow.service;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.RuleArtifact;
 import org.apache.shardingsphere.mcp.support.workflow.model.SecretReferenceValue;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
@@ -42,16 +42,16 @@ public final class WorkflowArtifactMaskUtils {
      * Create masked rule artifact map.
      *
      * @param ruleArtifact rule artifact
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @param propertyRequirements property requirements
      * @return masked rule artifact map
      */
-    public static Map<String, Object> createMaskedRuleArtifactMap(final RuleArtifact ruleArtifact, final WorkflowPropertySource propertySource,
+    public static Map<String, Object> createMaskedRuleArtifactMap(final RuleArtifact ruleArtifact, final WorkflowRequest request,
                                                                   final List<AlgorithmPropertyRequirement> propertyRequirements) {
         Map<String, Object> result = new LinkedHashMap<>(4, 1F);
         result.put(WorkflowFieldNames.OPERATION_TYPE, ruleArtifact.getOperationType());
-        result.put("sql", maskSensitiveSql(ruleArtifact.getSql(), propertySource, propertyRequirements));
-        result.put("redaction", createRedactionPayload(propertySource, propertyRequirements));
+        result.put("sql", maskSensitiveSql(ruleArtifact.getSql(), request, propertyRequirements));
+        result.put("redaction", createRedactionPayload(request, propertyRequirements));
         return result;
     }
     
@@ -59,13 +59,13 @@ public final class WorkflowArtifactMaskUtils {
      * Mask sensitive values inside SQL text.
      *
      * @param sql SQL text
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @param propertyRequirements property requirements
      * @return masked SQL text
      */
-    public static String maskSensitiveSql(final String sql, final WorkflowPropertySource propertySource, final List<AlgorithmPropertyRequirement> propertyRequirements) {
-        String result = WorkflowSecretReferenceUtils.replacePlaceholdersWithManualPlaceholders(sql, propertySource);
-        for (String each : collectSecretValues(propertySource, propertyRequirements)) {
+    public static String maskSensitiveSql(final String sql, final WorkflowRequest request, final List<AlgorithmPropertyRequirement> propertyRequirements) {
+        String result = WorkflowSecretReferenceUtils.replacePlaceholdersWithManualPlaceholders(sql, request);
+        for (String each : collectSecretValues(request, propertyRequirements)) {
             if (each.isEmpty()) {
                 continue;
             }
@@ -93,14 +93,14 @@ public final class WorkflowArtifactMaskUtils {
      *
      * @param properties property values
      * @param propertyRequirements property requirements
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @param algorithmRole algorithm role
      * @return masked property values
      */
     public static Map<String, String> maskPropertyMap(final Map<String, String> properties, final List<AlgorithmPropertyRequirement> propertyRequirements,
-                                                      final WorkflowPropertySource propertySource, final String algorithmRole) {
+                                                      final WorkflowRequest request, final String algorithmRole) {
         Map<String, String> result = new LinkedHashMap<>(properties.size(), 1F);
-        properties.forEach((key, value) -> result.put(key, isSecretProperty(propertyRequirements, key) || isSecretReferenceProperty(propertySource, algorithmRole, key)
+        properties.forEach((key, value) -> result.put(key, isSecretProperty(propertyRequirements, key) || isSecretReferenceProperty(request, algorithmRole, key)
                 || isSecretReferencePlaceholder(value) ? "******" : value));
         return result;
     }
@@ -108,11 +108,11 @@ public final class WorkflowArtifactMaskUtils {
     /**
      * Create secret reference summary payload.
      *
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return secret reference summary payload
      */
-    public static Map<String, Object> createSecretReferenceSummary(final WorkflowPropertySource propertySource) {
-        List<Map<String, Object>> references = WorkflowSecretReferenceUtils.createSafeSummaries(propertySource);
+    public static Map<String, Object> createSecretReferenceSummary(final WorkflowRequest request) {
+        List<Map<String, Object>> references = WorkflowSecretReferenceUtils.createSafeSummaries(request);
         Map<String, Object> result = new LinkedHashMap<>(4, 1F);
         result.put("required", !references.isEmpty());
         result.put("reference_count", references.size());
@@ -121,8 +121,8 @@ public final class WorkflowArtifactMaskUtils {
         return result;
     }
     
-    private static Map<String, Object> createRedactionPayload(final WorkflowPropertySource propertySource, final List<AlgorithmPropertyRequirement> propertyRequirements) {
-        List<String> redactedProperties = collectSecretPropertyNames(propertySource, propertyRequirements).stream().toList();
+    private static Map<String, Object> createRedactionPayload(final WorkflowRequest request, final List<AlgorithmPropertyRequirement> propertyRequirements) {
+        List<String> redactedProperties = collectSecretPropertyNames(request, propertyRequirements).stream().toList();
         Map<String, Object> result = new LinkedHashMap<>(5, 1F);
         result.put("applied", !redactedProperties.isEmpty());
         result.put("marker", "******");
@@ -137,40 +137,40 @@ public final class WorkflowArtifactMaskUtils {
         return 0 > separatorIndex ? redactedProperty : redactedProperty.substring(separatorIndex + 1);
     }
     
-    private static Set<String> collectSecretValues(final WorkflowPropertySource propertySource, final List<AlgorithmPropertyRequirement> propertyRequirements) {
+    private static Set<String> collectSecretValues(final WorkflowRequest request, final List<AlgorithmPropertyRequirement> propertyRequirements) {
         Set<String> result = new LinkedHashSet<>();
         for (AlgorithmPropertyRequirement each : propertyRequirements) {
             if (!each.isSecret()) {
                 continue;
             }
-            String value = getPropertyValue(propertySource, each);
+            String value = getPropertyValue(request, each);
             if (null != value && !value.isBlank()) {
                 result.add(value.trim());
             }
         }
-        propertySource.getSecretReferences().forEach((algorithmRole, references) -> references.keySet().forEach(
+        request.getSecretReferences().forEach((algorithmRole, references) -> references.keySet().forEach(
                 propertyKey -> result.add(SecretReferenceValue.createPlaceholder(algorithmRole, propertyKey))));
         return result;
     }
     
-    private static Set<String> collectSecretPropertyNames(final WorkflowPropertySource propertySource, final List<AlgorithmPropertyRequirement> propertyRequirements) {
+    private static Set<String> collectSecretPropertyNames(final WorkflowRequest request, final List<AlgorithmPropertyRequirement> propertyRequirements) {
         Set<String> result = new LinkedHashSet<>();
         for (AlgorithmPropertyRequirement each : propertyRequirements) {
             if (!each.isSecret()) {
                 continue;
             }
-            String value = getPropertyValue(propertySource, each);
+            String value = getPropertyValue(request, each);
             if (null != value && !value.isBlank()) {
                 result.add(each.getAlgorithmRole() + "." + each.getPropertyKey());
             }
         }
-        propertySource.getSecretReferences().forEach((algorithmRole, references) -> references.keySet().forEach(
+        request.getSecretReferences().forEach((algorithmRole, references) -> references.keySet().forEach(
                 propertyKey -> result.add(algorithmRole + "." + propertyKey)));
         return result;
     }
     
-    private static String getPropertyValue(final WorkflowPropertySource propertySource, final AlgorithmPropertyRequirement propertyRequirement) {
-        return propertySource.getAlgorithmProperties(propertyRequirement.getAlgorithmRole()).get(propertyRequirement.getPropertyKey());
+    private static String getPropertyValue(final WorkflowRequest request, final AlgorithmPropertyRequirement propertyRequirement) {
+        return request.getAlgorithmProperties(propertyRequirement.getAlgorithmRole()).get(propertyRequirement.getPropertyKey());
     }
     
     private static boolean isSecretProperty(final List<AlgorithmPropertyRequirement> propertyRequirements, final String propertyKey) {
@@ -189,7 +189,7 @@ public final class WorkflowArtifactMaskUtils {
         return null != value && value.startsWith("secret_reference:");
     }
     
-    private static boolean isSecretReferenceProperty(final WorkflowPropertySource propertySource, final String algorithmRole, final String propertyKey) {
-        return null != propertySource && propertySource.getSecretReferences(algorithmRole).containsKey(propertyKey);
+    private static boolean isSecretReferenceProperty(final WorkflowRequest request, final String algorithmRole, final String propertyKey) {
+        return null != request && request.getSecretReferences(algorithmRole).containsKey(propertyKey);
     }
 }
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactPayloadUtils.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactPayloadUtils.java
index ff7c41705cf..0670a6542bd 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactPayloadUtils.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactPayloadUtils.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.mcp.support.workflow.service;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 
 import java.util.Map;
 
@@ -42,11 +42,11 @@ public final class WorkflowArtifactPayloadUtils {
      * Create masked workflow artifact payload.
      *
      * @param snapshot workflow snapshot
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return masked workflow artifact payload
      */
-    public static Map<String, Object> createArtifactPayload(final WorkflowContextSnapshot snapshot, final WorkflowPropertySource propertySource) {
-        return WorkflowArtifactBundle.from(snapshot).toPayload(propertySource, snapshot.getPropertyRequirements());
+    public static Map<String, Object> createArtifactPayload(final WorkflowContextSnapshot snapshot, final WorkflowRequest request) {
+        return WorkflowArtifactBundle.from(snapshot).toPayload(request, snapshot.getPropertyRequirements());
     }
     
 }
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanPayloadBuilder.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanPayloadBuilder.java
index 20fe1544959..069851904d6 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanPayloadBuilder.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanPayloadBuilder.java
@@ -20,7 +20,6 @@ package org.apache.shardingsphere.mcp.support.workflow.service;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
 import org.apache.shardingsphere.mcp.support.protocol.MCPPayloadFieldNames;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.descriptor.WorkflowToolDescriptors;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmCandidate;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
@@ -89,12 +88,12 @@ public final class WorkflowPlanPayloadBuilder {
      * Build one workflow-plan payload map with generated artifacts.
      *
      * @param snapshot workflow snapshot
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return workflow-plan payload with generated artifacts
      */
-    public static Map<String, Object> buildWithArtifacts(final WorkflowContextSnapshot snapshot, final WorkflowPropertySource propertySource) {
+    public static Map<String, Object> buildWithArtifacts(final WorkflowContextSnapshot snapshot, final WorkflowRequest request) {
         Map<String, Object> result = build(snapshot);
-        result.putAll(WorkflowArtifactPayloadUtils.createArtifactPayload(snapshot, propertySource));
+        result.putAll(WorkflowArtifactPayloadUtils.createArtifactPayload(snapshot, request));
         return result;
     }
     
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupport.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupport.java
index afd63dc420e..0439623ee13 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupport.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowPlanningSupport.java
@@ -25,8 +25,8 @@ import org.apache.shardingsphere.mcp.support.database.spi.MCPMetadataQueryFacade
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.ClarifiedIntent;
 import org.apache.shardingsphere.mcp.support.workflow.model.InteractionPlan;
+import org.apache.shardingsphere.mcp.support.workflow.model.RuleWorkflowFeatureData;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFeatureData;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowIssue;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowIssueCode;
@@ -73,7 +73,8 @@ public final class WorkflowPlanningSupport {
      * @param <T> request type
      * @return prepared request
      */
-    public <T extends WorkflowRequest> T prepareSnapshot(final WorkflowContextSnapshot snapshot, final WorkflowKind workflowKind, final T request, final WorkflowFeatureData featureData,
+    public <T extends WorkflowRequest> T prepareSnapshot(final WorkflowContextSnapshot snapshot, final WorkflowKind workflowKind, final T request,
+                                                         final RuleWorkflowFeatureData featureData,
                                                          final ClarifiedIntent clarifiedIntent, final String summary,
                                                          final List<String> interactionSteps, final List<String> validationLayers) {
         WorkflowKind existingWorkflowKind = snapshot.getWorkflowKind();
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtils.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtils.java
index bd022c98ddf..9b0b12a0c5e 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtils.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtils.java
@@ -19,8 +19,8 @@ package org.apache.shardingsphere.mcp.support.workflow.service;
 
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.SecretReferenceValue;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -90,12 +90,12 @@ public final class WorkflowSecretReferenceUtils {
     /**
      * Create safe summaries for secret references.
      *
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return safe summaries
      */
-    public static List<Map<String, Object>> createSafeSummaries(final WorkflowPropertySource propertySource) {
+    public static List<Map<String, Object>> createSafeSummaries(final WorkflowRequest request) {
         List<Map<String, Object>> result = new LinkedList<>();
-        propertySource.getSecretReferences().forEach((algorithmRole, references) -> references.forEach(
+        request.getSecretReferences().forEach((algorithmRole, references) -> references.forEach(
                 (propertyKey, reference) -> result.add(reference.toSafeSummary(algorithmRole, propertyKey))));
         return result;
     }
@@ -104,15 +104,15 @@ public final class WorkflowSecretReferenceUtils {
      * Replace secret reference placeholders with manual placeholders in SQL.
      *
      * @param sql SQL text
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return SQL text with manual placeholders
      */
-    public static String replacePlaceholdersWithManualPlaceholders(final String sql, final WorkflowPropertySource propertySource) {
+    public static String replacePlaceholdersWithManualPlaceholders(final String sql, final WorkflowRequest request) {
         String result = sql;
-        if (null == propertySource) {
+        if (null == request) {
             return result;
         }
-        for (Entry<String, Map<String, SecretReferenceValue>> groupEntry : propertySource.getSecretReferences().entrySet()) {
+        for (Entry<String, Map<String, SecretReferenceValue>> groupEntry : request.getSecretReferences().entrySet()) {
             for (String each : groupEntry.getValue().keySet()) {
                 result = result.replace(SecretReferenceValue.createPlaceholder(groupEntry.getKey(), each), SecretReferenceValue.createManualPlaceholder(groupEntry.getKey(), each));
             }
@@ -123,24 +123,24 @@ public final class WorkflowSecretReferenceUtils {
     /**
      * Judge whether a workflow property source has secret references.
      *
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return whether secret references exist
      */
-    public static boolean hasSecretReferences(final WorkflowPropertySource propertySource) {
-        return null != propertySource && propertySource.getSecretReferences().values().stream().anyMatch(each -> !each.isEmpty());
+    public static boolean hasSecretReferences(final WorkflowRequest request) {
+        return null != request && request.getSecretReferences().values().stream().anyMatch(each -> !each.isEmpty());
     }
     
     /**
      * Judge whether a workflow property source has malformed secret references.
      *
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @return whether malformed secret references exist
      */
-    public static boolean hasMalformedSecretReferences(final WorkflowPropertySource propertySource) {
-        if (null == propertySource) {
+    public static boolean hasMalformedSecretReferences(final WorkflowRequest request) {
+        if (null == request) {
             return false;
         }
-        return propertySource.getSecretReferences().values().stream().flatMap(each -> each.values().stream()).anyMatch(SecretReferenceValue::isMalformed);
+        return request.getSecretReferences().values().stream().flatMap(each -> each.values().stream()).anyMatch(SecretReferenceValue::isMalformed);
     }
     
     /**
@@ -148,18 +148,18 @@ public final class WorkflowSecretReferenceUtils {
      *
      * @param expectedProperties expected properties
      * @param actualProperties actual properties
-     * @param propertySource workflow property source
+     * @param request workflow request
      * @param algorithmRole algorithm role
      * @return whether property maps match
      */
     public static boolean matchesManualPlaceholderProperties(final Map<String, String> expectedProperties, final Map<String, String> actualProperties,
-                                                             final WorkflowPropertySource propertySource, final String algorithmRole) {
-        if (null == propertySource) {
+                                                             final WorkflowRequest request, final String algorithmRole) {
+        if (null == request) {
             return expectedProperties.equals(actualProperties);
         }
         Map<String, String> comparableExpected = new LinkedHashMap<>(expectedProperties);
         Map<String, String> comparableActual = new LinkedHashMap<>(actualProperties);
-        for (String each : propertySource.getSecretReferences(algorithmRole).keySet()) {
+        for (String each : request.getSecretReferences(algorithmRole).keySet()) {
             String expectedPlaceholder = SecretReferenceValue.createPlaceholder(algorithmRole, each);
             if (!expectedPlaceholder.equals(expectedProperties.get(each))) {
                 continue;
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowApplySynchronizationHandler.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowApplySynchronizationHandler.java
deleted file mode 100644
index 98521f8f0b0..00000000000
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowApplySynchronizationHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.workflow.spi;
-
-import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureExecutionFacade;
-import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
-import org.apache.shardingsphere.mcp.support.database.spi.MCPMetadataQueryFacade;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-
-/**
- * Workflow apply synchronization handler.
- */
-@FunctionalInterface
-public interface MCPWorkflowApplySynchronizationHandler {
-    
-    /**
-     * Synchronize workflow state after apply execution.
-     *
-     * @param snapshot workflow snapshot
-     * @param metadataQueryFacade metadata query facade
-     * @param queryFacade direct query facade
-     * @param executionFacade execution facade
-     * @param sessionId session id
-     */
-    void synchronize(WorkflowContextSnapshot snapshot, MCPMetadataQueryFacade metadataQueryFacade,
-                     MCPFeatureQueryFacade queryFacade, MCPFeatureExecutionFacade executionFacade, String sessionId);
-}
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowRuntimeHandler.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowRuntimeHandler.java
index e7aa6cf3749..fb327d99b16 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowRuntimeHandler.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowRuntimeHandler.java
@@ -17,8 +17,42 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.spi;
 
+import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureExecutionFacade;
+import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
+import org.apache.shardingsphere.mcp.support.database.spi.MCPMetadataQueryFacade;
+import org.apache.shardingsphere.mcp.support.workflow.WorkflowSessionContext;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
+
+import java.util.Map;
+
 /**
  * Workflow runtime handler for validation and apply synchronization.
  */
-public interface MCPWorkflowRuntimeHandler extends MCPWorkflowValidationHandler, MCPWorkflowApplySynchronizationHandler {
+public interface MCPWorkflowRuntimeHandler {
+    
+    /**
+     * Validate one workflow plan.
+     *
+     * @param workflowSessionContext workflow session context
+     * @param metadataQueryFacade metadata query facade
+     * @param queryFacade direct query facade
+     * @param executionFacade execution facade
+     * @param sessionId session id
+     * @param snapshot workflow snapshot
+     * @return validation payload
+     */
+    Map<String, Object> validate(WorkflowSessionContext workflowSessionContext, MCPMetadataQueryFacade metadataQueryFacade,
+                                 MCPFeatureQueryFacade queryFacade, MCPFeatureExecutionFacade executionFacade, String sessionId, WorkflowContextSnapshot snapshot);
+    
+    /**
+     * Synchronize workflow state after apply execution.
+     *
+     * @param snapshot workflow snapshot
+     * @param metadataQueryFacade metadata query facade
+     * @param queryFacade direct query facade
+     * @param executionFacade execution facade
+     * @param sessionId session id
+     */
+    void synchronize(WorkflowContextSnapshot snapshot, MCPMetadataQueryFacade metadataQueryFacade,
+                     MCPFeatureQueryFacade queryFacade, MCPFeatureExecutionFacade executionFacade, String sessionId);
 }
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowValidationHandler.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowValidationHandler.java
deleted file mode 100644
index 086d5305763..00000000000
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/MCPWorkflowValidationHandler.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.workflow.spi;
-
-import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureExecutionFacade;
-import org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
-import org.apache.shardingsphere.mcp.support.database.spi.MCPMetadataQueryFacade;
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowSessionContext;
-import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
-
-import java.util.Map;
-
-/**
- * Workflow validation handler.
- */
-@FunctionalInterface
-public interface MCPWorkflowValidationHandler {
-    
-    /**
-     * Validate one workflow plan.
-     *
-     * @param workflowSessionContext workflow session context
-     * @param metadataQueryFacade metadata query facade
-     * @param queryFacade direct query facade
-     * @param executionFacade execution facade
-     * @param sessionId session id
-     * @param snapshot workflow snapshot
-     * @return validation payload
-     */
-    Map<String, Object> validate(WorkflowSessionContext workflowSessionContext, MCPMetadataQueryFacade metadataQueryFacade,
-                                 MCPFeatureQueryFacade queryFacade, MCPFeatureExecutionFacade executionFacade, String sessionId, WorkflowContextSnapshot snapshot);
-}
diff --git a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/WorkflowRuntimeDefinition.java b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/WorkflowRuntimeDefinition.java
index 7233a0b4050..2e41627c676 100644
--- a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/WorkflowRuntimeDefinition.java
+++ b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/workflow/spi/WorkflowRuntimeDefinition.java
@@ -17,7 +17,6 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.spi;
 
-import lombok.AllArgsConstructor;
 import lombok.Getter;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowKind;
 
@@ -25,14 +24,11 @@ import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowKind;
  * Workflow runtime definition.
  */
 @Getter
-@AllArgsConstructor
 public final class WorkflowRuntimeDefinition {
     
     private final WorkflowKind workflowKind;
     
-    private final MCPWorkflowValidationHandler validationHandler;
-    
-    private final MCPWorkflowApplySynchronizationHandler applySynchronizationHandler;
+    private final MCPWorkflowRuntimeHandler runtimeHandler;
     
     private final MCPWorkflowApplyArtifactValidator applyArtifactValidator;
     
@@ -44,7 +40,21 @@ public final class WorkflowRuntimeDefinition {
      * @param runtimeHandler workflow runtime handler
      */
     public WorkflowRuntimeDefinition(final WorkflowKind workflowKind, final MCPWorkflowRuntimeHandler runtimeHandler) {
-        this(workflowKind, runtimeHandler, runtimeHandler, createApplyArtifactValidator(runtimeHandler));
+        this(workflowKind, runtimeHandler, createApplyArtifactValidator(runtimeHandler));
+    }
+    
+    /**
+     * Create workflow runtime definition with an explicit apply artifact validator.
+     *
+     * @param workflowKind workflow kind
+     * @param runtimeHandler workflow runtime handler
+     * @param applyArtifactValidator apply artifact validator
+     */
+    public WorkflowRuntimeDefinition(final WorkflowKind workflowKind, final MCPWorkflowRuntimeHandler runtimeHandler,
+                                     final MCPWorkflowApplyArtifactValidator applyArtifactValidator) {
+        this.workflowKind = workflowKind;
+        this.runtimeHandler = runtimeHandler;
+        this.applyArtifactValidator = applyArtifactValidator;
     }
     
     private static MCPWorkflowApplyArtifactValidator createApplyArtifactValidator(final MCPWorkflowRuntimeHandler runtimeHandler) {
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseConfigurationTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseConfigurationTest.java
index a303b5dc0f1..f0ccae18ace 100644
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseConfigurationTest.java
+++ b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/jdbc/RuntimeDatabaseConfigurationTest.java
@@ -42,15 +42,6 @@ import static org.mockito.Mockito.when;
 
 class RuntimeDatabaseConfigurationTest {
     
-    @Test
-    void assertNewRuntimeDatabaseConfiguration() {
-        RuntimeDatabaseConfiguration actual = new RuntimeDatabaseConfiguration(RecordingDriver.JDBC_URL, "sa", "pwd", RecordingDriver.class.getName());
-        assertThat(actual.getJdbcUrl(), is(RecordingDriver.JDBC_URL));
-        assertThat(actual.getUsername(), is("sa"));
-        assertThat(actual.getPassword(), is("pwd"));
-        assertThat(actual.getDriverClassName(), is(RecordingDriver.class.getName()));
-    }
-    
     @Test
     void assertOpenConnectionWithoutCredentials() throws SQLException {
         RecordingDriver.reset();
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/DatabaseTestDataFactory.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/DatabaseTestDataFactory.java
deleted file mode 100644
index da8aca26c69..00000000000
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/DatabaseTestDataFactory.java
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.database.metadata.query;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.mcp.support.database.metadata.jdbc.RuntimeDatabaseConfiguration;
-import org.apache.shardingsphere.mcp.support.fixture.SupportDatabaseTypeFactoryMocker;
-
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Types;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-final class DatabaseTestDataFactory {
-    
-    private static List<DatabaseFixture> createDatabaseMetadata() {
-        return List.of(
-                new DatabaseFixture("logic_db", "MySQL", "", List.of(
-                        new SchemaFixture("public", List.of(
-                                new TableFixture("orders", List.of("order_id", "amount"), List.of("order_idx")),
-                                new TableFixture("order_items", List.of("item_id"), List.of())),
-                                List.of(new TableFixture("orders_view", List.of("order_id"), List.of())), List.of()))),
-                new DatabaseFixture("runtime_db", "PostgreSQL", "", List.of(
-                        new SchemaFixture("public", List.of(), List.of(), List.of("order_seq")))),
-                new DatabaseFixture("warehouse", "Hive", "", List.of(
-                        new SchemaFixture("warehouse", List.of(new TableFixture("facts", List.of(), List.of())), List.of(), List.of()))));
-    }
-    
-    static Map<String, RuntimeDatabaseConfiguration> createRuntimeDatabases() {
-        Map<String, RuntimeDatabaseConfiguration> result = new LinkedHashMap<>(3, 1F);
-        for (DatabaseFixture each : createDatabaseMetadata()) {
-            result.put(each.database, createRuntimeDatabaseConfiguration(each));
-        }
-        return result;
-    }
-    
-    private static RuntimeDatabaseConfiguration createRuntimeDatabaseConfiguration(final DatabaseFixture databaseMetadata) {
-        RuntimeDatabaseConfiguration result = mock(RuntimeDatabaseConfiguration.class);
-        try {
-            when(result.openConnection(databaseMetadata.database)).thenAnswer(invocation -> createConnection(databaseMetadata));
-        } catch (final SQLException ex) {
-            throw new IllegalStateException(ex);
-        }
-        return result;
-    }
-    
-    private static Connection createConnection(final DatabaseFixture databaseMetadata) throws SQLException {
-        Connection result = mock(Connection.class);
-        DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class);
-        Statement statement = mock(Statement.class);
-        when(result.getMetaData()).thenReturn(databaseMetaData);
-        when(result.createStatement()).thenReturn(statement);
-        when(databaseMetaData.getDatabaseProductVersion()).thenReturn(databaseMetadata.databaseVersion);
-        when(databaseMetaData.getURL()).thenReturn(SupportDatabaseTypeFactoryMocker.createJdbcUrl(databaseMetadata.databaseType));
-        when(databaseMetaData.getSearchStringEscape()).thenReturn("\\");
-        when(databaseMetaData.getTables(nullable(String.class), nullable(String.class), eq("%"), any(String[].class))).thenAnswer(invocation -> {
-            String[] tableTypes = invocation.getArgument(3, String[].class);
-            return createResultSet("TABLE".equals(tableTypes[0]) ? createTableRows(databaseMetadata) : createViewRows(databaseMetadata));
-        });
-        when(databaseMetaData.getColumns(nullable(String.class), nullable(String.class), anyString(), eq("%")))
-                .thenAnswer(invocation -> createResultSet(createColumnRows(databaseMetadata, invocation.getArgument(2, String.class))));
-        when(databaseMetaData.getIndexInfo(nullable(String.class), nullable(String.class), anyString(), eq(false), eq(false)))
-                .thenAnswer(invocation -> createResultSet(createIndexRows(databaseMetadata, invocation.getArgument(2, String.class))));
-        ResultSet sequenceResultSet = createResultSet(createSequenceRows(databaseMetadata));
-        when(statement.executeQuery(anyString())).thenReturn(sequenceResultSet);
-        return result;
-    }
-    
-    private static List<Map<String, Object>> createTableRows(final DatabaseFixture databaseMetadata) {
-        List<Map<String, Object>> result = new LinkedList<>();
-        for (SchemaFixture each : databaseMetadata.schemas) {
-            for (TableFixture table : each.tables) {
-                result.add(Map.of("TABLE_SCHEM", each.schema, "TABLE_CAT", "", "TABLE_NAME", table.name));
-            }
-        }
-        return result;
-    }
-    
-    private static List<Map<String, Object>> createViewRows(final DatabaseFixture databaseMetadata) {
-        List<Map<String, Object>> result = new LinkedList<>();
-        for (SchemaFixture each : databaseMetadata.schemas) {
-            for (TableFixture view : each.views) {
-                result.add(Map.of("TABLE_SCHEM", each.schema, "TABLE_CAT", "", "TABLE_NAME", view.name));
-            }
-        }
-        return result;
-    }
-    
-    private static List<Map<String, Object>> createColumnRows(final DatabaseFixture databaseMetadata, final String objectName) {
-        List<Map<String, Object>> result = new LinkedList<>();
-        String relationName = "%".equals(objectName) ? "" : unescapePattern(objectName);
-        for (SchemaFixture each : databaseMetadata.schemas) {
-            for (TableFixture table : each.tables) {
-                if (relationName.isEmpty() || table.name.equals(relationName)) {
-                    for (int i = 0; i < table.columns.size(); i++) {
-                        result.add(createColumnRow(table.name, table.columns.get(i), i + 1));
-                    }
-                }
-            }
-            for (TableFixture view : each.views) {
-                if (relationName.isEmpty() || view.name.equals(relationName)) {
-                    for (int i = 0; i < view.columns.size(); i++) {
-                        result.add(createColumnRow(view.name, view.columns.get(i), i + 1));
-                    }
-                }
-            }
-        }
-        return result;
-    }
-    
-    private static String unescapePattern(final String value) {
-        StringBuilder result = new StringBuilder(value.length());
-        boolean escaped = false;
-        for (char each : value.toCharArray()) {
-            if (escaped) {
-                result.append(each);
-                escaped = false;
-            } else if ('\\' == each) {
-                escaped = true;
-            } else {
-                result.append(each);
-            }
-        }
-        return escaped ? result.append('\\').toString() : result.toString();
-    }
-    
-    private static Map<String, Object> createColumnRow(final String relationName, final String columnName, final int ordinalPosition) {
-        return Map.of("TABLE_NAME", relationName, "COLUMN_NAME", columnName, "ORDINAL_POSITION", ordinalPosition,
-                "DATA_TYPE", Types.INTEGER, "TYPE_NAME", "INT", "NULLABLE", DatabaseMetaData.columnNullable);
-    }
-    
-    private static List<Map<String, Object>> createIndexRows(final DatabaseFixture databaseMetadata, final String tableName) {
-        List<Map<String, Object>> result = new LinkedList<>();
-        for (SchemaFixture each : databaseMetadata.schemas) {
-            for (TableFixture table : each.tables) {
-                if (table.name.equals(tableName)) {
-                    for (String index : table.indexes) {
-                        result.add(Map.of("INDEX_NAME", index, "TYPE", DatabaseMetaData.tableIndexOther, "NON_UNIQUE", false,
-                                "ORDINAL_POSITION", 1, "COLUMN_NAME", table.columns.isEmpty() ? "" : table.columns.getFirst()));
-                    }
-                }
-            }
-        }
-        return result;
-    }
-    
-    private static List<Map<String, Object>> createSequenceRows(final DatabaseFixture databaseMetadata) {
-        List<Map<String, Object>> result = new LinkedList<>();
-        for (SchemaFixture each : databaseMetadata.schemas) {
-            for (String sequence : each.sequences) {
-                result.add(Map.of("SEQUENCE_SCHEMA", each.schema, "SEQUENCE_NAME", sequence));
-            }
-        }
-        return result;
-    }
-    
-    private static ResultSet createResultSet(final List<Map<String, Object>> rows) throws SQLException {
-        ResultSet result = mock(ResultSet.class);
-        AtomicInteger rowIndex = new AtomicInteger(-1);
-        when(result.next()).thenAnswer(invocation -> rowIndex.incrementAndGet() < rows.size());
-        when(result.getString(anyString())).thenAnswer(invocation -> {
-            Object value = rows.get(rowIndex.get()).get(invocation.getArgument(0, String.class));
-            return null == value ? null : value.toString();
-        });
-        when(result.getInt(anyString())).thenAnswer(invocation -> getNumber(rows, rowIndex.get(), invocation.getArgument(0, String.class)).intValue());
-        when(result.getShort(anyString())).thenAnswer(invocation -> getNumber(rows, rowIndex.get(), invocation.getArgument(0, String.class)).shortValue());
-        when(result.getBoolean(anyString())).thenAnswer(invocation -> Boolean.TRUE.equals(rows.get(rowIndex.get()).get(invocation.getArgument(0, String.class))));
-        return result;
-    }
-    
-    private static Number getNumber(final List<Map<String, Object>> rows, final int rowIndex, final String columnLabel) {
-        Object value = rows.get(rowIndex).get(columnLabel);
-        return value instanceof Number ? (Number) value : 0;
-    }
-    
-    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
-    private static final class DatabaseFixture {
-        
-        private final String database;
-        
-        private final String databaseType;
-        
-        private final String databaseVersion;
-        
-        private final List<SchemaFixture> schemas;
-    }
-    
-    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
-    private static final class SchemaFixture {
-        
-        private final String schema;
-        
-        private final List<TableFixture> tables;
-        
-        private final List<TableFixture> views;
-        
-        private final List<String> sequences;
-    }
-    
-    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
-    private static final class TableFixture {
-        
-        private final String name;
-        
-        private final List<String> columns;
-        
-        private final List<String> indexes;
-    }
-}
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/MetadataQueryServiceTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/MetadataQueryServiceTest.java
index 17681f5f2a7..fa500f5e2fc 100644
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/MetadataQueryServiceTest.java
+++ b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/database/metadata/query/MetadataQueryServiceTest.java
@@ -47,10 +47,18 @@ import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 import org.mockito.MockedStatic;
 
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
 import java.util.List;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.Map;
 import java.util.Optional;
-import java.sql.Types;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.stream.Stream;
 
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -58,6 +66,10 @@ import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.nullable;
 import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.mockStatic;
@@ -81,7 +93,7 @@ class MetadataQueryServiceTest {
         mockDatabaseType("MySQL", false);
         mockDatabaseType("PostgreSQL", true);
         mockDatabaseType("Hive", false);
-        Map<String, RuntimeDatabaseConfiguration> runtimeDatabases = DatabaseTestDataFactory.createRuntimeDatabases();
+        Map<String, RuntimeDatabaseConfiguration> runtimeDatabases = createRuntimeDatabases();
         MCPDatabaseCapabilityProvider databaseCapabilityProvider = new MCPDatabaseCapabilityProvider(runtimeDatabases);
         metadataQueryService = new MetadataQueryService(databaseCapabilityProvider, new RequestScopedMetadataContext(runtimeDatabases, databaseCapabilityProvider));
     }
@@ -361,4 +373,171 @@ class MetadataQueryServiceTest {
                 Arguments.of("unsupported sequence", "logic_db", SupportedMCPMetadataObjectType.SEQUENCE, false),
                 Arguments.of("missing database", "unknown_db", SupportedMCPMetadataObjectType.TABLE, false));
     }
+    
+    private static Map<String, RuntimeDatabaseConfiguration> createRuntimeDatabases() {
+        Map<String, RuntimeDatabaseConfiguration> result = new LinkedHashMap<>(3, 1F);
+        for (DatabaseFixture each : createDatabaseMetadata()) {
+            result.put(each.database(), createRuntimeDatabaseConfiguration(each));
+        }
+        return result;
+    }
+    
+    private static List<DatabaseFixture> createDatabaseMetadata() {
+        return List.of(
+                new DatabaseFixture("logic_db", "MySQL", "", List.of(
+                        new SchemaFixture("public", List.of(
+                                new TableFixture("orders", List.of("order_id", "amount"), List.of("order_idx")),
+                                new TableFixture("order_items", List.of("item_id"), List.of())),
+                                List.of(new TableFixture("orders_view", List.of("order_id"), List.of())), List.of()))),
+                new DatabaseFixture("runtime_db", "PostgreSQL", "", List.of(
+                        new SchemaFixture("public", List.of(), List.of(), List.of("order_seq")))),
+                new DatabaseFixture("warehouse", "Hive", "", List.of(
+                        new SchemaFixture("warehouse", List.of(new TableFixture("facts", List.of(), List.of())), List.of(), List.of()))));
+    }
+    
+    private static RuntimeDatabaseConfiguration createRuntimeDatabaseConfiguration(final DatabaseFixture databaseMetadata) {
+        RuntimeDatabaseConfiguration result = mock(RuntimeDatabaseConfiguration.class);
+        try {
+            when(result.openConnection(databaseMetadata.database())).thenAnswer(invocation -> createConnection(databaseMetadata));
+        } catch (final SQLException ex) {
+            throw new IllegalStateException(ex);
+        }
+        return result;
+    }
+    
+    private static Connection createConnection(final DatabaseFixture databaseMetadata) throws SQLException {
+        Connection result = mock(Connection.class);
+        DatabaseMetaData databaseMetaData = mock(DatabaseMetaData.class);
+        Statement statement = mock(Statement.class);
+        when(result.getMetaData()).thenReturn(databaseMetaData);
+        when(result.createStatement()).thenReturn(statement);
+        when(databaseMetaData.getDatabaseProductVersion()).thenReturn(databaseMetadata.databaseVersion());
+        when(databaseMetaData.getURL()).thenReturn(SupportDatabaseTypeFactoryMocker.createJdbcUrl(databaseMetadata.databaseType()));
+        when(databaseMetaData.getSearchStringEscape()).thenReturn("\\");
+        when(databaseMetaData.getTables(nullable(String.class), nullable(String.class), eq("%"), any(String[].class))).thenAnswer(invocation -> {
+            String[] tableTypes = invocation.getArgument(3, String[].class);
+            return createResultSet("TABLE".equals(tableTypes[0]) ? createTableRows(databaseMetadata) : createViewRows(databaseMetadata));
+        });
+        when(databaseMetaData.getColumns(nullable(String.class), nullable(String.class), anyString(), eq("%")))
+                .thenAnswer(invocation -> createResultSet(createColumnRows(databaseMetadata, invocation.getArgument(2, String.class))));
+        when(databaseMetaData.getIndexInfo(nullable(String.class), nullable(String.class), anyString(), eq(false), eq(false)))
+                .thenAnswer(invocation -> createResultSet(createIndexRows(databaseMetadata, invocation.getArgument(2, String.class))));
+        ResultSet sequenceResultSet = createResultSet(createSequenceRows(databaseMetadata));
+        when(statement.executeQuery(anyString())).thenReturn(sequenceResultSet);
+        return result;
+    }
+    
+    private static List<Map<String, Object>> createTableRows(final DatabaseFixture databaseMetadata) {
+        List<Map<String, Object>> result = new LinkedList<>();
+        for (SchemaFixture each : databaseMetadata.schemas()) {
+            for (TableFixture table : each.tables()) {
+                result.add(Map.of("TABLE_SCHEM", each.schema(), "TABLE_CAT", "", "TABLE_NAME", table.name()));
+            }
+        }
+        return result;
+    }
+    
+    private static List<Map<String, Object>> createViewRows(final DatabaseFixture databaseMetadata) {
+        List<Map<String, Object>> result = new LinkedList<>();
+        for (SchemaFixture each : databaseMetadata.schemas()) {
+            for (TableFixture view : each.views()) {
+                result.add(Map.of("TABLE_SCHEM", each.schema(), "TABLE_CAT", "", "TABLE_NAME", view.name()));
+            }
+        }
+        return result;
+    }
+    
+    private static List<Map<String, Object>> createColumnRows(final DatabaseFixture databaseMetadata, final String objectName) {
+        List<Map<String, Object>> result = new LinkedList<>();
+        String relationName = "%".equals(objectName) ? "" : unescapePattern(objectName);
+        for (SchemaFixture each : databaseMetadata.schemas()) {
+            appendColumnRows(result, each.tables(), relationName);
+            appendColumnRows(result, each.views(), relationName);
+        }
+        return result;
+    }
+    
+    private static void appendColumnRows(final List<Map<String, Object>> result, final List<TableFixture> relations, final String relationName) {
+        for (TableFixture each : relations) {
+            if (relationName.isEmpty() || each.name().equals(relationName)) {
+                for (int i = 0; i < each.columns().size(); i++) {
+                    result.add(createColumnRow(each.name(), each.columns().get(i), i + 1));
+                }
+            }
+        }
+    }
+    
+    private static String unescapePattern(final String value) {
+        StringBuilder result = new StringBuilder(value.length());
+        boolean escaped = false;
+        for (char each : value.toCharArray()) {
+            if (escaped) {
+                result.append(each);
+                escaped = false;
+            } else if ('\\' == each) {
+                escaped = true;
+            } else {
+                result.append(each);
+            }
+        }
+        return escaped ? result.append('\\').toString() : result.toString();
+    }
+    
+    private static Map<String, Object> createColumnRow(final String relationName, final String columnName, final int ordinalPosition) {
+        return Map.of("TABLE_NAME", relationName, "COLUMN_NAME", columnName, "ORDINAL_POSITION", ordinalPosition,
+                "DATA_TYPE", Types.INTEGER, "TYPE_NAME", "INT", "NULLABLE", DatabaseMetaData.columnNullable);
+    }
+    
+    private static List<Map<String, Object>> createIndexRows(final DatabaseFixture databaseMetadata, final String tableName) {
+        List<Map<String, Object>> result = new LinkedList<>();
+        for (SchemaFixture each : databaseMetadata.schemas()) {
+            for (TableFixture table : each.tables()) {
+                if (table.name().equals(tableName)) {
+                    for (String index : table.indexes()) {
+                        result.add(Map.of("INDEX_NAME", index, "TYPE", DatabaseMetaData.tableIndexOther, "NON_UNIQUE", false,
+                                "ORDINAL_POSITION", 1, "COLUMN_NAME", table.columns().isEmpty() ? "" : table.columns().getFirst()));
+                    }
+                }
+            }
+        }
+        return result;
+    }
+    
+    private static List<Map<String, Object>> createSequenceRows(final DatabaseFixture databaseMetadata) {
+        List<Map<String, Object>> result = new LinkedList<>();
+        for (SchemaFixture each : databaseMetadata.schemas()) {
+            for (String sequence : each.sequences()) {
+                result.add(Map.of("SEQUENCE_SCHEMA", each.schema(), "SEQUENCE_NAME", sequence));
+            }
+        }
+        return result;
+    }
+    
+    private static ResultSet createResultSet(final List<Map<String, Object>> rows) throws SQLException {
+        ResultSet result = mock(ResultSet.class);
+        AtomicInteger rowIndex = new AtomicInteger(-1);
+        when(result.next()).thenAnswer(invocation -> rowIndex.incrementAndGet() < rows.size());
+        when(result.getString(anyString())).thenAnswer(invocation -> {
+            Object value = rows.get(rowIndex.get()).get(invocation.getArgument(0, String.class));
+            return null == value ? null : value.toString();
+        });
+        when(result.getInt(anyString())).thenAnswer(invocation -> getNumber(rows, rowIndex.get(), invocation.getArgument(0, String.class)).intValue());
+        when(result.getShort(anyString())).thenAnswer(invocation -> getNumber(rows, rowIndex.get(), invocation.getArgument(0, String.class)).shortValue());
+        when(result.getBoolean(anyString())).thenAnswer(invocation -> Boolean.TRUE.equals(rows.get(rowIndex.get()).get(invocation.getArgument(0, String.class))));
+        return result;
+    }
+    
+    private static Number getNumber(final List<Map<String, Object>> rows, final int rowIndex, final String columnLabel) {
+        Object value = rows.get(rowIndex).get(columnLabel);
+        return value instanceof Number ? (Number) value : 0;
+    }
+    
+    private record DatabaseFixture(String database, String databaseType, String databaseVersion, List<SchemaFixture> schemas) {
+    }
+    
+    private record SchemaFixture(String schema, List<TableFixture> tables, List<TableFixture> views, List<String> sequences) {
+    }
+    
+    private record TableFixture(String name, List<String> columns, List<String> indexes) {
+    }
 }
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/diagnostic/MCPDiagnosticCategoryTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/diagnostic/MCPDiagnosticCategoryTest.java
deleted file mode 100644
index 25cf2c534cd..00000000000
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/diagnostic/MCPDiagnosticCategoryTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.diagnostic;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-
-class MCPDiagnosticCategoryTest {
-    
-    @Test
-    void assertCategories() {
-        List<String> actual = List.of(
-                MCPDiagnosticCategory.NO_RUNTIME_DATABASE,
-                MCPDiagnosticCategory.UNKNOWN_DATABASE,
-                MCPDiagnosticCategory.DATABASE_NOT_VISIBLE,
-                MCPDiagnosticCategory.SCHEMA_NOT_VISIBLE,
-                MCPDiagnosticCategory.OBJECT_NOT_VISIBLE,
-                MCPDiagnosticCategory.INSUFFICIENT_PRIVILEGES,
-                MCPDiagnosticCategory.EMPTY_SCOPE,
-                MCPDiagnosticCategory.NOT_FOUND,
-                MCPDiagnosticCategory.ORIGIN_NOT_ALLOWED,
-                MCPDiagnosticCategory.SESSION_ATTRIBUTION_MISMATCH,
-                MCPDiagnosticCategory.SQL_SYNTAX_ERROR,
-                MCPDiagnosticCategory.EXECUTION_TIMEOUT,
-                MCPDiagnosticCategory.CONNECTION_INTERRUPTED,
-                MCPDiagnosticCategory.UNSUPPORTED_DATABASE_CAPABILITY,
-                MCPDiagnosticCategory.QUERY_FAILED);
-        assertThat(actual, is(List.of(
-                "no_runtime_database",
-                "unknown_database",
-                "database_not_visible",
-                "schema_not_visible",
-                "object_not_visible",
-                "insufficient_privileges",
-                "empty_scope",
-                "not_found",
-                "origin_not_allowed",
-                "session_attribution_mismatch",
-                "sql_syntax_error",
-                "execution_timeout",
-                "connection_interrupted",
-                "unsupported_database_capability",
-                "query_failed")));
-    }
-}
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/protocol/payload/MCPMapPayloadTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/protocol/payload/MCPMapPayloadTest.java
deleted file mode 100644
index 7c47c985b5c..00000000000
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/protocol/payload/MCPMapPayloadTest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.protocol.payload;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.Map;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.sameInstance;
-
-class MCPMapPayloadTest {
-    
-    @Test
-    void assertToPayload() {
-        Map<String, Object> expectedPayload = Map.of("foo_key", "bar_value");
-        Map<String, Object> actual = new MCPMapPayload(expectedPayload).toPayload();
-        assertThat(actual, sameInstance(expectedPayload));
-    }
-}
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/security/MCPClientSafetyPolicyTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/security/MCPClientSafetyPolicyTest.java
deleted file mode 100644
index 982cacec628..00000000000
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/security/MCPClientSafetyPolicyTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.mcp.support.security;
-
-import org.junit.jupiter.api.Test;
-import java.util.Map;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-class MCPClientSafetyPolicyTest {
-    
-    @Test
-    void assertCreateModelFacingPayload() {
-        Map<String, Object> actual = MCPClientSafetyPolicy.createModelFacingPayload();
-        assertThat(actual.get("identity_scope"), is("mcp_session"));
-        assertTrue(String.valueOf(actual.get("transport_scope")).contains("trusted session attribution"));
-        assertTrue(String.valueOf(actual.get("external_model_boundary")).contains("never calls external model providers"));
-        Map<?, ?> actualRuntimeProtection = (Map<?, ?>) actual.get("runtime_protection");
-        Map<?, ?> actualToolCallLimit = (Map<?, ?>) actualRuntimeProtection.get("tool_call_limit");
-        assertThat(actualToolCallLimit.get("scope"), is("session"));
-        assertThat(actualToolCallLimit.get("property"), is(MCPRuntimeProtectionPolicy.MAX_TOOL_CALLS_PER_SESSION_PROPERTY));
-        Map<?, ?> actualSQLExecutionLimits = (Map<?, ?>) actualRuntimeProtection.get("sql_execution_limits");
-        assertThat(((Map<?, ?>) actualSQLExecutionLimits.get("max_rows")).get("applied_field"), is("applied_max_rows"));
-        assertThat(((Map<?, ?>) actualSQLExecutionLimits.get("timeout_ms")).get("applied_field"), is("applied_timeout_ms"));
-    }
-}
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshotTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshotTest.java
index 69f6266dca8..8edf75d9ffa 100644
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshotTest.java
+++ b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/model/WorkflowContextSnapshotTest.java
@@ -67,7 +67,7 @@ class WorkflowContextSnapshotTest {
     @Test
     void assertClearPlanningStateRemovesTransientArtifacts() {
         WorkflowContextSnapshot snapshot = createSnapshot();
-        WorkflowFeatureData featureData = snapshot.getFeatureData();
+        RuleWorkflowFeatureData featureData = snapshot.getFeatureData();
         assertThat(snapshot.getFeatureData(), is(featureData));
         snapshot.clearPlanningState();
         assertTrue(snapshot.getIssues().isEmpty());
@@ -93,7 +93,7 @@ class WorkflowContextSnapshotTest {
         ClarifiedIntent clarifiedIntent = new ClarifiedIntent();
         clarifiedIntent.getClarificationMessages().add("provide schema");
         result.setClarifiedIntent(clarifiedIntent);
-        result.setFeatureData(new StubWorkflowFeatureData());
+        result.setFeatureData(new RuleWorkflowFeatureData(List.of(Map.of("rule", "encrypt_rule"))));
         InteractionPlan interactionPlan = new InteractionPlan();
         interactionPlan.setCurrentStep("review");
         interactionPlan.getValidationStrategy().put("layers", List.of("rule"));
@@ -120,11 +120,4 @@ class WorkflowContextSnapshotTest {
         return (List<String>) source.get(key);
     }
     
-    private static final class StubWorkflowFeatureData implements WorkflowFeatureData {
-        
-        @Override
-        public WorkflowFeatureData copy() {
-            return new StubWorkflowFeatureData();
-        }
-    }
 }
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundleTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundleTest.java
index 9db12593b55..796e126872f 100644
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundleTest.java
+++ b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactBundleTest.java
@@ -17,15 +17,14 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.service;
 
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.RuleArtifact;
 import org.apache.shardingsphere.mcp.support.workflow.model.SecretReferenceValue;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowContextSnapshot;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
-import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -36,7 +35,7 @@ class WorkflowArtifactBundleTest {
     void assertToExecutableArtifacts() {
         WorkflowContextSnapshot snapshot = new WorkflowContextSnapshot();
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE ENCRYPT RULE t"));
-        List<WorkflowArtifactBundle.ExecutableWorkflowArtifact> actual = WorkflowArtifactBundle.from(snapshot).toExecutableArtifacts(role -> Map.of(), List.of());
+        List<WorkflowArtifactBundle.ExecutableWorkflowArtifact> actual = WorkflowArtifactBundle.from(snapshot).toExecutableArtifacts(new WorkflowRequest(), List.of());
         assertThat(actual, is(List.of(new WorkflowArtifactBundle.ExecutableWorkflowArtifact("CREATE ENCRYPT RULE t", "CREATE ENCRYPT RULE t"))));
     }
     
@@ -45,7 +44,7 @@ class WorkflowArtifactBundleTest {
         WorkflowContextSnapshot snapshot = new WorkflowContextSnapshot();
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE ENCRYPT RULE t (PROPERTIES('aes-key-value'='primary-secret'))"));
         List<WorkflowArtifactBundle.ExecutableWorkflowArtifact> actual = WorkflowArtifactBundle.from(snapshot)
-                .toExecutableArtifacts(createPropertySource(), List.of(new AlgorithmPropertyRequirement("primary", "aes-key-value", true, true, "primary", "")));
+                .toExecutableArtifacts(createRequest(), List.of(new AlgorithmPropertyRequirement("primary", "aes-key-value", true, true, "primary", "")));
         assertThat(actual.size(), is(1));
         assertThat(actual.getFirst().sql(), is("CREATE ENCRYPT RULE t (PROPERTIES('aes-key-value'='primary-secret'))"));
         assertThat(actual.getFirst().displaySql(), is("CREATE ENCRYPT RULE t (PROPERTIES('aes-key-value'='******'))"));
@@ -56,28 +55,22 @@ class WorkflowArtifactBundleTest {
         WorkflowContextSnapshot snapshot = new WorkflowContextSnapshot();
         snapshot.getRuleArtifacts().add(new RuleArtifact("create", "CREATE ENCRYPT RULE t (PROPERTIES('aes-key-value'='secret_reference:primary.aes-key-value'))"));
         List<WorkflowArtifactBundle.ExecutableWorkflowArtifact> actual = WorkflowArtifactBundle.from(snapshot)
-                .toExecutableArtifacts(createSecretReferencePropertySource(), List.of());
+                .toExecutableArtifacts(createSecretReferenceRequest(), List.of());
         assertThat(actual.size(), is(1));
         assertThat(actual.getFirst().sql(), is("CREATE ENCRYPT RULE t (PROPERTIES('aes-key-value'='secret_reference:primary.aes-key-value'))"));
         assertThat(actual.getFirst().displaySql(), is("CREATE ENCRYPT RULE t (PROPERTIES('aes-key-value'='<SECRET_VALUE_PRIMARY_AES_KEY_VALUE>'))"));
     }
     
-    private WorkflowPropertySource createPropertySource() {
-        return algorithmRole -> "primary".equals(algorithmRole) ? Map.of("aes-key-value", "primary-secret") : Map.of();
+    private WorkflowRequest createRequest() {
+        WorkflowRequest result = new WorkflowRequest();
+        result.getPrimaryAlgorithmProperties().put("aes-key-value", "primary-secret");
+        return result;
     }
     
-    private WorkflowPropertySource createSecretReferencePropertySource() {
-        return new WorkflowPropertySource() {
-            
-            @Override
-            public Map<String, String> getAlgorithmProperties(final String algorithmRole) {
-                return "primary".equals(algorithmRole) ? Map.of("aes-key-value", "secret_reference:primary.aes-key-value") : Map.of();
-            }
-            
-            @Override
-            public Map<String, Map<String, SecretReferenceValue>> getSecretReferences() {
-                return Map.of("primary", Map.of("aes-key-value", SecretReferenceValue.create()));
-            }
-        };
+    private WorkflowRequest createSecretReferenceRequest() {
+        WorkflowRequest result = new WorkflowRequest();
+        result.getPrimaryAlgorithmProperties().put("aes-key-value", "secret_reference:primary.aes-key-value");
+        result.getPrimaryAlgorithmSecretReferences().put("aes-key-value", SecretReferenceValue.create());
+        return result;
     }
 }
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtilsTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtilsTest.java
index 788a75248cc..5ccae2db2c9 100644
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtilsTest.java
+++ b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowArtifactMaskUtilsTest.java
@@ -17,10 +17,10 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.service;
 
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.AlgorithmPropertyRequirement;
 import org.apache.shardingsphere.mcp.support.workflow.model.RuleArtifact;
 import org.apache.shardingsphere.mcp.support.workflow.model.SecretReferenceValue;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
@@ -33,21 +33,21 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class WorkflowArtifactMaskUtilsTest {
     
-    private final WorkflowPropertySource propertySource = createPropertySource();
+    private final WorkflowRequest request = createRequest();
     
     @Test
-    void assertCreateMaskedRuleArtifactMapMasksSecretPropertiesAcrossRoles() {
+    void assertCreateMaskedRuleArtifactMapMasksSecretProperties() {
         RuleArtifact ruleArtifact = new RuleArtifact("create", "SQL primary-secret 'assist-secret' like-secret");
-        Map<String, Object> actualRuleArtifact = WorkflowArtifactMaskUtils.createMaskedRuleArtifactMap(ruleArtifact, propertySource, List.of(
+        Map<String, Object> actualRuleArtifact = WorkflowArtifactMaskUtils.createMaskedRuleArtifactMap(ruleArtifact, request, List.of(
                 new AlgorithmPropertyRequirement("primary", "aes-key-value", true, true, "primary", ""),
-                new AlgorithmPropertyRequirement("assisted_query", "salt", true, true, "assist", ""),
-                new AlgorithmPropertyRequirement("like_query", "token", true, true, "like", "")));
+                new AlgorithmPropertyRequirement("primary", "salt", true, true, "assist", ""),
+                new AlgorithmPropertyRequirement("primary", "token", true, true, "like", "")));
         assertThat(actualRuleArtifact.get("operation_type"), is("create"));
         assertThat(actualRuleArtifact.get("sql"), is("SQL ****** '******' ******"));
         Map<?, ?> actualRedaction = (Map<?, ?>) actualRuleArtifact.get("redaction");
         assertTrue((Boolean) actualRedaction.get("applied"));
         assertThat(actualRedaction.get("redacted_count"), is(3));
-        assertThat(actualRedaction.get("redacted_properties"), is(List.of("primary.aes-key-value", "assisted_query.salt", "like_query.token")));
+        assertThat(actualRedaction.get("redacted_properties"), is(List.of("primary.aes-key-value", "primary.salt", "primary.token")));
         assertThat(actualRedaction.get("categories"), is(List.of("aes-key-value", "salt", "token")));
         assertFalse(actualRedaction.containsKey("secret_reference_summary"));
     }
@@ -61,39 +61,29 @@ class WorkflowArtifactMaskUtilsTest {
     
     @Test
     void assertMaskSecretReferencePlaceholder() {
-        WorkflowPropertySource source = createSecretReferencePropertySource();
-        assertThat(WorkflowArtifactMaskUtils.maskSensitiveSql("SQL secret_reference:primary.aes-key-value", source, List.of()), is("SQL <SECRET_VALUE_PRIMARY_AES_KEY_VALUE>"));
+        WorkflowRequest actualRequest = createSecretReferenceRequest();
+        assertThat(WorkflowArtifactMaskUtils.maskSensitiveSql("SQL secret_reference:primary.aes-key-value", actualRequest, List.of()), is("SQL <SECRET_VALUE_PRIMARY_AES_KEY_VALUE>"));
         assertThat(WorkflowArtifactMaskUtils.maskPropertyMap(Map.of("aes-key-value", "secret_reference:primary.aes-key-value"), List.of()), is(Map.of("aes-key-value", "******")));
-        assertThat(WorkflowArtifactMaskUtils.maskPropertyMap(Map.of("replace-char", "?"), List.of(), source, "primary"), is(Map.of("replace-char", "******")));
-        Map<?, ?> actualSummary = WorkflowArtifactMaskUtils.createSecretReferenceSummary(source);
+        assertThat(WorkflowArtifactMaskUtils.maskPropertyMap(Map.of("replace-char", "?"), List.of(), actualRequest, "primary"), is(Map.of("replace-char", "******")));
+        Map<?, ?> actualSummary = WorkflowArtifactMaskUtils.createSecretReferenceSummary(actualRequest);
         assertTrue((Boolean) actualSummary.get("required"));
         assertThat(actualSummary.get("reference_count"), is(2));
         assertThat(actualSummary.get("value_handling"), is("manual_execution"));
         assertFalse(String.valueOf(actualSummary).contains("placeholder://"));
     }
     
-    private WorkflowPropertySource createPropertySource() {
-        Map<String, Map<String, String>> properties = Map.of(
-                "primary", Map.of("aes-key-value", "primary-secret"),
-                "assisted_query", Map.of("salt", "assist-secret"),
-                "like_query", Map.of("token", "like-secret"));
-        return algorithmRole -> properties.getOrDefault(algorithmRole, Map.of());
+    private WorkflowRequest createRequest() {
+        WorkflowRequest result = new WorkflowRequest();
+        result.getPrimaryAlgorithmProperties().putAll(Map.of("aes-key-value", "primary-secret", "salt", "assist-secret", "token", "like-secret"));
+        return result;
     }
     
-    private WorkflowPropertySource createSecretReferencePropertySource() {
-        return new WorkflowPropertySource() {
-            
-            @Override
-            public Map<String, String> getAlgorithmProperties(final String algorithmRole) {
-                return Map.of("aes-key-value", "secret_reference:primary.aes-key-value");
-            }
-            
-            @Override
-            public Map<String, Map<String, SecretReferenceValue>> getSecretReferences() {
-                return Map.of("primary", Map.of(
-                        "aes-key-value", SecretReferenceValue.create(),
-                        "replace-char", SecretReferenceValue.create()));
-            }
-        };
+    private WorkflowRequest createSecretReferenceRequest() {
+        WorkflowRequest result = new WorkflowRequest();
+        result.getPrimaryAlgorithmProperties().put("aes-key-value", "secret_reference:primary.aes-key-value");
+        result.getPrimaryAlgorithmSecretReferences().putAll(Map.of(
+                "aes-key-value", SecretReferenceValue.create(),
+                "replace-char", SecretReferenceValue.create()));
+        return result;
     }
 }
diff --git a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtilsTest.java b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtilsTest.java
index 89bf5d32e6b..f4d0860c6b7 100644
--- a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtilsTest.java
+++ b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/workflow/service/WorkflowSecretReferenceUtilsTest.java
@@ -17,8 +17,8 @@
 
 package org.apache.shardingsphere.mcp.support.workflow.service;
 
-import org.apache.shardingsphere.mcp.support.workflow.WorkflowPropertySource;
 import org.apache.shardingsphere.mcp.support.workflow.model.SecretReferenceValue;
+import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowRequest;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
@@ -60,19 +60,8 @@ class WorkflowSecretReferenceUtilsTest {
     
     @Test
     void assertCreateSafeSummaries() {
-        WorkflowPropertySource propertySource = new WorkflowPropertySource() {
-            
-            @Override
-            public Map<String, String> getAlgorithmProperties(final String algorithmRole) {
-                return Map.of();
-            }
-            
-            @Override
-            public Map<String, Map<String, SecretReferenceValue>> getSecretReferences() {
-                return Map.of("primary", Map.of("aes-key-value", SecretReferenceValue.create()));
-            }
-        };
-        List<Map<String, Object>> actual = WorkflowSecretReferenceUtils.createSafeSummaries(propertySource);
+        WorkflowRequest request = createSecretReferenceRequest();
+        List<Map<String, Object>> actual = WorkflowSecretReferenceUtils.createSafeSummaries(request);
         assertThat(actual.size(), is(1));
         assertThat(actual.getFirst().get("label"), is("secret_placeholder:primary.aes-key-value"));
         assertFalse(String.valueOf(actual).contains("placeholder://secret-value-1"));
@@ -82,7 +71,7 @@ class WorkflowSecretReferenceUtilsTest {
     @Test
     void assertReplacePlaceholdersWithManualPlaceholders() {
         assertThat(WorkflowSecretReferenceUtils.replacePlaceholdersWithManualPlaceholders(
-                "PROPERTIES('aes-key-value'='secret_reference:primary.aes-key-value')", createSecretReferencePropertySource()),
+                "PROPERTIES('aes-key-value'='secret_reference:primary.aes-key-value')", createSecretReferenceRequest()),
                 is("PROPERTIES('aes-key-value'='<SECRET_VALUE_PRIMARY_AES_KEY_VALUE>')"));
     }
     
@@ -91,7 +80,7 @@ class WorkflowSecretReferenceUtilsTest {
         assertTrue(WorkflowSecretReferenceUtils.matchesManualPlaceholderProperties(
                 Map.of("aes-key-value", "secret_reference:primary.aes-key-value", "digest-algorithm-name", "SHA-256"),
                 Map.of("aes-key-value", "manually-filled-secret", "digest-algorithm-name", "SHA-256"),
-                createSecretReferencePropertySource(), "primary"));
+                createSecretReferenceRequest(), "primary"));
     }
     
     @Test
@@ -99,7 +88,7 @@ class WorkflowSecretReferenceUtilsTest {
         assertFalse(WorkflowSecretReferenceUtils.matchesManualPlaceholderProperties(
                 Map.of("aes-key-value", "secret_reference:primary.aes-key-value"),
                 Map.of("aes-key-value", "secret_reference:primary.aes-key-value"),
-                createSecretReferencePropertySource(), "primary"));
+                createSecretReferenceRequest(), "primary"));
     }
     
     @Test
@@ -107,7 +96,7 @@ class WorkflowSecretReferenceUtilsTest {
         assertFalse(WorkflowSecretReferenceUtils.matchesManualPlaceholderProperties(
                 Map.of("aes-key-value", "secret_reference:primary.aes-key-value"),
                 Map.of("aes-key-value", "<SECRET_VALUE_PRIMARY_AES_KEY_VALUE>"),
-                createSecretReferencePropertySource(), "primary"));
+                createSecretReferenceRequest(), "primary"));
     }
     
     @Test
@@ -115,21 +104,12 @@ class WorkflowSecretReferenceUtilsTest {
         assertFalse(WorkflowSecretReferenceUtils.matchesManualPlaceholderProperties(
                 Map.of("aes-key-value", "secret_reference:primary.aes-key-value"),
                 Map.of(),
-                createSecretReferencePropertySource(), "primary"));
+                createSecretReferenceRequest(), "primary"));
     }
     
-    private WorkflowPropertySource createSecretReferencePropertySource() {
-        return new WorkflowPropertySource() {
-            
-            @Override
-            public Map<String, String> getAlgorithmProperties(final String algorithmRole) {
-                return Map.of();
-            }
-            
-            @Override
-            public Map<String, Map<String, SecretReferenceValue>> getSecretReferences() {
-                return Map.of("primary", Map.of("aes-key-value", SecretReferenceValue.create()));
-            }
-        };
+    private WorkflowRequest createSecretReferenceRequest() {
+        WorkflowRequest result = new WorkflowRequest();
+        result.getPrimaryAlgorithmSecretReferences().put("aes-key-value", SecretReferenceValue.create());
+        return result;
     }
 }
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractFunctionalityE2ETest.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractFunctionalityE2ETest.java
deleted file mode 100644
index 1aca2065d19..00000000000
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractFunctionalityE2ETest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.test.e2e.mcp.functionality;
-
-import org.apache.shardingsphere.test.e2e.mcp.support.runtime.AbstractConfigBackedRuntimeE2ETest;
-import org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionPayloads;
-
-import java.util.List;
-import java.util.Map;
-
-abstract class AbstractFunctionalityE2ETest extends AbstractConfigBackedRuntimeE2ETest {
-    
-    protected final List<Map<String, Object>> getPayloadItems(final Map<String, Object> payload) {
-        return MCPInteractionPayloads.getRequiredObjectList(payload, "items");
-    }
-    
-    protected final List<String> getNestedNames(final Map<String, Object> item, final String nestedKey, final String nameKey) {
-        return ((List<?>) item.get(nestedKey)).stream().map(each -> String.valueOf(((Map<?, ?>) each).get(nameKey))).toList();
-    }
-}
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractMySQLRuntimeE2ETest.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractMySQLRuntimeE2ETest.java
index ae62258c6f5..382f2a88be2 100644
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractMySQLRuntimeE2ETest.java
+++ b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractMySQLRuntimeE2ETest.java
@@ -131,11 +131,28 @@ abstract class AbstractMySQLRuntimeE2ETest extends AbstractTransportParameterize
     }
     
     protected static Stream<Arguments> singleMetadataResourceCases() {
-        return FunctionalityTransportCases.singleMetadataResourceCases(LOGICAL_DATABASE_NAME);
+        return Stream.of(
+                Arguments.of("database detail", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME, "database", LOGICAL_DATABASE_NAME),
+                Arguments.of("schema detail", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME, "schema", LOGICAL_DATABASE_NAME),
+                Arguments.of("table column detail",
+                        "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME + "/tables/orders/columns/status", "column", "status"),
+                Arguments.of("view detail", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME
+                        + "/views/active_orders", "view", "active_orders"),
+                Arguments.of("view column detail", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME
+                        + "/views/active_orders/columns/status", "column", "status"),
+                Arguments.of("index detail", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME
+                        + "/tables/orders/indexes/idx_orders_status", "index", "idx_orders_status"));
     }
     
     protected static Stream<Arguments> collectionMetadataResourceCases() {
-        return FunctionalityTransportCases.collectionMetadataResourceCases(LOGICAL_DATABASE_NAME);
+        return Stream.of(
+                Arguments.of("schemas list", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas", "schema", List.of(LOGICAL_DATABASE_NAME)),
+                Arguments.of("tables list", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME + "/tables", "table",
+                        List.of("order_items", "orders")),
+                Arguments.of("table columns list", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME
+                        + "/tables/orders/columns", "column", List.of("amount", "order_id", "status")),
+                Arguments.of("view columns list", "shardingsphere://databases/" + LOGICAL_DATABASE_NAME + "/schemas/" + LOGICAL_DATABASE_NAME
+                        + "/views/active_orders/columns", "column", List.of("order_id", "status")));
     }
     
     protected void assertRecoveryResponse(final Map<String, Object> actual) {
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractTransportParameterizedE2ETest.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractTransportParameterizedE2ETest.java
index ebb0498f960..cea38eb8736 100644
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractTransportParameterizedE2ETest.java
+++ b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/AbstractTransportParameterizedE2ETest.java
@@ -17,18 +17,32 @@
 
 package org.apache.shardingsphere.test.e2e.mcp.functionality;
 
+import org.apache.shardingsphere.test.e2e.mcp.support.runtime.AbstractConfigBackedRuntimeE2ETest;
 import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
+import org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionPayloads;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.params.provider.Arguments;
 
+import java.util.List;
+import java.util.Map;
 import java.util.stream.Stream;
 
-abstract class AbstractTransportParameterizedE2ETest extends AbstractFunctionalityE2ETest {
+abstract class AbstractTransportParameterizedE2ETest extends AbstractConfigBackedRuntimeE2ETest {
     
     private RuntimeTransport transport = RuntimeTransport.HTTP;
     
     protected static Stream<Arguments> allTransportCases() {
-        return FunctionalityTransportCases.allTransportCases();
+        return Stream.of(
+                Arguments.of("http", RuntimeTransport.HTTP),
+                Arguments.of("stdio", RuntimeTransport.STDIO));
+    }
+    
+    protected final List<Map<String, Object>> getPayloadItems(final Map<String, Object> payload) {
+        return MCPInteractionPayloads.getRequiredObjectList(payload, "items");
+    }
+    
+    protected final List<String> getNestedNames(final Map<String, Object> item, final String nestedKey, final String nameKey) {
+        return ((List<?>) item.get(nestedKey)).stream().map(each -> String.valueOf(((Map<?, ?>) each).get(nameKey))).toList();
     }
     
     protected final void useTransport(final RuntimeTransport transport) {
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/FunctionalityTransportCases.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/FunctionalityTransportCases.java
deleted file mode 100644
index 43d5796f167..00000000000
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/functionality/FunctionalityTransportCases.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.test.e2e.mcp.functionality;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.test.e2e.mcp.support.runtime.RuntimeTransport;
-import org.junit.jupiter.params.provider.Arguments;
-
-import java.util.List;
-import java.util.stream.Stream;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-final class FunctionalityTransportCases {
-    
-    static Stream<Arguments> allTransportCases() {
-        return allTransports().map(each -> Arguments.of(getTransportName(each), each));
-    }
-    
-    static Stream<Arguments> singleMetadataResourceCases(final String logicalDatabaseName) {
-        return Stream.of(
-                Arguments.of("database detail", "shardingsphere://databases/" + logicalDatabaseName, "database", logicalDatabaseName),
-                Arguments.of("schema detail", "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName, "schema", logicalDatabaseName),
-                Arguments.of("table column detail",
-                        "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/tables/orders/columns/status", "column", "status"),
-                Arguments.of("view detail", "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/views/active_orders", "view", "active_orders"),
-                Arguments.of("view column detail",
-                        "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/views/active_orders/columns/status", "column", "status"),
-                Arguments.of("index detail",
-                        "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/tables/orders/indexes/idx_orders_status", "index", "idx_orders_status"));
-    }
-    
-    static Stream<Arguments> collectionMetadataResourceCases(final String logicalDatabaseName) {
-        return Stream.of(
-                Arguments.of("schemas list", "shardingsphere://databases/" + logicalDatabaseName + "/schemas", "schema", List.of(logicalDatabaseName)),
-                Arguments.of("tables list", "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/tables", "table", List.of("order_items", "orders")),
-                Arguments.of("table columns list", "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/tables/orders/columns", "column",
-                        List.of("amount", "order_id", "status")),
-                Arguments.of("view columns list", "shardingsphere://databases/" + logicalDatabaseName + "/schemas/" + logicalDatabaseName + "/views/active_orders/columns", "column",
-                        List.of("order_id", "status")));
-    }
-    
-    private static Stream<RuntimeTransport> allTransports() {
-        return Stream.of(RuntimeTransport.HTTP, RuntimeTransport.STDIO);
-    }
-    
-    private static String getTransportName(final RuntimeTransport transport) {
-        return RuntimeTransport.HTTP == transport ? "http" : "stdio";
-    }
-    
-}
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
index d880d695749..d7006f0fcf0 100644
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
+++ b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMConversationRunner.java
@@ -25,6 +25,7 @@ import org.apache.shardingsphere.test.e2e.mcp.llm.conversation.client.LLMToolCal
 import org.apache.shardingsphere.test.e2e.mcp.llm.config.LLME2EConfiguration;
 import org.apache.shardingsphere.test.e2e.mcp.support.transport.MCPInteractionTraceRecord;
 import org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPInteractionClient;
+import org.apache.shardingsphere.infra.util.json.JsonUtils;
 
 import java.io.IOException;
 import java.util.LinkedList;
@@ -67,15 +68,12 @@ public final class LLMConversationRunner {
     
     private final LLMMCPSafetyValidator safetyValidator = new LLMMCPSafetyValidator();
     
-    private final LLMMCPActionExecutor actionExecutor;
-    
     public LLMConversationRunner(final int maxTurns, final LLMChatModelClient llmChatClient, final MCPInteractionClient mcpInteractionClient,
                                  final String modelName) {
         this.maxTurns = maxTurns;
         this.llmChatClient = llmChatClient;
         this.mcpInteractionClient = mcpInteractionClient;
         this.modelName = modelName;
-        actionExecutor = new LLMMCPActionExecutor(mcpInteractionClient);
     }
     
     /**
@@ -176,7 +174,7 @@ public final class LLMConversationRunner {
             long startTime = System.currentTimeMillis();
             Map<String, Object> response;
             try {
-                response = actionExecutor.executeSafely(each.getName(), arguments);
+                response = executeAction(each.getName(), arguments);
             } catch (final IllegalArgumentException ex) {
                 artifacts.addTrace(MCPInteractionTraceRecord.createInvalidAction(
                         artifacts.nextSequence(), modelTurn, TOOL_CALL_KIND, each.getName(), arguments, "invalid_tool_arguments"));
@@ -190,7 +188,7 @@ public final class LLMConversationRunner {
             artifacts.addTrace(new MCPInteractionTraceRecord(
                     artifacts.nextSequence(), modelTurn, getActionKind(each.getName()), MCPInteractionTraceRecord.MODEL_TOOL_CALL_ORIGIN,
                     each.getName(), getTraceArguments(each.getName(), arguments), response, true, latencyMillis));
-            messages.add(LLMChatMessage.tool(each.getId(), LLMMCPModelFacingToolResponseFormatter.format(response)));
+            messages.add(LLMChatMessage.tool(each.getId(), JsonUtils.toJsonString(response)));
         }
         return Optional.empty();
     }
@@ -199,6 +197,24 @@ public final class LLMConversationRunner {
         return READ_RESOURCE_TOOL_NAME.equals(toolName) ? RESOURCE_READ_KIND : TOOL_CALL_KIND;
     }
     
+    private Map<String, Object> executeAction(final String actionName, final Map<String, Object> arguments) throws InterruptedException {
+        try {
+            return READ_RESOURCE_TOOL_NAME.equals(actionName)
+                    ? mcpInteractionClient.readResource(getRequiredResourceUri(arguments))
+                    : mcpInteractionClient.call(actionName, arguments);
+        } catch (final IOException | IllegalStateException ex) {
+            throw new IllegalStateException(String.format("MCP action `%s` failed: %s", actionName, ex.getMessage()), ex);
+        }
+    }
+    
+    private String getRequiredResourceUri(final Map<String, Object> arguments) {
+        Object value = arguments.get("uri");
+        if (!(value instanceof String) || ((String) value).trim().isEmpty()) {
+            throw new IllegalArgumentException("Resource URI is required.");
+        }
+        return ((String) value).trim();
+    }
+    
     private Map<String, Object> getTraceArguments(final String toolName, final Map<String, Object> arguments) {
         return READ_RESOURCE_TOOL_NAME.equals(toolName)
                 ? Map.of("uri", Objects.toString(arguments.get("uri"), "").trim())
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPActionExecutor.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPActionExecutor.java
deleted file mode 100644
index 6cbd15a6dc2..00000000000
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPActionExecutor.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.test.e2e.mcp.llm.conversation;
-
-import lombok.AccessLevel;
-import lombok.RequiredArgsConstructor;
-import org.apache.shardingsphere.test.e2e.mcp.support.transport.client.MCPInteractionClient;
-
-import java.io.IOException;
-import java.util.Map;
-
-@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
-final class LLMMCPActionExecutor {
-    
-    private final MCPInteractionClient mcpInteractionClient;
-    
-    Map<String, Object> executeSafely(final String actionName, final Map<String, Object> args) throws InterruptedException {
-        try {
-            return LLMConversationRunner.READ_RESOURCE_TOOL_NAME.equals(actionName)
-                    ? mcpInteractionClient.readResource(getRequiredResourceUri(args))
-                    : mcpInteractionClient.call(actionName, args);
-        } catch (final IOException | IllegalStateException ex) {
-            throw new IllegalStateException(String.format("MCP action `%s` failed: %s", actionName, ex.getMessage()), ex);
-        }
-    }
-    
-    private String getRequiredResourceUri(final Map<String, Object> args) {
-        Object value = args.get("uri");
-        if (!(value instanceof String) || ((String) value).trim().isEmpty()) {
-            throw new IllegalArgumentException("Resource URI is required.");
-        }
-        return ((String) value).trim();
-    }
-}
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPJsonValues.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPJsonValues.java
index 30ea13c0e35..9733aa6139d 100644
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPJsonValues.java
+++ b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPJsonValues.java
@@ -22,9 +22,6 @@ import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import lombok.AccessLevel;
 import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.infra.util.json.JsonUtils;
-
-import java.util.List;
 import java.util.Map;
 
 @NoArgsConstructor(access = AccessLevel.PRIVATE)
@@ -41,22 +38,16 @@ final class LLMMCPJsonValues {
         }
     }
     
-    static List<List<Object>> castToRows(final Object value) {
-        return JsonUtils.fromJsonString(JsonUtils.toJsonString(value), new TypeReference<>() {
-        });
-    }
-    
+    @SuppressWarnings("unchecked")
     static Map<String, Object> castToMap(final Object value) {
-        return JsonUtils.fromJsonString(JsonUtils.toJsonString(value), new TypeReference<>() {
-        });
-    }
-    
-    static <T> List<T> castToList(final Object value) {
-        if (null == value) {
-            return List.of();
+        if (!(value instanceof Map)) {
+            throw new IllegalArgumentException("Expected a JSON object.");
+        }
+        Map<?, ?> result = (Map<?, ?>) value;
+        if (!result.keySet().stream().allMatch(String.class::isInstance)) {
+            throw new IllegalArgumentException("Expected a JSON object with string keys.");
         }
-        return JsonUtils.fromJsonString(JsonUtils.toJsonString(value), new TypeReference<>() {
-        });
+        return (Map<String, Object>) result;
     }
     
 }
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPModelFacingToolResponseFormatter.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPModelFacingToolResponseFormatter.java
deleted file mode 100644
index a748d08aeeb..00000000000
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/LLMMCPModelFacingToolResponseFormatter.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.shardingsphere.test.e2e.mcp.llm.conversation;
-
-import lombok.AccessLevel;
-import lombok.NoArgsConstructor;
-import org.apache.shardingsphere.infra.util.json.JsonUtils;
-import org.apache.shardingsphere.mcp.support.protocol.MCPModelFacingPayloadContract;
-import org.apache.shardingsphere.mcp.support.protocol.MCPPayloadFieldNames;
-import org.apache.shardingsphere.mcp.support.protocol.MCPResponseMode;
-
-import java.util.Collection;
-import java.util.LinkedHashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-
-@NoArgsConstructor(access = AccessLevel.PRIVATE)
-final class LLMMCPModelFacingToolResponseFormatter {
-    
-    private static final int COMPACT_ITEM_LIMIT = 5;
-    
-    private static final List<String> GENERAL_FIELD_NAMES = List.of(
-            "response_mode", "error_code", "error_id", "summary", "message", "recovery_category", "result_kind", "status", "statement_type", "normalized_sql", "rows", "row_objects",
-            "returned_row_count", "plan_id", "workflow_resource");
-    
-    private static final List<String> POST_ACTION_FIELD_NAMES = List.of(
-            "completion", "count", "total_match_count", "truncated", "large_result_guidance", "search_context");
-    
-    static String format(final Map<String, Object> response) {
-        Map<String, Object> result = new LinkedHashMap<>(16, 1F);
-        copyFields(response, result, GENERAL_FIELD_NAMES);
-        copyCompactArtifactPackage(response, result, "manual_artifact_package");
-        copyCompactArtifactList(response, result, "exported_artifacts");
-        copyModelCriticalFields(response, result);
-        copyNextActions(response, result);
-        copyFields(response, result, POST_ACTION_FIELD_NAMES);
-        copyToolList(response, result);
-        copyCompactResourceList(response, result, "resources", "uri");
-        copyCompactResourceList(response, result, "resourceTemplates", "uriTemplate");
-        copyPromptList(response, result);
-        copyPromptMessages(response, result);
-        copyCompactItems(response, result);
-        copyCompactRecovery(response, result);
-        return JsonUtils.toJsonString(result.isEmpty() ? response : result);
-    }
-    
-    private static void copyCompactResourceList(final Map<String, Object> source, final Map<String, Object> target,
-                                                final String fieldName, final String uriFieldName) {
-        List<Map<String, Object>> resources = LLMMCPJsonValues.castToList(source.get(fieldName));
-        if (!resources.isEmpty()) {
-            List<Map<String, Object>> compactResources = new LinkedList<>();
-            for (Map<String, Object> each : resources) {
-                Map<String, Object> compactResource = new LinkedHashMap<>(8, 1F);
-                copyIfPresent(each, compactResource, uriFieldName);
-                copyIfPresent(each, compactResource, "name");
-                copyIfPresent(each, compactResource, "title");
-                copyIfPresent(each, compactResource, "mimeType");
-                compactResources.add(compactResource.isEmpty() ? each : compactResource);
-            }
-            target.put(fieldName, compactResources);
-        }
-    }
-    
-    private static void copyToolList(final Map<String, Object> source, final Map<String, Object> target) {
-        List<Map<String, Object>> tools = LLMMCPJsonValues.castToList(source.get("tools"));
-        if (tools.isEmpty()) {
-            return;
-        }
-        List<Map<String, Object>> compactTools = new LinkedList<>();
-        for (Map<String, Object> each : tools) {
-            Map<String, Object> compactTool = new LinkedHashMap<>(2, 1F);
-            copyIfPresent(each, compactTool, "name");
-            copyIfPresent(each, compactTool, "title");
-            if (!compactTool.isEmpty()) {
-                compactTools.add(compactTool);
-            }
-        }
-        target.put("tools", compactTools);
-    }
-    
-    private static void copyFields(final Map<String, Object> source, final Map<String, Object> target, final Collection<String> fieldNames) {
-        for (String each : fieldNames) {
-            copyIfPresent(source, target, each);
-        }
-    }
-    
-    private static void copyIfPresent(final Map<String, Object> source, final Map<String, Object> target, final String fieldName) {
-        if (source.containsKey(fieldName)) {
-            target.put(fieldName, source.get(fieldName));
-        }
-    }
-    
-    private static void copyModelCriticalFields(final Map<String, Object> source, final Map<String, Object> target) {
-        for (String each : MCPModelFacingPayloadContract.getModelCriticalFieldNames()) {
-            if (!MCPPayloadFieldNames.NEXT_ACTIONS.equals(each) && !MCPPayloadFieldNames.RECOVERY.equals(each)) {
-                copyIfPresent(source, target, each);
-            }
-        }
-    }
-    
-    private static void copyCompactItems(final Map<String, Object> source, final Map<String, Object> target) {
-        List<Map<String, Object>> items = LLMMCPJsonValues.castToList(source.get("items"));
-        if (items.isEmpty()) {
-            return;
-        }
-        List<Map<String, Object>> compactItems = new LinkedList<>();
-        int visibleItemCount = MCPResponseMode.SEARCH.equals(source.get("response_mode")) ? items.size() : Math.min(items.size(), COMPACT_ITEM_LIMIT);
-        for (Map<String, Object> each : items.subList(0, visibleItemCount)) {
-            Map<String, Object> compactItem = new LinkedHashMap<>(8, 1F);
-            copyIfPresent(each, compactItem, "database");
-            copyIfPresent(each, compactItem, "schema");
-            copyIfPresent(each, compactItem, "objectType");
-            copyIfPresent(each, compactItem, "table");
-            copyIfPresent(each, compactItem, "view");
-            copyIfPresent(each, compactItem, "column");
-            copyIfPresent(each, compactItem, "name");
-            copyIfPresent(each, compactItem, "resource");
-            compactItems.add(compactItem.isEmpty() ? each : compactItem);
-        }
-        target.put("items", compactItems);
-    }
-    
-    private static void copyPromptList(final Map<String, Object> source, final Map<String, Object> target) {
-        List<Map<String, Object>> prompts = LLMMCPJsonValues.castToList(source.get("prompts"));
-        if (prompts.isEmpty()) {
-            return;
-        }
-        List<String> names = new LinkedList<>();
-        for (Map<String, Object> each : prompts) {
-            String name = Objects.toString(each.get("name"), "").trim();
-            if (!name.isEmpty()) {
-                names.add(name);
-            }
-        }
-        target.put("prompts", names);
-    }
-    
-    private static void copyPromptMessages(final Map<String, Object> source, final Map<String, Object> target) {
-        copyIfPresent(source, target, "description");
-        List<Object> messages = LLMMCPJsonValues.castToList(source.get("messages"));
-        if (!messages.isEmpty()) {
-            target.put("message_count", messages.size());
-        }
-    }
-    
-    private static void copyCompactArtifactList(final Map<String, Object> source, final Map<String, Object> target, final String fieldName) {
-        List<Map<String, Object>> artifacts = LLMMCPJsonValues.castToList(source.get(fieldName));
-        if (artifacts.isEmpty()) {
-            return;
-        }
-        List<Map<String, Object>> summaries = new LinkedList<>();
-        for (Map<String, Object> each : artifacts.subList(0, Math.min(artifacts.size(), 3))) {
-            Map<String, Object> summary = new LinkedHashMap<>(4, 1F);
-            putArtifactCount(each, summary, "distsql_artifacts", "distsql_artifact_count");
-            if (!summary.isEmpty()) {
-                summaries.add(summary);
-            }
-        }
-        if (!summaries.isEmpty()) {
-            target.put(fieldName, summaries);
-        }
-    }
-    
-    private static void copyCompactArtifactPackage(final Map<String, Object> source, final Map<String, Object> target, final String fieldName) {
-        Object value = source.get(fieldName);
-        if (!(value instanceof Map)) {
-            return;
-        }
-        Map<String, Object> artifactPackage = LLMMCPJsonValues.castToMap(value);
-        Map<String, Object> summary = new LinkedHashMap<>(1, 1F);
-        putArtifactCount(artifactPackage, summary, "distsql_artifacts", "distsql_artifact_count");
-        if (!summary.isEmpty()) {
-            target.put(fieldName, summary);
-        }
-    }
-    
-    private static void putArtifactCount(final Map<String, Object> source, final Map<String, Object> target, final String sourceFieldName, final String targetFieldName) {
-        List<Object> artifacts = LLMMCPJsonValues.castToList(source.get(sourceFieldName));
-        if (!artifacts.isEmpty()) {
-            target.put(targetFieldName, artifacts.size());
-        }
-    }
-    
-    private static void copyCompactRecovery(final Map<String, Object> source, final Map<String, Object> target) {
-        if (!source.containsKey("recovery")) {
-            return;
-        }
-        Map<String, Object> recovery = LLMMCPJsonValues.castToMap(source.get("recovery"));
-        if (recovery.isEmpty()) {
-            return;
-        }
-        Map<String, Object> compactRecovery = new LinkedHashMap<>(8, 1F);
-        copyIfPresent(recovery, compactRecovery, "recovery_category");
-        copyIfPresent(recovery, compactRecovery, "category");
-        copyIfPresent(recovery, compactRecovery, "model_action");
-        copyIfPresent(recovery, compactRecovery, "plan_id");
-        copyIfPresent(recovery, compactRecovery, "completion_first");
-        copyIfPresent(recovery, compactRecovery, "suggested_arguments");
-        copyModelCriticalFields(recovery, compactRecovery);
-        target.put("recovery", compactRecovery);
-    }
-    
-    private static void copyNextActions(final Map<String, Object> source, final Map<String, Object> target) {
-        List<Map<String, Object>> nextActions = LLMMCPJsonValues.castToList(source.get(MCPPayloadFieldNames.NEXT_ACTIONS));
-        if (!nextActions.isEmpty()) {
-            target.put(MCPPayloadFieldNames.NEXT_ACTIONS, nextActions);
-        }
-    }
-}
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/client/LLMChatModelClient.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/client/LLMChatModelClient.java
index f2ac6780a15..c7315e32e68 100644
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/client/LLMChatModelClient.java
+++ b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/conversation/client/LLMChatModelClient.java
@@ -42,10 +42,6 @@ import java.util.stream.Collectors;
 @RequiredArgsConstructor
 public final class LLMChatModelClient {
     
-    private static final int COMPLETION_MAX_TOKENS = 512;
-    
-    private static final int READINESS_MAX_TOKENS = 64;
-    
     private final LLME2EConfiguration config;
     
     private final HttpClient httpClient;
@@ -88,7 +84,7 @@ public final class LLMChatModelClient {
      */
     public LLMChatCompletion complete(final List<LLMChatMessage> messages, final List<Map<String, Object>> tools,
                                       final String toolChoice, final boolean jsonResponse) throws IOException, InterruptedException {
-        HttpResponse<String> response = sendCompletionRequest(createCompletionRequestPayload(messages, tools, toolChoice, jsonResponse, COMPLETION_MAX_TOKENS), config.getRequestTimeoutSeconds());
+        HttpResponse<String> response = sendCompletionRequest(createCompletionRequestPayload(messages, tools, toolChoice, jsonResponse), config.getRequestTimeoutSeconds());
         if (200 != response.statusCode()) {
             throw new IllegalStateException(String.format("Model completion request failed with status %d%s.", response.statusCode(), createErrorCodeSuffix(response.body())));
         }
@@ -101,7 +97,7 @@ public final class LLMChatModelClient {
     }
     
     private Map<String, Object> createCompletionRequestPayload(final List<LLMChatMessage> messages, final List<Map<String, Object>> tools,
-                                                               final String toolChoice, final boolean jsonResponse, final int maxTokens) {
+                                                               final String toolChoice, final boolean jsonResponse) {
         Map<String, Object> requestPayload = new LinkedHashMap<>(16, 1F);
         requestPayload.put("model", config.getModelName());
         requestPayload.put("messages", createMessages(messages));
@@ -109,7 +105,6 @@ public final class LLMChatModelClient {
         requestPayload.put("temperature", 0);
         requestPayload.put("seed", 1);
         requestPayload.put("reasoning_effort", "none");
-        requestPayload.put("max_tokens", maxTokens);
         if (!tools.isEmpty()) {
             requestPayload.put("tools", tools);
         }
@@ -143,7 +138,7 @@ public final class LLMChatModelClient {
     
     HttpResponse<String> sendReadinessCompletionRequest(final List<LLMChatMessage> messages, final List<Map<String, Object>> tools,
                                                         final String toolChoice, final boolean jsonResponse) throws IOException, InterruptedException {
-        return sendCompletionRequest(createCompletionRequestPayload(messages, tools, toolChoice, jsonResponse, READINESS_MAX_TOKENS),
+        return sendCompletionRequest(createCompletionRequestPayload(messages, tools, toolChoice, jsonResponse),
                 Math.min(config.getRequestTimeoutSeconds(), config.getReadyTimeoutSeconds()));
     }
     
@@ -213,16 +208,21 @@ public final class LLMChatModelClient {
         if (null == value) {
             return List.of();
         }
-        return JsonUtils.fromJsonString(JsonUtils.toJsonString(value), new TypeReference<>() {
-        });
+        Preconditions.checkState(value instanceof List, "Expected a JSON array, but got `%s`.", value.getClass().getSimpleName());
+        List<?> values = (List<?>) value;
+        Preconditions.checkState(values.stream().allMatch(Map.class::isInstance), "Expected a JSON array of objects.");
+        return values.stream().map(this::castToMap).toList();
     }
     
+    @SuppressWarnings("unchecked")
     private Map<String, Object> castToMap(final Object value) {
         if (null == value) {
             return Map.of();
         }
-        return JsonUtils.fromJsonString(JsonUtils.toJsonString(value), new TypeReference<>() {
-        });
+        Preconditions.checkState(value instanceof Map, "Expected a JSON object, but got `%s`.", value.getClass().getSimpleName());
+        Map<?, ?> result = (Map<?, ?>) value;
+        Preconditions.checkState(result.keySet().stream().allMatch(String.class::isInstance), "Expected a JSON object with string keys.");
+        return (Map<String, Object>) result;
     }
     
     private Map<String, Object> parseJsonObject(final String responseBody, final String errorMessage) {
diff --git a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
index 95a36024cbf..e4e243fb94c 100644
--- a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
+++ b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/llm/fixture/LLMRuntimeSupport.java
@@ -179,7 +179,7 @@ public final class LLMRuntimeSupport {
                 .withExposedPorts(SERVER_PORT)
                 .withCommand("--host", "0.0.0.0", "--port", String.valueOf(SERVER_PORT), "-m", config.getModelMetadata().getContainerPath(), "--alias", config.getModelName(),
                         "--jinja", "--reasoning", "auto", "--reasoning-format", "deepseek", "--reasoning-budget", "0", "--chat-template-kwargs", "{\"enable_thinking\":false}",
-                        "--api-key", config.getApiKey(), "--no-ui", "-n", "512", "--parallel", "1", "-c", String.valueOf(CONTEXT_WINDOW_TOKENS),
+                        "--api-key", config.getApiKey(), "--no-ui", "--parallel", "1", "-c", String.valueOf(CONTEXT_WINDOW_TOKENS),
                         "-b", "256", "-ub", "128", "--cache-ram", "0", "--no-cache-prompt")
                 .waitingFor(Wait.forListeningPort())
                 .withStartupTimeout(Duration.ofMinutes(5));