Wheatfield Studio的LumApps MCP服务器
MCP(模型上下文协议)服务器,用于将LumApps API连接到人工智能助手 (微软复制工作室、Cursor、Claude等)。该项目通过将LumApps内联网转变为人工智能的活跃知识库,为MCP生态系统做出了贡献。
______________________________________________________________________
概述
此服务器将LumApps API公开为 MCP工具:内容搜索、文章检索、目录、有用链接(目录条目)、布局和样式检查以及CSS/小部件样式更新。助理可以以结构化的方式查询和使用您的内联网内容。
- 协议:MCP(流式HTTP 2025-06-18,与SSE兼容)
- 堆栈:FastAPI,Python 3.11
- 认证: 首选OIDC(SSO) (Azure AD、Okta、Ping等的Bearer JWT),带有可选的API密钥回退;后端的LumApps OAuth2(客户端凭据或令牌)
______________________________________________________________________
建筑
┌─────────────────┐ MCP (Streamable HTTP / SSE) ┌──────────────────┐
│ Cursor / │ ◄─────────────────────────────────► │ FastAPI MCP │
│ Copilot Studio │ X-API-Key or Bearer │ Server │
└─────────────────┘ └────────┬─────────┘
│
│ OAuth2 / API
▼
┌──────────────────┐
│ LumApps API │
│ (sites.lumapps) │
└──────────────────┘/mcp: 可流式传输的HTTP 传输(推荐)——MCP协议的单个GET/POST端点。/sse+/messages:面向老客户的SSE运输(传统)。- MCP工具:注册于
app/tools/(搜索、内容、人员、有用链接、布局/CSS检查、样式更新)。
______________________________________________________________________
先决条件
- Python 3.10+
- 具有API访问权限的LumApps帐户(客户端ID/机密或令牌)
- 用于保护MCP服务器访问的API密钥
______________________________________________________________________
安装
git clone https://github.com//lumapps-mcp-server.git
cd lumapps-mcp-server
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt配置
- 复制示例文件并设置变量:
cp .env.example .env
# Edit .env with your values (see below)- 必需变量:
- 认证:要么 OIDC_ISSUER_URL (对于SSO)或 MCP_API_KEY 随着 AUTH_ALLOW_API_KEY_FALLBACK=true (参见 SSO/OIDC). - LUMAPPS_ORG_ID:LumApps组织ID。 - 要么 LUMAPPS_READ_CLIENT_ID + LUMAPPS_READ_CLIENT_SECRET (或遗产 LUMAPPS_CLIENT_ID + LUMAPPS_CLIENT_SECRET),或 LUMAPPS_ACCESS_TOKEN (用于测试)。
- 可选变量:
- AUTH_MODE: oidc_preferred (默认)或 api_key_only.与 api_key_only,仅 MCP_API_KEY 被接受。 - AUTH_ALLOW_API_KEY_FALLBACK:当 oidc_preferred,如果没有承载令牌,则允许静态API密钥(默认值 true;set false 仅适用于SSO)。 - OIDC_ISSUER_URL, OIDC_AUDIENCE, OIDC_CLIENT_ID, OIDC_EMAIL_CLAIM, OIDC_USERNAME_CLAIM, OIDC_CLOCK_SKEW_SECONDS:参见 SSO/OIDC 和 .env.example. - MCP_PUBLIC_URL:公共服务器URL(例如devtunnel/ngrok),以便客户端在MCP事件中获得正确的URL。 - LUMAPPS_ADMIN_CLIENT_ID + LUMAPPS_ADMIN_CLIENT_SECRET:第二个LumApps OAuth应用程序 all.admin 范围(参见 读取与管理员凭据 在......下面 - 基于角色的访问控制 (参见 用户级RBAC): RBAC_ENABLED, RBAC_USE_LUMAPPS_NATIVE, RBAC_ORG_ADMIN_CLAIM,以及(回退) RBAC_ROLE_CLAIM, RBAC_*_PATTERNS, RBAC_DENY_API_KEY_FOR_NON_READ, RBAC_CONTENT_SITE_CACHE_*. - CORS_ORIGINS:额外的CORS源(逗号分隔)。 - LOG_LEVEL, MAX_SEARCH_RESULTS等等。
环境命名(Kubernetes/企业):对于读取凭证, LUMAPPS_READ_CLIENT_ID 和 LUMAPPS_READ_CLIENT_SECRET 是首选;设置后,它们优先于 LUMAPPS_CLIENT_ID / LUMAPPS_CLIENT_SECRET这两种命名方案都支持向后兼容性。
重要:永远不要承诺 .env 文件(列在 .gitignore).
读取与管理员凭据
LumApps OAuth应用程序是使用固定范围创建的: all.read (只读)或 all.admin (读+写)。此服务器分离 终端用户工具 (阅读)自 管理工具 (修改)当配置了两个凭据对时,使用两个凭据配对:
| 目的 | 环境变量 | LumApps作用域 | 工具 |
|---|---|---|---|
| 阅读(最终用户) | LUMAPPS_READ_CLIENT_ID + LUMAPPS_READ_CLIENT_SECRET (或 LUMAPPS_CLIENT_ID + LUMAPPS_CLIENT_SECRET) | all.read | search_content, get_content_body, find_person, get_useful_links, search_site |
| 管理员(内容+结构) | LUMAPPS_ADMIN_CLIENT_ID + LUMAPPS_ADMIN_CLIENT_SECRET | all.admin | inspect_lumapps_element, update_widget_style, update_global_css, update_site_global_settings |
- 推荐设置:创建 两个OAuth应用程序 同一组织的LumApps中:一个 all.read (供最终用户搜索和检查),一个带有 all.admin (用于CSS和小部件更新)。在中设置读取应用程序
LUMAPPS_READ_CLIENT_ID/LUMAPPS_READ_CLIENT_SECRET(或遗产LUMAPPS_CLIENT_ID/LUMAPPS_CLIENT_SECRET)以及中的管理应用程序LUMAPPS_ADMIN_CLIENT_ID/LUMAPPS_ADMIN_CLIENT_SECRET服务器将使用read应用程序读取工具,使用admin应用程序修改工具;令牌按用户和配置文件缓存。 - 只读部署:如果您只设置了读取凭据, 检查和修改工具不起作用.
inspect_lumapps_element,update_global_css,update_widget_style和update_site_global_settings需要管理员应用程序;在没有管理员凭据的情况下调用它们将返回一个明确的错误。 - 单个令牌(测试):如果您设置
LUMAPPS_ACCESS_TOKEN,该令牌用于读取和管理;不需要单独的管理员凭据。令牌必须具有您使用的工具所需的范围(如果您调用修改工具,则为管理范围)。
______________________________________________________________________
跑步
本地
uvicorn app.main:app --reload --port 8000- API
- 文件:
- MCP端点(流式HTTP):
码头工人
docker compose up --build仅构建生产映像(多阶段、非根):
docker build -t lumapps-mcp-server:latest .
docker run --rm -p 8000:8000 --env-file .env lumapps-mcp-server:latest连接客户端:
- 光标 (本地):使用URL
http://localhost:8000/mcp密钥设置在MCP_API_KEY. - 副驾驶工作室 无法使用本地主机;它需要一个 公共URL.选项:
- 生产:在真实环境(例如Azure、AWS)上托管服务器,并使用该公共基础URL+ /mcp 在Copilot工作室。
Kubernetes(企业/本地)
服务器是容器化的,用于编排部署。使用清单 k8s/ 在集群内部部署。
- 构建并推送图像 (根据需要替换注册表/命名空间):
docker build -t your-registry/lumapps-mcp-server:latest .
docker push your-registry/lumapps-mcp-server:latest- 配置:
- 编辑 k8s/configmap.yaml 和你一起 LUMAPPS_ORG_ID, LUMAPPS_HAUSSMANN_CELL以及其他非秘密设置。 - 使用真实凭据创建密钥(不要提交)。选项: - 内联:替换中的占位符 k8s/secrets.yaml 具有实际价值(使用 stringData 对于纯文本),则 kubectl apply -f k8s/secrets.yaml. - 推荐:从文字或秘密管理器创建秘密,这样凭据就永远不会接触到仓库:\ kubectl create secret generic lumapps-mcp-secrets --from-literal=MCP_API_KEY=... --from-literal=LUMAPPS_READ_CLIENT_ID=... --from-literal=LUMAPPS_READ_CLIENT_SECRET=...\ 添加 LUMAPPS_ADMIN_CLIENT_ID / LUMAPPS_ADMIN_CLIENT_SECRET 如果你使用修改工具。
- 部署:
- 更新 k8s/deployment.yaml 如果不使用,请将图像添加到注册表URL lumapps-mcp-server:latest 当地。 - 按顺序申请: kubectl apply -f k8s/configmap.yaml, kubectl apply -f k8s/secrets.yaml, kubectl apply -f k8s/deployment.yaml, kubectl apply -f k8s/service.yaml.
- 探针:部署使用
/health为了活泼和/ready准备就绪。根据您的环境要求,通过Ingress或LoadBalancer公开服务。
证书留在你的范围内;尽可能使用现有的秘密管理(例如外部秘密、保险库)。
______________________________________________________________________
暴露的MCP工具
| 工具 | 描述 | 级别 | LumApps凭据 |
|---|---|---|---|
search_content | 搜索LumApps内容(标题、摘录、, content_id) | 阅读 | 阅读(全部阅读) |
get_content_body | 获取完整的文章正文 content_id | 阅读 | 阅读 |
find_person | 在目录中搜索人员 | 已读 | 已读 |
get_useful_links | 搜索有用的链接(目录条目:培训、IT、培训等) | 阅读 | 阅读 |
search_site | 列出或搜索LumApps站点(实例)以进行发现和用户确认 | 阅读 | 阅读 |
inspect_lumapps_element | 检查页面布局或站点全局CSS(仅限API);准备编辑 | 内容 | 管理员(可以编辑/站点管理员) |
update_global_css | 更新站点全局CSS | Structural | admin(all.admin) |
update_widget_style | 更新页面上的小部件样式 | 内容 | admin+canEdit |
update_site_global_settings | 更新网站页脚HTML和/或页眉脚本 | 结构化 | 管理员 |
- 水平:RBAC敏感性。 阅读 =任何经过身份验证的用户。 内容 =页面/网站上的贡献者或管理员(检查+小部件样式)。 结构性的 =仅限站点管理员(全局CSS、全局设置)。
- LumApps凭据: 阅读-水平工具使用 读 应用程序。 内容 (
inspect_lumapps_element,update_widget_style)以及 结构性的 工具使用 管理员 应用程序(LUMAPPS_ADMIN_CLIENT_ID/LUMAPPS_ADMIN_CLIENT_SECRET)当配置时。看 读取与管理员凭据.何时 用户级RBAC 如果已启用,API键无法单独运行内容或结构工具。
修改工具操作规则
的工具模式 update_widget_style, update_global_css 和 update_site_global_settings 指示AI遵守严格的规则,未经用户同意,不得进行任何更改:
- 始终运行
inspect_lumapps_element第一 --为了准确content_id/widget_id或者在更改CSS之前针对正确的元素。 - 向用户展示修改 --描述或显示将要更改的内容(除非有用,否则不需要公开原始JSON或CSS)。
- 等待明确确认 --在用户在聊天中回答“是”或“确认”(或等效)之前,不要调用该工具。
- 永远不要默默地应用更改 --人工智能在未获得确认的情况下不得调用这些工具。
这些规则嵌入到工具中 description 在MCP模式中,以便助手(Copilot Studio、Cursor等)读取它们并相应地进行操作。使用 search_site 在运行修改工具之前,列出可用的网站并询问用户使用哪一个(例如“我找到了‘Sustainability Global’和‘Sustainable France’;你想修改哪一个?”)。
______________________________________________________________________
MCP资源
作为MCP资源公开的静态或半静态文档(客户端可以直接列出并读取它们以获取上下文):
| URI | 描述 |
|---|---|
lumapps://lumapps-mcp-server/css-variables | LumApps CSS变量引用(静态文档)。 |
lumapps://lumapps-mcp-server/layout-and-widget-styling | 布局(行、单元格、粘性)、行/单元格和小部件样式(间距、边框、背景、页眉/页脚、悬停)。 |
lumapps://lumapps-mcp-server/style-and-theme | 网站样式(主题):结构、属性、样式表、页脚/页眉、样式/保存流。 |
lumapps://lumapps-mcp-server/customizations-api | 自定义API:JavaScript(目标、位置、组件)和CSS(锚、最佳实践)。 |
内容存储在 app/resources/ 并且可以在不改变代码的情况下进行更新。
______________________________________________________________________
安全
- MCP身份验证:双模式。
- OIDC优先 (默认):发送 Authorization: Bearer 来自您的IdP(Azure AD、Okta、Ping等)。服务器验证JWT(签名、颁发者、受众、到期),并将每个工具调用绑定到经过验证的用户; user_email 取自令牌声明,不得被客户端覆盖。 - API密钥回退:当 AUTH_ALLOW_API_KEY_FALLBACK=true,您仍然可以使用 X-API-Key, Authorization: Bearer ,或查询 apiKey / token 随着 MCP_API_KEY。仅适用于生产SSO,设置 AUTH_ALLOW_API_KEY_FALLBACK=false.何时 用户级RBAC 已启用,API密钥单独为 只读:内容和结构工具被拒绝,需要OIDC身份。
- 根端点:
GET /未经身份验证(仅供参考)。POST /仅在经过身份验证时接受JSON-RPC(与/mcp). - 秘密:没有硬编码的秘密;一切都来自配置(
pydantic-settings+.env). .env:仅用于地方发展;不得进行版本控制。在生产中使用环境变量或机密存储。
用户级RBAC
服务器强制执行 用户级 角色检查,以便在使用AI代理时尊重LumApps治理。当 RBAC_USE_LUMAPPS_NATIVE=true (默认),权限基于 LumApps原生API 和 OIDC,避免依赖单个“all.admin”令牌:
- 全局管理员(平台): Lumpps用户令牌 payload(通过模拟获得的令牌)必须包含
isOrgAdmin: true(可通过以下方式配置RBAC_ORG_ADMIN_CLAIM).该令牌由OAuth2客户端凭据+用户电子邮件生成;这一说法来自LumApps,而不是OIDC JWT。 - 站点管理员(结构工具):PPS
GET service/front-init?fields=user回报user.instancesSuperAdmin(用户为管理员的站点ID)和user.isSuperAdmin。用户必须在该列表中(或isSuperAdmin)forupdate_global_css和update_site_global_settings. - 内容编辑器(内容工具):PPS
GET content/get?uid=...&fields=canEdit返回用户是否可以编辑该页面。用于inspect_lumapps_element和update_widget_style当针对特定内容时;当只针对一个站点时(例如检查全局CSS),需要站点管理员。
阅读工具 对任何经过身份验证的用户(API密钥或OIDC)保持可用。如果LumApps在写入时返回401/403,服务器将返回一条安全的、对治理友好的消息。在本机模式下,如果无法获得用于RBAC检查的LumApps用户令牌,则拒绝访问(失败关闭)。短暂缓存可解决 content_id → site_id 用于小部件更新。
当 RBAC_USE_LUMAPPS_NATIVE=false,服务器将回退到 OIDC角色模式 (RBAC_ADMIN_PATTERNS, RBAC_CONTRIBUTOR_PATTERNS, RBAC_GLOBAL_ADMIN_PATTERNS)与 {site_id} 替代。
为RBAC回退配置OIDC
当使用回退(角色没有LumApps API)时,服务器读取 角色声明 从JWT(默认值: groups)并将其值与配置的模式进行匹配。配置您的IdP(Azure AD、Okta、Ping等),使令牌包含正确的值:
| 目标 | 索赔(默认 groups)必须包含 | 示例值 |
|---|---|---|
| 全局管理员 (所有工具) | 其中之一 RBAC_GLOBAL_ADMIN_PATTERNS | lumapps:site:*:admin 或 lumapps:global:admin |
| 站点管理员 (网站的结构工具) | 混凝土图案 site_id 从 RBAC_ADMIN_PATTERNS | lumapps:site:abc123:admin |
| 贡献者/内容 (网站的内容工具) | 模式来自 RBAC_CONTRIBUTOR_PATTERNS | lumapps:site:abc123:contributor 或 lumapps:site:abc123:admin |
- 索赔名称:设置
RBAC_ROLE_CLAIM持有该列表的索赔(例如。groups,roles,或定制索赔,如lumapps_roles). - 花样格式:图案使用
{site_id}作为占位符。服务器将其替换为目标站点ID,并检查 精确匹配 在索赔价值中。对于全局管理员,使用不带占位符的文字值(例如。lumapps:site:*:admin). - IdP设置:在Azure AD中,将LumApps站点/角色数据映射到组成员资格或自定义声明(例如通过声明映射策略或SAML/SCIM)。在Okta中,使用组或自定义声明。确保令牌实际上包含以下字符串
lumapps:site::admin对于用户为管理员的每个站点。
示例:对于网站管理员用户 prod-portal 现场贡献者 marketingJWT声称(例如。 groups)应至少包括 lumapps:site:prod-portal:admin 和 lumapps:site:marketing:contributor (或 lumapps:site:marketing:admin).
SSO/OIDC(企业)
要使用公司SSO并将每个操作与经过验证的人类身份联系起来:
- 集
OIDC_ISSUER_URL向您的IdP发行人(例如。https://login.microsoftonline.com//v2.0用于Microsoft Entra ID)。 - 可选设置
OIDC_DISCOVERY_URL如果发现不在{OIDC_ISSUER_URL}/.well-known/openid-configuration. - 集
OIDC_AUDIENCE和OIDC_CLIENT_ID到IdP在令牌中期望的值aud索赔。 - 配置
OIDC_EMAIL_CLAIM和OIDC_USERNAME_CLAIM如果您的IdP使用不同的索赔名称(默认值:email,preferred_username). - 让MCP客户端(Copilot Studio、Cursor等)获取当前用户的身份令牌,并将其作为
Authorization: Bearer每一个请求。
然后,服务器使用令牌的声明来解决 user_email 对于LumApps;客户提供 user_email 当工具中的参数与标记不匹配时,会被忽略或拒绝。这符合GDPR/SOC2对用户身份识别和撤销的要求。
______________________________________________________________________
演示
视频在 assets/videos/ (使用Git LFS跟踪)。主要回顾:
Your browser does not support the video tag.
| 功能 | 视频 |
|---|---|
| 搜索 | 01-深度内容搜索.mp4 |
| 人们 | 02-人群探索.mp4 |
| 链接 | 03-smart-intent-links.mp4 |
| 起草 | 04-ai内容起草.mp4 |
| 设计 | 05-发动机视觉布局.mp4 |
| 建筑师 | 06-全球架构.mp4 |
______________________________________________________________________
测试
身份验证和终点回归测试已上线 tests/。使用以下命令运行它们:
pip install -r requirements.txt
python -m pytest tests/ -v需要最小环境变量(或默认值) tests/conftest.py): MCP_API_KEY, LUMAPPS_ORG_ID,LumApps读取凭据以启动应用程序。
______________________________________________________________________
更多文件
- 使用devtunnel和MCP检查员进行测试 --在隧道后面运行并使用MCP检查器。
______________________________________________________________________
许可证
这个项目是开源的 Apache许可证2.0.
______________________________________________________________________
贡献
欢迎投稿(问题、拉取请求)。请阅读 贡献.md 了解如何在提交之前使用MCP检查器测试您的更改。对于较大的更改,请先打开一个问题进行讨论。
______________________________________________________________________
_免责声明:这是一个社区驱动的项目,与LumApps没有正式联系或认可。_
