Skip to content

feat(mcp): add remove_chart_from_dashboard tool#40958

Merged
aminghadersohi merged 9 commits into
apache:masterfrom
aminghadersohi:mcp-remove-chart-from-dashboard
Jun 30, 2026
Merged

feat(mcp): add remove_chart_from_dashboard tool#40958
aminghadersohi merged 9 commits into
apache:masterfrom
aminghadersohi:mcp-remove-chart-from-dashboard

Conversation

@aminghadersohi

Copy link
Copy Markdown
Contributor

SUMMARY

Adds a new MCP tool, remove_chart_from_dashboard, the missing inverse of add_chart_to_existing_dashboard. Without it, agents that add a wrong chart to a dashboard have no recovery path.

The tool:

  • Removes all CHART layout components referencing the chart from position_json (a chart can appear under multiple tabs), and prunes ROW/COLUMN containers left empty by the removal so no orphaned wrapper nodes remain. TAB/TABS/GRID/ROOT containers are intentionally never pruned.
  • Explicitly passes the updated slices relationship (ORM objects with the removed chart excluded) to UpdateDashboardCommand, since updating position_json alone does not sync dashboard.slices.
  • Cleans stale chart references from json_metadata: expanded_slices, timed_refresh_immune_slices, and filter_scopes (both filter-chart keys and per-column immune lists). When metadata changed, the new layout is included under "positions" so DashboardDAO.set_dash_metadata takes its legacy branch that preserves and re-scopes filter_scopes instead of dropping them.
  • Error cases: dashboard not found, no edit permission (permission_denied=True so the LLM informs the user instead of attempting a workaround), and chart not present in the dashboard.
  • Annotated with ToolAnnotations(readOnlyHint=False, destructiveHint=True) and tags=["mutate"] / Dashboard-write RBAC, mirroring add_chart_to_existing_dashboard (same authorization, command write, and post-write eager re-fetch patterns).

The chart itself is not deleted — it remains available to other dashboards.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

N/A (MCP service tool, no UI changes)

TESTING INSTRUCTIONS

  1. Run the unit tests: pytest tests/unit_tests/mcp_service/dashboard/tool/test_remove_chart_from_dashboard.py
  2. Or manually via an MCP client connected to the MCP service:
    • Call add_chart_to_existing_dashboard with a dashboard_id/chart_id, then remove_chart_from_dashboard with the same arguments.
    • Verify the chart disappears from the dashboard, the layout has no empty leftover rows/columns, and json_metadata no longer references the chart.

Tests cover: dashboard not found, permission denied, chart not in dashboard, simple grid removal with empty-row pruning, chart inside a COLUMN (sibling kept; lone chart prunes COLUMN+ROW), chart under multiple tabs (all occurrences removed, tabs kept), json_metadata cleanup, chart attached to slices but absent from layout, and malformed-metadata robustness.

ADDITIONAL INFORMATION

  • Has associated issue:
  • Required feature flags:
  • Changes UI
  • Includes DB Migration (follow approval process in SIP-59)
    • Migration is atomic, supports rollback & is backwards-compatible
    • Confirm DB migration upgrade and downgrade tested
    • Runtime estimates and downtime expectations provided
  • Introduces new feature or API
  • Removes existing feature or API

@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 17.70335% with 172 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.43%. Comparing base (bf88c62) to head (451eaab).

Files with missing lines Patch % Lines
...vice/dashboard/tool/remove_chart_from_dashboard.py 12.43% 169 Missing ⚠️
superset/mcp_service/dashboard/schemas.py 80.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #40958      +/-   ##
==========================================
- Coverage   64.50%   64.43%   -0.07%     
==========================================
  Files        2666     2667       +1     
  Lines      146864   147073     +209     
  Branches    33910    33939      +29     
==========================================
+ Hits        94728    94760      +32     
- Misses      50421    50596     +175     
- Partials     1715     1717       +2     
Flag Coverage Δ
hive 39.08% <17.70%> (-0.07%) ⬇️
mysql 57.66% <17.70%> (-0.13%) ⬇️
postgres 57.73% <17.70%> (-0.13%) ⬇️
presto 40.64% <17.70%> (-0.07%) ⬇️
python 59.14% <17.70%> (-0.13%) ⬇️
sqlite 57.36% <17.70%> (-0.13%) ⬇️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aminghadersohi
aminghadersohi marked this pull request as ready for review June 12, 2026 21:16
@bito-code-review

bito-code-review Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #19fe4a

