Claude Code 接 MCP 服务器:三种 scope 存在哪、四种传输怎么选、工具搜索为什么默认开
判断该不该接 MCP 服务器的标准很具体:你有没有在反复从另一个工具里复制数据粘贴进对话。issue 描述、监控面板的报错、数据库查询结果——如果这些内容你每天都在手工搬运,那个系统就该接进来。反过来,为了「功能齐全」而接一堆用不上的服务器,只是在消耗启动时间。
三种 scope 的存储位置容易记混,先记住这张表:
| scope | 在哪些项目里加载 | 团队共享 | 存储位置 |
|---|---|---|---|
| local(默认) | 仅当前项目 | 否 | ~/.claude.json |
| project | 仅当前项目 | 是,通过版本控制 | 项目根的 .mcp.json |
| user | 你的所有项目 | 否 | ~/.claude.json |
旧版本对 scope 的叫法不同:现在的 local 曾叫 project,现在的 user 曾叫 global。看老文章时注意这一层。
四种传输方式
Section titled “四种传输方式”# HTTP:远程服务器的推荐选择claude mcp add --transport http notion https://mcp.notion.com/mcp
# 带 Bearer tokenclaude 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.json或claude mcp add-json配。
在 JSON 配置里,type 字段接受 streamable-http 作为 http 的别名。MCP 规范用的是前者这个名字,所以从服务端文档抄来的配置可以直接用。
stdio 服务器的 -- 是必须的
Section titled “stdio 服务器的 -- 是必须的”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 和服务器名之间放一个其他选项。
一个常见的配置错误
Section titled “一个常见的配置错误”JSON 配置里写了 url 但没写 type,是配置错误。Claude Code 把没有 type 的条目当作 stdio 服务器,于是报:
MCP server "<name>" has a "url" but no "type"; add "type": "http" (or "sse" / "ws") to this entryv2.1.202 之前这个错误的措辞是 command: expected string, received undefined,看起来完全不像是缺 type 导致的。搜到旧报错信息时,答案是加 type 字段。
project scope 与信任边界
Section titled “project scope 与信任边界”project scope 的服务器写在项目根的 .mcp.json 里,提交进版本控制,团队每个人拿到同一套工具:
{ "mcpServers": { "shared-server": { "type": "http", "url": "https://example.com/mcp" } }}出于安全考虑,使用 .mcp.json 里的服务器之前 Claude Code 会要求你批准。要重置批准记录:
claude mcp reset-project-choices这里有一层容易忽略的防御。v2.1.196 起,在你信任这个 workspace 之前(跑一次 claude 并接受信任对话框),claude mcp list 和 claude mcp get 只从没有提交进仓库的设置文件读取 .mcp.json 的批准记录。
意思是:一个克隆下来的仓库不能自己批准自己的服务器。提交在项目 .claude/settings.json 里的 enableAllProjectMcpServers 或 enabledMcpjsonServers 在未信任的文件夹里被忽略,服务器停在 ⏸ Pending approval 状态。
在未信任的文件夹里仍然生效的批准来源:
- 你的
~/.claude/settings.json - managed 设置
- 通过
--settings传入的设置
disabledMcpjsonServers 里的条目在任何设置文件里都能拒绝服务器——拒绝方向不受信任门槛限制。
.mcp.json 的环境变量展开
Section titled “.mcp.json 的环境变量展开”团队共享配置时,机器相关的路径和密钥不能写死。.mcp.json 支持两种展开语法:
${VAR}:展开为环境变量的值${VAR:-default}:有值用值,无值用默认
可展开的位置:command、args、env、url、headers。
{ "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.json 的 command 或 args 里用 ${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 时就在场。其他服务器继续在后台连接。
工具命名与权限规则
Section titled “工具命名与权限规则”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 字段)用这个。
有一批服务器名是内置保留的:workspace、claude-in-chrome、computer-use、Claude Preview、Claude Browser。配置里用了保留名,Claude Code 加载时跳过并警告;claude mcp add 会直接报错。
MCP 工具输出超过 10,000 token 时 Claude Code 给警告,默认上限 25,000 token。上限可调:
export MAX_MCP_OUTPUT_TOKENS=50000警告阈值固定,不可调。
经常撞警告的服务器,如果不是你维护的,可以请作者加 anthropic/maxResultSizeChars 标注或做分页。这个标注对返回图片数据的工具无效——那种情况只能调 MAX_MCP_OUTPUT_TOKENS。
服务器连不上时,按这个顺序查:
claude mcp list看健康状态。✔ Connected/! Needs authentication/✘ Failed to connect/⏸ Pending approval四种状态指向完全不同的原因。注意 WebSocket 服务器不出现在这个列表里,用claude mcp get <name>或/mcp面板查。- 同一个输出里看有没有缺环境变量的警告。
⏸ Pending approval说明是信任问题,交互式跑一次claude批准。! Needs authentication用/mcp或claude mcp login <name>走 OAuth。✘ 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 成本有具体数字感。
还没确认的点
Section titled “还没确认的点”WaitForMcpServers工具的具体行为。文档提到在没有 tool search 的配置里 Claude 用它等待服务器连接,细节没有核实。- channels 机制(服务器主动推消息进会话)的完整配置流程。本文只提到它的存在。
- 自动后台化的边界情况。主对话里超过两分钟的 MCP 调用会转为后台任务,但 subagent 的调用、IDE 服务器的调用不会——这些例外背后的完整规则没有逐条核实。
- managed MCP 配置(
managed-mcp.json、allowedMcpServers)的部署细节。