Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion superset/mcp_service/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def get_default_instructions(
- duplicate_dashboard: Duplicate an existing dashboard, optionally deep-copying its charts (requires write access)
- add_chart_to_existing_dashboard: Add a chart to an existing dashboard (requires write access)
- manage_native_filters: Add, update, remove, or reorder native filters on a dashboard (requires write access; supports filter_select and filter_time)
- remove_chart_from_dashboard: Remove a chart from an existing dashboard (requires write access)

Annotation Layers:
- list_annotation_layers: List annotation layers with advanced filters (1-based pagination)
Expand Down Expand Up @@ -428,7 +429,8 @@ def get_default_instructions(
charts, or dashboards). SQL execution is a separate permission — see execute_sql below.
- Write tools (generate_chart, generate_dashboard, update_chart, duplicate_dashboard,
create_dataset, create_virtual_dataset, save_sql_query, add_chart_to_existing_dashboard,
manage_native_filters, update_chart_preview) require write
manage_native_filters, remove_chart_from_dashboard,
update_chart_preview) require write
permissions. These tools are only listed for users who have the necessary access.
If a write tool does not appear in the tool list, the current user lacks write access.
- execute_sql requires SQL Lab access (execute_sql_query permission), which is separate
Expand Down Expand Up @@ -700,6 +702,7 @@ def create_mcp_app(
get_dashboard_layout,
list_dashboards,
manage_native_filters,
remove_chart_from_dashboard,
update_dashboard,
)
from superset.mcp_service.database.tool import ( # noqa: F401, E402
Expand Down
52 changes: 52 additions & 0 deletions superset/mcp_service/dashboard/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,58 @@ def sanitize_error_for_llm_context(cls, value: str | None) -> str | None:
return sanitize_for_llm_context(value, field_path=("error",))


class RemoveChartFromDashboardRequest(BaseModel):
"""Request schema for removing a chart from an existing dashboard."""

dashboard_id: int = Field(
..., description="ID of the dashboard to remove the chart from"
)
chart_id: int = Field(
..., description="ID of the chart to remove from the dashboard"
)


class RemoveChartFromDashboardResponse(BaseModel):
"""Response schema for removing a chart from a dashboard."""

dashboard: DashboardInfo | None = Field(
None, description="The updated dashboard info, if successful"
)
dashboard_url: str | None = Field(
None, description="URL to view the updated dashboard"
)
removed_layout_keys: list[str] = Field(
default_factory=list,
description=(
"Layout component IDs that were removed from position_json "
"(the CHART components plus any ROW/COLUMN containers that "
"became empty as a result)."
),
)
error: str | None = Field(None, description="Error message, if operation failed")
permission_denied: bool = Field(
default=False,
description=(
"True when the operation failed because the current user does not "
"have edit rights on the target dashboard. When True, inform the "
"user — do NOT attempt a workaround without confirming first."
),
)

@field_validator("error")
@classmethod
def sanitize_error_for_llm_context(cls, value: str | None) -> str | None:
"""Wrap error text before it is exposed to LLM context.

The error may echo dashboard-controlled text (e.g. the dashboard
title), which must be wrapped so the LLM treats it as data, not
instructions.
"""
if value is None:
return value
return sanitize_for_llm_context(value, field_path=("error",))


class GenerateDashboardRequest(BaseModel):
"""Request schema for generating a dashboard."""

Expand Down
2 changes: 2 additions & 0 deletions superset/mcp_service/dashboard/tool/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from .get_dashboard_layout import get_dashboard_layout
from .list_dashboards import list_dashboards
from .manage_native_filters import manage_native_filters
from .remove_chart_from_dashboard import remove_chart_from_dashboard
from .update_dashboard import update_dashboard

__all__ = [
Expand All @@ -32,5 +33,6 @@
"duplicate_dashboard",
"add_chart_to_existing_dashboard",
"manage_native_filters",
"remove_chart_from_dashboard",
"update_dashboard",
]
Loading
Loading