apache/shardingsphere · error · MCPMultipleSQLStatementsException
Only one SQL statement is allowed.
Error message
Only one SQL statement is allowed.
What it means
Thrown by SQLStatementScanner.findStatementEndIndex as MCPMultipleSQLStatementsException when a `;` token is followed by any further token. The MCP execute tool intentionally accepts exactly one statement per call; a trailing semicolon is fine only if nothing (except lexer noise already filtered) comes after it.
Source
Thrown at mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementScanner.java:239
continue;
}
if (startsWithExecutableCommentMarker(text.substring(currentIndex))) {
return true;
}
int commentEndIndex = text.indexOf("*/", currentIndex + 2);
currentIndex = -1 == commentEndIndex ? text.length() : commentEndIndex + 2;
}
return false;
}
private int findStatementEndIndex(final List<Token> tokens, final int sqlLength) {
for (int index = 0; index < tokens.size(); index++) {
Token each = tokens.get(index);
if (!";".equals(each.getText())) {
continue;
}
if (index + 1 < tokens.size()) {
throw new MCPMultipleSQLStatementsException();
}
return each.getStartIndex();
}
return sqlLength;
}
private List<Token> getTokensBefore(final List<Token> tokens, final int stopIndex) {
List<Token> result = new ArrayList<>();
for (Token each : tokens) {
if (each.getStartIndex() < stopIndex) {
result.add(each);
}
}
return result;
}
private List<Token> getVisibleTokens(final String sql, final List<Token> tokens, final boolean lineCommentsHandledByLexer) {
List<Token> result = new ArrayList<>();View on GitHub (pinned to e952770a21)
Solutions
- Split the batch on statement boundaries and submit each statement as its own execute_sql call
- Strip trailing semicolons and anything after them (including trailing comments) before submission
- Use a purpose-built batch/import path if you truly need multi-statement execution
Example fix
// before
execute_sql("UPDATE t SET a=1; UPDATE t SET b=2;")
// after
execute_sql("UPDATE t SET a=1")
execute_sql("UPDATE t SET b=2") Defensive patterns
Strategy: validation
Validate before calling
// Exactly one statement: only one ';', and it must be last
String trimmed = sql.strip();
long semicolons = trimmed.chars().filter(c -> c == ';').count();
boolean trailingOnly = trimmed.endsWith(";") && trimmed.indexOf(';') == trimmed.length() - 1;
if (semicolons > 1 || (semicolons == 1 && !trailingOnly)) throw new IllegalArgumentException("Split into single statements");
if (trailingOnly) sql = trimmed.substring(0, trimmed.length() - 1); Try / catch
try {
executeSql(sql);
} catch (MCPMultipleSQLStatementsException e) {
for (String each : splitStatements(sql)) executeSql(each);
} Prevention
- Always split batches client-side; the tool accepts exactly one statement
- Strip trailing semicolons and trailing comments
When it happens
Trigger: Any submitted SQL containing a `;` with subsequent tokens — e.g. `SELECT 1; SELECT 2`, `INSERT ...; COMMIT;`, or `SELECT 1; ` followed by a comment token that was not filtered. The loop throws at the first `;` that is not the last visible token.
Common situations: Batch scripts and migration files replayed whole into execute_sql; agents concatenating tool outputs with semicolons; clients that always append `;` plus a trailing comment.
Related errors
- Statement is not supported by the MCP contract.
- Metadata introspection SQL should use MCP metadata resources
- Statement is not a transaction command.
- Locking read statements such as SELECT ... FOR UPDATE are no
- %s execution_mode is required.
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/368c7f27b33734c4.
Report an issue: GitHub.