managed-mcp.json 与白名单黑名单配置项在 Claude Code 中的角色分工(详解企业级 MCP 管控的叠加方式)
企业级 Claude Code 部署里,IT 管理员管 MCP 服务器通常用两套机制:一是 managed-mcp.json 这份“基线配置“,二是它内部的 allowedMcpServers 与 deniedMcpServers 两组名单。两者并不是同一份配置的不同字段,而是不同管控面:一个负责“提供/挂载“,一个负责“白名单/黑名单筛选“。它们可以叠加生效,且 deny 规则优先级高于 allow——同一台服务器同时被两条规则命中时,会被拒绝。
一、managed-mcp.json:组织级 MCP 基线
1.1 文件位置
managed-mcp.json 是一份“管理员下发“的 JSON 配置文件,由 IT 部署到客户端固定路径:
| 操作系统 | managed-mcp.json 路径 |
|---|---|
| macOS | /Library/Application Support/ClaudeCode/managed-mcp.json |
| Linux | ~/.config/ClaudeCode/managed-mcp.json |
| Windows | %APPDATA%\ClaudeCode\managed-mcp.json |
这份文件与用户级的 .mcp.json 并存,但优先级更高:用户无法删除、修改或禁用其中声明的 server,开发者的本地配置只能“追加“,不能“覆盖“。
1.2 它管什么
managed-mcp.json 既能直接挂载一组强制 server,也能定义名单策略。挂载 server 时结构与 .mcp.json 相同:
{
"mcpServers": {
"company-knowledge-base": {
"type": "http",
"url": "https://kb.internal.example.com/mcp",
"description": "内部知识库与文档检索"
},
"approved-database": {
"type": "stdio",
"command": "npx",
"args": ["@company/db-mcp-server"],
"env": { "DB_HOST": "readonly-replica.internal.example.com" }
}
}
}
这些 server 在每位开发者的 Claude Code 会话里自动出现,开发者无权移除。它们就像组织的“基础设施基线“——必须可用,必须统一。
二、allowedMcpServers / deniedMcpServers:白名单与黑名单
2.1 写在同一份文件里
名单字段也写在 managed-mcp.json 里,因此这份文件承担了“基线挂载 + 名单策略“两件事。结构是:
{
"allowedMcpServers": [
{ "serverName": "github", "serverUrl": "https://api.github.com/mcp" },
{ "serverName": "company-internal", "serverCommand": "company-mcp-server" }
],
"deniedMcpServers": [
{ "serverName": "untrusted-*" },
{ "serverUrl": "http://*" }
]
}
每条规则支持三种匹配方式:按 serverName、按 serverUrl、按 serverCommand(可执行命令)。serverName 字段支持通配符,常见做法是用前缀表达“某个家族“或“某个项目“。
2.2 它们管什么
allowedMcpServers:白名单。开发者本地.mcp.json里添加的 server 名字/URL/命令必须命中某条 allow 规则,否则无法连接。deniedMcpServers:黑名单。即使开发者本地声明了某个 server,只要命中 deny 规则就会被拦截。
只配置 allowedMcpServers 不配置 deniedMcpServers:白名单兜底,未列入名单的 server 一律无法连接。把 allowedMcpServers 设为空数组 [],相当于“只许用 managed-mcp.json 里挂载的 server,开发者不许加任何额外 server”。
三、两套机制的角色对照
| 维度 | managed-mcp.json 的 mcpServers | allowedMcpServers | deniedMcpServers |
|---|---|---|---|
| 角色 | 基线挂载 | 白名单筛选 | 黑名单筛选 |
| 影响对象 | 全员客户端 | 开发者自定义 server | 开发者自定义 server |
| 是否能“加“ | 能(直接挂载) | 否(只决定哪些“允许加“) | 否(只决定哪些“被禁“) |
| 是否能“禁“ | 否(管理员声明的不会因为名单消失) | 否 | 能(拒绝特定 server) |
| 匹配粒度 | 单 server 配置 | 名字/URL/命令 | 名字/URL/命令 |
| 典型场景 | 内部知识库、强约束数据库 | 允许 company-* 系列 |
屏蔽 *-experimental、所有 http:// |
注意:managed-mcp.json 里挂载的 server 自身不受 allowedMcpServers / deniedMcpServers 名单影响——它们是基线,已经“在内“,名单是用来管基线之外的 server 的。
四、它们能否叠加生效
答案是可以叠加,并且顺序与优先级有明确约定:
- managed-mcp.json 的 mcpServers:先被加载,对所有用户强制可用;
- allowedMcpServers:在开发者尝试加载本地 server 时生效,只有命中 allow 规则的 server 才被允许;
- deniedMcpServers:在 allow 之后生效,只要命中 deny 规则,无论是否在 allow 名单,都会被拒绝;
- 当同一台 server 同时被 allow 与 deny 命中,deny 优先。
这意味着:管理员可以同时表达“全员必须有 A/B/C”(managed-mcp.json)、”开发者可以加 D/E/F”(allowedMcpServers)、”禁止任何 experimental 名称“(deniedMcpServers)。三者分层独立,又通过优先级串成一条决策链。
4.1 一个典型的企业 lockdown 配方
{
"mcpServers": {
"company-knowledge-base": {
"type": "http",
"url": "https://kb.internal.example.com/mcp"
}
},
"allowedMcpServers": [
{ "serverName": "company-*" },
{ "serverName": "approved-*" }
],
"deniedMcpServers": [
{ "serverName": "*-experimental" },
{ "serverUrl": "http://*" }
]
}
效果:组织基线是 company-knowledge-base;开发者可以加 company-*、approved-* 系列;所有 *-experimental、所有 http:// 协议 server 全部禁止。http://localhost:xxx 这种明文本地端点也被一并封堵,需要走 https:// 或 stdio。
五、和用户级 .mcp.json 的关系
managed-mcp.json 与开发者本地的 ~/.claude.json / .mcp.json 是两条不同的配置链:
- 用户级
.mcp.json:开发者自己写的本地 MCP server 列表,跨项目共享。 - managed-mcp.json:组织下发的基线 + 名单策略,跨用户共享。
- 加载顺序:先 managed,后 user;managed 里的 server 永远可见,用户级 server 必须穿过 allow/deny 名单才能生效。
- 修改权限:managed 用户不能改;user 开发者可改,但受名单约束。
把这份关系记牢,在排障“为什么我加的 MCP server 没了“时第一时间能想到去查 allowedMcpServers/deniedMcpServers,而不是怀疑配置写错。
六、落地时的两个易错点
易错点 1:把名单当成“挂载“。allowedMcpServers 不会自动加载任何 server,它只决定“开发者能不能加载“。想给全员一份基线,必须在 mcpServers 字段里挂载,名单只是筛选层。
易错点 2:deny 规则的通配范围。* 通配写在 serverName 上是“名字匹配“,写在 serverUrl 上是“URL 模式匹配“,二者不要混淆。例如 { "serverUrl": "http://*" } 封的是 URL 前缀,而 { "serverName": "http-*" } 封的是“名字以 http- 开头的 server”,命中的是完全不同的对象。
到这里,企业级 MCP 管控的“基线 + 白名单 + 黑名单“三层模型就清晰了:managed-mcp.json 负责“装“什么,allowedMcpServers 负责“允许加“什么,deniedMcpServers 负责“必须挡“什么。三者叠加,deny 永远赢。
七、自检配置是否生效的三个动作
写完 managed-mcp.json 后,建议在客户端依次确认:
- 启动 Claude Code,观察 init 消息里是否列出
company-knowledge-base等基线 server; - 故意添加一个
*-experimental名称的本地 server,验证它被 deny 拦下; - 把
allowedMcpServers设为空数组,验证任何用户级 server 都无法加载。
把这三步加进 IT 上线 checklist,能在配置发出去的第一时间捕获规则漏洞。
常见问题(FAQ)
Q1:managed-mcp.json 必须是 IT 部署吗?开发者能自己写吗?
可以本地放,但文件路径在系统目录,企业部署通常由 MDM/集中配置工具下发,开发者无法篡改。
Q2:deniedMcpServers 能影响 managed-mcp.json 里挂载的 server 吗?
不能。基线 server 一律放行,名单只对开发者自定义 server 生效。
Q3:把 allowedMcpServers 设为空数组会怎样?
开发者无法添加任何 server,整个环境只能使用 managed-mcp.json 里声明的基线,达到最严格 lockdown。