Actionable Suggestions - 0
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py - 1
Review Details
  • Files reviewed - 5 · Commit Range: 8f2823f..8f2823f
    • superset/mcp_service/app.py
    • superset/mcp_service/dashboard/schemas.py
    • superset/mcp_service/dashboard/tool/__init__.py
    • superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
    • tests/unit_tests/mcp_service/dashboard/tool/test_remove_chart_from_dashboard.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@aminghadersohi
aminghadersohi force-pushed the mcp-remove-chart-from-dashboard branch from 8f2823f to 1ae5e61 Compare June 25, 2026 19:03
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
aminghadersohi added a commit to aminghadersohi/superset that referenced this pull request Jun 25, 2026
- _find_chart_keys now matches chartId as both int and str to handle
  imported/hand-edited layouts where chartId may be stored as a string
- validate position_json parses to a dict before passing to layout helpers,
  preventing AttributeError on malformed-but-valid JSON (e.g. "[]")
- test: add return type annotation to mock_auth fixture; add docstrings
  to _chart_node and _call_remove test helpers

Addresses CodeAnt AI review findings on apache#40958.
@bito-code-review

bito-code-review Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #db9f95

Actionable Suggestions - 0
Additional Suggestions - 4
  • superset/mcp_service/app.py - 2
    • Inconsistent middleware registration · Line 134-134
      `remove_chart_from_dashboard` is documented in `app.py` but not registered in `permission_tag_map` at line 1058. Compare with `add_chart_to_existing_dashboard` which is registered. This inconsistent registration could affect permission validation behavior.
      Code suggestion
      --- superset/mcp_service/middleware.py (lines 1055-1060) ---
       1055:         "list_dashboards": "dashboard",
       1056:         "get_dashboard_info": "dashboard",
       1057:         "generate_dashboard": "dashboard",
       1058:         "add_chart_to_existing_dashboard": "dashboard",
       1059: +       "remove_chart_from_dashboard": "dashboard",
       1060:     }
    • Missing from mutate tools doc · Line 134-134
      The tool-search-optimization.md documentation at line 37 lists `add_chart_to_existing_dashboard` in the mutate tools section but does not include `remove_chart_from_dashboard`. This creates documentation inconsistency for a tool with equivalent write semantics.
  • superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py - 2
    • Inconsistent response fields on exception · Line 439-443
      In the exception handler, include `removed_layout_keys` (e.g., an empty list) and explicitly set `permission_denied=False` to match the response schema and other code paths. Ensure `removed_layout_keys` is initialized in all cases.
    • Inconsistent dashboard info fields · Line 364-375
      The fallback `DashboardInfo` construction on line 365 is missing `created_on` and `changed_on` fields that are included in the success-path construction at lines 389-390. This inconsistency means clients receive different data shapes depending on whether the re-fetch succeeded or failed.
      Code suggestion
      --- a/superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
      +++ b/superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
       @@ -365,6 +365,8 @@ def remove_chart_from_dashboard(
                            id=updated_dashboard.id,
                            dashboard_title=updated_dashboard.dashboard_title,
                            published=updated_dashboard.published,
      +                    created_on=updated_dashboard.created_on,
      +                    changed_on=updated_dashboard.changed_on,
                            chart_count=len(remaining_slices),
                            url=dashboard_url,
                        ),
Review Details
  • Files reviewed - 5 · Commit Range: 1ae5e61..af9ac74
    • superset/mcp_service/app.py
    • superset/mcp_service/dashboard/schemas.py
    • superset/mcp_service/dashboard/tool/__init__.py
    • superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
    • tests/unit_tests/mcp_service/dashboard/tool/test_remove_chart_from_dashboard.py
  • Files skipped - 0
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

aminghadersohi added a commit to aminghadersohi/superset that referenced this pull request Jun 26, 2026
- _find_chart_keys now matches chartId as both int and str to handle
  imported/hand-edited layouts where chartId may be stored as a string
- validate position_json parses to a dict before passing to layout helpers,
  preventing AttributeError on malformed-but-valid JSON (e.g. "[]")
- test: add return type annotation to mock_auth fixture; add docstrings
  to _chart_node and _call_remove test helpers

Addresses CodeAnt AI review findings on apache#40958.
@aminghadersohi
aminghadersohi force-pushed the mcp-remove-chart-from-dashboard branch from af9ac74 to 4b889c5 Compare June 26, 2026 14:40
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

