settings.json 全局 vs 项目层级
理解 Claude Code 的 settings 三层模型(用户级 / 项目级 / local)的合并规则、覆盖优先级与最常踩的坑
在终端 Agent 里挂 MCP server 的两种方式 —— claude mcp add 命令 vs settings.json 配置文件,含 stdio 与远程 server 的踩坑要点
内容摘要
在终端里跑 AI Agent,绕不开一个高频问题:**怎么让它访问外部工具?** 你想让 Claude Code 查 Sentry 错误、读 PostgreSQL 表、提 GitHub PR——这些事要么靠 shell 命令现凑(脆弱、上下文乱),要么走 [MCP(Model Context Protocol)](/mcp/cards/what-is-mcp) 把外部能力以"标准协议"的方式注册进来。后者就是这张卡要讲的事。
在终端里跑 AI Agent,绕不开一个高频问题:怎么让它访问外部工具? 你想让 Claude Code 查 Sentry 错误、读 PostgreSQL 表、提 GitHub PR——这些事要么靠 shell 命令现凑(脆弱、上下文乱),要么走 MCP(Model Context Protocol) 把外部能力以"标准协议"的方式注册进来。后者就是这张卡要讲的事。
CLI Agent 接 MCP 和 Claude Desktop 接 MCP 的本质一致——都是 Host 启一个 Client、Client 连一个 Server——但 CLI 端的配置入口完全不同:
| 维度 | Claude Desktop | Claude Code(CLI) |
|---|---|---|
| 配置方式 | 手动编辑 claude_desktop_config.json | claude mcp add 命令 + .mcp.json 文件 |
| 配置作用域 | 一份全局配置 | local / project / user 三级 |
| 团队协作 | 不支持(配置不进 Git) | .mcp.json 进 Git,团队 clone 即用 |
| 加新 Server 后是否要重启 | 必须重启 App | 改完进对话敲 /mcp 刷新即可 |
| 远程 Server 鉴权 | 手动填 Token | OAuth 2.0 浏览器流程 |
| 反向能力(Sampling 等) | 完整支持 | 当前不支持 Sampling |
CLI 端的两种挂载方式不是对立的——
claude mcp add在底层就是写文件,写到哪个文件由--scope决定。命令式适合个人快速试,配置式(特别是 project 作用域的.mcp.json)适合团队共享和版本管理。
| 要素 | 说明 |
|---|---|
| 两种入口 | 命令式 claude mcp add / 配置式编辑 .mcp.json 或 ~/.claude.json |
| 三种传输 | stdio(本地子进程,零网络)/ HTTP(远程,OAuth 友好)/ SSE(远程,已 deprecated) |
| 三级作用域 | local(默认,仅自己 + 当前项目)/ project(团队共享 .mcp.json)/ user(自己跨所有项目) |
| 状态查看 | 终端 claude mcp list;对话内 /mcp |
| 环境变量展开 | .mcp.json 支持 ${VAR} 与 ${VAR:-default} 占位符,避免把 secret 写进 Git |
注意中间那段循环——Server 进程是在 CLI 启动时一次性拉起的。如果是 stdio Server,它就跟着 claude 进程的生命周期走,CLI 退出 Server 也跟着死;如果是 HTTP Server,断线时 Claude Code 会用指数退避重连最多 5 次,5 次失败后在 /mcp 里标 failed,需要手动 retry。stdio 进程崩了不会自动重启,要重新进会话。
claude mcp add 命令式最常用、最快的方式。一条命令搞定,比手动编辑 JSON 省心。语法:
# 基本形式(注意所有 flag 必须在 name 之前,stdio 启动命令在 -- 之后)
claude mcp add [options] <name> [-- <command> [args...]]
# 拉起一个本地 dbhub 进程,连只读 Postgres
claude mcp add db --transport stdio \
--env LOG_LEVEL=info \
-- npx -y @bytebase/dbhub --dsn "postgresql://readonly:pass@localhost:5432/analytics"
# 验证
claude mcp list
# 应该输出:db: npx -y @bytebase/dbhub --dsn ...
几个关键点:
--transport stdio 是默认值,可省略,但显式写出来更清楚。--env KEY=VAL 把环境变量塞给子进程,可重复多次。-- 是分隔符,左边是 Claude Code 自己的 flag,右边是要 spawn 的命令本体。漏掉它,Claude 会把 npx 当成 claude mcp add 的参数,报奇怪的错。db)是你自己起的别名,后面 claude mcp get db / claude mcp remove db 都用这个名字。# 远程 server 一行命令,不需要写 token
claude mcp add sentry --transport http https://mcp.sentry.dev/mcp
# 进对话授权
claude
# 在对话里输入:
# /mcp
# 选 sentry → Authenticate → 浏览器弹 OAuth 页 → 授权完成
--transport http 是当前推荐的远程协议;--transport sse 还能用但官方已标 deprecated,新接入直接选 http。
如果远程 Server 不走 OAuth,要手填 header:
claude mcp add my-internal-api --transport http https://api.internal.com/mcp \
--header "Authorization: Bearer $INTERNAL_TOKEN" \
--header "X-Tenant: acme"
# 默认:local(只在当前项目可见,写到 ~/.claude.json 的 projects.<当前路径>.mcpServers)
claude mcp add stripe --transport http https://mcp.stripe.com
# project:写到项目根目录的 .mcp.json,进 Git,团队共享
claude mcp add paypal --scope project --transport http https://mcp.paypal.com/mcp
# user:写到 ~/.claude.json 的 user 段,自己所有项目都生效
claude mcp add github --scope user --transport http https://api.githubcopilot.com/mcp/
优先级 local > project > user,同名 Server 高优先级覆盖低优先级。
claude mcp list # 列所有 Server
claude mcp get sentry # 看某个 Server 详情(含 OAuth 状态)
claude mcp remove sentry # 删除
claude mcp reset-project-choices # 重置 .mcp.json 的批准状态
claude mcp serve # 把 Claude Code 自己当 Server,供别的 Host 调
claude mcp add-from-claude-desktop # 从 Desktop 一键导入(仅 macOS / WSL)
当你需要团队共享、或者要写复杂的 env 变量展开时,编辑文件比命令式更直观。
.mcp.json(项目根目录){
"mcpServers": {
"sentry": {
"type": "http",
"url": "https://mcp.sentry.dev/mcp"
},
"internal-api": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
},
"db-readonly": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@bytebase/dbhub",
"--dsn",
"${DATABASE_URL}"
],
"env": {
"LOG_LEVEL": "info"
}
}
}
}
这个文件可以、也应该提交到 Git,团队成员 clone 仓库后第一次启 Claude Code 会弹确认框(防止恶意仓库塞 Server 进来),同意后就跟自己配的没区别。
环境变量展开规则:
${VAR} —— 取环境变量 VAR 的值,未设置则解析失败,整个 .mcp.json 都加载不了。${VAR:-default} —— VAR 没设置时回退到 default。command、args 中的每一项、env 的 value、url、headers 的 value。写完团队 Wiki 里告诉每个人:export API_KEY=xxx、export DATABASE_URL=xxx,剩下的事 Claude Code 替大家管。绝对不要把 token 直接写进 .mcp.json,否则进 Git 历史就洗不掉。
~/.claude.jsonlocal 和 user 作用域都落在 ~/.claude.json,结构大致是:
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/"
}
},
"projects": {
"/Users/me/work/project-a": {
"mcpServers": {
"stripe": {
"type": "http",
"url": "https://mcp.stripe.com"
}
}
}
}
}
顶层 mcpServers 是 user 作用域(所有项目可见);projects.<绝对路径>.mcpServers 是 local 作用域(仅那个目录可见)。一般不建议手改这个文件——用 claude mcp add --scope user/local 让 Claude Code 自己写更稳。
claude mcp add-json 一次塞一坨配置复杂 server 可以直接传 JSON:
claude mcp add-json weather '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer abc"}}'
适合脚本批量初始化场景。
/mcp$ claude
> /mcp
✔ sentry connected 2 tools, OAuth authorized
✔ db-readonly connected 8 tools
○ internal-api pending reconnecting (attempt 2/5)
✗ legacy-sse failed Connection refused. [r]etry [d]isable
> 看看 Sentry 最近 24h 错误最多的 endpoint
[调用工具:sentry.list_errors,参数:{ "lookback": "24h" }]
最近 24 小时报错最多的是 /api/checkout,共 1287 次……
绿色勾 = 已连上、工具就绪;圆圈 = 重连中;红叉 = 5 次都失败、需手动 retry。
| 维度 | Claude Code | Cursor | VS Code(Copilot Chat) | Claude Desktop |
|---|---|---|---|---|
| 配置入口 | claude mcp add 命令 + .mcp.json | Settings UI 或 .cursor/mcp.json | Settings UI 或 .vscode/mcp.json | 手动编辑 claude_desktop_config.json |
| 配置文件根字段 | mcpServers | mcpServers | servers(注意,不是 mcpServers) | mcpServers |
| 项目级共享文件 | .mcp.json(仓库根) | .cursor/mcp.json(仓库根) | .vscode/mcp.json(仓库根) | 不支持 |
| 全局/用户作用域 | ~/.claude.json + --scope user | ~/.cursor/mcp.json | 用户 profile 设置 | 唯一一份全局配置 |
| 三级作用域 | ✅ local / project / user | ⚠️ 项目 + 全局两级 | ⚠️ 工作区 + 用户两级 | ❌ 全局一份 |
| 传输支持 | stdio / HTTP / SSE | stdio / HTTP | stdio / HTTP / SSE | stdio / HTTP |
| OAuth 流程 | /mcp 内置一键授权 | 内置授权 | inputs + 手填或 OAuth | 手动配 token |
| 环境变量占位符 | ${VAR} ${VAR:-default} | ${env:VAR} | ${env:VAR} ${input:NAME} | 不支持占位符(要写实值) |
| 管理命令 | claude mcp list/get/remove | UI 操作 | UI 操作 | 改 JSON + 重启 |
| 加 Server 后需重启 | ❌ /mcp 刷新即可 | ❌ 自动检测 | ❌ 自动检测 | ✅ 必须重启 App |
核心区别一句话:
.mcp.json 是它的招牌,纯命令行重度用户首选。servers 字段跟其他三家不一致,迁移配置时容易踩坑。| 误区 | 准确理解 |
|---|---|
以为 .mcp.json 是 Claude Desktop 的配置 | Desktop 的配置叫 claude_desktop_config.json,路径在 ~/Library/Application Support/Claude/。.mcp.json 是 Claude Code 在项目根目录创建的团队共享文件,两者文件名都不一样。 |
| 以为远程 MCP 必须 HTTP / 必须公网域名 | 远程 transport 有 HTTP(推荐)和 SSE(已 deprecated)两种,localhost 上的进程也能用 HTTP 暴露。stdio 才是"本地默认",HTTP 不等于必须公网。 |
以为 claude mcp add 不可逆 | 完全可逆。claude mcp remove <name> 删掉,或者直接编辑 ~/.claude.json / .mcp.json 把那段去掉就行。claude mcp reset-project-choices 还能重置项目批准状态。 |
以为加完 Server 必须重启 claude | 不用。在对话里敲 /mcp 就会重新读配置、重连 Server。只有第一次添加全新 Server 时,建议起一次新会话确保 tool 列表注入。 |
以为 --env 和 .mcp.json 里的 env 等价 | 作用域不同。--env 跟着命令走,写到 local 作用域只对自己生效;.mcp.json 里的 env 是 project 作用域、团队共享。秘密信息永远用环境变量占位符 ${API_KEY},不要把实值写进 .mcp.json。 |
以为 stdio Server 的 command 可以直接写 npx(在 Windows 上) | Windows native(非 WSL)不能直接 spawn npx,必须套 cmd /c:-- cmd /c npx -y @some/package。漏了会报 "Connection closed"。 |
以为 .mcp.json 进 Git 会泄露 secret | 只要严格使用 ${API_KEY} 占位符,仓库里没有真值,每个团队成员在自己机器 export API_KEY=xxx 即可。会泄露的从来不是 .mcp.json 本身,而是把实值硬编码进去的人。 |
claude mcp add| 优势 | 劣势 |
|---|---|
一行搞定,不用记 JSON 字段名(type / command / args 顺序) | 配置复杂时(多 env、多 header)命令越写越长,可读性下降 |
--scope 一个 flag 切换三级作用域,零成本试错 | 不适合团队共享 —— 命令式的 local 配置只在你机器上 |
| 自带校验,写错 transport 类型会立即报错 | 无法表达 ${VAR:-default} 这种环境变量回退 |
claude mcp add-from-claude-desktop 一键迁移已有配置 | Windows 下 stdio 命令需要套 cmd /c,命令式写起来更绕 |
.mcp.json / ~/.claude.json)| 优势 | 劣势 |
|---|---|
.mcp.json 进 Git,团队 clone 即获得统一工具栈 | 改完没有自动校验,JSON 写错(多逗号、漏引号)整份配置加载失败 |
支持 ${VAR} / ${VAR:-default} 环境变量展开,secret 不进 Git | 必须教会团队成员设置对应 env,新人冷启动有学习成本 |
| 复杂 server 一次性写清楚,比拼接命令直观 | 项目作用域首次使用要弹批准框(虽然这是好的安全设计) |
| 可写注释、可用 IDE schema 校验、可 review diff | 手改 ~/.claude.json 容易破坏 Claude Code 自身管理的字段,建议只用 claude mcp add --scope user/local |
实战配比:个人快速试用走命令式(local 作用域),团队稳定用的工具走 .mcp.json(project 作用域 + 占位符),自己跨项目通用的工具走命令式(--scope user)。
参考答案:
走 project 作用域,写进项目根目录的 .mcp.json,提交到 Git。
理由:
.mcp.json 走 PR review,所有人下次 pull 自动更新。${SENTRY_TOKEN} 占位符,每个人在自己 .zshrc 里 export SENTRY_TOKEN=xxx,仓库里没有秘密。具体配置:
{
"mcpServers": {
"sentry": {
"type": "http",
"url": "https://mcp.sentry.dev/mcp",
"headers": {
"Authorization": "Bearer ${SENTRY_TOKEN}"
}
}
}
}
如果是个人偏好的工具(比如自己喜欢的笔记 MCP),用 user 作用域 (--scope user);如果是含个人测试 token 的临时实验,用 local 作用域避免误提交。
参考答案:
{
"mcpServers": {
"my-python-server": {
"type": "stdio",
"command": "python",
"args": [
"${PROJECT_ROOT:-.}/scripts/server.py",
"--mode",
"production"
],
"env": {
"OPENAI_API_KEY": "${OPENAI_API_KEY}",
"LOG_LEVEL": "${LOG_LEVEL:-info}"
}
}
}
}
关键点:
command 用 python,不写绝对路径,让每个人系统 PATH 里的 Python 都能跑。args 里用 ${PROJECT_ROOT:-.} 兜底当前目录,避免脚本路径硬编码。env.OPENAI_API_KEY 用占位符——.mcp.json 里只有 ${OPENAI_API_KEY} 这串字面量,没有真值。LOG_LEVEL 给个默认值 info,团队成员不用必须设置。团队 README 里同步写一段:"使用前请 export OPENAI_API_KEY=sk-..."。新人冷启动一次后,后续完全无感。
如果想再稳一点,加一个 .env.example 列出所有需要 export 的变量,让团队成员对照设置。
参考答案:
会遇到 "Connection closed" 错误,Server 一启动就死。原因是 Windows native 的进程模型不能直接 spawn npx——npx 在 Windows 上其实是 npx.cmd 这种批处理脚本,必须通过 cmd.exe 解释器才能执行。
错的写法:
claude mcp add my-server --transport stdio -- npx -y @some/package
# Claude Code 内部会执行 spawn("npx", ["-y", "@some/package"])
# Windows: ENOENT,没法直接 spawn .cmd 文件
正确写法:套一层 cmd /c:
claude mcp add my-server --transport stdio -- cmd /c npx -y @some/package
# 内部变成 spawn("cmd", ["/c", "npx", "-y", "@some/package"])
# 由 cmd.exe 解释 npx.cmd,工作正常
或者写到 .mcp.json 里:
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "cmd",
"args": ["/c", "npx", "-y", "@some/package"]
}
}
}
macOS / Linux 没事是因为这些系统上 npx 是真正的可执行脚本(带 shebang #!/usr/bin/env node),可以被 execve 直接加载,不需要 shell 中转。
附带一个延伸坑:Windows 上配置 env 变量时,如果 npm 没全局安装、出现 ${APPDATA} 路径错误,需要在 env 里手动设置 APPDATA 的展开值(比如 "APPDATA": "C:\\Users\\you\\AppData\\Roaming\\")。这是 Claude Desktop 时代就有的老问题,Claude Code 在 native Windows 上沿用了同样的行为。
如果你不想踩这一类坑,最稳的方案是直接用 WSL2 跑 Claude Code——WSL 内的环境是 Linux,所有 stdio Server 配置和 Mac 完全一致,团队的 .mcp.json 也可以无缝复用。
servers):https://code.visualstudio.com/docs/copilot/reference/mcp-configuration(查询日期 2026-04-22)优先展示同分类且标签更接近的内容,方便继续串联学习。
理解 Claude Code 的 settings 三层模型(用户级 / 项目级 / local)的合并规则、覆盖优先级与最常踩的坑
理解 Claude Code 的生命周期 hook(PreToolUse / PostToolUse / Stop / Notification 等),何时该用、典型用例与避坑
理解 Claude Code 等 CLI Agent 的工具白名单 / 危险权限 / sandbox 边界,知道 bypassPermissions 何时该开