TREK 管理员实战:MCP Access 面板全面管理 OAuth 会话与 API 令牌
2026/9/14 22:38:19 网站建设 项目流程

TREK 管理员实战:MCP Access 面板全面管理 OAuth 会话与 API 令牌

【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK

MCP Access 是 TREK 管理后台(Admin Panel)中用于集中管理全实例 MCP 接入凭证的核心面板:管理员可以查看任意用户的 MCP OAuth 会话与长期 API 令牌,并一键撤销、删除。本文以 wiki/Admin-MCP-Tokens.md 为骨架,结合 server/src/nest/admin/admin.controller.ts、server/src/services/adminService.ts、server/src/services/authService.ts 等源码,讲清两类凭证的差异、表格字段含义、操作背后的失效机制,以及trekoa_/trek_两种令牌前缀的来源。

MCP Access 面板:全实例 MCP 凭证总览

MCP Access面板(对应前端组件 client/src/components/Admin/AdminMcpTokensPanel.tsx)展示的是全实例范围内所有用户的活跃 MCP OAuth 会话与 API 令牌,而普通用户在个人设置中只能看到自己的令牌。作为管理员,你可以对它们执行撤销(revoke)和删除(delete)操作。

该面板有两个重要的前置条件:

  1. 仅当 MCP addon 启用时才可见:MCP 作为集成型 addon 存放在addons表中(id 为mcp,默认enabled = 0,见 server/src/db/migrations.ts),需先在 Admin-Addons 面板中启用它;
  2. 需要管理员权限:面板的读取与操作 API 都挂在 admin 命名空间下,受管理后台鉴权保护。

从源码看,面板背后是 4 个管理端接口(见 server/src/nest/admin/admin.controller.ts):

HTTP 接口方法作用
/admin/mcp-tokensGET列出所有用户的 MCP API 令牌
/admin/mcp-tokens/:idDELETE删除指定 MCP API 令牌
/admin/oauth-sessionsGET列出所有活跃的 OAuth 会话
/admin/oauth-sessions/:idDELETE撤销指定 OAuth 会话

前端通过 client/src/api/client.ts 中的adminApi.mcpTokens()adminApi.deleteMcpToken()adminApi.oauthSessions()adminApi.revokeOAuthSession()调用这些接口。

面板下方分为两个区块:OAuth SessionsAPI Tokens,二者代表 TREK 支持的两类 MCP 接入凭证。

OAuth Sessions:推荐的标准授权方式

OAuth 会话产生于用户通过OAuth 2.1 流程授权某个 MCP 客户端接入 TREK 之时,这是官方推荐、也是唯一支持细粒度权限的接入方式。

授权流程速览

从 server/src/mcp/oauthProvider.ts 的实现可以看到完整链路:

  1. MCP 客户端通过动态客户端注册(DCR,RFC 7591)注册自身,注册时校验redirect_uris:仅允许 HTTPS、loopback HTTP(localhost / 127.0.0.1 / ::1)或带点号的自定义私有 scheme,并拦截javascript:data:等危险 scheme(见 oauthProvider.ts);
  2. 用户被重定向到 TREK 的/oauth/consent授权同意页,携带client_idredirect_uriscopecode_challenge(S256 PKCE)等参数;
  3. 用户批准后,客户端用授权码 + code verifier 换取访问令牌与刷新令牌;TREK 在换取令牌时写入审计日志oauth.token.issue(见 oauthProvider.ts);
  4. 后续每次 MCP 请求携带访问令牌,由verifyAccessToken解析出对应用户、客户端与授权 scope 集合(见 oauthProvider.ts)。

表格列说明

OAuth Sessions 表格各列含义如下(与原文档一致):

说明
Client name已注册 OAuth 客户端的名称;其下方以徽章(badge)形式展示已授予的 scope,最多显示 6 个,超出部分显示 "+N more",点击可展开/收起(前端常量SCOPES_PREVIEW = 6,见 AdminMcpTokensPanel.tsx)
Owner授权该会话的用户名
Created会话建立日期
(操作)垃圾桶图标按钮,点击后弹出确认框,用于撤销会话

撤销会话及其底层联动

撤销操作流程:点击行内垃圾桶图标 → 确认弹窗 → 调用DELETE /admin/oauth-sessions/:id。服务端 adminService.ts 的处理是:

  1. oauth_tokens表中该记录的revoked_at置为当前时间;
  2. 调用revokeUserSessionsForClient(user_id, client_id)只关闭该用户与该客户端的 MCP 会话,不影响该用户其他客户端的会话;
  3. 写入审计日志,action 为admin.oauth_session.revoke(见 admin.controller.ts)。

