fes-mcp
Sisense Meta-Management MCP 服务器
⚠️ 实验性项目声明
来自 Sisense 现场工程团队的社区贡献工具
本项目是 Sisense 现场工程团队开发的实验性工具,旨在帮助客户学习和探索 Sisense 的功能。 它不属于 Sisense 核心产品发布生命周期的一部分,也不经过与一般可用(GA)Sisense 功能相同的验证、支持或认证流程。它按“原样”提供—— 参见支持与贡献。
一个符合标准的 MCP 服务器,将 Sisense 环境操作作为 AI 就绪工具暴露出来,由 PySisense SDK 提供支持:治理、资产和用户/组管理、生命周期任务和健康检查——而非图表构建或分析问答。
它适用于任何 Sisense 用户:每次工具调用都使用调用用户自己的 Sisense 凭据运行,因此结果和权限正是该用户在 Sisense 中可以看到和执行的,由 Sisense 的 API 原生强制执行。
仅工具,无代理。 Claude Desktop、Claude Code、claude.ai、Cursor——任何 MCP 客户端都自带代理;本项目宣传并执行约 100 个精选工具(仪表板、数据模型、用户/组、文件夹、插件、健康检查等)。
架构
MCP 规范的现代形态,作为两个协作服务以两个 Docker 镜像(fes-auth、fes-mcp——由单个多阶段 Dockerfile 构建,共享层)交付:
fes-auth — 授权服务器(AS)。负责关于谁在调用的一切:面向 MCP 客户端的 OAuth 2.1(PKCE、动态客户端注册、发现)、浏览器登录页面,以及将每个已签发 MCP 令牌映射到用户 Sisense 令牌的凭据库。它将每个工具调用代理到资源服务器,并注入 Sisense 凭据。
fes-mcp — 资源服务器(RS)。无状态,不感知 OAuth。从每个请求中读取注入的凭据,对照 Sisense 验证(缓存),并以该用户身份针对该 Sisense 实例运行工具。
flowchart LR
subgraph clients [MCP clients]
C1[Claude Desktop]
C2[Claude Code]
C3[claude.ai / Cursor]
end
subgraph box [one host - docker compose]
subgraph AS [fes-auth : authorization server]
O[OAuth 2.1\nPKCE + DCR + discovery]
L[/login page/]
V[(vault\nMCP token → Sisense credential)]
P[/mcp proxy\ninjects credential headers/]
end
subgraph RS [fes-mcp : resource server]
T[Tool layer\nregistry-driven, ~100 tools]
D[Dispatcher\nper-credential PySisense client]
end
end
R[(tool registry JSON\nauto-generated from SDK)] -.defines.-> T
C1 & C2 & C3 -- "MCP over HTTPS\nBearer <MCP token>" --> P
C1 & C2 & C3 -. "browser: sign in once" .-> L
P -- "Authorization: Bearer <Sisense token>\nX-Sisense-Url: <instance>\n(internal network only)" --> T
T --> D
D -- "REST, as the signed-in user" --> F[(Sisense Fusion Deployment)]两个服务之间的接缝只是那两个头加上 401 契约,因此每一半都可以独立演进——或被替换——而另一方不会察觉。两个服务之间故意没有共享密钥——信任基于内部网络(RS 的端口从不发布)。
登录流程(用户体验)
每个用户在其 MCP 客户端中添加一次连接器,在 URL 中指定自己的 Sisense 实例:
https://your-host/mcp?target=https://acme.sisense.comsequenceDiagram
participant U as User (browser)
participant C as MCP client
participant A as fes-auth
participant S as Sisense
C->>A: POST /mcp?target=<sisense url> (no token)
A-->>C: 401 + resource metadata URL (carries target)
C->>A: discovery + client registration (RFC 7591)
C->>U: open browser at A's /login
Note over U,A: target present → instance fixed,<br/>only username/password asked<br/>(no target → domain field shown)
U->>A: username/password (or API token for SSO)
A->>S: POST /api/v1/authentication/login
S-->>A: user's Sisense token (kept server-side, in the vault)
A-->>C: authorization code → MCP access token (PKCE)
Note over C,A: from here, silent — token refresh is automatic客户端永远不会看到 Sisense 凭据;服务器从不存储密码(仅用于一次性签发用户的令牌,然后丢弃)。使用 SSO/MFA 实例的用户改为粘贴其个人 Sisense API 令牌进行登录。
工具调用(稳定状态)
sequenceDiagram
participant C as MCP client
participant A as fes-auth (proxy)
participant R as fes-mcp (tools)
participant S as Sisense (target)
C->>A: POST /mcp (Bearer <MCP token>)
A->>A: validate token → vault → Sisense credential
A->>R: same request + Authorization: Bearer <Sisense token><br/>+ X-Sisense-Url: <instance>
R->>S: verify credential (TTL-cached) · SDK call as that user
S-->>R: result (user's permissions, user in audit log)
R-->>A: MCP response (streamed)
A-->>C: MCP response (streamed)凭据生命周期与自愈
资源服务器在
FES_MCP_VERIFY_TTL秒(默认 300)后重新验证每个(实例,令牌)对。在 Sisense 中被撤销的令牌会在该窗口内变成 HTTP 401。fes-auth 将 RS 的 401 视为凭据失效:它删除库条目并重新质询 MCP 客户端,客户端的下一步是重新运行登录流程。因此,服务器端撤销无需手动步骤即可传播。
会话按设计为内存态(无数据库):重启 fes-auth 会使所有用户退出——每个用户的下一次调用会再次弹出浏览器登录(设置
?target=后,只需用户名/密码)。重启 fes-mcp 不可见:它不持有任何状态。
部署(docker compose)
docker compose up --build这会构建两个镜像(docker build --target fes-auth|fes-mcp),并且只发布 :8200 上的 fes-auth;fes-mcp 保持内部。在前端终止 TLS(ALB / nginx / Caddy)——MCP 客户端需要 HTTPS 进行 OAuth——并设置 FES_MCP_PUBLIC_URL 为该公共 URL:
FES_MCP_PUBLIC_URL=https://your-host.example.com docker compose up -d --build然后用户将 https://your-host.example.com/mcp?target=https://their-instance.sisense.com 添加为自定义连接器。?target= 部分是可选的——没有它,登录页面会要求输入 Sisense URL 作为第三个字段。
fes-auth 上的端点:/mcp(代理的 MCP)、/login、/.well-known/* + /authorize + /token + /register(OAuth 2.1)、/(状态)、/healthz。包含加固措施:按 IP 的登录速率限制、CSRF 保护的登录表单、带请求 ID 的访问日志。
快速开始(本地开发)
需要 Python 3.11+ 和 uv。本地开发完全跳过 AS:stdio 传输默认使用 env 认证——来自 .env 的一个凭据,一切以你的身份运行。
uv sync
cp .env.example .env # set SISENSE_DOMAIN / SISENSE_TOKEN
uv run fes-mcp # stdio transportMCP 客户端配置(例如 claude_desktop_config.json):
{
"mcpServers": {
"sisense": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/fes_mcp", "fes-mcp"]
}
}
}要在没有 Docker 的情况下本地运行完整拆分:
FES_MCP_TRANSPORT=http uv run fes-mcp & # RS on :8200 (upstream auth)
FES_MCP_PORT=8300 FES_MCP_RS_URL=http://127.0.0.1:8200 uv run fes-auth
# connector: http://127.0.0.1:8300/mcp?target=https://your.sisense.com布局
src/fes_mcp/—settings(环境配置)·registry(加载/过滤)·dispatcher(按凭据的 SDK 分发)·upstream(RS 凭据验证)·auth(OAuth 提供者 + 登录页面)·authserver(fes-auth 服务 + 代理)·middleware(访问日志)·server(FastMCP 组装)config/tools.registry.with_examples.json— 自动生成的工具注册表。绝不手写;当 PySisense 更新时,使用./refresh_registry.sh重新生成。config/allowlist.txt— 精选的工具表面,每行一个工具。删除/注释一行以移除工具。未列出的工具永远不会暴露,因此注册表刷新不会静默扩大表面。(迁移工具故意未列出——它们需要此服务器未建模的双实例连接。)变更工具由
FES_MCP_ALLOW_MUTATIONS=true门控——参见安全了解完整的变更保护措施。
技术与安全考虑
凭据处理
MCP 客户端永远不会看到 Sisense 凭据,服务器从不存储密码——密码仅用于一次性调用 Sisense 的登录 API 以签发用户自己的令牌,然后丢弃。Sisense 令牌存在于 fes-auth 的内存库中,键为 MCP 访问令牌,并在刷新轮换后继续有效。在开发模式下,单个环境凭据(SISENSE_DOMAIN/SISENSE_TOKEN)保留在你的机器上。没有任何内容持久化到磁盘:fes-auth 重启会清空库(所有用户重新登录)——这是为了没有数据库和静态加密表面而做出的有意权衡。
托管表面上的加固:按 IP 的登录速率限制、CSRF 保护的登录表单、带请求 ID 的访问日志,以及每次调用的工具日志(工具 / 用户域 / 结果 / 持续时间)。
授权
没有自定义内容:授权是 Sisense 的工作。每次工具调用都使用调用用户自己的 Sisense 令牌运行,因此 Sisense 在每次 API 调用上强制执行其真实权限,权限错误原样返回给客户端。这也是服务器不仅限管理员的原因——任何 Sisense 用户都恰好获得自己的范围。
两个服务之间的信任
fes-auth ↔ fes-mcp 之间的信任是网络级别的:没有共享密钥。RS 的端口绝不能从内部网络外部访问(compose 只发布 fes-auth)。纵深防御:FES_MCP_ALLOWED_SISENSE_ORIGINS 固定 RS 将在 X-Sisense-Url 中接受的 Sisense 来源。
变更操作
变更工具仅在 FES_MCP_ALLOW_MUTATIONS=true 时暴露,始终携带 destructiveHint,在禁用时作为第二层在服务器端阻止,并写入变更审计日志。
除此之外,变更工具在执行前会请求人类批准——通过 MCP 引导,在声明该能力的客户端上(Claude Code、Cursor、VS Code)。调用中途会弹出继续/中止对话框,披露确切参数;中止或拒绝不会改变任何内容。在没有引导的客户端上(Claude Desktop、claude.ai),调用正常进行,客户端的工具批准流程加上 destructiveHint 注释是保护措施,与任何 MCP 服务器一样。
在没有对话框的情况下继续是有意决定(失败开放),而非疏忽:引导是可选客户端能力,可能被行为异常的客户端自动应答,因此严格视为 UX——授权边界始终是用户自己的 Sisense 权限。
流向 LLM 提供者的数据流
此服务器没有摘要或数据脱敏层:每个工具结果——完整行,而非 {ok, count} 元数据——都返回给 MCP 客户端并进入模型的上下文。这是设计使然,也是多步骤工具链能够工作的原因:模型只有实际看到数据,才能推理、过滤并将一个工具的输出馈送到下一个调用。
后果:谁将此服务器连接到 MCP 客户端,谁就接受 Sisense 数据(仪表板内容、查询结果、用户列表等)流向该客户端的 LLM 提供者——例如 Anthropic(用于 Claude)——在他们与该提供者的自身条款下。服务器无法强制执行或限定此范围;这是每个部署需要有意识地做出的接受。
推荐使用指南
从只读开始:在非生产环境中建立信心之前,保持
FES_MCP_ALLOW_MUTATIONS=false(默认值)。将
config/allowlist.txt精简到部署实际需要的工具——更少的工具意味着更少的数据暴露和更清晰的批准故事。探索时优先使用非生产 Sisense 实例;工具的安全性仅取决于登录用户的权限。
使用支持引导的 MCP 客户端(Claude Code、Cursor)测试破坏性操作,以便看到确认对话框。
配置
变量 | 默认值 | 使用者 | 用途 |
| — | fes-mcp | 开发模式( |
|
| 两者 | 调用 Sisense 时验证 TLS |
| 按传输:http ⇒ | fes-mcp | 凭据来源 |
|
| fes-mcp |
|
|
| 两者 | HTTP 绑定 |
| — | fes-auth | 公共基础 URL(OAuth 发现/重定向) |
| — | fes-auth | 要代理工具调用的资源服务器 |
|
| fes-mcp | 已验证的(实例,令牌)对受信任的秒数 |
| —(接受任何) | fes-mcp |
|
|
| fes-mcp | 逗号分隔的 tool_ids / 模块覆盖 |
|
| fes-mcp | 暴露变更工具 |
| 捆绑的注册表 | fes-mcp | 备用注册表 JSON |
|
| 两者 | 日志详细程度(仅 stderr) |
测试
uv run python -m pytest(python -m 很重要:它将仓库根目录放在 sys.path 上,测试模块的 from tests.conftest import … 导入依赖于此。)
49 个测试,无需网络和凭据(Sisense 和 SDK 均被模拟):注册表选择、调度器验证/错误、MCP 往返、变更确认(批准/中止/拒绝/无能力)、上游凭据验证(注入的标头、401 契约、来源允许列表、TTL 撤销),以及完整的 AS+RS 拆分——带和不带 ?target= 的 OAuth 流程、发现元数据、代理工具调用、刷新轮换、Sisense 端撤销时的自愈,以及滥用路径(伪造的 CSRF、暴力破解速率限制、过期会话)。
注册表重新生成
./refresh_registry.sh # rebuild config/ from the installed PySisense SDK新的 SDK 方法会进入注册表,但在显式添加到 config/allowlist.txt 之前保持隐藏状态。
支持与贡献
这是一个由 Sisense 现场工程团队维护的实验性社区贡献项目,按**"原样"**提供。
请勿提交 GSS 工单 — 这不是 Sisense 的 GA 功能。
如有使用问题或需要入门帮助,请联系您的客户成功经理(CSM),他们会将反馈转达给现场工程团队。
欢迎通过仓库提交问题和贡献。
许可证
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Runtime permission, approval, and audit layer for AI agent tool execution.
Manage SRG+ hubs, channels, content, assets, users, and workspaces from any MCP-aware AI agent.
Manage AI assistants, history, calls, campaigns, contacts, knowledge, messaging, and automations.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/hnegi01/fes-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server