aminghadersohi opened a new pull request, #42543: URL: https://github.com/apache/superset/pull/42543
### SUMMARY **Proof-of-concept:** make Superset's MCP tools return a chart that renders as a **real, interactive visualization** inside MCP Apps hosts (Claude web/desktop, ChatGPT, VS Code Copilot, Cursor, Goose, …) instead of a prose summary — using the **MCP Apps extension (SEP-1865, stable 2026-01-26)**. Motivation + landscape research: [`mcp-native-viz-research.md`](https://github.com/aminghadersohi/superset/blob/research-mcp-native-viz-clients/mcp-native-viz-research.md). Feature/architecture doc: [`superset/mcp_service/chart/MCP_APPS_CHART_VIEWER.md`](https://github.com/aminghadersohi/superset/blob/research-mcp-native-viz-clients/superset/mcp_service/chart/MCP_APPS_CHART_VIEWER.md). **How it works** - `render_chart` returns Superset's `ChartData` as `structuredContent` + a text summary, and its tool descriptor carries `_meta.ui.resourceUri = ui://superset/chart-viewer/v1`. Hosts fetch that resource and render a sandboxed iframe widget. - `render_chart_requery` (`_meta.ui.visibility: ["app"]`) is the widget's drill/zoom callback. - Both wrap the shared, **already-authorized** `get_chart_data_core`, so Chart/read RBAC, dataset-access checks, guest scoping and RLS apply on **every** call — the widget cannot exceed the caller's entitlements. **The widget** (`chart_viewer/`, React + ECharts, single 778 KiB self-contained bundle): line/bar/area/big-number/table with a styled-table fallback; Superset theming, dark/light sync; and the interactive bits — animated bar⇄line⇄area morphing, click-to-drill, brush-to-zoom re-query, live metric chips, and an "ask about this" hook that pushes a selected datapoint into the model's context. **Two scoped infra changes** (both narrow, nothing else affected): - `StructuredContentStripperMiddleware` gets a keep-list (`MCP_STRUCTURED_CONTENT_KEEP_TOOLS`, default `{render_chart, render_chart_requery}`) so widget tools retain `structuredContent`; everything else is still stripped. - The widget tools are pinned in `MCP_TOOL_SEARCH_CONFIG.always_visible` so hosts see the UI descriptor. - `@tool(meta=...)` now threads `_meta` onto tool descriptors. **Security:** independently reviewed. No privilege-escalation / RLS-bypass path — both tools are read-only `Chart/read` delegating to the same authorized data path. iframe CSP is declared on the `ui://` resource; no secrets in the bundle; the generic `call_tool` proxy is never exposed to the widget. The widget **never shows sample data when embedded** (renders a connection error), surfaces `ChartError` states, and treats unknown host capabilities as unsupported. > ⚠️ **Draft / PoC.** Exploratory; not proposed for merge as-is. The built widget bundle (`chart_viewer/dist/index.html`) is committed (force-added past the global `dist` gitignore) so the server works without a Node build step — a production pipeline should build it in CI instead and drop the committed artifact. If pursued for real, this would go through a SIP. ### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF _Live host capture pending a public HTTPS Superset MCP endpoint (Claude calls originate from Anthropic's cloud; ChatGPT developer mode needs a Business/Enterprise workspace)._ Verified locally via tool registration + the MCP Inspector-equivalent path. ### TESTING INSTRUCTIONS - Python: `pytest tests/unit_tests/mcp_service/chart/tool/test_render_chart.py tests/unit_tests/mcp_service/test_middleware.py`. Full `tests/unit_tests/mcp_service/` suite passes (3107; 1 unrelated pre-existing `health_check` flake). - Widget: `cd superset/mcp_service/chart/resources/chart_viewer && npm install && npm test` (16 tests: adapter + bridge contract) and `npm run build`. - End-to-end: register the Superset MCP server as a custom connector in an MCP Apps host and ask it to render a chart by id. Runbook in `MCP_APPS_CHART_VIEWER.md`. ### ADDITIONAL INFORMATION - [ ] Has associated issue: - [ ] Required feature flags: - [x] Changes UI - [ ] Includes DB Migration - [x] Introduces new feature or API - [ ] Removes existing feature or API **Known follow-ups:** migrate the widget bridge onto the vendored `@modelcontextprotocol/ext-apps` SDK transport (currently a spec-conformant hand-rolled bridge with a contract test); build the bundle in CI rather than committing it; live host captures once a public staging endpoint is available. 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected] --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
