选择配置与生效方式
本参考对应 v2.4.0。YAML 只允许一个文档,未知字段会被拒绝。不要把管理 API 的 JSON 对象直接粘贴为 YAML:例如 YAML 的 headers 是键值映射,API 的 headers 是对象数组;enabled 是托管 backend 的 API 字段,不是 YAML backend 字段。HTTP 工具组及 OpenAPI 导入只能通过控制台/API 管理。
| 场景 | 从哪里开始 | 需要准备 |
|---|---|---|
| 默认本地管理台 + SQLite | 默认模板、启动步骤 | 网关 URL、加密密钥两个变量;在 UI 添加后端 |
| 高级纯 YAML 部署 | 独立示例 | 在 YAML 逐个填写后端地址与凭证,显式发布已审核的只读工具 |
| 本机管理、SQLite | 完整配置文件、启动步骤 | 网关 URL、固定加密密钥 |
| 团队远程管理 | 部署示例与变量清单 | 管理 URL、SQLite 或 PostgreSQL、HTTPS 代理;企业身份可选 |
| SSO / Vault 个人账号 | SSO、Vault | 在托管配置上增加所需模块;飞书示例还需真实租户验收 |
| 配置 | 修改位置 | 如何生效 |
|---|---|---|
server.listen、server.public_url、全部 auth、admin、client_authorization、vault |
YAML / 服务环境 | 重启;SIGHUP 拒绝这些字段的变化 |
其他 server 字段 |
YAML | SIGHUP,见热重载 |
backends(未启用 admin) |
YAML | SIGHUP;至少需要一个后端 |
backends(已启用 admin) |
首次从 YAML 导入,以后使用控制台/API | 空数据库只导入一次;之后 YAML backend 修改和其变量不会覆盖数据库 |
| HTTP 工具组、OpenAPI、用户权限、客户端授权记录 | 控制台/用户门户/API | 保存或完成所需审批后生效;不通过 YAML 导入 |
管理模式也始终严格解析 YAML;已忽略的 backend 中出现未知字段仍会报错。不要删除数据库来强制重新导入:其中还保存工具组、授权和审计等数据。
环境变量与 Secret
${NAME} 只在下表列出的字段展开,不是所有字符串都支持。变量从 MCPHub 进程环境读取;shell 中另行 export 不会改变已运行服务的环境,轮换时应更新服务环境并重启。MCPHub 不自动加载 .env。
| 支持展开的位置 | 具体字段 |
|---|---|
server、auth |
server.listen、public_url、allowed_origins[];auth.issuer |
admin |
listen、mode、public_url、client_id、client_secret_env、database_driver、database_dsn_env、database_path、encryption_key_env、required_scopes[] |
admin.approvals |
required_scopes[]、step_up_acr_values[];policy_changes.required_scopes[]、policy_changes.subjects[];notifications.url、notifications.secret;audit_archive.url、audit_archive.signing_key、audit_archive.key_id |
client_authorization |
client_id、client_secret_env |
YAML backends[] |
id、url、headers 的值、required_scopes[]、published_tools[];oauth 的全部字符串字段与 scopes[] |
YAML backends[].tool_rules[] |
match、required_scopes[];resource_rules[].argument、allowed_values[] |
auth.sso.*、vault.*、backends[].credentials.*、tool_rules[].approval.* 和 effect 不展开;请填写实际字面值。duration、数字、布尔字段也不支持占位符。变量名只接受 [A-Za-z_][A-Za-z0-9_]*;未设置的受支持变量会报错。${NAME:-default}、$NAME 不是默认值/替换语法,可能保留为字面量,不要使用。
*_env 字段存放的是环境变量名,不是 Secret 本身:
# 片段:两种写法用途不同,请放在各自配置段。
admin:
encryption_key_env: MCPHUB_CONFIG_KEY # 从这个变量读取 Base64 编码的 32 字节密钥。
# 后端凭证在 UI 中按服务分别配置。
不要写 encryption_key_env: ${MCPHUB_CONFIG_KEY},否则会把密钥值误当变量名。数据库加密密钥只生成一次,备份和重启保留原值。SSO/Vault 同样通过各自的 *_env 引用 Secret,值由服务管理器或 Secret store 注入。
required: false 只允许后端连接失败;该 backend 的 URL、OAuth 字段和受支持环境变量仍须完整有效。它不是“禁用配置”。不使用某个 YAML backend 时,应从当前配置移除该条目。
server
| 字段 | 默认值 | 说明 |
|---|---|---|
listen |
:8080 |
HTTP 监听地址。SIGHUP 不可修改,修改后需重启。 |
public_url |
无 | 必填的绝对 HTTPS URL,必须包含 MCP 路径(例如 https://hub.example.com/mcp),不能有 query 或 fragment。路径不能含 percent-encoded 字符,也不能是 /healthz、/readyz 或 /.well-known/oauth-protected-resource。它既是 MCP 地址,也是 JWT 的 audience。SIGHUP 不可修改。 |
page_size |
1000 |
聚合 MCP 目录分页大小,必须大于 0。 |
request_timeout |
60s |
普通请求与后端调用的默认超时;必须大于 0。长连接订阅在请求体读取后使用独立生命周期,见下方说明。 |
drain_timeout |
15s |
SIGTERM/SIGINT 关停,以及 SIGHUP 替换旧运行时等待活动请求的最长时间;必须大于 0。 |
refresh_interval |
5m |
后端目录刷新的最大间隔;后端返回更短 TTL 时会提前刷新,最终间隔不会低于 5 秒。必须大于 0。 |
catalog_ttl |
30s |
对 MCP 目录/发现结果声明的 private TTL;允许为 0,但不能为负数。 |
max_request_body_bytes |
4194304(4 MiB) |
MCP POST body 上限,超出返回 413;必须大于 0。 |
allowed_origins |
[] |
额外允许的浏览器 HTTPS Origin。每项只能是 https://authority,不允许路径、query、fragment、通配符;MCPHub 自身 public_url 的 origin 自动允许。 |
duration 使用 Go time.ParseDuration 语法,例如 500ms、60s、5m。public_url 的路径就是 MCP 入口路径;上例入口为 /mcp。路径中的 percent-encoded 字符会被拒绝,/healthz、/readyz 和 /.well-known/oauth-protected-resource 是保留路径。
请求超时与长连接订阅的具体行为
普通 MCP 请求和后端调用的默认超时;必须大于 0。MCP 监听器的所有 HTTP 路由在 request body 被消费或关闭前都使用该值作为读取 deadline,未认证或被拒绝请求的慢 body 也会有界结束。MCP 处理继续后,普通 MCP POST 还会用它设置 response 写入 deadline 和 request context;新版 subscriptions/listen POST 在 body 读完后保持长连接,不使用普通的 response 写入和 request context timeout。但 runtime 或 client context 取消仍会让底层 write deadline 立即到期,因此代际 drain 或 client 断开时,慢 subscription write 会被打断。
vault
可选;启用后要求托管数据库。address 必填,mount 默认 secret,prefix 默认 mcphub,auth_mount 默认 approle。使用 role_id_env + secret_id_env,或单独的 token_env,两种方式互斥。全部字段是字面值,不展开 ${...};所有全局 Vault 配置修改后需重启。
凭证引用放在 backends[].credentials。个人模式还要求用户门户及 该 backend 自身的 require_client_grant: true;只开全局严格模式不能替代此字段的配置校验。完整的字段、路径、权限和回调见 Vault 专题。
admin
默认模板启用管理平台,通过独立监听器提供嵌入式 UI 和 JSON API;本地模式仅回环访问并要求内建账号登录,远程模式通过 HTTPS 使用内建账号或可选企业认证。它管理 backend 和工具组配置;进程配置仍由 YAML 管理,哪些字段可热重载见生效方式表。
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled |
false |
启用管理平台,并让所选数据库成为配置事实来源。 |
mode |
local |
local 仅本机;内建模式仍要求账号登录。remote 经 HTTPS 使用内建或企业管理员认证。 |
listen |
127.0.0.1:8081 |
本地模式必须是数字回环地址;远程模式可监听私有地址,外部需 HTTPS 代理。 |
public_url |
无 | 远程模式必填,HTTPS origin,不带路径或尾部 /;同时作为管理员 JWT audience。 |
client_id |
内建模式 mcphub-admin |
管理台浏览器 OAuth 客户端 ID。 |
client_secret_env |
无 | 可选机密客户端的 secret 环境变量名;默认使用公开客户端。 |
required_scopes |
[mcphub:admin] |
内建和远程管理所需的全部 scope,不允许空列表。 |
database_driver |
sqlite |
sqlite 或 postgres。 |
database_dsn_env |
MCPHUB_DATABASE_URL |
PostgreSQL 连接串所在的环境变量;使用 PostgreSQL 时不能同时设置 database_path。 |
database_path |
无 | SQLite 启用时必填;相对路径以 YAML 文件所在目录解析。 |
encryption_key_env |
MCPHUB_CONFIG_KEY |
保存 Base64 编码 32 字节 AES 密钥的环境变量名;丢失或改变密钥会导致已存 Secret 无法解密。 |
request_retention |
720h(30 天) |
已完成 MCP POST 请求历史的保留期,范围 24h–8760h;到期记录自动清理。诊断与导出见管理员手册。 |
空数据库首次启动时,MCPHub 会在一个事务中导入展开后的 YAML backends。bootstrap 标记写入后,所选数据库成为唯一 backend 来源,之后修改 YAML backend 不再生效。Header 值和 OAuth client secret 使用 AES-256-GCM 加密,管理 API 永不返回明文。SQLite 在读改写事务读取前取得写锁;并发本机管理最多等待 5 秒,超时返回失败,不重放变更。
默认 UI 地址为 http://127.0.0.1:8081/,可以在不中断进程的情况下注册、测试、编辑、启停和删除后端。Required 后端连接失败时变更会被拒绝,当前 runtime 不受影响;optional 后端不可用时可以保存,并在后台持续重连。
JSON API 位于 /api/v1。单项 backend 响应携带 ETag;更新和删除必须通过 If-Match 提交该 revision,过期写入返回 409 revision_conflict。Secret 字段只返回是否已配置;编辑时省略 Secret 值表示保留,省略对应 Header 或 OAuth 配置表示删除。审计 actor 为已认证用户的内部 subject、无身份高级本地管理的 local 或后台刷新 system,只记录脱敏结果。
其他配置专题
| 配置块或任务 | 参考 |
|---|---|
auth.sso、本地用户授权、部门/组同步与管理员恢复 |
SSO 与用户管理 |
client_authorization、门户回调与强制客户端授权 |
管理员手册:启用客户端授权 |
vault、backends[].credentials、共享/个人账号 |
Vault 配置与运维 |
| HTTPS、远程管理与数据库 | 部署指南 |
| 完整 YAML | 基础示例、远程 SQLite、远程 PostgreSQL |
从完整 YAML 示例启动
默认 config.example.yaml 与 v2.4.0 服务端发行包、在线模板一致:本地管理台、SQLite、backends: []。它只要求 MCPHUB_PUBLIC_URL 和 MCPHUB_CONFIG_KEY,后端地址与认证凭证在 UI 中按服务配置。
在新的私有部署目录中下载模板并启动,替换两个 HTTPS 地址:
curl -fL https://samuelsupe.github.io/mcphub/examples/config.example.yaml -o config.yaml
export MCPHUB_PUBLIC_URL=https://hub.example.com/mcp
umask 077
mkdir -p secrets
test -f secrets/config.key || openssl rand -base64 32 > secrets/config.key
export MCPHUB_CONFIG_KEY="$(cat secrets/config.key)"
mcphub validate --config config.yaml
mcphub init-admin --config config.yaml
mcphub serve --config config.yaml
打开 http://127.0.0.1:8081/,按 启动管理台 → 添加后端 → 测试连接 → 发布工具 操作。每个后端分别填写服务地址和 Header/OAuth 凭证;只发布明确分类为 read 的已审核工具,并配置所需 scope。使用同一个密钥重启后,服务配置、凭证和工具权限从 SQLite 恢复。
validate 是只读配置检查,不验证身份登录、后端连接或实际工具调用。serve 初始化新数据库。检查 /healthz、/readyz,然后按部署验收实际调用工具。
远程管理员使用远程模板,补充管理员 origin、身份客户端和 scope;纯 YAML 部署使用独立的高级示例,在文件中按后端填写实际地址、凭证、发布名单及只读策略。
用户不保存直接权限。在「用户与组」创建组,为组分配角色、Scope、工具和资源权限,再把用户加入组。初始化会创建 Administrators 管理员组。身份 API 的用户成员关系更新与组权限更新分别使用不同正文,见组管理和接口契约。
命名与 URI 映射
- 工具和 prompt 对外名称为
<backend-id>.<原名>。原名必须匹配[A-Za-z0-9_.-]{1,128};拼接命名空间后超过 128 个字符时,会在保留 backend 前缀的前提下截断并追加原名 SHA-256 的短后缀。非法元数据和映射后的冲突项会被省略,并记录日志。 - 静态资源和结果中的
ResourceLink/embedded resource 统一编码为mcphub://<backend-id>/r/<base64url-no-padding(original-uri)>。MCPHub 收到该 URI 后解码并向对应后端读取;结果中的资源 URI 会递归改写。 - 资源模板编码为
mcphub://<backend-id>/t/<sha256(original-template)>,并保留 URI 模板变量的 query 表达式(例如{?id})。读取和 completion 会把公开模板还原为后端原始模板。 - 后端 tool、prompt 或 resource 结果中的
ResourceLink、EmbeddedResource、ResourceContentsURI 会被改写,并按 backend 记录为已签发资源。只要 URI 摘要仍被保留,就可以继续 read 和 subscribe,但不会逐项加入公开的resources目录。每个 backend 最多保留 16,384 个不同的已签发 URI SHA-256 摘要;最旧摘要被淘汰后,该 URI 可能无法再被新 read 或 subscription 使用,但已有订阅的取消和 session 清理仍按 session 映射处理。resource updated通知不会创建目录项。 - 资源订阅按 upstream MCP session 跟踪并去重;后端按原始 URI 共享并做引用计数;未配对的取消订阅会忽略,session 关闭会清理,后端重连会恢复全部已跟踪订阅;backend protocol 支持该确认时,还要等待
notifications/subscriptions/acknowledged,全部完成后才标记 ready。确认中的 subscription ID 会映射回原订阅 URI;即使 2026 resource update 的 event URI 不同,也会向这些 URI 扇出。timeout、取消订阅以及 session/重连清理会删除映射。现代subscriptions/listenstream 取消或断连时,清理会脱离已取消的 upstream context,但仍受 backendrequest_timeout和 session lifecycle 约束,因此旧协议 backend 仍会收到resources/unsubscribe。任一恢复失败时 backend 保持 unavailable,连接循环会再次重试。
每个 token 的 scope 集合决定一个独立的后端 view;因此同一个 MCP 连接只会看到该 token 有权访问的能力。