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 32a929182f8 Standardize feature descriptors and fix completions 
(#38833)
32a929182f8 is described below

commit 32a929182f8d160d1779b2f7db9442ae7932a954
Author: Liang Zhang <[email protected]>
AuthorDate: Tue Jun 9 10:16:48 2026 +0800

    Standardize feature descriptors and fix completions (#38833)
    
    * Complete encrypt feature template contract
    
    - Add missing encrypt workflow output schema fields
    - Align encrypt prompt with assisted and LIKE query algorithm inputs
    - Enforce template output fields in descriptor validation
    - Cover completion targets, SPI registration, and secret-safe candidates
    - Mark Speckit traceability tasks as complete
    
    * Standardize feature descriptors and fix completions
    
    - align feature descriptor content, style, and completion design across MCP 
feature modules
    - fix feature plugin completions by using prompt targets instead of fixed 
resources
    - add fallback plugin catalogs and regression coverage for 
readwrite-splitting, shadow, and sharding
    - update MCP E2E baseline contract and validation to prevent static 
resource completion regressions
    
    * Standardize feature descriptors and fix completions
    
    - align feature descriptor content, style, and completion design across MCP 
feature modules
    - fix feature plugin completions by using prompt targets instead of fixed 
resources
    - add fallback plugin catalogs and regression coverage for 
readwrite-splitting, shadow, and sharding
    - update MCP E2E baseline contract and validation to prevent static 
resource completion regressions
---
 .../descriptor/EncryptToolDescriptorValidator.java | 10 ++-
 .../mcp-descriptors/mcp-descriptor-encrypt.yaml    | 44 +++++++++++--
 .../prompts/plan-encrypt-rule.md                   |  2 +
 .../encrypt/EncryptMCPHandlerProviderTest.java     |  8 +++
 .../EncryptAlgorithmCompletionProviderTest.java    | 60 ++++++++++++-----
 .../EncryptToolDescriptorValidatorTest.java        | 51 ++++++++++++++-
 .../mcp-descriptors/mcp-descriptor-mask.yaml       |  5 --
 .../MaskToolDescriptorValidatorTest.java           |  8 ++-
 .../ReadwriteSplittingInspectionService.java       | 15 ++++-
 ...re.mcp.support.completion.MCPCompletionProvider | 17 +++++
 .../mcp-descriptor-readwrite-splitting.yaml        |  5 --
 ...dwriteSplittingToolDescriptorValidatorTest.java |  9 ++-
 .../ReadwriteSplittingInspectionServiceTest.java   | 25 ++++++-
 .../tool/service/ShadowInspectionService.java      | 15 ++++-
 ...re.mcp.support.completion.MCPCompletionProvider | 17 +++++
 .../mcp-descriptors/mcp-descriptor-shadow.yaml     |  5 --
 .../ShadowToolDescriptorValidatorTest.java         |  8 ++-
 .../tool/service/ShadowInspectionServiceTest.java  | 25 ++++++-
 .../tool/service/ShardingInspectionService.java    | 35 +++++++++-
 ...re.mcp.support.completion.MCPCompletionProvider | 17 +++++
 .../mcp-descriptors/mcp-descriptor-sharding.yaml   | 76 +++++++++++++++++++---
 .../ShardingToolDescriptorValidatorTest.java       | 15 ++++-
 .../service/ShardingInspectionServiceTest.java     | 45 ++++++++++++-
 .../descriptor/MCPDescriptorCatalogValidator.java  | 19 +++++-
 .../descriptor/MCPDescriptorCatalogIndexTest.java  |  2 +
 .../HttpTransportCompletionE2ETest.java            | 27 +++++---
 .../model-contract/capabilities.yaml               | 42 +++++++++---
 27 files changed, 517 insertions(+), 90 deletions(-)

diff --git 
a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidator.java
 
b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidator.java
index 3d9e7b9cfdb..3d510110cec 100644
--- 
a/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidator.java
+++ 
b/mcp/features/encrypt/src/main/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidator.java
@@ -23,6 +23,7 @@ import 
org.apache.shardingsphere.mcp.support.descriptor.MCPToolDescriptorValidat
 import 
org.apache.shardingsphere.mcp.support.descriptor.MCPToolDescriptorValidationUtils;
 import org.apache.shardingsphere.mcp.support.protocol.MCPPayloadFieldNames;
 import org.apache.shardingsphere.mcp.support.workflow.model.WorkflowFieldNames;
+import 
org.apache.shardingsphere.mcp.support.workflow.service.WorkflowArtifactPayloadUtils;
 
 import java.util.List;
 
@@ -31,6 +32,11 @@ import java.util.List;
  */
 public final class EncryptToolDescriptorValidator implements 
MCPToolDescriptorValidator {
     
+    private static final List<String> REQUIRED_OUTPUT_FIELDS = 
List.of("response_mode", WorkflowFieldNames.PLAN_ID, "workflow_kind", "status", 
"missing_required_inputs",
+            MCPPayloadFieldNames.RESOURCES_TO_READ, 
MCPPayloadFieldNames.NEXT_ACTIONS, "argument_provenance", "proxy_topology_hint",
+            WorkflowArtifactPayloadUtils.PAYLOAD_KEY_DISTSQL_ARTIFACTS, 
WorkflowArtifactPayloadUtils.PAYLOAD_KEY_DDL_ARTIFACTS, 
WorkflowArtifactPayloadUtils.PAYLOAD_KEY_INDEX_PLAN,
+            "derived_column_plan", "masked_property_preview");
+    
     @Override
     public boolean supports(final MCPToolDescriptor toolDescriptor) {
         return 
EncryptFeatureDefinition.PLAN_TOOL_NAME.equals(toolDescriptor.getName());
@@ -38,8 +44,6 @@ public final class EncryptToolDescriptorValidator implements 
MCPToolDescriptorVa
     
     @Override
     public void validate(final MCPToolDescriptor toolDescriptor) {
-        
MCPToolDescriptorValidationUtils.validateRequiredOutputFields(toolDescriptor,
-                List.of("response_mode", WorkflowFieldNames.PLAN_ID, 
"workflow_kind", "status", "missing_required_inputs",
-                        MCPPayloadFieldNames.RESOURCES_TO_READ, 
MCPPayloadFieldNames.NEXT_ACTIONS));
+        
MCPToolDescriptorValidationUtils.validateRequiredOutputFields(toolDescriptor, 
REQUIRED_OUTPUT_FIELDS);
     }
 }
diff --git 
a/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-encrypt.yaml
 
b/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-encrypt.yaml
index e97032d8f7e..cfd766ae558 100644
--- 
a/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-encrypt.yaml
+++ 
b/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-encrypt.yaml
@@ -132,13 +132,6 @@ completionTargets:
       - assisted_query_algorithm_type
       - like_query_algorithm_type
     maxValues: 50
-  - referenceType: resource
-    reference: shardingsphere://features/encrypt/algorithms
-    arguments:
-      - algorithm_type
-      - assisted_query_algorithm_type
-      - like_query_algorithm_type
-    maxValues: 50
 resourceNavigation:
   - from: shardingsphere://features/encrypt/algorithms
     to: database_gateway_plan_encrypt_rule
@@ -377,9 +370,46 @@ tools:
         intent_inference:
           type: object
           description: "Resolved operation type, inferred values, unresolved 
fields, and reasoning notes."
+        argument_provenance:
+          type: object
+          description: "Source of important workflow arguments, such as 
user-provided, inferred, or server-defaulted values."
         review_focus:
           type: object
           description: "Compact planning review focus: artifact categories, 
side-effect scope, manual-only mode, and next review action."
+        proxy_topology_hint:
+          type: object
+          description: "Proxy metadata view expected by this workflow and safe 
recovery guidance when runtime metadata looks inconsistent."
+        distsql_artifacts:
+          type: array
+          description: "Masked rule DistSQL artifacts generated for review 
before applying the workflow."
+          items:
+            type: object
+        ddl_artifacts:
+          type: array
+          description: "Reviewable DDL artifact list returned by workflow 
payloads; encrypt rule planning normally leaves this empty."
+          items:
+            type: object
+        index_plan:
+          type: array
+          description: "Reviewable index plan list returned by workflow 
payloads; encrypt rule planning normally leaves this empty."
+          items:
+            type: object
+        derived_column_plan:
+          type: object
+          description: "Encrypt-specific physical column plan for cipher, 
assisted-query, and LIKE-query columns."
+        masked_property_preview:
+          type: object
+          description: "Encrypt-specific preview of algorithm properties with 
secret values masked before returning them to MCP clients."
+          properties:
+            primary:
+              type: object
+              description: "Masked primary encrypt algorithm properties."
+            assisted_query:
+              type: object
+              description: "Masked assisted-query algorithm properties."
+            like_query:
+              type: object
+              description: "Masked LIKE-query algorithm properties."
         next_actions:
           type: array
           description: "Ordered model-facing recommendations for the next call 
or user question."
diff --git 
a/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/prompts/plan-encrypt-rule.md
 
b/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/prompts/plan-encrypt-rule.md
index c6492306bc6..5d45e14066b 100644
--- 
a/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/prompts/plan-encrypt-rule.md
+++ 
b/mcp/features/encrypt/src/main/resources/META-INF/shardingsphere-mcp/prompts/plan-encrypt-rule.md
@@ -23,6 +23,8 @@ User context:
 - table: {{table}}
 - column: {{column}}
 - algorithm_type: {{algorithm_type}}
+- assisted_query_algorithm_type: {{assisted_query_algorithm_type}}
+- like_query_algorithm_type: {{like_query_algorithm_type}}
 - plan_id: {{plan_id}}
 
 Model path:
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 83f65b549ee..12ef9c24558 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
@@ -17,6 +17,7 @@
 
 package org.apache.shardingsphere.mcp.feature.encrypt;
 
+import org.apache.shardingsphere.mcp.api.MCPHandlerProvider;
 import org.apache.shardingsphere.mcp.api.resource.MCPResourceHandler;
 import org.apache.shardingsphere.mcp.api.tool.MCPToolHandler;
 import 
org.apache.shardingsphere.mcp.feature.encrypt.tool.service.EncryptWorkflowValidationService;
@@ -25,10 +26,12 @@ import org.junit.jupiter.api.Test;
 
 import java.util.Collection;
 import java.util.List;
+import java.util.ServiceLoader;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.isA;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 class EncryptMCPHandlerProviderTest {
     
@@ -47,6 +50,11 @@ class EncryptMCPHandlerProviderTest {
         assertThat(actual.getToolName(), 
is("database_gateway_plan_encrypt_rule"));
     }
     
+    @Test
+    void assertLoadByServiceLoader() {
+        
assertTrue(ServiceLoader.load(MCPHandlerProvider.class).stream().map(ServiceLoader.Provider::type).anyMatch(EncryptMCPHandlerProvider.class::equals));
+    }
+    
     @Test
     void assertGetWorkflowDefinitions() {
         WorkflowRuntimeDefinition actual = new 
EncryptMCPHandlerProvider().getWorkflowDefinitions().iterator().next();
diff --git 
a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionProviderTest.java
 
b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionProviderTest.java
index d192e9a8202..c056de096a9 100644
--- 
a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionProviderTest.java
+++ 
b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/completion/EncryptAlgorithmCompletionProviderTest.java
@@ -19,20 +19,26 @@ package 
org.apache.shardingsphere.mcp.feature.encrypt.completion;
 
 import org.apache.shardingsphere.mcp.feature.encrypt.EncryptFeatureDefinition;
 import org.apache.shardingsphere.mcp.support.completion.MCPCompletionCandidate;
-import 
org.apache.shardingsphere.mcp.support.completion.MCPCompletionProviderResult;
+import org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider;
 import 
org.apache.shardingsphere.mcp.support.completion.MCPCompletionRequestContext;
 import 
org.apache.shardingsphere.mcp.support.database.MCPDatabaseHandlerContext;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
 import 
org.apache.shardingsphere.mcp.support.descriptor.MCPCompletionTargetDescriptor;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
@@ -45,37 +51,57 @@ class EncryptAlgorithmCompletionProviderTest {
     }
     
     @Test
-    void assertSupports() {
-        assertTrue(new 
EncryptAlgorithmCompletionProvider().supports(createRequestContext(EncryptFeatureDefinition.PLAN_PROMPT_NAME,
 "algorithm_type")));
+    void assertLoadByServiceLoader() {
+        
assertTrue(ServiceLoader.load(MCPCompletionProvider.class).stream().map(ServiceLoader.Provider::type).anyMatch(EncryptAlgorithmCompletionProvider.class::equals));
     }
     
-    @Test
-    void assertSupportsWithAlgorithmResource() {
-        assertTrue(new 
EncryptAlgorithmCompletionProvider().supports(createRequestContext(EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI,
 "like_query_algorithm_type")));
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("supportedReferences")
+    void assertSupports(final String name, final String referenceType, final 
String reference, final String argumentName) {
+        assertTrue(new 
EncryptAlgorithmCompletionProvider().supports(createRequestContext(referenceType,
 reference, argumentName)));
     }
     
-    @Test
-    void assertSupportsWithForeignReference() {
-        assertFalse(new 
EncryptAlgorithmCompletionProvider().supports(createRequestContext("plan_mask_rule",
 "algorithm_type")));
+    @ParameterizedTest(name = "{0}")
+    @MethodSource("unsupportedReferences")
+    void assertSupportsWithForeignReference(final String name, final String 
referenceType, final String reference, final String argumentName) {
+        assertFalse(new 
EncryptAlgorithmCompletionProvider().supports(createRequestContext(referenceType,
 reference, argumentName)));
     }
     
     @Test
     void assertComplete() {
         MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
         when(queryFacade.queryWithAnyDatabase("SHOW ENCRYPT ALGORITHM 
PLUGINS")).thenReturn(List.of(
-                Map.of("type", "AES", "description", "AES encryptor"),
+                Map.of("type", "AES", "description", "AES encryptor", 
"aes-key-value", "secret-value"),
                 Map.of("type", "")));
         MCPDatabaseHandlerContext handlerContext = 
mock(MCPDatabaseHandlerContext.class);
         when(handlerContext.getQueryFacade()).thenReturn(queryFacade);
-        MCPCompletionProviderResult actual = new 
EncryptAlgorithmCompletionProvider().complete(handlerContext,
-                
createRequestContext(EncryptFeatureDefinition.PLAN_PROMPT_NAME, 
"algorithm_type"));
-        List<MCPCompletionCandidate> actualCandidates = new 
ArrayList<>(actual.getCandidates());
+        List<MCPCompletionCandidate> actualCandidates = new ArrayList<>(new 
EncryptAlgorithmCompletionProvider().complete(handlerContext,
+                createRequestContext("prompt", 
EncryptFeatureDefinition.PLAN_PROMPT_NAME, "algorithm_type")).getCandidates());
         assertThat(actualCandidates.size(), is(1));
-        assertThat(actualCandidates.get(0).getValue(), is("AES"));
-        assertThat(actualCandidates.get(0).getLabel(), is("AES encryptor"));
+        assertThat(actualCandidates.getFirst().getValue(), is("AES"));
+        assertThat(actualCandidates.getFirst().getLabel(), is("AES 
encryptor"));
+        assertThat(actualCandidates.getFirst().getSource(), 
is("encrypt-algorithm"));
+        assertNull(actualCandidates.getFirst().getUpdateTime());
+        assertThat(actualCandidates.getFirst().getRankingReason(), is(""));
+    }
+    
+    private static Collection<Arguments> supportedReferences() {
+        return List.of(
+                Arguments.of("prompt algorithm_type", "prompt", 
EncryptFeatureDefinition.PLAN_PROMPT_NAME, "algorithm_type"),
+                Arguments.of("prompt assisted_query_algorithm_type", "prompt", 
EncryptFeatureDefinition.PLAN_PROMPT_NAME, "assisted_query_algorithm_type"),
+                Arguments.of("prompt like_query_algorithm_type", "prompt", 
EncryptFeatureDefinition.PLAN_PROMPT_NAME, "like_query_algorithm_type"),
+                Arguments.of("resource algorithm_type", "resource", 
EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI, "algorithm_type"),
+                Arguments.of("resource assisted_query_algorithm_type", 
"resource", EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI, 
"assisted_query_algorithm_type"),
+                Arguments.of("resource like_query_algorithm_type", "resource", 
EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI, "like_query_algorithm_type"));
+    }
+    
+    private static Collection<Arguments> unsupportedReferences() {
+        return List.of(
+                Arguments.of("foreign prompt", "prompt", "plan_mask_rule", 
"algorithm_type"),
+                Arguments.of("foreign resource", "resource", 
"shardingsphere://features/mask/algorithms", "algorithm_type"));
     }
     
-    private MCPCompletionRequestContext createRequestContext(final String 
reference, final String argumentName) {
-        return new MCPCompletionRequestContext("session-1", new 
MCPCompletionTargetDescriptor("prompt", reference, List.of(argumentName), 50, 
Map.of()), argumentName, Map.of());
+    private MCPCompletionRequestContext createRequestContext(final String 
referenceType, final String reference, final String argumentName) {
+        return new MCPCompletionRequestContext("session-1", new 
MCPCompletionTargetDescriptor(referenceType, reference, List.of(argumentName), 
50, Map.of()), argumentName, Map.of());
     }
 }
diff --git 
a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidatorTest.java
 
b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidatorTest.java
index 8164012690e..c2137f2e557 100644
--- 
a/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidatorTest.java
+++ 
b/mcp/features/encrypt/src/test/java/org/apache/shardingsphere/mcp/feature/encrypt/descriptor/EncryptToolDescriptorValidatorTest.java
@@ -23,7 +23,10 @@ import 
org.apache.shardingsphere.mcp.feature.encrypt.EncryptFeatureDefinition;
 import 
org.apache.shardingsphere.mcp.support.descriptor.MCPCompletionTargetDescriptor;
 import 
org.apache.shardingsphere.mcp.support.descriptor.MCPDescriptorCatalogIndex;
 import 
org.apache.shardingsphere.mcp.support.descriptor.MCPShardingSphereMetadataKeys;
+import 
org.apache.shardingsphere.mcp.support.descriptor.MCPToolDescriptorValidator;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -31,6 +34,7 @@ import java.nio.charset.StandardCharsets;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.ServiceLoader;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.is;
@@ -45,6 +49,11 @@ class EncryptToolDescriptorValidatorTest {
         assertTrue(new 
EncryptToolDescriptorValidator().supports(MCPDescriptorCatalogIndex.getRequiredToolDescriptor(EncryptFeatureDefinition.PLAN_TOOL_NAME)));
     }
     
+    @Test
+    void assertLoadByServiceLoader() {
+        
assertTrue(ServiceLoader.load(MCPToolDescriptorValidator.class).stream().map(ServiceLoader.Provider::type).anyMatch(EncryptToolDescriptorValidator.class::equals));
+    }
+    
     @Test
     void assertPromptUsesGuidanceName() {
         MCPPromptDescriptor actual = 
findPrompt(EncryptFeatureDefinition.PLAN_PROMPT_NAME);
@@ -58,8 +67,15 @@ class EncryptToolDescriptorValidatorTest {
         List<String> expectedArguments = List.of("algorithm_type", 
"assisted_query_algorithm_type", "like_query_algorithm_type");
         MCPCompletionTargetDescriptor promptCompletionTarget = 
findCompletionTarget("prompt", EncryptFeatureDefinition.PLAN_PROMPT_NAME);
         assertThat(promptCompletionTarget.getArguments(), 
is(expectedArguments));
-        MCPCompletionTargetDescriptor resourceCompletionTarget = 
findCompletionTarget("resource", 
EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI);
-        assertThat(resourceCompletionTarget.getArguments(), 
is(expectedArguments));
+        assertFalse(hasCompletionTarget("resource", 
EncryptFeatureDefinition.ALGORITHMS_RESOURCE_URI));
+    }
+    
+    @Test
+    void assertPromptExposesCompletionArguments() throws IOException {
+        String actual = 
readResource("META-INF/shardingsphere-mcp/prompts/plan-encrypt-rule.md");
+        for (String each : findCompletionTarget("prompt", 
EncryptFeatureDefinition.PLAN_PROMPT_NAME).getArguments()) {
+            assertTrue(actual.contains("- " + each + ": {{" + each + "}}"));
+        }
     }
     
     @Test
@@ -75,6 +91,18 @@ class EncryptToolDescriptorValidatorTest {
         assertTrue(supportProperties.containsKey("selected_interaction"));
     }
     
+    @Test
+    @SuppressWarnings("unchecked")
+    void assertOutputSchemaDeclaresPlanResponseFields() {
+        MCPToolDescriptor descriptor = 
MCPDescriptorCatalogIndex.getRequiredToolDescriptor(EncryptFeatureDefinition.PLAN_TOOL_NAME);
+        Map<String, Object> actual = (Map<String, Object>) 
descriptor.getOutputSchema().get("properties");
+        assertTrue(actual.keySet().containsAll(List.of(
+                "response_mode", "plan_id", "workflow_kind", "status", 
"issues", "global_steps", "current_step", "algorithm_recommendations",
+                "property_requirements", "validation_strategy", 
"delivery_mode", "execution_mode", "intent_inference", "argument_provenance", 
"review_focus",
+                "missing_required_inputs", "clarification_questions", 
"resources_to_read", "proxy_topology_hint", "next_actions", "distsql_artifacts",
+                "ddl_artifacts", "index_plan", "derived_column_plan", 
"masked_property_preview")));
+    }
+    
     @Test
     @SuppressWarnings("unchecked")
     void assertDescriptorIsRuleDistSQLOnly() {
@@ -112,6 +140,20 @@ class EncryptToolDescriptorValidatorTest {
         assertThat(actual.getMessage(), is("Tool 
`database_gateway_plan_encrypt_rule` outputSchema must declare 
`resources_to_read`."));
     }
     
+    @ParameterizedTest(name = "{0}")
+    @ValueSource(strings = {"argument_provenance", "masked_property_preview"})
+    @SuppressWarnings("unchecked")
+    void assertValidateRejectsMissingTemplateOutputField(final String 
fieldName) {
+        MCPToolDescriptor descriptor = 
MCPDescriptorCatalogIndex.getRequiredToolDescriptor(EncryptFeatureDefinition.PLAN_TOOL_NAME);
+        Map<String, Object> outputSchema = new 
LinkedHashMap<>(descriptor.getOutputSchema());
+        Map<String, Object> properties = new LinkedHashMap<>((Map<String, 
Object>) outputSchema.get("properties"));
+        properties.remove(fieldName);
+        outputSchema.put("properties", properties);
+        IllegalStateException actual = 
assertThrows(IllegalStateException.class, () -> new 
EncryptToolDescriptorValidator().validate(new MCPToolDescriptor(
+                descriptor.getName(), descriptor.getTitle(), 
descriptor.getDescription(), descriptor.getInputSchema(), outputSchema, 
descriptor.getAnnotations(), descriptor.getMeta())));
+        assertThat(actual.getMessage(), is("Tool 
`database_gateway_plan_encrypt_rule` outputSchema must declare `" + fieldName + 
"`."));
+    }
+    
     private MCPPromptDescriptor findPrompt(final String promptName) {
         return 
MCPDescriptorCatalogIndex.getPromptDescriptors().stream().filter(each -> 
promptName.equals(each.getName())).findFirst().orElseThrow();
     }
@@ -121,6 +163,11 @@ class EncryptToolDescriptorValidatorTest {
                 .filter(each -> referenceType.equals(each.getReferenceType()) 
&& reference.equals(each.getReference())).findFirst().orElseThrow();
     }
     
+    private boolean hasCompletionTarget(final String referenceType, final 
String reference) {
+        return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
+                .anyMatch(each -> 
referenceType.equals(each.getReferenceType()) && 
reference.equals(each.getReference()));
+    }
+    
     private String readResource(final String resourceName) throws IOException {
         try (InputStream inputStream = 
Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName))
 {
             return new String(inputStream.readAllBytes(), 
StandardCharsets.UTF_8);
diff --git 
a/mcp/features/mask/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-mask.yaml
 
b/mcp/features/mask/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-mask.yaml
index 3b765fed567..7662e4b011e 100644
--- 
a/mcp/features/mask/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-mask.yaml
+++ 
b/mcp/features/mask/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-mask.yaml
@@ -122,11 +122,6 @@ completionTargets:
     arguments:
       - algorithm_type
     maxValues: 50
-  - referenceType: resource
-    reference: shardingsphere://features/mask/algorithms
-    arguments:
-      - algorithm_type
-    maxValues: 50
 resourceNavigation:
   - from: shardingsphere://features/mask/algorithms
     to: database_gateway_plan_mask_rule
diff --git 
a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/descriptor/MaskToolDescriptorValidatorTest.java
 
b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/descriptor/MaskToolDescriptorValidatorTest.java
index e736a612414..b04082fe2d6 100644
--- 
a/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/descriptor/MaskToolDescriptorValidatorTest.java
+++ 
b/mcp/features/mask/src/test/java/org/apache/shardingsphere/mcp/feature/mask/descriptor/MaskToolDescriptorValidatorTest.java
@@ -57,8 +57,7 @@ class MaskToolDescriptorValidatorTest {
     void assertExposeCompletionTargets() {
         MCPCompletionTargetDescriptor promptCompletionTarget = 
findCompletionTarget("prompt", MaskFeatureDefinition.PLAN_PROMPT_NAME);
         assertThat(promptCompletionTarget.getArguments(), 
is(List.of("algorithm_type")));
-        MCPCompletionTargetDescriptor resourceCompletionTarget = 
findCompletionTarget("resource", MaskFeatureDefinition.ALGORITHMS_RESOURCE_URI);
-        assertThat(resourceCompletionTarget.getArguments(), 
is(List.of("algorithm_type")));
+        assertFalse(hasCompletionTarget("resource", 
MaskFeatureDefinition.ALGORITHMS_RESOURCE_URI));
     }
     
     @Test
@@ -126,6 +125,11 @@ class MaskToolDescriptorValidatorTest {
                 .filter(each -> referenceType.equals(each.getReferenceType()) 
&& reference.equals(each.getReference())).findFirst().orElseThrow();
     }
     
+    private boolean hasCompletionTarget(final String referenceType, final 
String reference) {
+        return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
+                .anyMatch(each -> 
referenceType.equals(each.getReferenceType()) && 
reference.equals(each.getReference()));
+    }
+    
     private String readResource(final String resourceName) throws IOException {
         try (InputStream inputStream = 
Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName))
 {
             return new String(inputStream.readAllBytes(), 
StandardCharsets.UTF_8);
diff --git 
a/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionService.java
 
b/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionService.java
index 25ddc200329..369f94e0f16 100644
--- 
a/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionService.java
+++ 
b/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionService.java
@@ -17,7 +17,9 @@
 
 package org.apache.shardingsphere.mcp.feature.readwritesplitting.tool.service;
 
+import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
+import 
org.apache.shardingsphere.mcp.support.workflow.service.WorkflowDistSQLQueryUtils;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSQLUtils;
 
 import java.util.LinkedHashMap;
@@ -96,7 +98,18 @@ public final class ReadwriteSplittingInspectionService {
      * @return algorithm plugin rows with built-in property hints
      */
     public List<Map<String, Object>> queryLoadBalanceAlgorithmPlugins(final 
MCPFeatureQueryFacade queryFacade) {
-        return queryFacade.queryWithAnyDatabase("SHOW LOAD BALANCE ALGORITHM 
PLUGINS").stream().map(this::appendPropertyGuidance).toList();
+        return 
queryAlgorithmRows(queryFacade).stream().map(this::appendPropertyGuidance).toList();
+    }
+    
+    private List<Map<String, Object>> queryAlgorithmRows(final 
MCPFeatureQueryFacade queryFacade) {
+        try {
+            return queryFacade.queryWithAnyDatabase("SHOW LOAD BALANCE 
ALGORITHM PLUGINS");
+        } catch (final MCPQueryFailedException ex) {
+            if 
(WorkflowDistSQLQueryUtils.isUnsupportedDistSQLQueryFailure(ex)) {
+                return List.of(Map.of("type", "RANDOM"), Map.of("type", 
"ROUND_ROBIN"), Map.of("type", "WEIGHT"));
+            }
+            throw ex;
+        }
     }
     
     private Map<String, Object> appendPropertyGuidance(final Map<String, 
Object> row) {
diff --git 
a/mcp/features/readwrite-splitting/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
 
b/mcp/features/readwrite-splitting/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
index 596414d6512..e9c5a8d4902 100644
--- 
a/mcp/features/readwrite-splitting/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
+++ 
b/mcp/features/readwrite-splitting/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
@@ -1 +1,18 @@
+#
+# 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.
+#
+
 
org.apache.shardingsphere.mcp.feature.readwritesplitting.completion.ReadwriteSplittingLoadBalanceAlgorithmCompletionProvider
diff --git 
a/mcp/features/readwrite-splitting/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-readwrite-splitting.yaml
 
b/mcp/features/readwrite-splitting/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-readwrite-splitting.yaml
index 1d539363ef5..55bcc9eec2f 100644
--- 
a/mcp/features/readwrite-splitting/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-readwrite-splitting.yaml
+++ 
b/mcp/features/readwrite-splitting/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-readwrite-splitting.yaml
@@ -212,11 +212,6 @@ completionTargets:
     arguments:
       - load_balancer_type
     maxValues: 50
-  - referenceType: resource
-    reference: 
shardingsphere://features/readwrite-splitting/load-balance-algorithm-plugins
-    arguments:
-      - load_balancer_type
-    maxValues: 50
 resourceNavigation:
   - from: 
shardingsphere://features/readwrite-splitting/databases/{database}/rules
     to: database_gateway_plan_readwrite_splitting_rule
diff --git 
a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/descriptor/ReadwriteSplittingToolDescriptorValidatorTest.java
 
b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/descriptor/ReadwriteSplittingToolDescriptorValidatorTest.java
index 2f0dfe110b8..b3abc64a117 100644
--- 
a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/descriptor/ReadwriteSplittingToolDescriptorValidatorTest.java
+++ 
b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/descriptor/ReadwriteSplittingToolDescriptorValidatorTest.java
@@ -52,9 +52,7 @@ class ReadwriteSplittingToolDescriptorValidatorTest {
         MCPCompletionTargetDescriptor promptCompletionTarget = 
findCompletionTarget("prompt", 
ReadwriteSplittingFeatureDefinition.PLAN_RULE_PROMPT_NAME);
         assertThat(promptCompletionTarget.getArguments(), 
is(List.of(ReadwriteSplittingFeatureDefinition.LOAD_BALANCER_TYPE_FIELD)));
         assertThat(promptCompletionTarget.getMaxValues(), is(50));
-        MCPCompletionTargetDescriptor resourceCompletionTarget = 
findCompletionTarget("resource", 
ReadwriteSplittingFeatureDefinition.LOAD_BALANCE_ALGORITHM_PLUGINS_RESOURCE_URI);
-        assertThat(resourceCompletionTarget.getArguments(), 
is(List.of(ReadwriteSplittingFeatureDefinition.LOAD_BALANCER_TYPE_FIELD)));
-        assertThat(resourceCompletionTarget.getMaxValues(), is(50));
+        assertFalse(hasCompletionTarget("resource", 
ReadwriteSplittingFeatureDefinition.LOAD_BALANCE_ALGORITHM_PLUGINS_RESOURCE_URI));
     }
     
     @Test
@@ -114,6 +112,11 @@ class ReadwriteSplittingToolDescriptorValidatorTest {
                 .filter(each -> referenceType.equals(each.getReferenceType()) 
&& reference.equals(each.getReference())).findFirst().orElseThrow();
     }
     
+    private boolean hasCompletionTarget(final String referenceType, final 
String reference) {
+        return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
+                .anyMatch(each -> 
referenceType.equals(each.getReferenceType()) && 
reference.equals(each.getReference()));
+    }
+    
     private String readResource(final String resourceName) throws IOException {
         try (InputStream inputStream = 
Thread.currentThread().getContextClassLoader().getResourceAsStream(resourceName))
 {
             return new String(inputStream.readAllBytes(), 
StandardCharsets.UTF_8);
diff --git 
a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionServiceTest.java
 
b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionServiceTest.java
index bdf86890fb0..6f26b996018 100644
--- 
a/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionServiceTest.java
+++ 
b/mcp/features/readwrite-splitting/src/test/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingInspectionServiceTest.java
@@ -17,15 +17,20 @@
 
 package org.apache.shardingsphere.mcp.feature.readwritesplitting.tool.service;
 
+import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
 import org.junit.jupiter.api.Test;
 
+import java.sql.SQLException;
+import java.sql.SQLSyntaxErrorException;
 import java.util.List;
 import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -52,7 +57,25 @@ class ReadwriteSplittingInspectionServiceTest {
         MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
         when(queryFacade.queryWithAnyDatabase("SHOW LOAD BALANCE ALGORITHM 
PLUGINS")).thenReturn(List.of(Map.of("type", "WEIGHT")));
         List<Map<String, Object>> actual = new 
ReadwriteSplittingInspectionService().queryLoadBalanceAlgorithmPlugins(queryFacade);
-        assertThat(actual.get(0).get("property_guidance").toString(), 
containsString("numeric property"));
+        assertThat(actual.getFirst().get("property_guidance").toString(), 
containsString("numeric property"));
+    }
+    
+    @Test
+    void assertQueryLoadBalanceAlgorithmPluginsWithUnavailableDistSQL() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW LOAD BALANCE ALGORITHM 
PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("syntax error near 
'LOAD BALANCE ALGORITHM PLUGINS'", new SQLSyntaxErrorException("syntax 
error")));
+        List<Map<String, Object>> actual = new 
ReadwriteSplittingInspectionService().queryLoadBalanceAlgorithmPlugins(queryFacade);
+        assertTrue(actual.stream().anyMatch(each -> 
"ROUND_ROBIN".equals(each.get("type"))));
+        assertTrue(actual.stream().anyMatch(each -> 
"ROUND_ROBIN".equals(each.get("type")) && "No required 
properties.".equals(each.get("property_guidance"))));
+    }
+    
+    @Test
+    void assertQueryLoadBalanceAlgorithmPluginsPropagatesQueryFailure() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW LOAD BALANCE ALGORITHM 
PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("Connection refused.", 
new SQLException("Connection refused.")));
+        assertThrows(MCPQueryFailedException.class, () -> new 
ReadwriteSplittingInspectionService().queryLoadBalanceAlgorithmPlugins(queryFacade));
     }
     
     @Test
diff --git 
a/mcp/features/shadow/src/main/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionService.java
 
b/mcp/features/shadow/src/main/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionService.java
index 06e70f60a36..e21238175c2 100644
--- 
a/mcp/features/shadow/src/main/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionService.java
+++ 
b/mcp/features/shadow/src/main/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionService.java
@@ -17,7 +17,9 @@
 
 package org.apache.shardingsphere.mcp.feature.shadow.tool.service;
 
+import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
+import 
org.apache.shardingsphere.mcp.support.workflow.service.WorkflowDistSQLQueryUtils;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSQLUtils;
 
 import java.util.LinkedHashMap;
@@ -118,7 +120,18 @@ public final class ShadowInspectionService {
      * @return shadow algorithm plugin rows with built-in property guidance
      */
     public List<Map<String, Object>> queryAlgorithmPlugins(final 
MCPFeatureQueryFacade queryFacade) {
-        return queryFacade.queryWithAnyDatabase("SHOW SHADOW ALGORITHM 
PLUGINS").stream().map(this::appendPropertyGuidance).toList();
+        return 
queryAlgorithmRows(queryFacade).stream().map(this::appendPropertyGuidance).toList();
+    }
+    
+    private List<Map<String, Object>> queryAlgorithmRows(final 
MCPFeatureQueryFacade queryFacade) {
+        try {
+            return queryFacade.queryWithAnyDatabase("SHOW SHADOW ALGORITHM 
PLUGINS");
+        } catch (final MCPQueryFailedException ex) {
+            if 
(WorkflowDistSQLQueryUtils.isUnsupportedDistSQLQueryFailure(ex)) {
+                return List.of(Map.of("type", "SQL_HINT"), Map.of("type", 
"REGEX_MATCH"), Map.of("type", "VALUE_MATCH"));
+            }
+            throw ex;
+        }
     }
     
     private Map<String, Object> appendPropertyGuidance(final Map<String, 
Object> row) {
diff --git 
a/mcp/features/shadow/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
 
b/mcp/features/shadow/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
index bef2dae2795..f5970149aa8 100644
--- 
a/mcp/features/shadow/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
+++ 
b/mcp/features/shadow/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
@@ -1 +1,18 @@
+#
+# 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.
+#
+
 
org.apache.shardingsphere.mcp.feature.shadow.completion.ShadowAlgorithmCompletionProvider
diff --git 
a/mcp/features/shadow/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-shadow.yaml
 
b/mcp/features/shadow/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-shadow.yaml
index 8422d9450e9..a1f712ffac4 100644
--- 
a/mcp/features/shadow/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-shadow.yaml
+++ 
b/mcp/features/shadow/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-shadow.yaml
@@ -282,11 +282,6 @@ completionTargets:
     arguments:
       - algorithm_type
     maxValues: 50
-  - referenceType: resource
-    reference: shardingsphere://features/shadow/algorithm-plugins
-    arguments:
-      - algorithm_type
-    maxValues: 50
 resourceNavigation:
   - from: shardingsphere://features/shadow/databases/{database}/rules
     to: database_gateway_plan_shadow_rule
diff --git 
a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/descriptor/ShadowToolDescriptorValidatorTest.java
 
b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/descriptor/ShadowToolDescriptorValidatorTest.java
index 5ab423aeb29..16ef0c16542 100644
--- 
a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/descriptor/ShadowToolDescriptorValidatorTest.java
+++ 
b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/descriptor/ShadowToolDescriptorValidatorTest.java
@@ -52,8 +52,7 @@ class ShadowToolDescriptorValidatorTest {
         assertThat(rulePromptCompletionTarget.getArguments(), 
is(List.of(ShadowFeatureDefinition.ALGORITHM_TYPE_FIELD)));
         MCPCompletionTargetDescriptor defaultPromptCompletionTarget = 
findCompletionTarget("prompt", 
ShadowFeatureDefinition.PLAN_DEFAULT_ALGORITHM_PROMPT_NAME);
         assertThat(defaultPromptCompletionTarget.getArguments(), 
is(List.of(ShadowFeatureDefinition.ALGORITHM_TYPE_FIELD)));
-        MCPCompletionTargetDescriptor resourceCompletionTarget = 
findCompletionTarget("resource", 
ShadowFeatureDefinition.ALGORITHM_PLUGINS_RESOURCE_URI);
-        assertThat(resourceCompletionTarget.getArguments(), 
is(List.of(ShadowFeatureDefinition.ALGORITHM_TYPE_FIELD)));
+        assertFalse(hasCompletionTarget("resource", 
ShadowFeatureDefinition.ALGORITHM_PLUGINS_RESOURCE_URI));
     }
     
     @Test
@@ -99,4 +98,9 @@ class ShadowToolDescriptorValidatorTest {
         return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
                 .filter(each -> referenceType.equals(each.getReferenceType()) 
&& reference.equals(each.getReference())).findFirst().orElseThrow();
     }
+    
+    private boolean hasCompletionTarget(final String referenceType, final 
String reference) {
+        return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
+                .anyMatch(each -> 
referenceType.equals(each.getReferenceType()) && 
reference.equals(each.getReference()));
+    }
 }
diff --git 
a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionServiceTest.java
 
b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionServiceTest.java
index 565011e484a..8b8324f57f1 100644
--- 
a/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionServiceTest.java
+++ 
b/mcp/features/shadow/src/test/java/org/apache/shardingsphere/mcp/feature/shadow/tool/service/ShadowInspectionServiceTest.java
@@ -17,15 +17,20 @@
 
 package org.apache.shardingsphere.mcp.feature.shadow.tool.service;
 
+import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
 import org.junit.jupiter.api.Test;
 
+import java.sql.SQLException;
+import java.sql.SQLSyntaxErrorException;
 import java.util.List;
 import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -59,6 +64,24 @@ class ShadowInspectionServiceTest {
         when(queryFacade.queryWithAnyDatabase("SHOW SHADOW ALGORITHM 
PLUGINS")).thenReturn(List.of(Map.of("type", "VALUE_MATCH")));
         List<Map<String, Object>> actual = new 
ShadowInspectionService().queryAlgorithmPlugins(queryFacade);
         assertThat(actual.size(), is(1));
-        assertThat(String.valueOf(actual.get(0).get("property_guidance")), 
containsString("operation"));
+        assertThat(String.valueOf(actual.getFirst().get("property_guidance")), 
containsString("operation"));
+    }
+    
+    @Test
+    void assertQueryAlgorithmPluginsWithUnavailableDistSQL() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW SHADOW ALGORITHM PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("syntax error near 
'SHADOW ALGORITHM PLUGINS'", new SQLSyntaxErrorException("syntax error")));
+        List<Map<String, Object>> actual = new 
ShadowInspectionService().queryAlgorithmPlugins(queryFacade);
+        assertTrue(actual.stream().anyMatch(each -> 
"VALUE_MATCH".equals(each.get("type"))));
+        assertTrue(actual.stream().anyMatch(each -> 
"VALUE_MATCH".equals(each.get("type")) && 
String.valueOf(each.get("property_guidance")).contains("operation")));
+    }
+    
+    @Test
+    void assertQueryAlgorithmPluginsPropagatesQueryFailure() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW SHADOW ALGORITHM PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("Connection refused.", 
new SQLException("Connection refused.")));
+        assertThrows(MCPQueryFailedException.class, () -> new 
ShadowInspectionService().queryAlgorithmPlugins(queryFacade));
     }
 }
diff --git 
a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionService.java
 
b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionService.java
index 0de6254867f..6b2c6962340 100644
--- 
a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionService.java
+++ 
b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionService.java
@@ -17,7 +17,9 @@
 
 package org.apache.shardingsphere.mcp.feature.sharding.tool.service;
 
+import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
+import 
org.apache.shardingsphere.mcp.support.workflow.service.WorkflowDistSQLQueryUtils;
 import org.apache.shardingsphere.mcp.support.workflow.service.WorkflowSQLUtils;
 
 import java.util.LinkedHashMap;
@@ -37,7 +39,7 @@ public final class ShardingInspectionService {
      * @return sharding algorithm plugin rows
      */
     public List<Map<String, Object>> queryAlgorithmPlugins(final 
MCPFeatureQueryFacade queryFacade) {
-        return queryFacade.queryWithAnyDatabase("SHOW SHARDING ALGORITHM 
PLUGINS").stream().map(this::appendShardingAlgorithmGuidance).toList();
+        return queryPluginRows(queryFacade, "SHOW SHARDING ALGORITHM PLUGINS", 
getShardingAlgorithmPluginRows()).stream().map(this::appendShardingAlgorithmGuidance).toList();
     }
     
     /**
@@ -47,7 +49,36 @@ public final class ShardingInspectionService {
      * @return key generate algorithm plugin rows
      */
     public List<Map<String, Object>> queryKeyGenerateAlgorithmPlugins(final 
MCPFeatureQueryFacade queryFacade) {
-        return queryFacade.queryWithAnyDatabase("SHOW KEY GENERATE ALGORITHM 
PLUGINS").stream().map(this::appendKeyGeneratorGuidance).toList();
+        return queryPluginRows(queryFacade, "SHOW KEY GENERATE ALGORITHM 
PLUGINS", 
getKeyGenerateAlgorithmPluginRows()).stream().map(this::appendKeyGeneratorGuidance).toList();
+    }
+    
+    private List<Map<String, Object>> queryPluginRows(final 
MCPFeatureQueryFacade queryFacade, final String sql, final List<Map<String, 
Object>> fallbackRows) {
+        try {
+            return queryFacade.queryWithAnyDatabase(sql);
+        } catch (final MCPQueryFailedException ex) {
+            if 
(WorkflowDistSQLQueryUtils.isUnsupportedDistSQLQueryFailure(ex)) {
+                return fallbackRows;
+            }
+            throw ex;
+        }
+    }
+    
+    private List<Map<String, Object>> getShardingAlgorithmPluginRows() {
+        return List.of(
+                Map.of("type", "MOD"),
+                Map.of("type", "HASH_MOD"),
+                Map.of("type", "VOLUME_RANGE"),
+                Map.of("type", "BOUNDARY_RANGE"),
+                Map.of("type", "AUTO_INTERVAL"),
+                Map.of("type", "INTERVAL"),
+                Map.of("type", "CLASS_BASED"),
+                Map.of("type", "INLINE"),
+                Map.of("type", "COMPLEX_INLINE"),
+                Map.of("type", "HINT_INLINE"));
+    }
+    
+    private List<Map<String, Object>> getKeyGenerateAlgorithmPluginRows() {
+        return List.of(Map.of("type", "SNOWFLAKE"), Map.of("type", "UUID"));
     }
     
     /**
diff --git 
a/mcp/features/sharding/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
 
b/mcp/features/sharding/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
index 48b5edcdb99..8ba2f2d5ee3 100644
--- 
a/mcp/features/sharding/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
+++ 
b/mcp/features/sharding/src/main/resources/META-INF/services/org.apache.shardingsphere.mcp.support.completion.MCPCompletionProvider
@@ -1 +1,18 @@
+#
+# 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.
+#
+
 
org.apache.shardingsphere.mcp.feature.sharding.completion.ShardingAlgorithmCompletionProvider
diff --git 
a/mcp/features/sharding/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-sharding.yaml
 
b/mcp/features/sharding/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-sharding.yaml
index 252ff929687..e8aa352d1fe 100644
--- 
a/mcp/features/sharding/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-sharding.yaml
+++ 
b/mcp/features/sharding/src/main/resources/META-INF/shardingsphere-mcp/mcp-descriptors/mcp-descriptor-sharding.yaml
@@ -318,7 +318,7 @@ prompts:
     description: "Guide the model to plan sharding table rule DistSQL."
     binding:
       templateResource: 
META-INF/shardingsphere-mcp/prompts/plan-sharding-table-rule.md
-    arguments: &commonPromptArguments
+    arguments:
       - name: database
         title: Logical Database
         description: "ShardingSphere logical database."
@@ -327,6 +327,10 @@ prompts:
         title: Operation Type
         description: "create, alter, or drop."
         required: false
+      - name: algorithm_type
+        title: Sharding Algorithm
+        description: "Optional sharding algorithm type."
+        required: false
     meta:
       org.apache.shardingsphere/related-tools:
         - database_gateway_plan_sharding_table_rule
@@ -343,7 +347,15 @@ prompts:
     description: "Guide the model to plan sharding table reference rule 
DistSQL."
     binding:
       templateResource: 
META-INF/shardingsphere-mcp/prompts/plan-sharding-table-reference-rule.md
-    arguments: *commonPromptArguments
+    arguments: &commonPromptArguments
+      - name: database
+        title: Logical Database
+        description: "ShardingSphere logical database."
+        required: false
+      - name: operation_type
+        title: Operation Type
+        description: "create, alter, or drop."
+        required: false
     meta:
       org.apache.shardingsphere/related-tools:
         - database_gateway_plan_sharding_table_reference_rule
@@ -360,7 +372,19 @@ prompts:
     description: "Guide the model to plan default sharding strategy DistSQL."
     binding:
       templateResource: 
META-INF/shardingsphere-mcp/prompts/plan-sharding-default-strategy.md
-    arguments: *commonPromptArguments
+    arguments:
+      - name: database
+        title: Logical Database
+        description: "ShardingSphere logical database."
+        required: false
+      - name: operation_type
+        title: Operation Type
+        description: "create, alter, or drop."
+        required: false
+      - name: algorithm_type
+        title: Sharding Algorithm
+        description: "Optional default sharding algorithm type."
+        required: false
     meta:
       org.apache.shardingsphere/related-tools:
         - database_gateway_plan_sharding_default_strategy
@@ -377,7 +401,19 @@ prompts:
     description: "Guide the model to plan sharding key generator DistSQL."
     binding:
       templateResource: 
META-INF/shardingsphere-mcp/prompts/plan-sharding-key-generator.md
-    arguments: *commonPromptArguments
+    arguments:
+      - name: database
+        title: Logical Database
+        description: "ShardingSphere logical database."
+        required: false
+      - name: operation_type
+        title: Operation Type
+        description: "create, alter, or drop."
+        required: false
+      - name: key_generator_type
+        title: Key Generator Algorithm
+        description: "Optional key generator algorithm type."
+        required: false
     meta:
       org.apache.shardingsphere/related-tools:
         - database_gateway_plan_sharding_key_generator
@@ -394,7 +430,19 @@ prompts:
     description: "Guide the model to plan sharding key generate strategy 
DistSQL."
     binding:
       templateResource: 
META-INF/shardingsphere-mcp/prompts/plan-sharding-key-generate-strategy.md
-    arguments: *commonPromptArguments
+    arguments:
+      - name: database
+        title: Logical Database
+        description: "ShardingSphere logical database."
+        required: false
+      - name: operation_type
+        title: Operation Type
+        description: "create, alter, or drop."
+        required: false
+      - name: key_generator_type
+        title: Key Generator Algorithm
+        description: "Optional key generator algorithm type."
+        required: false
     meta:
       org.apache.shardingsphere/related-tools:
         - database_gateway_plan_sharding_key_generate_strategy
@@ -424,13 +472,23 @@ prompts:
         - "Ask when database, component type, or component name is unclear."
         - "Ask before applying generated component cleanup DistSQL that 
changes runtime state."
 completionTargets:
-  - referenceType: resource
-    reference: shardingsphere://features/sharding/algorithm-plugins
+  - referenceType: prompt
+    reference: plan_sharding_table_rule
     arguments:
       - algorithm_type
     maxValues: 50
-  - referenceType: resource
-    reference: 
shardingsphere://features/sharding/key-generate-algorithm-plugins
+  - referenceType: prompt
+    reference: plan_sharding_default_strategy
+    arguments:
+      - algorithm_type
+    maxValues: 50
+  - referenceType: prompt
+    reference: plan_sharding_key_generator
+    arguments:
+      - key_generator_type
+    maxValues: 50
+  - referenceType: prompt
+    reference: plan_sharding_key_generate_strategy
     arguments:
       - key_generator_type
     maxValues: 50
diff --git 
a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/descriptor/ShardingToolDescriptorValidatorTest.java
 
b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/descriptor/ShardingToolDescriptorValidatorTest.java
index adf3071d74b..41afa08f8c3 100644
--- 
a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/descriptor/ShardingToolDescriptorValidatorTest.java
+++ 
b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/descriptor/ShardingToolDescriptorValidatorTest.java
@@ -53,12 +53,18 @@ class ShardingToolDescriptorValidatorTest {
     
     @Test
     void assertExposeCompletionTargets() {
-        MCPCompletionTargetDescriptor algorithmCompletionTarget = 
findCompletionTarget("resource", 
ShardingFeatureDefinition.ALGORITHM_PLUGINS_RESOURCE_URI);
+        MCPCompletionTargetDescriptor algorithmCompletionTarget = 
findCompletionTarget("prompt", 
ShardingFeatureDefinition.PLAN_TABLE_RULE_PROMPT_NAME);
         assertThat(algorithmCompletionTarget.getArguments(), 
is(List.of("algorithm_type")));
         assertThat(algorithmCompletionTarget.getMaxValues(), is(50));
-        MCPCompletionTargetDescriptor keyGeneratorCompletionTarget = 
findCompletionTarget("resource", 
ShardingFeatureDefinition.KEY_GENERATE_ALGORITHM_PLUGINS_RESOURCE_URI);
+        MCPCompletionTargetDescriptor defaultStrategyCompletionTarget = 
findCompletionTarget("prompt", 
ShardingFeatureDefinition.PLAN_DEFAULT_STRATEGY_PROMPT_NAME);
+        assertThat(defaultStrategyCompletionTarget.getArguments(), 
is(List.of("algorithm_type")));
+        MCPCompletionTargetDescriptor keyGeneratorCompletionTarget = 
findCompletionTarget("prompt", 
ShardingFeatureDefinition.PLAN_KEY_GENERATOR_PROMPT_NAME);
         assertThat(keyGeneratorCompletionTarget.getArguments(), 
is(List.of("key_generator_type")));
         assertThat(keyGeneratorCompletionTarget.getMaxValues(), is(50));
+        MCPCompletionTargetDescriptor keyGenerateStrategyCompletionTarget = 
findCompletionTarget("prompt", 
ShardingFeatureDefinition.PLAN_KEY_GENERATE_STRATEGY_PROMPT_NAME);
+        assertThat(keyGenerateStrategyCompletionTarget.getArguments(), 
is(List.of("key_generator_type")));
+        assertFalse(hasCompletionTarget("resource", 
ShardingFeatureDefinition.ALGORITHM_PLUGINS_RESOURCE_URI));
+        assertFalse(hasCompletionTarget("resource", 
ShardingFeatureDefinition.KEY_GENERATE_ALGORITHM_PLUGINS_RESOURCE_URI));
     }
     
     @Test
@@ -112,4 +118,9 @@ class ShardingToolDescriptorValidatorTest {
         return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
                 .filter(each -> referenceType.equals(each.getReferenceType()) 
&& reference.equals(each.getReference())).findFirst().orElseThrow();
     }
+    
+    private boolean hasCompletionTarget(final String referenceType, final 
String reference) {
+        return 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors().stream()
+                .anyMatch(each -> 
referenceType.equals(each.getReferenceType()) && 
reference.equals(each.getReference()));
+    }
 }
diff --git 
a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionServiceTest.java
 
b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionServiceTest.java
index 920f5454fec..3aff51ce69b 100644
--- 
a/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionServiceTest.java
+++ 
b/mcp/features/sharding/src/test/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingInspectionServiceTest.java
@@ -17,12 +17,15 @@
 
 package org.apache.shardingsphere.mcp.feature.sharding.tool.service;
 
+import 
org.apache.shardingsphere.mcp.api.protocol.exception.MCPQueryFailedException;
 import 
org.apache.shardingsphere.mcp.support.database.spi.MCPFeatureQueryFacade;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
+import java.sql.SQLException;
+import java.sql.SQLSyntaxErrorException;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Stream;
@@ -30,6 +33,8 @@ import java.util.stream.Stream;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsString;
 import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
@@ -50,7 +55,25 @@ class ShardingInspectionServiceTest {
         MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
         when(queryFacade.queryWithAnyDatabase("SHOW SHARDING ALGORITHM 
PLUGINS")).thenReturn(List.of(Map.of("type", "INLINE")));
         List<Map<String, Object>> actual = new 
ShardingInspectionService().queryAlgorithmPlugins(queryFacade);
-        assertThat(actual.get(0).get("property_guidance").toString(), 
containsString("algorithm-expression"));
+        assertThat(actual.getFirst().get("property_guidance").toString(), 
containsString("algorithm-expression"));
+    }
+    
+    @Test
+    void assertQueryAlgorithmPluginsWithUnavailableDistSQL() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW SHARDING ALGORITHM 
PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("syntax error near 
'SHARDING ALGORITHM PLUGINS'", new SQLSyntaxErrorException("syntax error")));
+        List<Map<String, Object>> actual = new 
ShardingInspectionService().queryAlgorithmPlugins(queryFacade);
+        assertTrue(actual.stream().anyMatch(each -> 
"INLINE".equals(each.get("type"))));
+        assertTrue(actual.stream().anyMatch(each -> 
"INLINE".equals(each.get("type")) && 
String.valueOf(each.get("property_guidance")).contains("algorithm-expression")));
+    }
+    
+    @Test
+    void assertQueryAlgorithmPluginsPropagatesQueryFailure() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW SHARDING ALGORITHM 
PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("Connection refused.", 
new SQLException("Connection refused.")));
+        assertThrows(MCPQueryFailedException.class, () -> new 
ShardingInspectionService().queryAlgorithmPlugins(queryFacade));
     }
     
     @Test
@@ -58,7 +81,25 @@ class ShardingInspectionServiceTest {
         MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
         when(queryFacade.queryWithAnyDatabase("SHOW KEY GENERATE ALGORITHM 
PLUGINS")).thenReturn(List.of(Map.of("type", "UUID")));
         List<Map<String, Object>> actual = new 
ShardingInspectionService().queryKeyGenerateAlgorithmPlugins(queryFacade);
-        assertThat(actual.get(0).get("property_guidance").toString(), is("No 
required properties."));
+        assertThat(actual.getFirst().get("property_guidance").toString(), 
is("No required properties."));
+    }
+    
+    @Test
+    void assertQueryKeyGenerateAlgorithmPluginsWithUnavailableDistSQL() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW KEY GENERATE ALGORITHM 
PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("syntax error near 'KEY 
GENERATE ALGORITHM PLUGINS'", new SQLSyntaxErrorException("syntax error")));
+        List<Map<String, Object>> actual = new 
ShardingInspectionService().queryKeyGenerateAlgorithmPlugins(queryFacade);
+        assertTrue(actual.stream().anyMatch(each -> 
"SNOWFLAKE".equals(each.get("type"))));
+        assertTrue(actual.stream().anyMatch(each -> 
"SNOWFLAKE".equals(each.get("type")) && 
String.valueOf(each.get("property_guidance")).contains("worker-id")));
+    }
+    
+    @Test
+    void assertQueryKeyGenerateAlgorithmPluginsPropagatesQueryFailure() {
+        MCPFeatureQueryFacade queryFacade = mock(MCPFeatureQueryFacade.class);
+        when(queryFacade.queryWithAnyDatabase("SHOW KEY GENERATE ALGORITHM 
PLUGINS"))
+                .thenThrow(new MCPQueryFailedException("Connection refused.", 
new SQLException("Connection refused.")));
+        assertThrows(MCPQueryFailedException.class, () -> new 
ShardingInspectionService().queryKeyGenerateAlgorithmPlugins(queryFacade));
     }
     
     private static Stream<Arguments> assertDatabaseScopedQueryArguments() {
diff --git 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogValidator.java
 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogValidator.java
index 2c2e671423a..d61ca2bdb05 100644
--- 
a/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogValidator.java
+++ 
b/mcp/support/src/main/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogValidator.java
@@ -305,11 +305,12 @@ final class MCPDescriptorCatalogValidator {
         Map<String, Set<String>> promptArguments = 
prompts.stream().collect(Collectors.toMap(MCPPromptDescriptor::getName,
                 each -> 
each.getArguments().stream().map(MCPPromptArgumentDescriptor::getName).collect(Collectors.toSet())));
         Set<String> promptNames = promptArguments.keySet();
-        Set<String> resourceUris = 
resources.stream().map(MCPResourceDescriptor::getUriTemplate).collect(Collectors.toSet());
+        Map<String, MCPResourceDescriptor> resourceDescriptors = 
resources.stream().collect(Collectors.toMap(MCPResourceDescriptor::getUriTemplate,
 each -> each));
         Map<String, MCPCompletionTargetDescriptor> registered = new 
LinkedHashMap<>(descriptors.size(), 1F);
         for (MCPCompletionTargetDescriptor each : descriptors) {
-            validateCompletionReference(each, promptNames, resourceUris);
+            validateCompletionReference(each, promptNames, 
resourceDescriptors.keySet());
             validatePromptCompletionArguments(each, promptArguments);
+            validateResourceCompletionArguments(each, resourceDescriptors);
             ShardingSpherePreconditions.checkState(null == 
registered.putIfAbsent(each.getReferenceType() + ":" + each.getReference(), 
each),
                     () -> new IllegalStateException(String.format("Duplicate 
MCP completion target `%s:%s`.", each.getReferenceType(), 
each.getReference())));
         }
@@ -326,6 +327,20 @@ final class MCPDescriptorCatalogValidator {
         }
     }
     
+    private static void validateResourceCompletionArguments(final 
MCPCompletionTargetDescriptor descriptor, final Map<String, 
MCPResourceDescriptor> resources) {
+        if (!"resource".equals(descriptor.getReferenceType())) {
+            return;
+        }
+        MCPResourceDescriptor resource = 
resources.get(descriptor.getReference());
+        ShardingSpherePreconditions.checkState(resource.isTemplated(),
+                () -> new IllegalStateException(String.format("Completion 
target `resource:%s` must reference a resource template.", 
descriptor.getReference())));
+        Set<String> templateVariables = new HashSet<>(new 
MCPUriTemplate(resource.getUriTemplate()).getVariableNames());
+        for (String each : descriptor.getArguments()) {
+            
ShardingSpherePreconditions.checkState(templateVariables.contains(each), () -> 
new IllegalStateException(
+                    String.format("Completion target `resource:%s` argument 
`%s` is not a URI template variable.", descriptor.getReference(), each)));
+        }
+    }
+    
     private static void validateCompletionReference(final 
MCPCompletionTargetDescriptor descriptor, final Set<String> promptNames, final 
Set<String> resourceUris) {
         if ("prompt".equals(descriptor.getReferenceType())) {
             
ShardingSpherePreconditions.checkState(promptNames.contains(descriptor.getReference()),
diff --git 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogIndexTest.java
 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogIndexTest.java
index bb2e61845b4..f2025f71f9d 100644
--- 
a/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogIndexTest.java
+++ 
b/mcp/support/src/test/java/org/apache/shardingsphere/mcp/support/descriptor/MCPDescriptorCatalogIndexTest.java
@@ -101,6 +101,8 @@ class MCPDescriptorCatalogIndexTest {
     void assertGetCompletionTargetDescriptors() {
         Collection<MCPCompletionTargetDescriptor> actualDescriptors = 
MCPDescriptorCatalogIndex.getCompletionTargetDescriptors();
         assertTrue(actualDescriptors.stream().anyMatch(each -> 
"prompt".equals(each.getReferenceType()) && 
"inspect_metadata".equals(each.getReference())));
+        assertTrue(actualDescriptors.stream().filter(each -> 
"resource".equals(each.getReferenceType()))
+                .allMatch(each -> 
MCPDescriptorCatalogIndex.getRequiredResourceDescriptor(each.getReference()).isTemplated()));
     }
     
     @Test
diff --git 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
index 1c75fb92087..55ef7d8cadc 100644
--- 
a/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
+++ 
b/test/e2e/mcp/src/test/java/org/apache/shardingsphere/test/e2e/mcp/runtime/programmatic/HttpTransportCompletionE2ETest.java
@@ -81,14 +81,19 @@ class HttpTransportCompletionE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ET
         launchHttpTransport();
         HttpClient httpClient = HttpClient.newHttpClient();
         String sessionId = initializeSession(httpClient);
-        assertTrue(completeValues(httpClient, sessionId, 
createResourceReference("shardingsphere://features/readwrite-splitting/load-balance-algorithm-plugins"),
-                "load_balancer_type", "ROUND", 
Map.of()).contains("ROUND_ROBIN"));
-        assertTrue(completeValues(httpClient, sessionId, 
createResourceReference("shardingsphere://features/shadow/algorithm-plugins"),
-                "algorithm_type", "VALUE", Map.of()).contains("VALUE_MATCH"));
-        assertTrue(completeValues(httpClient, sessionId, 
createResourceReference("shardingsphere://features/sharding/algorithm-plugins"),
-                "algorithm_type", "INLINE", Map.of()).contains("INLINE"));
-        assertTrue(completeValues(httpClient, sessionId, 
createResourceReference("shardingsphere://features/sharding/key-generate-algorithm-plugins"),
-                "key_generator_type", "SNOW", Map.of()).contains("SNOWFLAKE"));
+        Map<String, Object> loadBalanceAlgorithmCompletion = 
complete(httpClient, sessionId, Map.of("type", "ref/prompt", "name", 
"plan_readwrite_splitting_rule"),
+                "load_balancer_type", "ROUND", Map.of());
+        List<String> loadBalanceAlgorithmValues = 
extractCompletionValues(loadBalanceAlgorithmCompletion);
+        assertTrue(loadBalanceAlgorithmValues.contains("ROUND_ROBIN"), 
loadBalanceAlgorithmCompletion::toString);
+        List<String> shadowAlgorithmValues = completeValues(httpClient, 
sessionId, Map.of("type", "ref/prompt", "name", "plan_shadow_rule"),
+                "algorithm_type", "VALUE", Map.of());
+        assertTrue(shadowAlgorithmValues.contains("VALUE_MATCH"), 
shadowAlgorithmValues::toString);
+        List<String> shardingAlgorithmValues = completeValues(httpClient, 
sessionId, Map.of("type", "ref/prompt", "name", "plan_sharding_table_rule"),
+                "algorithm_type", "INLINE", Map.of());
+        assertTrue(shardingAlgorithmValues.contains("INLINE"), 
shardingAlgorithmValues::toString);
+        List<String> keyGenerateAlgorithmValues = completeValues(httpClient, 
sessionId, Map.of("type", "ref/prompt", "name", "plan_sharding_key_generator"),
+                "key_generator_type", "SNOW", Map.of());
+        assertTrue(keyGenerateAlgorithmValues.contains("SNOWFLAKE"), 
keyGenerateAlgorithmValues::toString);
     }
     
     @Test
@@ -111,7 +116,11 @@ class HttpTransportCompletionE2ETest extends 
AbstractHttpProgrammaticRuntimeE2ET
     private List<String> completeValues(final HttpClient httpClient, final 
String sessionId, final Map<String, Object> reference,
                                         final String argumentName, final 
String argumentValue,
                                         final Map<String, String> 
contextArguments) throws IOException, InterruptedException {
-        Map<String, Object> completion = castToMap(complete(httpClient, 
sessionId, reference, argumentName, argumentValue, 
contextArguments).get("completion"));
+        return extractCompletionValues(complete(httpClient, sessionId, 
reference, argumentName, argumentValue, contextArguments));
+    }
+    
+    private List<String> extractCompletionValues(final Map<String, Object> 
result) {
+        Map<String, Object> completion = castToMap(result.get("completion"));
         return ((List<?>) 
completion.get("values")).stream().map(String::valueOf).toList();
     }
     
diff --git 
a/test/e2e/mcp/src/test/resources/baseline-contract/model-contract/capabilities.yaml
 
b/test/e2e/mcp/src/test/resources/baseline-contract/model-contract/capabilities.yaml
index d3fc6d24d88..4c865fa3313 100644
--- 
a/test/e2e/mcp/src/test/resources/baseline-contract/model-contract/capabilities.yaml
+++ 
b/test/e2e/mcp/src/test/resources/baseline-contract/model-contract/capabilities.yaml
@@ -171,9 +171,9 @@ common_flows:
   referenced_resources: ['shardingsphere://capabilities']
 protocolAvailability: {resources: true, resourceTemplates: true, tools: true, 
toolAnnotations: true,
   toolOutputSchemas: true, prompts: true, completions: true, 
resourceNavigation: true}
-fingerprints: {algorithm: sha256, descriptorCatalog: 
0b3cb84bfe1e23964958210cf6ce96c8b613202cd5f5611b7845bb968d558370,
-  promptSet: 41a84db849ce19f25f172068e5a176f74fc726429402b9d675d5197acc51d7e2, 
resourceNavigation: 
64bf1a1ca4856b55a21b09922aa8df6e7bb7f043faa38977680d1a1e3c060bae,
-  modelFacingSchemas: 
83b4b8d44382cbbfdee351e86dea044690caa90032832ce08bade4dff11777b9}
+fingerprints: {algorithm: sha256, descriptorCatalog: 
20e22dc1490af50d39f00aeb1d5fb35c298773096268b70adc898d7f31800d06,
+  promptSet: 63e5b9cb3fada77bc332fd0f958c390d66b538944bdc4ba75501cac5106cd3f3, 
resourceNavigation: 
64bf1a1ca4856b55a21b09922aa8df6e7bb7f043faa38977680d1a1e3c060bae,
+  modelFacingSchemas: 
424743fa39de1312cfc2c19748d2da2773638c31596b747334468b3f130b1067}
 resources:
 - uri: shardingsphere://capabilities
   name: server-capability-catalog
@@ -802,16 +802,19 @@ prompts:
   arguments:
   - {name: database, required: false}
   - {name: operation_type, required: false}
+  - {name: algorithm_type, required: false}
 - name: plan_sharding_key_generate_strategy
   title: Plan Sharding Key Generate Strategy
   arguments:
   - {name: database, required: false}
   - {name: operation_type, required: false}
+  - {name: key_generator_type, required: false}
 - name: plan_sharding_key_generator
   title: Plan Sharding Key Generator
   arguments:
   - {name: database, required: false}
   - {name: operation_type, required: false}
+  - {name: key_generator_type, required: false}
 - name: plan_sharding_rule_component_cleanup
   title: Plan Sharding Rule Component Cleanup
   arguments:
@@ -827,6 +830,7 @@ prompts:
   arguments:
   - {name: database, required: false}
   - {name: operation_type, required: false}
+  - {name: algorithm_type, required: false}
 - name: recover_workflow
   title: Recover Workflow
   arguments:
@@ -887,18 +891,38 @@ completionTargets:
   reference: plan_encrypt_rule
   arguments: [algorithm_type, assisted_query_algorithm_type, 
like_query_algorithm_type]
   maxValues: 50
-- referenceType: resource
-  reference: shardingsphere://features/encrypt/algorithms
-  arguments: [algorithm_type, assisted_query_algorithm_type, 
like_query_algorithm_type]
-  maxValues: 50
 - referenceType: prompt
   reference: plan_mask_rule
   arguments: [algorithm_type]
   maxValues: 50
-- referenceType: resource
-  reference: shardingsphere://features/mask/algorithms
+- referenceType: prompt
+  reference: plan_readwrite_splitting_rule
+  arguments: [load_balancer_type]
+  maxValues: 50
+- referenceType: prompt
+  reference: plan_shadow_rule
+  arguments: [algorithm_type]
+  maxValues: 50
+- referenceType: prompt
+  reference: plan_default_shadow_algorithm
+  arguments: [algorithm_type]
+  maxValues: 50
+- referenceType: prompt
+  reference: plan_sharding_table_rule
   arguments: [algorithm_type]
   maxValues: 50
+- referenceType: prompt
+  reference: plan_sharding_default_strategy
+  arguments: [algorithm_type]
+  maxValues: 50
+- referenceType: prompt
+  reference: plan_sharding_key_generator
+  arguments: [key_generator_type]
+  maxValues: 50
+- referenceType: prompt
+  reference: plan_sharding_key_generate_strategy
+  arguments: [key_generator_type]
+  maxValues: 50
 - referenceType: prompt
   reference: inspect_metadata
   arguments: [database, schema]

Reply via email to