{"record":{"id":"2b810f5ed55c7c34","repo":"apache/shardingsphere","slug":"statement-is-not-supported-by-the-mcp-contract-2b810f","errorCode":null,"errorMessage":"Statement is not supported by the MCP contract.","messagePattern":"Statement is not supported by the MCP contract\\.","errorType":"exception","errorClass":"MCPUnsupportedSQLStatementException","httpStatus":null,"severity":"error","filePath":"mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectExtractor.java","lineNumber":194,"sourceCode":"            for (IdentifierValue each : ((DropSchemaStatement) sqlStatement).getSchemaNames()) {\n                addNamespaceIdentifier(each, result);\n            }\n        }\n    }\n    \n    private void extractSequenceTargets(final SQLStatement sqlStatement, final Collection<SQLStatementObjectName> result) {\n        if (sqlStatement instanceof CreateSequenceStatement) {\n            addName(((CreateSequenceStatement) sqlStatement).getSequenceName(), result);\n        } else if (sqlStatement instanceof AlterSequenceStatement) {\n            addName(((AlterSequenceStatement) sqlStatement).getSequenceName(), result);\n        } else if (sqlStatement instanceof DropSequenceStatement) {\n            for (Object each : ((DropSequenceStatement) sqlStatement).getSequenceNames()) {\n                if (each instanceof String) {\n                    addName((String) each, result);\n                } else if (each instanceof SimpleTableSegment) {\n                    addTable((SimpleTableSegment) each, result);\n                } else {\n                    throw new MCPUnsupportedSQLStatementException();\n                }\n            }\n        }\n    }\n    \n    private void extractMergeTables(final SQLStatement sqlStatement, final Collection<SQLStatementObjectName> result) {\n        if (sqlStatement instanceof MergeStatement) {\n            addTableSegment(((MergeStatement) sqlStatement).getSource(), result);\n        }\n    }\n    \n    private void extractCommonTableExpressionTables(final SQLStatement sqlStatement, final Collection<SQLStatementObjectName> result) {\n        findWithSegment(sqlStatement).ifPresent(with -> {\n            for (CommonTableExpressionSegment each : with.getCommonTableExpressions()) {\n                TableExtractor extractor = new TableExtractor();\n                extractor.extractTablesFromSelect(each.getSubquery().getSelect());\n                addTableSegments(extractor.getTableContext(), result);\n            }","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/SQLStatementObjectExtractor.java#L176-L212","documentation":"SQLStatementObjectExtractor walks parsed statements to collect referenced object names; in extractSequenceTargets for DROP SEQUENCE, each dropped name may be a String or a SimpleTableSegment, but any other AST node type triggers MCPUnsupportedSQLStatementException. It is a defensive guard ensuring every object reference in an accepted statement can be extracted for cross-schema checking — an unextractable DROP SEQUENCE form is treated as unsupported rather than silently skipping schema validation.","triggerScenarios":"A DROP SEQUENCE statement whose parsed sequence-name AST contains a node type other than String or SimpleTableSegment for the target dialect — unusual qualified names or dialect-specific name forms in DROP SEQUENCE lists.","commonSituations":"Multi-name DROP SEQUENCE ... a, b, c statements; dialect-specific quoted/qualified sequence identifiers; grammar/parser versions that produce a different name segment type than the extractor expects.","solutions":["Split multi-name DROP SEQUENCE statements into one sequence per statement.","Use plain unqualified sequence names and select the schema via the tool's schema argument.","If a single simple DROP SEQUENCE fails, capture the dialect and statement and report it as an extractor gap."],"exampleFix":"// before\nawait tools.call('database_gateway_execute_update', { sql: 'DROP SEQUENCE seq_a, seq_b', execution_mode: 'execute' }); // unextractable form -> unsupported\n\n// after\nawait tools.call('database_gateway_execute_update', { sql: 'DROP SEQUENCE seq_a', execution_mode: 'execute' });\nawait tools.call('database_gateway_execute_update', { sql: 'DROP SEQUENCE seq_b', execution_mode: 'execute' });","handlingStrategy":"validation","validationCode":"// One sequence per DROP statement\nfunction splitDropSequence(sql) {\n  const m = sql.match(/^\\s*DROP\\s+SEQUENCE\\s+(.+?)\\s*;?\\s*$/i);\n  if (!m) return [sql];\n  return m[1].split(',').map(name => `DROP SEQUENCE ${name.trim()}`);\n}\nfor (const stmt of splitDropSequence(sql)) {\n  await tools.call('database_gateway_execute_update', { sql: stmt, execution_mode });\n}","typeGuard":"function isSimpleDropSequence(sql) {\n  return /^\\s*DROP\\s+SEQUENCE\\s+[A-Za-z_][\\w$]*\\s*;?\\s*$/i.test(sql);\n}","tryCatchPattern":"try {\n  return await tools.call('database_gateway_execute_update', { sql, execution_mode });\n} catch (e) {\n  if (/not supported by the MCP contract/.test(e.message) && /^\\s*DROP\\s+SEQUENCE\\b/i.test(sql) && sql.includes(',')) {\n    for (const one of sql.split(/,(?![^()]*\\))/)) await tools.call('database_gateway_execute_update', { sql: one.trim(), execution_mode });\n    return;\n  }\n  throw e;\n}","preventionTips":["Issue one DROP SEQUENCE per statement instead of comma lists.","Prefer unqualified sequence names with the schema selected via arguments.","Report extractor gaps with dialect and failing statement shape."],"tags":["mcp","sql","sequences","ddl","ast","unsupported"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}