diff --git a/superset/mcp_service/chart/tool/get_chart_type_schema.py b/superset/mcp_service/chart/tool/get_chart_type_schema.py index dc21f3c6203..896d54d3099 100644 --- a/superset/mcp_service/chart/tool/get_chart_type_schema.py +++ b/superset/mcp_service/chart/tool/get_chart_type_schema.py @@ -126,14 +126,27 @@ def _get_chart_type_schema_impl( """Pure logic for chart type schema lookup — no auth, no decorators.""" adapter = _CHART_TYPE_ADAPTERS.get(chart_type) if adapter is None: + # Return a structured error matching ChartGenerationError's shape so + # MCP clients consuming the response see a populated error_type, + # message, details, and suggestions rather than a bare dict. + valid_types_str = ", ".join(VALID_CHART_TYPES) return { - "error": f"Unknown chart_type: {chart_type!r}", + "error": { + "error_type": "invalid_chart_type", + "message": f"Unknown chart_type: {chart_type!r}", + "details": ( + f"Chart type {chart_type!r} is not supported. " + f"Must be one of: {valid_types_str}." + ), + "suggestions": [ + f"Use one of: {valid_types_str}", + "Check spelling and ensure lowercase", + "Call this tool again with a valid chart_type to see " + "its schema and examples", + ], + "error_code": "INVALID_CHART_TYPE", + }, "valid_chart_types": VALID_CHART_TYPES, - "hint": ( - "Use one of the valid chart_type values listed above. " - "Call this tool again with a valid chart_type to see " - "its schema and examples." - ), } schema = adapter.json_schema() diff --git a/tests/unit_tests/mcp_service/chart/tool/test_get_chart_type_schema.py b/tests/unit_tests/mcp_service/chart/tool/test_get_chart_type_schema.py index f7f2d166a5a..1da1b587b01 100644 --- a/tests/unit_tests/mcp_service/chart/tool/test_get_chart_type_schema.py +++ b/tests/unit_tests/mcp_service/chart/tool/test_get_chart_type_schema.py @@ -70,6 +70,24 @@ class TestGetChartTypeSchema: assert "valid_chart_types" in result assert result["valid_chart_types"] == VALID_CHART_TYPES + def test_invalid_chart_type_returns_structured_error(self) -> None: + """Invalid chart_type must return a populated, structured error body. + + Without this guarantee, MCP clients see an empty/unstructured payload + and cannot self-correct (Eval 26 Test 26.5). + """ + result = _call_schema("nonexistent") + err = result["error"] + assert isinstance(err, dict) + assert err["error_type"] == "invalid_chart_type" + assert err["error_code"] == "INVALID_CHART_TYPE" + assert "nonexistent" in err["message"] + assert err["details"] + assert err["suggestions"] + # Suggestions must name at least one valid chart type so callers know + # what to try next. + assert any(vt in " ".join(err["suggestions"]) for vt in VALID_CHART_TYPES) + def test_examples_match_chart_type(self) -> None: result = _call_schema("pie") for example in result["examples"]: