LumApps MCP服务

连接LumApps API与AI助手的MCP协议服务器,提供内容搜索、文章检索、目录查询等功能,适用于企业内部知识库管理。

  • by Wheatfield-STUDIO
  • Python
  • 本地部署
  • 5 星标
  • 更新于
在 GitHub 查看 Wheatfield-STUDIO/mcp-server-lumapps

使用说明

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/<your-org>/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

配置

  1. 复制示例文件并设置变量:
cp .env.example .env
# Edit .env with your values (see below)
  1. 必需变量:

    • 认证:要么 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 (用于测试)。
  2. 可选变量:

    • 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

码头工人

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.选项:
    • 隧道 (dev或demo):公开服务器 devtunnel 或 吸烟,然后设置 MCP_PUBLIC_URL 在 .env 并使用隧道URL(例如。 https://xxxx.devtunnels.ms/mcp)在Copilot工作室。看 使用devtunnel和MCP检查员进行测试.
    • 生产:在真实环境(例如Azure、AWS)上托管服务器,并使用该公共基础URL+ /mcp 在Copilot工作室。

Kubernetes(企业/本地)

服务器是容器化的,用于编排部署。使用清单 k8s/ 在集群内部部署。

  1. 构建并推送图像 (根据需要替换注册表/命名空间):

    docker build -t your-registry/lumapps-mcp-server:latest .
    docker push your-registry/lumapps-mcp-server:latest
    
  2. 配置:

    • 编辑 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 如果你使用修改工具。
  3. 部署:

    • 更新 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.
  4. 探针:部署使用 /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遵守严格的规则,未经用户同意,不得进行任何更改:

  1. 始终运行 inspect_lumapps_element 第一 --为了准确 content_id/widget_id 或者在更改CSS之前针对正确的元素。
  2. 向用户展示修改 --描述或显示将要更改的内容(除非有用,否则不需要公开原始JSON或CSS)。
  3. 等待明确确认 --在用户在聊天中回答“是”或“确认”(或等效)之前,不要调用该工具。
  4. 永远不要默默地应用更改 --人工智能在未获得确认的情况下不得调用这些工具。

这些规则嵌入到工具中 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 <user-id-token> 来自您的IdP(Azure AD、Okta、Ping等)。服务器验证JWT(签名、颁发者、受众、到期),并将每个工具调用绑定到经过验证的用户; user_email 取自令牌声明,不得被客户端覆盖。
    • API密钥回退:当 AUTH_ALLOW_API_KEY_FALLBACK=true,您仍然可以使用 X-API-Key, Authorization: Bearer <static-key>,或查询 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)for update_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:<siteId>:admin 对于用户为管理员的每个站点。

示例:对于网站管理员用户 prod-portal 现场贡献者 marketingJWT声称(例如。 groups)应至少包括 lumapps:site:prod-portal:admin 和 lumapps:site:marketing:contributor (或 lumapps:site:marketing:admin).

SSO/OIDC(企业)

要使用公司SSO并将每个操作与经过验证的人类身份联系起来:

  1. 集 OIDC_ISSUER_URL 向您的IdP发行人(例如。 https://login.microsoftonline.com/<tenant>/v2.0 用于Microsoft Entra ID)。
  2. 可选设置 OIDC_DISCOVERY_URL 如果发现不在 {OIDC_ISSUER_URL}/.well-known/openid-configuration.
  3. 集 OIDC_AUDIENCE 和 OIDC_CLIENT_ID 到IdP在令牌中期望的值 aud 索赔。
  4. 配置 OIDC_EMAIL_CLAIM 和 OIDC_USERNAME_CLAIM 如果您的IdP使用不同的索赔名称(默认值: email, preferred_username).
  5. 让MCP客户端(Copilot Studio、Cursor等)获取当前用户的身份令牌,并将其作为 Authorization: Bearer <token> 每一个请求。

然后,服务器使用令牌的声明来解决 user_email 对于LumApps;客户提供 user_email 当工具中的参数与标记不匹配时,会被忽略或拒绝。这符合GDPR/SOC2对用户身份识别和撤销的要求。


演示

视频在 assets/videos/ (使用Git LFS跟踪)。主要回顾:

功能 视频
搜索 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读取凭据以启动应用程序。


更多文件


许可证

这个项目是开源的 Apache许可证2.0.


贡献

欢迎投稿(问题、拉取请求)。请阅读 贡献.md 了解如何在提交之前使用MCP检查器测试您的更改。对于较大的更改,请先打开一个问题进行讨论。


免责声明:这是一个社区驱动的项目,与LumApps没有正式联系或认可。