跳转到内容

Claude Code 接 MCP 服务器:三种 scope 存在哪、四种传输怎么选、工具搜索为什么默认开

约 22 分钟 难度:进阶 动手章

判断该不该接 MCP 服务器的标准很具体:你有没有在反复从另一个工具里复制数据粘贴进对话。issue 描述、监控面板的报错、数据库查询结果——如果这些内容你每天都在手工搬运,那个系统就该接进来。反过来,为了「功能齐全」而接一堆用不上的服务器,只是在消耗启动时间。

三种 scope 的存储位置容易记混,先记住这张表:

scope在哪些项目里加载团队共享存储位置
local(默认)仅当前项目~/.claude.json
project仅当前项目是,通过版本控制项目根的 .mcp.json
user你的所有项目~/.claude.json

旧版本对 scope 的叫法不同:现在的 local 曾叫 project,现在的 user 曾叫 global。看老文章时注意这一层。

Terminal window
# HTTP:远程服务器的推荐选择
claude mcp add --transport http notion https://mcp.notion.com/mcp
# 带 Bearer token
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
# stdio:本地进程
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-server

怎么选:

  • HTTP:远程服务器的默认选择。支持 OAuth,云服务里支持面最广。
  • stdio:本地进程,适合需要直接访问系统或跑自定义脚本的场景。
  • SSE:已废弃,只有仅暴露 SSE 端点的服务还需要它。
  • WebSocket:持久双向连接,适合服务器主动推事件的场景。不支持 OAuth,也不能用 --transport 标志添加,只能通过 .mcp.jsonclaude mcp add-json 配。

在 JSON 配置里,type 字段接受 streamable-http 作为 http 的别名。MCP 规范用的是前者这个名字,所以从服务端文档抄来的配置可以直接用。

Terminal window
claude mcp add --env KEY=value --transport stdio myserver -- python server.py --port 8080

-- 分隔 Claude 自己的选项(--transport--env--scope)和要运行的命令。-- 之后的一切原样传给服务器。

没有 --,上面这条命令里的 --port 会被 Claude Code 当成自己的选项去解析然后报错。

--env 接受多个 KEY=value 对,所以服务器名不能紧跟在 --env 后面——CLI 会把名字读成另一个键值对然后拒绝。至少在 --env 和服务器名之间放一个其他选项。

JSON 配置里写了 url 但没写 type,是配置错误。Claude Code 把没有 type 的条目当作 stdio 服务器,于是报:

MCP server "<name>" has a "url" but no "type"; add "type": "http" (or "sse" / "ws") to this entry

v2.1.202 之前这个错误的措辞是 command: expected string, received undefined,看起来完全不像是缺 type 导致的。搜到旧报错信息时,答案是加 type 字段。

project scope 的服务器写在项目根的 .mcp.json 里,提交进版本控制,团队每个人拿到同一套工具:

{
"mcpServers": {
"shared-server": {
"type": "http",
"url": "https://example.com/mcp"
}
}
}

出于安全考虑,使用 .mcp.json 里的服务器之前 Claude Code 会要求你批准。要重置批准记录:

Terminal window
claude mcp reset-project-choices

这里有一层容易忽略的防御。v2.1.196 起,在你信任这个 workspace 之前(跑一次 claude 并接受信任对话框),claude mcp listclaude mcp get 只从没有提交进仓库的设置文件读取 .mcp.json 的批准记录。

意思是:一个克隆下来的仓库不能自己批准自己的服务器。提交在项目 .claude/settings.json 里的 enableAllProjectMcpServersenabledMcpjsonServers 在未信任的文件夹里被忽略,服务器停在 ⏸ Pending approval 状态。

在未信任的文件夹里仍然生效的批准来源:

  • 你的 ~/.claude/settings.json
  • managed 设置
  • 通过 --settings 传入的设置

disabledMcpjsonServers 里的条目在任何设置文件里都能拒绝服务器——拒绝方向不受信任门槛限制。

团队共享配置时,机器相关的路径和密钥不能写死。.mcp.json 支持两种展开语法:

  • ${VAR}:展开为环境变量的值
  • ${VAR:-default}:有值用值,无值用默认

可展开的位置:commandargsenvurlheaders

{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}

变量未设置且没有默认值时,配置仍然加载:Claude Code 在 claude mcp list 输出里为该服务器报一个缺变量警告,并把未展开的 ${VAR} 文本原样使用。所以服务器连不上、报的是认证错误时,先检查 claude mcp list 有没有这个警告——把字面量 ${API_KEY} 当 token 发出去,服务端返回的当然是 401。

CLAUDE_PROJECT_DIR 是一个特例。Claude Code 会把它设进 stdio 服务器进程的环境里,但它不在 Claude Code 自己的环境里。所以在 .mcp.jsoncommandargs 里用 ${CLAUDE_PROJECT_DIR} 展开需要带默认值:${CLAUDE_PROJECT_DIR:-.}。插件提供的 MCP 配置直接替换这个占位符,不需要默认值。

tool search:为什么接很多服务器也不会撑爆上下文