会话被撤销后立即失效,该 MCP 客户端必须重新走一遍授权流程才能继续发请求。

前缀trekoa_与令牌存储安全

OAuth 访问令牌使用前缀trekoa_,刷新令牌使用trekrf_前缀。生成逻辑在 server/src/services/oauthService.ts:trekoa_+ 32 字节加密随机数(randomBytes(32))的 hex 编码。

安全存储方面,TREK 不落库明文令牌,而是只存 SHA-256 哈希(hashToken),并在校验时使用常量时间比较timingSafeEqualHex防时序攻击(见 oauthService.ts)。oauth_tokens表对access_token_hashrefresh_token_hash均建有唯一索引(见 migrations.ts)。

API Tokens:用户的长期静态令牌

API 令牌(MCP tokens)是用户在个人设置中自行创建的长期令牌,适合脚本化或 CLI 类客户端直接以 Bearer 方式携带,不需要走浏览器授权流程。它们以trek_前缀标识。

表格列说明

说明
Token name用户为令牌起的标签,下方以等宽字体显示其截断前缀(如trek_ab12c...
Owner创建该令牌的用户名
Created令牌创建日期
Last used最近一次使用该令牌发起 API 调用的日期;从未使用过则显示 "Never"
(操作)垃圾桶图标按钮,点击后弹出确认框,用于删除令牌

令牌的创建与限制(源码级)

用户在个人设置(Integrations 页)创建令牌时,服务端 authService.ts 施加以下规则:

  • 命名必填且不超过 100 字符
  • 每用户最多 10 个令牌,超出返回 400 错误;
  • 原始令牌为trek_+ 24 字节加密随机的 hex 编码;
  • 数据库仅保存 SHA-256 哈希与前 13 个字符的前缀rawToken.slice(0, 13)),用于界面展示与识别;
  • 原始令牌仅在创建响应中返回一次(raw_token字段),之后无法再查看。

表结构与唯一索引见 migrations.ts:mcp_tokens表含user_id(级联删除)、nametoken_hashtoken_prefixcreated_atlast_used_at

删除令牌

删除操作:点击垃圾桶图标 → 确认 → 调用DELETE /admin/mcp-tokens/:id。服务端 adminService.ts 的处理是:

  1. 校验令牌存在,不存在返回 404;
  2. mcp_tokens表物理删除该记录;
  3. 调用revokeUserSessions(token.user_id)终止该用户的全部活跃 MCP 会话(注意:这里比 OAuth 撤销更彻底,是所有会话,而不限于某个客户端)。

令牌一旦删除立即失效。如果用户仍需访问,必须回到个人设置中重新创建一个新令牌。

令牌验证与 Last used 更新

每当一个trek_令牌被用于 MCP 请求,服务端通过 verifyMcpToken 完成校验:对传入令牌做 SHA-256 哈希后查mcp_tokens表并 JOIN 用户表,命中即同步更新last_used_at,失败返回 null。这正是 "Last used" 列的数据来源。

撤销背后的会话联动机制

MCP 会话(即活跃的流式 HTTP 连接)与令牌一一对应,因此令牌撤销必须同步清理内存中的会话。这一联动由 server/src/mcp/sessionManager.ts 承担:

  • McpSession结构包含userIdscopesclientIdisStaticTokenlastActivity等字段,其中scopes为 null 表示静态trek_令牌(或 JWT),即全权限访问;为字符串数组则表示 OAuth 2.1 授权的作用域(见 sessionManager.ts);
  • revokeUserSessions(userId):遍历并关闭该用户的所有MCP 会话——删除trek_令牌时调用;
  • revokeUserSessionsForClient(userId, clientId):只关闭特定用户 × 特定 OAuth 客户端组合的会话——撤销 OAuth 会话时调用,避免误伤该用户其他客户端;
  • evictOldestSessionForUser:按lastActivity淘汰最久未使用的会话,保证单用户会话数有上限时不会因客户端丢失Mcp-Session-Id而彻底锁死集成(见 sessionManager.ts)。

同时值得注意的是,静态trek_令牌在 scopes.ts 中被明确定义为null scopes = static trek_ token = full access,即拥有完整权限;而 OAuth 会话的权限则受用户在同意页授予的 scope 约束。这也是文档推荐优先使用 OAuth 方式接入的原因——它支持最小权限授权,而静态令牌是"一刀切"的全权限凭证。

相关页面

  • MCP-Overview:MCP 整体架构与接入概念
  • MCP-Setup:客户端接入配置(OAuth / 静态令牌两种方式)
  • Admin-Panel-Overview:管理后台各面板总览
  • Admin-Addons:启用 MCP addon 的入口(面板可见前提)

【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询