Addressed in 9fe80bb — the 4 additional suggestions from Bito run #db9f95:

  1. permission_tag_map / TOOL_OBJECT_TYPE_MAP — added "remove_chart_from_dashboard": "dashboard" to FieldPermissionsMiddleware.TOOL_OBJECT_TYPE_MAP in middleware.py, matching the pattern for add_chart_to_existing_dashboard.

  2. tool-search-optimization.md mutate list — added remove_chart_from_dashboard to the mutate tools row in the docs.

  3. Consistent exception handler response — added removed_layout_keys=[] and permission_denied=False to the outer except handler's RemoveChartFromDashboardResponse.

  4. Fallback DashboardInfo missing fields — added created_on and changed_on to the re-fetch-fallback DashboardInfo construction so it matches the success path shape.

Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py Outdated
aminghadersohi added a commit to aminghadersohi/superset that referenced this pull request Jun 26, 2026
- _find_chart_keys now matches chartId as both int and str to handle
  imported/hand-edited layouts where chartId may be stored as a string
- validate position_json parses to a dict before passing to layout helpers,
  preventing AttributeError on malformed-but-valid JSON (e.g. "[]")
- test: add return type annotation to mock_auth fixture; add docstrings
  to _chart_node and _call_remove test helpers

Addresses CodeAnt AI review findings on apache#40958.
@aminghadersohi
aminghadersohi force-pushed the mcp-remove-chart-from-dashboard branch from 9fe80bb to 283fb13 Compare June 26, 2026 15:55
@aminghadersohi

Copy link
Copy Markdown
Contributor Author

Addressed review comment (CodeAnt, comment 3482429213): Fixed the positions/set_dash_metadata slices-overwrite bug in commit 283fb13.

The positions key is no longer injected into the json_metadata blob passed to UpdateDashboardCommand. Instead, _clean_json_metadata runs against the original metadata in-place, and the cleaned result is written directly to updated_dashboard.json_metadata + db.session.commit() after the re-fetch — bypassing DashboardDAO.set_dash_metadata's positions branch which would have overwritten dashboard.slices from layout data and silently dropped charts present in the slices relationship but absent from position_json.

The test now asserts "json_metadata" not in update_data and verifies the cleaned metadata on updated_dashboard.json_metadata directly.

Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
@bito-code-review

bito-code-review Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #1f6456

Actionable Suggestions - 0
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • tests/unit_tests/mcp_service/dashboard/tool/test_remove_chart_from_dashboard.py - 1
  • superset/mcp_service/dashboard/schemas.py - 1
Review Details
  • Files reviewed - 6 · Commit Range: ca542f9..283fb13
    • superset/mcp_service/app.py
    • superset/mcp_service/dashboard/schemas.py
    • superset/mcp_service/dashboard/tool/__init__.py
    • superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
    • superset/mcp_service/middleware.py
    • tests/unit_tests/mcp_service/dashboard/tool/test_remove_chart_from_dashboard.py
  • Files skipped - 1
    • superset/mcp_service/docs/tool-search-optimization.md - Reason: Filter setting
  • Tools
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@aminghadersohi
aminghadersohi force-pushed the mcp-remove-chart-from-dashboard branch from fe7cdc4 to 520750a Compare June 29, 2026 16:40
aminghadersohi added a commit to aminghadersohi/superset that referenced this pull request Jun 29, 2026
- _find_chart_keys now matches chartId as both int and str to handle
  imported/hand-edited layouts where chartId may be stored as a string
- validate position_json parses to a dict before passing to layout helpers,
  preventing AttributeError on malformed-but-valid JSON (e.g. "[]")
- test: add return type annotation to mock_auth fixture; add docstrings
  to _chart_node and _call_remove test helpers

Addresses CodeAnt AI review findings on apache#40958.
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py Outdated
@netlify

netlify Bot commented Jun 29, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit d33ee6c
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a44195dcca101000703c0a7
😎 Deploy Preview https://deploy-preview-40958--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py Outdated
Comment thread superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
@aminghadersohi
aminghadersohi requested a review from rusackas June 29, 2026 18:43
@bito-code-review

bito-code-review Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #88aeb7

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: 283fb13..d17e951
    • superset/mcp_service/dashboard/tool/remove_chart_from_dashboard.py
    • tests/unit_tests/mcp_service/dashboard/tool/test_remove_chart_from_dashboard.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@aminghadersohi
