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 7c34e857164 Simplify MCP validation and verify runtime limits (#39299)
7c34e857164 is described below
commit 7c34e8571640da5c1a6098733e6f780c03ba35b0
Author: Liang Zhang <[email protected]>
AuthorDate: Sat Aug 1 11:49:11 2026 +0800
Simplify MCP validation and verify runtime limits (#39299)
* Fix Oracle pre-12.2 column case sensitivity
Use Oracle's default case-sensitive behavior for character columns
when COLLATION metadata is unavailable before version 12.2.
Reuse the Oracle data type classification for non-character columns
and preserve the existing 12.2+ collation handling.
* Fix Oracle pre-12.2 column case sensitivity
Use Oracle's default case-sensitive behavior for character columns
when COLLATION metadata is unavailable before version 12.2.
Reuse the Oracle data type classification for non-character columns
and preserve the existing 12.2+ collation handling.
* Simplify MCP validation and verify runtime limits
Simplify create and drop workflow state checks by comparing the
expected and actual rule state directly.
Verify that SQL execution tool descriptors remain aligned with MCP
runtime row and timeout limits.
* Simplify MCP validation and verify runtime limits
Simplify create and drop workflow state checks by comparing the
expected and actual rule state directly.
Verify that SQL execution tool descriptors remain aligned with MCP
runtime row and timeout limits.
---
.github/workflows/e2e-mcp.yml | 2 ++
.../core/tool/handler/ToolDefinitionRegistryTest.java | 15 +++++++++++++++
.../tool/service/BroadcastWorkflowValidationService.java | 3 ++-
.../ReadwriteSplittingRuleWorkflowValidationService.java | 11 ++++++-----
.../tool/service/ShardingWorkflowValidationService.java | 16 ++++++++++------
5 files changed, 35 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/e2e-mcp.yml b/.github/workflows/e2e-mcp.yml
index 1f727ad1736..e587e63192d 100644
--- a/.github/workflows/e2e-mcp.yml
+++ b/.github/workflows/e2e-mcp.yml
@@ -311,6 +311,8 @@ jobs:
restore-maven-repository: 'false'
docker-image-archives: mcp-llm-runtime-image.tar
- name: Run MCP LLM E2E
+ env:
+ TESTCONTAINERS_RYUK_DISABLED: 'true'
run: ./mvnw -pl test/e2e/mcp test -Pe2e.mcp.llm -DskipITs
-Dspotless.skip=true -Dtest='${{ matrix.test }}' -Dmcp.llm.artifact-root="${{
github.workspace }}/test/e2e/mcp/target/llm-e2e" -Dmcp.llm.run-id=gha-${{
github.run_id }}-${{ github.run_attempt }}-${{ matrix.id }} -B -ntp
- name: Upload MCP LLM E2E Artifacts
if: always()
diff --git
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/ToolDefinitionRegistryTest.java
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/ToolDefinitionRegistryTest.java
index 4526ba00b2b..6df3f9e4ff8 100644
---
a/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/ToolDefinitionRegistryTest.java
+++
b/mcp/core/src/test/java/org/apache/shardingsphere/mcp/core/tool/handler/ToolDefinitionRegistryTest.java
@@ -35,6 +35,7 @@ import
org.apache.shardingsphere.mcp.core.protocol.exception.MCPToolArgumentCont
import
org.apache.shardingsphere.mcp.core.protocol.exception.UnsupportedToolException;
import org.apache.shardingsphere.mcp.core.resource.ResourceTestDataFactory;
import
org.apache.shardingsphere.mcp.core.resource.ResourceTestDataFactory.RequestContextFixture;
+import
org.apache.shardingsphere.mcp.support.security.MCPRuntimeProtectionPolicy;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.internal.configuration.plugins.Plugins;
@@ -81,6 +82,20 @@ class ToolDefinitionRegistryTest {
assertField(actual.get(5), "approved_steps", "array", List.of(),
false);
}
+ @Test
+ void assertGetSupportedToolDescriptorsWithRuntimeProtectionLimits() {
+ List<MCPToolDescriptor> descriptors =
ToolDefinitionRegistry.getSupportedToolDescriptors();
+ for (String each : List.of("database_gateway_execute_query",
"database_gateway_execute_explain_query", "database_gateway_execute_update")) {
+ MCPToolDescriptor descriptor = descriptors.stream().filter(tool ->
each.equals(tool.getName())).findFirst().orElseThrow();
+ Map<?, ?> actualMaxRows = findField(descriptor, "max_rows");
+ assertThat(actualMaxRows.get("default"),
is(MCPRuntimeProtectionPolicy.DEFAULT_MAX_ROWS));
+ assertThat(actualMaxRows.get("maximum"),
is(MCPRuntimeProtectionPolicy.MAX_ROWS_LIMIT));
+ Map<?, ?> actualTimeout = findField(descriptor, "timeout_ms");
+ assertThat(actualTimeout.get("default"),
is(MCPRuntimeProtectionPolicy.DEFAULT_TIMEOUT_MILLISECONDS));
+ assertThat(actualTimeout.get("maximum"),
is(MCPRuntimeProtectionPolicy.MAX_TIMEOUT_MILLISECONDS));
+ }
+ }
+
@Test
void assertGetToolDefinition() {
assertThat(ToolDefinitionRegistry.getToolDefinition("database_gateway_search_metadata").getDescriptor().getName(),
is("database_gateway_search_metadata"));
diff --git
a/mcp/features/broadcast/src/main/java/org/apache/shardingsphere/mcp/feature/broadcast/tool/service/BroadcastWorkflowValidationService.java
b/mcp/features/broadcast/src/main/java/org/apache/shardingsphere/mcp/feature/broadcast/tool/service/BroadcastWorkflowValidationService.java
index 14fc41c2309..ccee76bb073 100644
---
a/mcp/features/broadcast/src/main/java/org/apache/shardingsphere/mcp/feature/broadcast/tool/service/BroadcastWorkflowValidationService.java
+++
b/mcp/features/broadcast/src/main/java/org/apache/shardingsphere/mcp/feature/broadcast/tool/service/BroadcastWorkflowValidationService.java
@@ -75,10 +75,11 @@ public final class BroadcastWorkflowValidationService
implements MCPWorkflowRunt
final ValidationReport
validationReport, final MCPFeatureQueryFacade queryFacade) {
BroadcastWorkflowRequest request = (BroadcastWorkflowRequest)
snapshot.getRequest();
boolean dropWorkflow = WorkflowLifecycleUtils.isDropWorkflow(snapshot);
+ boolean expectedRuleExists = !dropWorkflow;
for (String each : request.getTargetTables()) {
boolean ruleExists = broadcastRules.stream().anyMatch(rule ->
queryFacade.isSameIdentifier(
request.getDatabase(), IdentifierScope.TABLE, each,
WorkflowRuleValueUtils.getRuleValue(rule, "broadcast_table")));
- if (dropWorkflow && ruleExists || !dropWorkflow && !ruleExists) {
+ if (expectedRuleExists != ruleExists) {
addRuleMismatch(validationReport, dropWorkflow, each);
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
broadcastRules, "Broadcast rule state does not match the planned DistSQL
artifact.");
}
diff --git
a/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingRuleWorkflowValidationService.java
b/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingRuleWorkflowValidationService.java
index 9b6f329392f..daafcaa809e 100644
---
a/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingRuleWorkflowValidationService.java
+++
b/mcp/features/readwrite-splitting/src/main/java/org/apache/shardingsphere/mcp/feature/readwritesplitting/tool/service/ReadwriteSplittingRuleWorkflowValidationService.java
@@ -81,10 +81,9 @@ public final class
ReadwriteSplittingRuleWorkflowValidationService implements MC
}
private void addRuleDistSQLIssues(final List<Map<String, Object>> issues,
final WorkflowContextSnapshot snapshot, final String sql, final String
displaySql) {
- if (!isReadwriteSplittingRuleDistSQL(sql) || !(snapshot.getRequest()
instanceof ReadwriteSplittingRuleWorkflowRequest)) {
+ if (!isReadwriteSplittingRuleDistSQL(sql) || !(snapshot.getRequest()
instanceof final ReadwriteSplittingRuleWorkflowRequest request)) {
return;
}
- ReadwriteSplittingRuleWorkflowRequest request =
(ReadwriteSplittingRuleWorkflowRequest) snapshot.getRequest();
addLoadBalancerIssue(issues, request, displaySql);
addWeightIssues(issues, request, displaySql);
}
@@ -142,11 +141,13 @@ public final class
ReadwriteSplittingRuleWorkflowValidationService implements MC
final ValidationReport
validationReport, final MCPFeatureQueryFacade queryFacade) {
ReadwriteSplittingRuleWorkflowRequest request =
(ReadwriteSplittingRuleWorkflowRequest) snapshot.getRequest();
boolean ruleExists = containsRule(rules, queryFacade,
request.getDatabase(), request.getRuleName());
- if (WorkflowLifecycleUtils.isDropWorkflow(snapshot) && ruleExists ||
!WorkflowLifecycleUtils.isDropWorkflow(snapshot) && !ruleExists) {
- addRuleMismatch(validationReport, request.getRuleName(),
WorkflowLifecycleUtils.isDropWorkflow(snapshot));
+ boolean dropWorkflow = WorkflowLifecycleUtils.isDropWorkflow(snapshot);
+ boolean expectedRuleExists = !dropWorkflow;
+ if (expectedRuleExists != ruleExists) {
+ addRuleMismatch(validationReport, request.getRuleName(),
dropWorkflow);
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
rules, "Readwrite-splitting rule state does not match the planned DistSQL
artifact.");
}
- if (!WorkflowLifecycleUtils.isDropWorkflow(snapshot) &&
!matchesRuleShape(rules, queryFacade, request)) {
+ if (!dropWorkflow && !matchesRuleShape(rules, queryFacade, request)) {
addRuleShapeMismatch(validationReport, request.getRuleName());
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
rules, "Readwrite-splitting rule fields do not match the planned DistSQL
artifact.");
}
diff --git
a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowValidationService.java
b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowValidationService.java
index 5b68ec393d2..1b5d3786dc9 100644
---
a/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowValidationService.java
+++
b/mcp/features/sharding/src/main/java/org/apache/shardingsphere/mcp/feature/sharding/tool/service/ShardingWorkflowValidationService.java
@@ -110,12 +110,14 @@ public final class ShardingWorkflowValidationService
implements MCPWorkflowRunti
private ValidationSection validateNamedState(final WorkflowContextSnapshot
snapshot, final ValidationReport validationReport,
final List<Map<String,
Object>> rows, final MCPFeatureQueryFacade queryFacade, final String
databaseName,
final String fieldName, final
String expected, final boolean shapeMatches) {
- boolean exists = containsNamedRow(rows, queryFacade, databaseName,
fieldName, expected);
- if (WorkflowLifecycleUtils.isDropWorkflow(snapshot) && exists ||
!WorkflowLifecycleUtils.isDropWorkflow(snapshot) && !exists) {
+ boolean ruleExists = containsNamedRow(rows, queryFacade, databaseName,
fieldName, expected);
+ boolean dropWorkflow = WorkflowLifecycleUtils.isDropWorkflow(snapshot);
+ boolean expectedRuleExists = !dropWorkflow;
+ if (expectedRuleExists != ruleExists) {
addMismatch(validationReport, fieldName, expected);
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
rows, "Sharding rule state does not match the planned DistSQL artifact.");
}
- if (!WorkflowLifecycleUtils.isDropWorkflow(snapshot) && !shapeMatches)
{
+ if (!dropWorkflow && !shapeMatches) {
addMismatch(validationReport, fieldName, expected);
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
rows, "Sharding rule fields do not match the planned DistSQL artifact.");
}
@@ -216,13 +218,15 @@ public final class ShardingWorkflowValidationService
implements MCPWorkflowRunti
private ValidationSection validateDefaultStrategy(final
WorkflowContextSnapshot snapshot, final ValidationReport validationReport,
final List<Map<String,
Object>> rows, final MCPFeatureQueryFacade queryFacade, final
ShardingWorkflowRequest request) {
- boolean exists = rows.stream().anyMatch(each ->
queryFacade.isSameIdentifier(request.getDatabase(), IdentifierScope.TABLE,
request.getDefaultStrategyType(),
+ boolean strategyExists = rows.stream().anyMatch(each ->
queryFacade.isSameIdentifier(request.getDatabase(), IdentifierScope.TABLE,
request.getDefaultStrategyType(),
WorkflowRuleValueUtils.getRuleValue(each, "name")) &&
!WorkflowRuleValueUtils.getRuleValue(each, "type").isEmpty());
- if (WorkflowLifecycleUtils.isDropWorkflow(snapshot) && exists ||
!WorkflowLifecycleUtils.isDropWorkflow(snapshot) && !exists) {
+ boolean dropWorkflow = WorkflowLifecycleUtils.isDropWorkflow(snapshot);
+ boolean expectedStrategyExists = !dropWorkflow;
+ if (expectedStrategyExists != strategyExists) {
addMismatch(validationReport, "name",
request.getDefaultStrategyType());
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
rows, "Default sharding strategy state does not match the planned DistSQL
artifact.");
}
- if (!WorkflowLifecycleUtils.isDropWorkflow(snapshot) &&
!matchesDefaultStrategy(rows, queryFacade, request)) {
+ if (!dropWorkflow && !matchesDefaultStrategy(rows, queryFacade,
request)) {
addMismatch(validationReport, "name",
request.getDefaultStrategyType());
return new ValidationSection(WorkflowLifecycle.STATUS_FAILED,
rows, "Default sharding strategy fields do not match the planned DistSQL
artifact.");
}