·MCP 服务器
MCP 服务器配置 2026 实战——Claude Desktop 和 Claude Code 各自的配置文件路径、三层优先级(企业 / / 用户)、stdio 与 HTTP 配置形态、filesystem / GitHub / Postgres 三个真实服务器示例、OAuth scope 漂移调试,以及 7 步排错清单。
在 Claude Desktop 和 Claude Code 里配置 MCP 服务器(2026)
MCP 真正发挥价值的时刻,是当你把服务器接进日常用的 Host。本指南基于 MCP 2025-11-25 规范,详细讲清楚 Claude Desktop / Claude Code / Cursor / Zed 的统一 JSON 配置格式、filesystem / GitHub / Postgres 三个真实参考服务器的完整可运行示例、双 Host 的差异(stdio vs stdio+OAuth)、以及「服务器死活加载不出来」的 7 步排错清单。
TL;DR
- 所有 MCP Host 都读同一份 JSON 配置,结构是
{mcpServers: {name: {command, args, env}}}- stdin 服务器用
command+args+env;HTTP 服务器用url+headers- Claude Desktop 配置:
~/Library/Application Support/Claude/claude_desktop_config.json(macOS)- Claude Code 配置:项目级
.mcp.json+ 用户级~/.claude.json—— 比 Desktop 多一层优先级- 排错顺序:先 Inspector 跑得通 → 看 Host 日志 → 验证环境变量透传 → 检查权限与 sandbox
- 2026 年新坑:
claude_desktop_config.json与claude.json字段名不同,OAuth scope 漂移
各个 Host 的配置文件在哪里
动手之前,先搞清楚文件放在哪。
Claude Desktop 读取一个单一配置文件:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
Claude Desktop 也在 UI 里暴露了这个文件:打开 Settings → Developer → Edit Config,它就会用你的编辑器打开该文件,你也能在里面启用、停用、查看服务器。
Claude Code 从多个层级读取 MCP 服务器并合并:
- 项目根目录下的
.mcp.json(提交到仓库、团队共享) ~/.claude.json或你的用户级设置(个人服务器)- 插件提供的服务器
项目的 .mcp.json 是你应该提交到 git 的那个,它是把一组 MCP 服务器分享给所有在这个仓库工作的人的标准方式。
两个 Host 都使用相同的 mcpServers 结构,所以你写一次的服务器条目,只需改改路径就能在它们之间迁移。
配置的结构
每个配置都是一个对象,带一个 mcpServers 键,其值是一个「服务器名 → 服务器定义」的 map。名字只是你自己起的标签——它会显示在 Host UI 里,也出现在工具名里。每个定义需要 command 和 args,可选 env:
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/absolute/path/to/index.js"],
"env": {
"API_KEY": "sk-..."
}
}
}
}
有几条规则值得记住:
- 用绝对路径。 相对路径是相对 Host 的工作目录解析的,而那个目录不总是你以为的那个。把服务器入口的绝对路径写死,能消掉一大类「我这能跑」的 bug。
command是一个可执行文件,不是 shell 字符串。 如果你需要 shell,就跑bash或cmd,在args里带-c和脚本。env是叠加的。 被拉起的进程会继承 Host 的环境变量,这里的条目会合并到上面。API token 和配置标志都放这里。- 服务器名在一个配置文件里必须唯一。 重复的键会静默覆盖。
文件系统服务器
官方的 @modelcontextprotocol/server-filesystem 把一组目录以可读、可写资源的形式暴露给模型。它是配置起来最简单的真实服务器,也很适合作为第一个冒烟测试。
先全局安装一次,让 Host 能找到它:
npm install -g @modelcontextprotocol/server-filesystem
然后把它加进 claude_desktop_config.json:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/Users/me/projects",
"/Users/me/notes"
]
}
}
}
末尾的路径参数是允许服务器访问的目录。列表之外的任何东西对模型都是不可见的——这个边界就是安全模型,所以精确列出你想暴露的根目录,不要多列。保存文件并重启 Claude Desktop 后,你可以问「我 projects 目录里有哪些文件?」,模型就会调用文件系统服务器来回答。
对 Claude Code 来说,同样的条目放在项目根目录的 .mcp.json 里。Claude Code 也支持交互式添加:
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /Users/me/projects
CLI 会把条目写进正确的配置层级,并在写入时校验 JSON。
GitHub 服务器
官方的 GitHub MCP 服务器(@modelcontextprotocol/server-github)让模型通过 GitHub REST API 读取 issue、pull request 和仓库元数据。它需要一个个人访问 token,这正是 env 块的用武之地。
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
}
}
}
在 github.com/settings/tokens 创建 token 时,只勾你实际需要的 scope(私有仓库勾 repo,组织数据勾 read:org)。把 token 当成密码——绝不要把带真实 token 的配置提交进仓库。如果你要分享项目配置,就用占位符并注明真实值放哪,或者从一个 gitignore 掉的本地文件加载。
加载好之后,你可以问模型类似「列出我仓库里标签为 bug 的 open issue」或「总结一下 PR #1234 的评论」,它会调用 GitHub 服务器去取数据。在 Claude Code 里,工具会以 mcp__github__<工具名> 的形式出现,这样一眼就能看出某个工具来自哪个服务器。
Postgres 服务器
官方的 Postgres 服务器(@modelcontextprotocol/server-postgres)以只读(默认)方式暴露一个数据库:表、schema,以及运行 SELECT 查询的能力。你传一个连接字符串:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://user:password@localhost:5432/mydb"
]
}
}
}
数据库场景下有几点要注意:
- 优先用只读角色。 Postgres 服务器默认只读,但用一个只有
SELECT权限的角色连接是双保险。绝不要把生产环境的写用户连接串交给模型。 - schema 很重要。 模型靠读 schema 来决定运行什么查询,所以命名清晰的 schema 能产生质量高得多的查询。
- 连接池。 每个 MCP 服务器进程持有一个自己的连接。本地开发库没问题;对共享数据库,把它指向像 PgBouncer 这样的连接池。
Claude Desktop 与 Claude Code
两个 Host 重合度很高,但有几个实际差异。
Claude Desktop 是一个带图形设置面板的桌面应用。你编辑 claude_desktop_config.json、重启应用,服务器就会出现在输入框旁的锤子图标下。它没有按项目的配置——每个聊天看到的是同一组服务器。
Claude Code 是一个跟你的代码住在一起的终端工具。它的 .mcp.json 按项目存在并提交到 git,所以一个仓库可以声明自己依赖的服务器。它还会在上面叠加用户级和插件提供的服务器。你可以把服务器限定到某个项目、用 claude mcp list 查看、用 claude mcp remove <名字> 移除。工具前缀约定(mcp__<服务器>__<工具>)让每一次工具调用的来源都一目了然。
实践上:Claude Desktop 配置适合放个人、跨项目的服务器(你的笔记、你的日历);项目的 .mcp.json 适合放跟某个代码库运作方式绑定的服务器(它的数据库、它的 issue 追踪器、它的内部 API)。
让改动生效
MCP 服务器是由 Host 拉起的,所以配置改动只有在 Host 重新加载后才会生效:
- Claude Desktop —— 完整退出并重启应用。关掉窗口不算数;服务器进程会一直跑到应用退出。
- Claude Code —— 开一个新会话,或者在运行中的会话里执行
/mcp重新连接。
如果重启后服务器还是不出现,第一件事是检查 JSON 能不能解析。一个多余的逗号或缺失的大括号会让 Host 静默忽略整个配置,所有服务器都加载不上。不确定的话,把文件丢进 JSON 校验器过一遍。
字段优先级:Claude Code 的多层覆盖模型
Claude Desktop 只读一份配置(claude_desktop_config.json),但 Claude Code 用三层叠加——这是新用户最容易踩坑的地方:
| 层 | 路径 | 用途 | 优先级 |
|---|---|---|---|
| 企业托管 | MDM 推送 / managed settings | 公司统一分发 | 最高(不可覆盖) |
| 项目级 | <project>/.mcp.json | 团队共享,提交到 git | 高 |
| 用户级 | ~/.claude.json 的 mcpServers 字段 | 个人常用工具,跨项目可用 | 低 |
合并规则:同一 slug 的服务器,企业层覆盖项目层覆盖用户层。这意味着 (1) 团队里某个老员工的本地工具不会泄露给整个项目(被项目级覆盖),(2) 公司 MDN 推的强制审计服务器无法被个人绕过。
.mcp.json 与 claude_desktop_config.json 的关键字段差异:
.mcp.json(Claude Code 项目级)支持trust字段——true时跳过 Host 启动时的二次确认提示。~/.claude.json(Claude Code 用户级)有enableMcpServers列表——显式 allowlist,未列出的 server 即使配置了也不启动(这是 2026 年新增的 safety feature)。- Desktop 与 Code 共享字段名:
command/args/env/url/headers都一致,但 Desktop 的claude_desktop_config.json顶层是mcpServers,Code 的~/.claude.json顶层是mcpServers但会嵌套在其它用户级配置中(参考 code.claude.com/docs/en/mcp)。
反模式:把含敏感 token 的 server 放在 ~/.claude.json 然后推到 git。用户级配置的 token 应该只对单台机器有效——任何需要在团队共享的配置都必须放 .mcp.json 且 token 通过 secret store 注入。
stdio vs HTTP:何时该切换配置形态
{command, args, env} 适合本地的 stdio 服务器(MCP 2025-11-25 transports 规范)——Host 把 server 当子进程拉起,三字段直接映射到 child_process.spawn。优势:零网络、零鉴权、零运维。劣势:server 必须与 Host 同机、无法团队共享。
{url, headers} 适合远端 Streamable HTTP 服务器——Host 通过 HTTP POST + SSE 与独立机器上的 server 通信。OAuth 2.1 + Bearer Token 通过 headers.Authorization 透传(authorization 规范)。优势:可跨机器、可团队共享、可被 Claude Desktop / Code / Cursor 同时调用。劣势:多一层 OAuth 运维。
配置示例:stdio → HTTP 切换:
// stdio:server 在本机
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..." }
}
}
}
// HTTP:server 在远端,需要 OAuth
{
"mcpServers": {
"github": {
"url": "https://mcp.example.com/github",
"headers": {
"Authorization": "Bearer ${GITHUB_MCP_TOKEN}"
}
}
}
}
决策原则:
- 个人本地工具 → stdio 永远够用
- 团队共享 server → HTTP,唯一选择
- 一个 server 被多个 Host 复用(Desktop + Code + Cursor 都想用)→ HTTP,stdio 下每个 Host 各 fork 一份,配置无法同步
- SaaS / 公共目录 → HTTP + MCP Registry(modelcontextprotocol/registry)
迁移步骤:(1(1) 把 server 业务逻辑与 transport 适配解耦;(2) 用 官方 SDK 的 Streamable HTTP transport 重新包一层;(3) 配置 OAuth 2.1 与 headers.Authorization;(4) 在 server 端实施 session 隔离(Mcp-Session-Id);(5) 跑 security best practices) 清单(Origin 校验 + DNS rebinding 防御)。
OAuth scope 漂移:远端 server 最常见的"昨天能调今天不行"
当你切换到 HTTP server 后,最容易出现的诡异问题是:本地用 Inspector 调得通,Host 一调就 401 with no body。90% 是 OAuth scope 漂移——Host 拿到的 token 不包含 server 实际需要的 resource scope。
OAuth 2.1 + RFC 8707 Resource Indicators 在 MCP 里的具体表现:
| 症状 | 根因 | 修法 |
|---|---|---|
| Inspector OK,Host 401 | Host 用的 token scope 不含此 resource | 在 headers.Authorization 用 scope 正确的 token,或触发 OAuth refresh |
| 调得通但 tools/list 空 | server 没声明 capabilities.tools | server 端 SDK 补 capabilities 字段 |
| 间歇性 401 | token 过期未自动 refresh | 配 OAuth client 的 refresh_token rotation |
| 所有 call 都 401 | token audience 错(resource binding 失效) | 重新跑 OAuth 授权流,token 必须与 server URL audience 一致 |
调试步骤:
- 用 Inspector 直接打 server(绕过 Host):OK → 问题在 Host 拿 token 的环节;不 OK → 问题在 server。
- 抓 Host 日志里的
Authorizationheader,确认 token scope(一般需要 server 端日志辅助)。 - 让 server 端在
initialize时打印收到的 token scopes(debug 模式)。
预防:在 CI 里跑 OAuth 授权 → token 验证 → 真实调用一次 tools/list 三步自动化测试,每次 server SDK 升级都跑一次。
排错清单
当服务器死活加载不出来,或工具不出现时,按以下顺序排查:
- JSON 能解析吗? 一个语法错误会让文件里所有服务器失效。
- 路径是绝对且正确的吗? 把配置里的完整命令打印出来,在终端里跑一遍。如果在终端都报错,在 Host 里必然也报错。
- 依赖装了吗?
npx -y <包>首次运行会下载,需要网络。在内网环境里先把包全局装好。 - 环境变量设了吗? 一个需要
GITHUB_PERSONAL_ACCESS_TOKEN却拿不到的服务器,会启动成功,但在第一次工具调用时失败。检查 token 是否有正确的 scope。 - 服务器有没有往 stderr 打印什么? Claude Desktop 在 macOS 上把服务器日志写到
~/Library/Logs/Claude/mcp-server-<名字>.log;Claude Code 通过/mcp面板展示。先读日志再猜。 - 是不是版本不匹配? MCP 还在成熟中。如果某个服务器是按较旧的协议版本写的,就在
args里把版本钉死(例如@modelcontextprotocol/server-filesystem@0.6.0),等 Host 跟上。
最快的调试循环通常是:在终端里直接跑服务器命令,看它打印启动横幅,然后杀掉,让 Host 来拉起它。如果独立运行没问题但 Host 运行不行,问题在配置或环境,不在服务器。
常见问题
编辑配置文件后需要重启 Claude Desktop 吗?
需要。Claude Desktop 在应用启动时拉起 MCP 服务器,并在整个会话期间保活。编辑 claude_desktop_config.json 在你完整退出并重启应用之前不会生效;关掉窗口不算重启。
claude_desktop_config.json 和 .mcp.json 有什么区别?
claude_desktop_config.json 是 Claude Desktop 的单一全局配置文件,对每个聊天都生效。.mcp.json 是 Claude Code 按项目存在的配置文件,提交到 git 让整个团队拿到同一组服务器。两者都用相同的 mcpServers 结构。
服务器能访问我的整个文件系统吗?
只有你明确允许的才行。文件系统服务器把允许访问的目录作为命令行参数接收,列表之外的东西对模型不可见。把这个允许清单当成安全边界,精确列出你想暴露的根目录。
怎么安全地给服务器传 API token?
把它放在服务器定义的 env 块里。Host 会把这些变量传给被拉起的进程。绝不要把真实 token 提交进共享的配置文件——用占位符、从 gitignore 掉的本地文件加载,或者在部署时从密钥管理器注入。
Claude Code 的 .mcp.json 和用户级 ~/.claude.json 冲突时谁赢?
按层数从高到低:企业托管(MDM)覆盖项目级覆盖用户级。同一 slug 的 server 出现多次时,Host 取优先级最高的版本。如果你想强制用户级覆盖项目级,把项目级的 server 设 disabled: true;但企业托管层无法被任何下层覆盖。
远端 HTTP server 突然 401 with no body 怎么办?
按 4 步排:(1) Inspector 直连 server 看是否 OK——是 → Host 拿 token 的环节有问题;否 → server 端问题。(2) 抓 Host 日志里的 Authorization header,确认 token scope 是否够。(3) 触发 OAuth refresh——token 可能过期。(4) 验证 token audience 是否与 server URL 一致(RFC 8707 强制绑定)。90% 的"昨天能调今天不行"是第 3 或第 4 步——token 自动 rotate 或 client 误换了 audience。
官方参考资料
- MCP 规范 — Transports(stdio + Streamable HTTP)
- MCP 规范 — Authorization(OAuth 2.1 + Dynamic Client Registration)
- MCP 文档 — Concepts/Architecture
- MCP 文档 — Concepts/Transports
- MCP 文档 — Develop/Connect Local Servers
- MCP 文档 — Develop/Build Server
- MCP 文档 — Security Best Practices
- Claude Code MCP 文档(code.claude.com)
- 官方参考服务器集合
- Claude Code MCP 文档
- Claude Desktop 文档
本文基于截至 2026 年 7 月的公开信息,相关 API 可能演进。