aminghadersohi force-pushed the mcp-remove-chart-from-dashboard branch from d17e951 to d33ee6c Compare June 30, 2026 19:30
aminghadersohi added a commit to aminghadersohi/superset that referenced this pull request Jun 30, 2026
- _find_chart_keys now matches chartId as both int and str to handle
  imported/hand-edited layouts where chartId may be stored as a string
- validate position_json parses to a dict before passing to layout helpers,
  preventing AttributeError on malformed-but-valid JSON (e.g. "[]")
- test: add return type annotation to mock_auth fixture; add docstrings
  to _chart_node and _call_remove test helpers

Addresses CodeAnt AI review findings on apache#40958.
aminghadersohi and others added 9 commits June 30, 2026 21:10
- _find_chart_keys now matches chartId as both int and str to handle
  imported/hand-edited layouts where chartId may be stored as a string
- validate position_json parses to a dict before passing to layout helpers,
  preventing AttributeError on malformed-but-valid JSON (e.g. "[]")
- test: add return type annotation to mock_auth fixture; add docstrings
  to _chart_node and _call_remove test helpers

Addresses CodeAnt AI review findings on apache#40958.
- Fix ruff E501: shorten _call_remove docstring to ≤88 chars
- Add remove_chart_from_dashboard to FieldPermissionsMiddleware
  TOOL_OBJECT_TYPE_MAP (was missing, unlike add_chart_to_existing_dashboard)
- Add remove_chart_from_dashboard to tool-search-optimization.md mutate
  tools list for documentation consistency
- Add created_on/changed_on to the re-fetch-fallback DashboardInfo path
  so its shape matches the successful re-fetch path
- Add removed_layout_keys=[] and permission_denied=False to the exception
  handler response for a consistent schema across all code paths
…n_metadata

When remove_chart_from_dashboard cleaned stale references from
json_metadata and routed the updated blob through UpdateDashboardCommand,
DashboardDAO.set_dash_metadata's positions branch ran and overwrote
dashboard.slices from layout data — silently dropping charts that were
in the slices relationship but absent from position_json. Instead, write
the cleaned metadata directly to updated_dashboard.json_metadata and
commit, bypassing the positions branch entirely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _clean_json_metadata now also removes the chart's entry from
  default_filters (stored as a JSON-encoded string inside json_metadata),
  matching the pruning done by DashboardDAO.set_dash_metadata when
  the positions branch runs.
- The secondary json_metadata commit (written directly to avoid the
  set_dash_metadata positions-branch slices overwrite) is now wrapped
  in its own try/except: if it fails, the chart removal is still
  reported as successful and the error is logged as a warning, since
  the chart has already been detached from layout and slices.
- Update docstrings and module-level description to mention default_filters.
- Add test_clean_json_metadata_cleans_default_filters unit test.
- Extend test_json_metadata_cleanup to cover default_filters cleanup.
Moves the json_metadata read from before UpdateDashboardCommand.run() to
after the re-fetch so cleanup is applied to the latest persisted state.
The old approach read a pre-command snapshot and wrote it back after the
re-fetch, silently overwriting any concurrent edits to dashboard metadata.

Updates test_json_metadata_cleanup to place json_metadata on the re-fetched
dashboard mock (updated_dashboard), reflecting the new read path.
…ard malformed layout

- Extract _clean_filter_scopes and _clean_default_filters helpers to bring
  _clean_json_metadata McCabe complexity from 14 to below the ruff C901
  threshold of 10.
- Fix bug in _clean_default_filters: when default_filters is already a dict
  (not a JSON-encoded string), re-serialize it back to a JSON string after
  removing the chart key so downstream json.loads calls don't receive a dict.
- Return an error response instead of silently using an empty layout when
  position_json cannot be parsed; this prevents accidentally wiping dashboard
  layouts on malformed data.
- Add test_clean_json_metadata_reserializes_dict_default_filters and
  test_malformed_position_json_returns_error covering the two bug fixes.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…=True

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@aminghadersohi
aminghadersohi force-pushed the mcp-remove-chart-from-dashboard branch from da20872 to 451eaab Compare June 30, 2026 21:23
@aminghadersohi
aminghadersohi merged commit 2bd9ab4 into apache:master Jun 30, 2026
57 of 59 checks passed
@bito-code-review

Copy link
Copy Markdown
Contributor

Bito Automatic Review Skipped – PR Already Merged

Bito scheduled an automatic review for this pull request, but the review was skipped because this PR was merged before the review could be run.
No action is needed if you didn't intend to review it. To get a review, you can type /review in a comment and save it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants