Superset MCP Server
# Superset MCP Server
Local `stdio` MCP server for reviewing Apache Superset dashboards, retrieving chart data, executing SQL through SQL Lab, and creating or updating saved queries.
The server only calls Superset's public REST API. It does not connect directly to an analytical database. No delete, dashboard mutation, chart mutation, dataset mutation, database-administration, screenshot, or generic arbitrary-request tools are exposed.
## Superset's built-in MCP server
Superset 5.0+ also includes an official MCP service that an administrator can run alongside the Superset deployment:
```text
superset mcp run --host 127.0.0.1 --port 5008
```
That service is the preferred option when your Superset version includes it and you have deployment access. It provides native RBAC enforcement, audit logging, chart/dashboard creation, SQL execution, and saved-query creation at an HTTP `/mcp` endpoint. See the official [MCP deployment guide](https://superset.apache.org/admin-docs/configuration/mcp-server/) and [available tools](https://superset.apache.org/user-docs/using-superset/using-ai-with-superset/).
This repository remains useful when:
- the Superset administrator has not deployed the built-in MCP process;
- only the public REST URL and a normal Superset login are available;
- a local stdio MCP server is required; or
- saved-query inspection and update support are needed in addition to the built-in server's documented `save_sql_query` creation tool.
Do not deploy both integrations under the same MCP server name without intentionally choosing which one future projects should use.
## Requirements
- Python 3.11 or newer (Python 3.13 is supported by this project)
- Network access from this machine to your Superset URL
- A dedicated Superset account with only the roles and database permissions the MCP server needs
`execute_sql` deliberately passes SQL through unchanged. Superset's database configuration and the underlying database user are therefore the security boundary for DML, DDL, CTAS, and other statements. Use a least-privilege account.
## Windows setup
Run these commands from `super_set_mcp` in PowerShell:
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
Copy-Item .env.example .env
```
Edit `.env` with the real connection values. Do not commit `.env`.
```dotenv
SUPERSET_URL=https://superset.example.com
SUPERSET_USERNAME=mcp-service-user
SUPERSET_PASSWORD=replace-me
SUPERSET_PROVIDER=db
SUPERSET_VERIFY_SSL=true
```
The URL must be the Superset base URL without `/api/v1`. `SUPERSET_PROVIDER` can be changed to `ldap` when that is how the Superset login endpoint is configured.
## Run and validate
Run the server over stdio:
```powershell
.\.venv\Scripts\python.exe -m superset_mcp.server
```
The process waits silently for MCP protocol messages; that is normal for a stdio server. Before using any data or write tool, call `superset_status`. It checks login and current-user access and, by default, probes Superset's OpenAPI endpoint.
Run the mocked test suite without contacting Superset:
```powershell
.\.venv\Scripts\python.exe -m pytest
```
## MCP client configuration
Use an absolute path so future projects can launch the same server regardless of their working directory:
```json
{
"mcpServers": {
"superset": {
"command": "C:\\path\\to\\super_set_mcp\\.venv\\Scripts\\python.exe",
"args": ["-m", "superset_mcp.server"],
"cwd": "C:\\path\\to\\super_set_mcp"
}
}
}
```
Keeping `cwd` set to this folder allows `pydantic-settings` to load its local `.env`. If a client supports an `env` map, secrets may instead be injected by the client or a secret manager; do not place real credentials in shared project configuration.
## Tools
| Tool | Purpose |
| --- | --- |
| `superset_status` | Validate settings, JWT login, current user, and optional OpenAPI availability |
| `list_dashboards` | Search and paginate dashboards |
| `get_dashboard` | Read dashboard metadata by ID or slug |
| `get_dashboard_charts` | Read a dashboard's chart definitions and form data |
| `get_dashboard_datasets` | Read datasets used by a dashboard |
| `get_chart` | Read chart metadata |
| `get_chart_data` | Retrieve data for a saved chart query |
| `list_databases` | Find accessible database IDs for SQL Lab and saved queries |
| `execute_sql` | Execute SQL unchanged through SQL Lab |
| `get_query` | Inspect query history or asynchronous status |
| `get_sql_result` | Retrieve asynchronous results using `resultsKey` |
| `list_saved_queries` | Search and paginate saved queries |
| `get_saved_query` | Read one saved query |
| `create_saved_query` | Preview/create a saved query; requires `confirm=true` to write |
| `update_saved_query` | Preview/update while preserving unspecified fields; requires `confirm=true` to write |
There is no saved-query delete tool.
## Recommended first-use sequence
1. Configure the real URL and credentials locally.
2. Call `superset_status`.
3. Call `list_databases`, `list_dashboards`, and `list_saved_queries` to validate read permissions.
4. Review a dashboard through `get_dashboard`, `get_dashboard_charts`, and `get_dashboard_datasets`.
5. Retrieve chart data only when needed; `force=true` bypasses Superset's cache and may increase database load.
6. Execute SQL only after verifying the selected database ID and role. Long-running deployments can use `run_async=true`, then `get_query`/`get_sql_result`.
7. Call create/update first with the default `confirm=false`, inspect the preview, and call again with `confirm=true` only when the payload is correct.
## Troubleshooting
- `configured: false`: one or more required `SUPERSET_*` settings are missing or the URL is invalid.
- HTTP 401: check username, password, provider, and whether REST login is enabled.
- HTTP 403: the Superset role lacks access to the dashboard, chart, database, SQL Lab, or saved-query resource.
- TLS/transport error: keep `SUPERSET_VERIFY_SSL=true` and install/configure the organization's trusted CA. Disable verification only for a controlled temporary diagnostic.
- OpenAPI unavailable: the deployment may not expose `/api/v1/_openapi`; normal tools can still work. Superset's Swagger UI may also require `FAB_API_SWAGGER_UI = True`.
- Result expired (HTTP 410): rerun the asynchronous query because its result key is no longer retained by Superset.
- Response too large: increase `SUPERSET_MAX_RESPONSE_BYTES` cautiously or reduce query/page limits.
## Security behavior
- Passwords and JWTs remain in environment configuration and process memory; they are never returned by tools.
- On HTTP 401, the client tries the refresh token and then performs one fresh login if refresh fails.
- API error output includes method, public API path, status, and safe error fields, but excludes request headers and credentials.
- Page sizes, query limits, request timeouts, and response bytes are bounded by environment settings.
- Saved-query updates fetch the existing record and preserve fields not supplied by the caller.
- Optional update fields set to `null` are treated as omitted by the MCP tool. This version does not expose field-clearing semantics.
## API references
- [Superset API reference](https://superset.apache.org/developer-docs/api/)
- [Security and JWT endpoints](https://superset.apache.org/developer-docs/api/security/)
- [Dashboards](https://superset.apache.org/developer-docs/api/dashboards/)
- [Charts](https://superset.apache.org/developer-docs/api/charts/)
- [Queries and saved queries](https://superset.apache.org/developer-docs/api/queries/)
- [SQL Lab](https://superset.apache.org/developer-docs/api/sql-lab/)
- [MCP Python SDK](https://py.sdk.modelcontextprotocol.io/)
TDQS
Scored across 25 tools
Most tools have clear, distinct purposes targeting specific resources and actions. The only potential confusion is between get_sql_result (async result retrieval) and get_query (query history/status), and between get_chart_data and get_chart, but descriptions are sufficiently clear.
The vast majority follow a consistent verb_noun snake_case pattern (list_, get_, create_, update_, execute_). The single outlier is superset_status, which is not verb-first but still readable and not disruptive.
At 25 tools, this is at the heavy end of the borderline range. Each tool has a purpose, but the granularity is excessive in places (e.g., four dashboard-related getters), making the surface feel larger than necessary.
The set covers most core workflows for dashboards, charts, datasets, saved queries, and SQL execution, but there are notable gaps: no list_charts, no delete operations for any resource, and no get_database by ID. These missing operations will require workarounds.