20-mcp-credentials.md 3.3 KB

20 MCP 凭据

状态:已实施(2026-11-04)。补充 ADR-0021(第三方 MCP 服务)。

1. 问题

每个 MCP 服务各自保存请求头(mcp_servers.headers)或环境变量(env)。同一个后端提供多个 MCP 服务时,令牌要在每个服务里重复填写;更换令牌时要逐个修改。

2. 方案

凭据是一组命名的密钥值,服务引用而不是复制:

字段 说明
名称、说明 名称唯一
类型 http:请求头,用于远程服务;stdio:环境变量,用于本地进程
值 若干键值(如 Authorization: Bearer …),保存后不再返回明文
适用地址 仅 http:若干地址前缀;不填表示可用于任意地址
  • 服务增加 credential_id。连接时合并:{ ...凭据的值, ...服务自己的值 },同名以服务自己填写的为准。
  • 合并发生在 McpServerService 交给连接层之前(rows()、列工具、测试连接),连接层的连接键包含合并后的值:凭据修改后,下次使用自动按新值重新连接;修改值时还会主动刷新使用它的服务。
  • 凭据只在服务端使用;新建、修改、删除记入审计(只记名称、键名与适用地址,不记值)。

3. 适用地址(前缀匹配)

  • 规范化:只接受 http / https,不能带查询参数、片段、用户名;协议与主机小写。
  • 匹配:协议、主机、端口完全相同;路径按段匹配——https://a.com/mcp 匹配 /mcp、/mcp/orders,不匹配 /mcp2;https://a.com 不匹配 https://a.com.evil.com。
  • 服务端强制:http 服务只能选择适用地址包含其地址的凭据;修改凭据的适用地址时,若有使用它的服务不再匹配则拒绝;连接时再次检查,不匹配时不合并。
  • 没有适用地址的凭据可用于任意地址,后台选择时提醒确认服务地址可信。

4. 后台

  • "MCP 服务"页增加"凭据"一栏:列出类型、键名、适用地址、使用它的服务;正在使用的凭据不能删除、不能改变类型。
  • 添加服务时有"凭据"下拉框(只列类型一致的凭据,地址不匹配的不可选)。新建服务时按地址自动选择:正好有一个限定了适用地址的凭据匹配时选中它;手动选择后不再自动改动。
  • 编辑已有服务时可以"把这个服务的请求头 / 环境变量保存为凭据":用已保存的值新建凭据(默认适用地址为服务地址的协议 + 主机),服务改为引用它,自己的请求头 / 环境变量清空。
  • 接口:POST /admin/v1/mcp/credentials、PUT|DELETE /admin/v1/mcp/credentials/:id、POST /admin/v1/mcp/servers/:id/save-credential;GET /admin/v1/mcp 返回 credentials。

5. 不包括

OAuth 授权的服务:令牌与各自的授权流程绑定,按服务保存,不纳入凭据。

6. 实施记录

  • services/mcp-credentials.ts(凭据、前缀匹配、合并、保存为凭据),services/mcp-servers.ts 在连接前合并;迁移 0022_mcp_credentials。
  • 后台 McpView.vue。
  • 测试 test/mcp-credentials.test.ts:前缀匹配与规范化、引用凭据连接、同名覆盖、地址 / 类型限制、更换令牌后重新连接、保存为凭据、本地进程的环境变量。