Section titled “tool search:为什么接很多服务器也不会撑爆上下文”

tool search 默认开启。它的作用是把工具定义延迟加载:会话开始时只加载工具名和服务器说明,Claude 需要用某个工具时通过一个搜索工具去发现它。只有实际用到的工具进入上下文。

这解决了一个真实问题:每个 MCP 服务器的完整工具定义(参数 schema、描述)都很占 token。接五六个服务器,光工具定义就能吃掉可观的上下文。

从使用体验上你感觉不到区别。Claude Code 也因此不设固定的每服务器工具数上限,实际限制是上下文预算。

ENABLE_TOOL_SEARCH 的取值:

行为
未设置全部延迟加载(几个特定部署环境下回退为前置加载)
true全部延迟加载
auto阈值模式:工具定义能装进上下文窗口的 10% 就前置加载,超出部分延迟
auto:N阈值模式,自定义百分比,N 取 0-100
false全部前置加载

tool search 需要支持 tool_reference 块的模型:Claude Sonnet 4.5、Haiku 4.5、Opus 4.5 及更新的模型。

有少数工具是每轮都要用的,让它们走搜索反而多一次往返。给那个服务器加 alwaysLoad

{
"mcpServers": {
"core-tools": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"alwaysLoad": true
}
}
}

代价要知道:alwaysLoad: true 会让启动阻塞到该服务器连上(上限是 5 秒的标准连接超时)。MCP 启动本来是非阻塞的,但这些工具必须在构建第一个 prompt 时就在场。其他服务器继续在后台连接。

MCP 工具的可调用名是 mcp__<server>__<tool>。在权限规则、skill 的 allowed-tools、subagent 的 tools 字段、hook matcher 里引用工具时用这个全名。

插件捆绑的 MCP 服务器命名不同,是 mcp__plugin_<plugin-name>_<server-name>__<tool-name>

mcp__plugin_my-plugin_database-tools__query

这一点会造成一个隐蔽的失效:针对裸服务器名写的 hook matcher,比如 mcp__database-tools__.*,对插件捆绑的服务器永远不会触发。hook 没反应时,先确认这个服务器是不是来自插件。

服务器本身注册的名字是 plugin:<plugin-name>:<server-name>,在需要「配置的服务器名」的地方(比如 mcp_tool hook 的 server 字段)用这个。

有一批服务器名是内置保留的:workspaceclaude-in-chromecomputer-useClaude PreviewClaude Browser。配置里用了保留名,Claude Code 加载时跳过并警告;claude mcp add 会直接报错。

MCP 工具输出超过 10,000 token 时 Claude Code 给警告,默认上限 25,000 token。上限可调:

Terminal window
export MAX_MCP_OUTPUT_TOKENS=50000

警告阈值固定,不可调。

经常撞警告的服务器,如果不是你维护的,可以请作者加 anthropic/maxResultSizeChars 标注或做分页。这个标注对返回图片数据的工具无效——那种情况只能调 MAX_MCP_OUTPUT_TOKENS

服务器连不上时,按这个顺序查:

  1. claude mcp list 看健康状态。✔ Connected / ! Needs authentication / ✘ Failed to connect / ⏸ Pending approval 四种状态指向完全不同的原因。注意 WebSocket 服务器不出现在这个列表里,用 claude mcp get <name>/mcp 面板查。
  2. 同一个输出里看有没有缺环境变量的警告。
  3. ⏸ Pending approval 说明是信任问题,交互式跑一次 claude 批准。
  4. ! Needs authentication/mcpclaude mcp login <name> 走 OAuth。
  5. ✘ Failed to connect 且配了 headers.Authorization:如果服务端拒绝这个头,Claude Code 报连接失败,不会回退到 OAuth。确认 token 对这个端点有效,或者干脆删掉这个头改用 OAuth 流程。

claude mcp add 保存配置时不校验凭据,所以占位符值会被接受,问题在之后连接时才暴露。加完总是用 /mcp 确认一次。

  • 挑一个你每天都在手工复制内容的系统(issue 追踪、监控面板),接进来,然后连续用三天。三天后判断它是真的省事了还是只是看起来酷。
  • .mcp.json 里故意写一个未定义的 ${SOME_VAR},跑 claude mcp list 看警告长什么样。这个警告一旦见过一次,以后遇到莫名的 401 就会先想到它。
  • ENABLE_TOOL_SEARCH=false 启动一次,用 /context 对比上下文占用。这能让你对工具定义的 token 成本有具体数字感。
  • WaitForMcpServers 工具的具体行为。文档提到在没有 tool search 的配置里 Claude 用它等待服务器连接,细节没有核实。
  • channels 机制(服务器主动推消息进会话)的完整配置流程。本文只提到它的存在。
  • 自动后台化的边界情况。主对话里超过两分钟的 MCP 调用会转为后台任务,但 subagent 的调用、IDE 服务器的调用不会——这些例外背后的完整规则没有逐条核实。
  • managed MCP 配置(managed-mcp.jsonallowedMcpServers)的部署细节。
这一节有错或讲不清? 提个 Issue 直接改文档 请作者催更