内容
# MCP Apache Superset
一个连接LLM客户端(Claude Code、Claude Desktop、Cursor等)到本地或远程Apache Superset实例的最小化模型上下文协议(MCP)服务器。
## 目录
- [功能](#功能)
- [前提条件](#前提条件)
- [安装](#安装)
- [配置](#配置)
- [身份验证](#身份验证)
- [数据库身份验证(默认)](#数据库身份验证默认)
- [SSO / OAuth2 / OIDC](#sso--oauth2--oidc)
- [LDAP](#ldap)
- [访问令牌(预身份验证)](#访问令牌预身份验证)
- [使用](#使用)
- [Claude Code](#claude-code)
- [Claude Desktop](#claude-desktop)
- [开发模式](#开发模式)
- [可用工具](#可用工具)
- [本地运行Superset](#本地运行superset)
- [架构](#架构)
---
## 功能
- 12种工具,涵盖图表、仪表板、数据集、数据库、SQL执行和查询历史
- 自动身份验证,401错误时刷新令牌
- CSRF令牌处理,用于写入操作
- 支持数据库身份验证、OAuth2/OIDC单点登录、LDAP和预身份验证访问令牌
- 除了MCP SDK和Zod之外,没有外部依赖
---
## 前提条件
- **Node.js** >= 18
- **Apache Superset** 运行并可访问(本地或远程)
---
## 安装
```bash
git clone <此仓库>
cd mcp-apache
npm install
npm run build
```
---
## 配置
所有配置均通过环境变量完成:
| 变量 | 默认值 | 描述 |
|---|---|---|
| `SUPERSET_URL` | `http://localhost:8088` | Superset基准URL |
| `SUPERSET_USERNAME` | `admin` | 数据库/LDAP身份验证的用户名 |
| `SUPERSET_PASSWORD` | `admin` | 数据库/LDAP身份验证的密码 |
| `SUPERSET_ACCESS_TOKEN` | _(无)_ | 预身份验证JWT访问令牌(跳过登录) |
| `SUPERSET_AUTH_PROVIDER` | `db` | 身份验证提供者:`db`、`ldap`、`oauth`或`token` |
复制示例文件以开始:
```bash
cp .env.example .env
```
---
## 身份验证
MCP服务器支持多种身份验证方法,以匹配您的Superset部署。
### 数据库身份验证(默认)
最简单的方法。Superset在自己的元数据数据库中存储用户。
```bash
SUPERSET_AUTH_PROVIDER=db
SUPERSET_USERNAME=admin
SUPERSET_PASSWORD=admin
```
服务器调用`POST /api/v1/security/login`,提供者为`"db"`,并接收JWT访问令牌。
---
### SSO / OAuth2 / OIDC
当Superset配置为OAuth2或OpenID Connect(Azure AD、Okta、Keycloak、Google等)时,您不能直接通过REST API登录,因为流程需要浏览器重定向。有两种方法:
#### 选项A:使用预身份验证访问令牌
这是MCP服务器的**推荐方法**。您在MCP流程之外获取令牌并直接传递它。
**步骤1:** 在`superset_config.py`中为Superset配置OAuth2/OIDC:
```python
from flask_appbuilder.security.manager import AUTH_OAUTH
AUTH_TYPE = AUTH_OAUTH
OAUTH_PROVIDERS = [
{
"name": "keycloak", # 或 "azure"、"okta"、"google" 等
"icon": "fa-key",
"token_key": "access_token",
"remote_app": {
"client_id": "superset-client",
"client_secret": "您的客户端密钥",
"server_metadata_url": "https://keycloak.example.com/realms/myrealm/.well-known/openid-configuration",
"api_base_url": "https://keycloak.example.com/realms/myrealm/protocol/openid-connect",
"access_token_url": "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token",
"authorize_url": "https://keycloak.example.com/realms/myrealm/protocol/openid-connect/auth",
"client_kwargs": {
"scope": "openid email profile"
},
},
}
]
# 将 OAuth 角色映射到 Superset 角色
AUTH_ROLES_MAPPING = {
"superset_admin": ["Admin"],
"superset_alpha": ["Alpha"],
"superset_gamma": ["Gamma"],
}
AUTH_ROLES_SYNC_AT_LOGIN = True
```
**步骤2:** 通过OAuth2客户端凭证或资源所有者密码授权(适用于服务帐户)获取令牌:
```bash
# 客户端凭证授权(服务到服务,无用户上下文)
curl -X POST https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token \
-d "grant_type=client_credentials" \
-d "client_id=superset-client" \
-d "client_secret=您的客户端密钥"
# 资源所有者密码授权(如果由您的IdP启用)
curl -X POST https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token \
-d "grant_type=password" \
-d "client_id=superset-client" \
-d "client_secret=您的客户端密钥" \
-d "username=svc-mcp" \
-d "password=SVC_PASSWORD" \
-d "scope=openid"
```
**步骤3:** 将令牌传递给MCP服务器:
```bash
SUPERSET_AUTH_PROVIDER=token
SUPERSET_ACCESS_TOKEN=eyJhbGciOiJSUzI1NiIs...
```
**步骤4(可选):** 使用包装脚本自动刷新令牌:
```bash
#!/bin/bash
# refresh-and-run.sh
export SUPERSET_ACCESS_TOKEN=$(curl -s -X POST \
https://keycloak.example.com/realms/myrealm/protocol/openid-connect/token \
-d "grant_type=client_credentials" \
-d "client_id=superset-client" \
-d "client_secret=$OAUTH_CLIENT_SECRET" | jq -r '.access_token')
export SUPERSET_AUTH_PROVIDER=token
export SUPERSET_URL=http://localhost:8088
node /path/to/mcp-apache/dist/index.js
```
然后在您的MCP配置中:
```json
{
"mcpServers": {
"superset": {
"command": "/path/to/refresh-and-run.sh"
}
}
}
```
#### 选项B:使用Superset的登录端点和OAuth(有限)
一些Superset部署即使配置了OAuth,也会公开标准登录端点。在这种情况下,您仍然可以通过创建本地服务帐户为MCP服务器使用数据库身份验证:
```bash
# 即使OAuth是主要身份验证,也在Superset中创建本地DB用户
superset fab create-admin \
--username mcp-service \
--firstname MCP \
--lastname Service \
--email mcp@internal \
--password 强密码
```
然后使用`SUPERSET_AUTH_PROVIDER=db`和服务帐户凭据配置MCP服务器。
---
### LDAP
当Superset使用LDAP身份验证时:
```python
# superset_config.py
from flask_appbuilder.security.manager import AUTH_LDAP
AUTH_TYPE = AUTH_LDAP
AUTH_LDAP_SERVER = "ldap://ldap.example.com"
AUTH_LDAP_USE_TLS = True
AUTH_LDAP_SEARCH = "ou=users,dc=example,dc=com"
AUTH_LDAP_UID_FIELD = "sAMAccountName"
AUTH_LDAP_BIND_USER = "CN=superset-svc,OU=ServiceAccounts,DC=example,DC=com"
AUTH_LDAP_BIND_PASSWORD = "绑定密码"
```
MCP服务器配置:
```bash
SUPERSET_AUTH_PROVIDER=ldap
SUPERSET_USERNAME=您的LDAP用户名
SUPERSET_PASSWORD=您的LDAP密码
```
内部调用相同的`/api/v1/security/login`端点,但提供者为`"ldap"`。
---
### 访问令牌(预身份验证)
如果您已经拥有有效的Superset JWT(通过任何方法),请完全跳过登录流程:
```bash
SUPERSET_AUTH_PROVIDER=token
SUPERSET_ACCESS_TOKEN=eyJhbGciOiJIUzI1NiIs...
```
服务器将在`Authorization: Bearer`头部直接使用此令牌。**注意:** 当令牌过期时,请求将失败,状态码为401。使用上述包装脚本方法进行自动刷新。
---
## 使用
### Claude Code
添加到您的项目的`.claude/settings.json`或全局`~/.claude/settings.json`:
```json
{
"mcpServers": {
"superset": {
"command": "node",
"args": ["C:/development/git/mcp-apache/dist/index.js"],
"env": {
"SUPERSET_URL": "http://localhost:8088",
"SUPERSET_USERNAME": "admin",
"SUPERSET_PASSWORD": "admin"
}
}
}
}
```
### Claude Desktop
添加到`claude_desktop_config.json`:
```json
{
"mcpServers": {
"superset": {
"command": "node",
"args": ["/绝对路径/to/mcp-apache/dist/index.js"],
"env": {
"SUPERSET_URL": "http://localhost:8088",
"SUPERSET_USERNAME": "admin",
"SUPERSET_PASSWORD": "admin"
}
}
}
}
```
### 开发模式
无需编译即可运行(使用`tsx`):
```bash
npm run dev
```
或在您的MCP配置中:
```json
{
"mcpServers": {
"superset": {
"command": "npx",
"args": ["tsx", "/path/to/mcp-apache/src/index.ts"],
"env": {
"SUPERSET_URL": "http://localhost:8088",
"SUPERSET_USERNAME": "admin",
"SUPERSET_PASSWORD": "admin"
}
}
}
}
```
---
## 可用工具
### 图表
| 工具 | 参数 | 描述 |
|---|---|---|
| `list_charts` | `page?`, `page_size?` | 列出所有图表,支持分页 |
| `get_chart` | `id` | 获取图表元数据(类型、数据源、参数) |
| `get_chart_data` | `id` | 执行图表查询并返回结果数据 |
### 仪表板
| 工具 | 参数 | 描述 |
|---|---|---|
| `list_dashboards` | `page?`, `page_size?` | 列出所有仪表板 |
| `get_dashboard` | `id` | 获取仪表板元数据和布局 |
### 数据集
| 工具 | 参数 | 描述 |
|---|---|---|
| `list_datasets` | `page?`, `page_size?` | 列出已注册的数据集(表/视图) |
| `get_dataset` | `id` | 获取数据集模式、列和指标 |
### 数据库
| 工具 | 参数 | 描述 |
|---|---|---|
| `list_databases` | _(无)_ | 列出所有已配置的数据库连接 |
| `get_database` | `id` | 获取数据库的连接详情 |
### SQL 执行
| 工具 | 参数 | 描述 |
|---|---|---|
| `execute_sql` | `database_id`, `sql`, `schema?` | 通过 SQL Lab 运行任意 SQL 查询 |
| `list_saved_queries` | `page?`, `page_size?` | 列出已保存的 SQL Lab 查询 |
| `list_queries` | `page?`, `page_size?` | 列出最近的查询执行历史 |
---
## 本地运行Superset
### Docker(最快)
```bash
docker run -d -p 8088:8088 --name superset apache/superset
# 首次初始化
docker exec -it superset superset fab create-admin \
--username admin \
--firstname Admin \
--lastname Admin \
--email admin@example.com \
--password admin
docker exec -it superset superset db upgrade
docker exec -it superset superset init
```
在 http://localhost:8088 访问
### Docker Compose(全栈,带示例)
```bash
git clone https://github.com/apache/superset.git
cd superset
docker compose -f docker-compose-non-dev.yml up -d
```
这启动了Superset,带有Redis、PostgreSQL和预加载的示例仪表板。
---
## 架构
```
┌─────────────────┐ 标准输入/输出 ┌──────────────────────┐
│ LLM 客户端 │◄──────────────────►│ MCP 服务器 │
│ (Claude Code) │ MCP 协议 │ (此项目) │
└─────────────────┘ └──────────┬───────────┘
│ HTTP/REST
▼
┌──────────────────────┐
│ Apache Superset │
│ /api/v1/* │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ 数据源 │
│ (PostgreSQL、MySQL、 │
│ BigQuery等) │
└──────────────────────┘
```
**身份验证流程:**
1. MCP服务器启动 → 调用`POST /api/v1/security/login`(或使用预配置的令牌)
2. 接收JWT访问令牌 + 获取CSRF令牌
3. 所有后续API调用均包含`Authorization: Bearer <token>` + `X-CSRFToken`
4. 在401响应时 → 自动重新身份验证和重试
---
## 许可证
MIT