avatar


6.MCP

简介

Claude Code的本质是"大模型+工具调用循环+有限上下文窗口",而工具调用循环(agent loop)的能力上限,就是工具集的上限——内置工具止步于本地文件、shell与通用的网页抓取,接不进数据库、Issue系统、浏览器自动化这类真实工程里天天要碰的外部系统。《5.Hooks》中的Hooks(钩子)把循环内部的固定点管住了,但它管的是流程节点,扩展不了工具集的能力边界;那一章Hook类型里留下的mcp_tool伏笔,本章回收:它引用的正是MCP工具。

给循环补上外部系统这块能力,逐个写脚本、手工导数据都不可持续,需要的是一个标准协议:外部系统按协议把能力暴露出来,Claude Code按协议接入,两边各实现一次。这就是MCP。本章完整展开MCP在交互式使用下的形态:协议提供什么能力、如何添加与管理服务器、认证、权限与命名、性能与安全,最后是排障经验。

MCP是什么

MCP(Model Context Protocol,模型上下文协议)是一个开源标准协议。外部系统实现一个MCP服务器,把自己的能力以标准形式暴露出来;Claude Code作为MCP客户端接入这台服务器,循环里就多了一批可调用的能力。数据库、Jira、GitHub、浏览器,接法完全一致。

一台MCP服务器可以暴露三类能力,它们在Claude Code中各有对应的入口:

能力 是什么 在Claude Code中的入口
Tools(工具) 供Claude调用的可执行函数,如查询数据、调用API 进入工具调用循环,与内置工具一样被自动选用,规范名为mcp__<server>__<tool>
Resources(资源) 可按需读取的数据实体,如一条Issue、一个文件 会话中用@server:scheme://id引用,如@github:issue://123
Prompts(提示) 服务器预置的提示模板 成为斜杠命令/mcp__server__name,如/mcp__github__list_prs

三类能力里,Tools覆盖绝大多数场景;Resources适合把一份外部数据精确拉进上下文;Prompts则把服务器作者写好的任务模板变成一条斜杠命令(提示名与服务器名中的空格会转换为下划线)。

添加与管理服务器

CLI命令

MCP服务器用claude mcp命令族管理:

命令 说明
claude mcp add 添加服务器;远程形式为claude mcp add <name> <url>,本地stdio形式把启动命令放在--之后
claude mcp list 列出所有已配置服务器及连接状态
claude mcp get <name> 查看单台服务器的详细配置与错误详情
claude mcp remove <name> 删除服务器,可用--scope指定从哪个范围删
claude mcp add-json <name> '<json>' 用一段JSON直接配置服务器
claude mcp add-from-claude-desktop 从Claude Desktop导入已配置的服务器
claude mcp login <name> / claude mcp logout <name> OAuth登录与清除凭证,见下文认证一节
claude mcp serve 把Claude Code自身作为一台MCP服务器启动,供其他MCP客户端调用
claude mcp reset-project-choices 重置项目级服务器的批准状态

claude mcp add的常用参数:

参数 说明
--transport {http\|sse\|stdio\|ws} 传输方式,默认stdio,远程推荐http
--scope {local\|project\|user} 配置存储范围,默认local
--header "Key: Value" 附加请求头,常用于传Bearer token
--env KEY=value 传递给服务器的环境变量
--client-id--client-secret--callback-port <PORT> 预配置OAuth凭证,见下文认证一节

传输方式

传输 用途 特点 认证方式
HTTP 远程托管服务(推荐) 标准请求响应,可靠性高 OAuth、Bearer token、headersHelper
SSE 远程托管(已废弃) Server-Sent Events单向推送,仅为兼容旧配置保留 静态header
stdio 本地进程 以子进程方式启动本地程序,可访问本地文件与数据库socket 环境变量、本地权限
WebSocket 持久连接、事件推送 双向通信,不支持OAuth 静态header、headersHelper

选型准则一句话:本地进程选stdio,远程一律HTTP;SSE只在迁移旧配置时会遇到,WebSocket留给需要持久双向连接的场景。另外,stdio服务器的进程环境里会注入CLAUDE_PROJECT_DIR(项目根目录),本地服务器可据此定位项目文件。

配置范围

同一台服务器登记在哪个范围,决定了它对谁生效、存在哪个文件里:

范围 存储位置 生效范围 进版本库
local ~/.claude.json中当前项目的条目 仅当前项目、当前用户
project 项目根目录的.mcp.json 克隆该仓库的所有人
user ~/.claude.json顶层的mcpServers 当前用户的所有项目
plugin 插件内打包的.mcp.json 插件启用时自动加载,见《9.Plugins》 随插件分发
claude.ai 云端(claude.ai的connectors配置页) 登录该账户的Claude Code 否(云端)

同名服务器同时存在于多个范围时,按local>project>user>plugin>claude.ai取高优先级的那个。不想加载claude.ai连接器时,可在settings.json中设disableClaudeAiConnectors: true,或以环境变量ENABLE_CLAUDEAI_MCP_SERVERS=false启动。

.mcp.json

claude mcp add --scope project写入的就是项目根目录的.mcp.json,也可以直接手写。示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"headers": {
"Authorization": "Bearer ${GITHUB_TOKEN}"
}
},
"mydb": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "${DB_URL:-postgresql://localhost:5432/appdb}"]
}
}
}

主要字段:

字段 适用传输 说明
type 全部 httpssestdiows之一
url HTTP/SSE/WS 服务器端点
headers HTTP/SSE/WS 静态请求头
headersHelper HTTP/WS 指向一个脚本,运行时用其输出作为请求头,见下文认证一节
oauth HTTP 预配置OAuth:clientIdcallbackPortscopesauthServerMetadataUrl
commandargsenv stdio 本地进程的启动命令、参数与环境变量
timeout 全部 超时,毫秒
alwaysLoad 全部 跳过工具延迟加载,见下文性能一节

配置值支持环境变量展开:${VAR}在运行时替换为环境变量值,${VAR:-default}在变量未设置时使用默认值;展开在commandargsurlheadersenv字段中都生效。这是把.mcp.json安全提交进仓库的关键——文件里只留${GITHUB_TOKEN}这样的引用,真实凭证在每个人自己的环境变量里。

会话内管理

会话内运行/mcp打开交互面板,可以查看各服务器的连接状态与工具数量、发起认证、手动重连或切断连接。

注意:.mcp.json在会话启动时一次性读取,改动配置后必须重启会话才生效。

认证

远程服务器的标准认证是OAuth,流程是:

  1. 添加服务器,如claude mcp add --transport http <name> <url>
  2. 会话内运行/mcp,选中该服务器,执行Authenticate
  3. 浏览器完成登录后,token由Claude Code保存并自动刷新。

不进会话也可以直接在命令行认证:claude mcp login <name>;在SSH或没有图形界面的机器上加--no-browser,会改为给出URL让我们在别处完成登录。claude mcp logout <name>清除已存储的凭证。

有些服务器不支持OAuth动态注册,需要预先配置凭证。示例代码:

1
2
3
claude mcp add --transport http \
--client-id <ID> --client-secret --callback-port 8080 \
my-server https://internal.example.com/mcp

注意:--client-secret不直接跟值,命令会提示输入,避免密钥留在shell历史里。

不走OAuth的自定义认证(如公司SSO换token),用headersHelper字段指向一个脚本,由脚本动态生成请求头,见下文示例一节。

token刷新失败时,交互会话里会收到通知,指引回/mcp面板重新认证;非交互运行(-p或Agent SDK)时没有人可提示,Claude会被告知相应工具不可用,并指名需要重新认证的服务器。

权限与命名

每台服务器的每个工具,在Claude Code里都有一个规范名,模式为mcp__<server_name>__<tool_name>,例如GitHub服务器的create_issue工具就是mcp__github__create_issue。服务器名与工具名中不属于A-Za-z0-9_-的字符会被替换为_

这个命名空间可以直接用在权限规则里:写完整工具名精确控制单个工具,写mcp__<server>__*通配整台服务器。示例代码:

1
2
3
4
5
6
{
"permissions": {
"allow": ["mcp__github__*"],
"deny": ["mcp__dangerous_server__*"]
}
}

权限规则的通用语法、六种模式与deny>ask>allow的优先级见《1.概述》,本节只是MCP命名空间下的增量。

另外,项目级.mcp.json来自仓库、可能由别人提交,所以其中的服务器首次使用前需要我们显式批准;批准状态可用claude mcp reset-project-choices整体重置。

性能与安全

性能

  • 工具延迟加载(默认启用)
    启动时只加载服务器名与说明,具体的工具定义在需要时才查询。这使得配置大量服务器也不会把上下文成本抬高。加载策略由环境变量ENABLE_TOOL_SEARCH控制,取值truefalseautoauto:N
  • alwaysLoad
    对少数关键服务器,在配置中设"alwaysLoad": true,其工具定义始终加载,跳过按需查询。
  • 输出上限
    MCP工具单次返回超过10000 tokens会触发警告,上限可用环境变量MAX_MCP_OUTPUT_TOKENS调整(如MAX_MCP_OUTPUT_TOKENS=50000)。服务器作者可在工具元数据_meta["anthropic/maxResultSizeChars"]中声明支持更大的结果,硬上限500000字符。
  • 远程超时
    HTTP服务器的首字节等待预算至少60秒;空闲5分钟无响应会自动中止,可用环境变量CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT(毫秒)调整。stdio本地进程不受这两条限制。

安全

第一是信任问题。MCP服务器有权访问Claude会话中的全部内容与工具结果,接入一台服务器等于把会话敞开给它,只连接我们信任的服务器(Anthropic Directory中的服务器经过审查)。

第二是凭证安全。OAuth token由Claude Code自动刷新,存储在系统密钥链(macOS)或凭证文件(Windows/Linux)中,不落入项目目录;而静态Bearer token一旦明文写进.mcp.json,就会随仓库提交而泄露。敏感值按上文的${VAR}约定引用环境变量,或改用headersHelper动态获取,不要硬编码。

还要警惕提示注入风险。MCP服务器返回的内容会进入Claude的上下文,恶意服务器可以在返回数据里夹带指令(如"忽略之前的所有指令")。权限系统与上下文隔离是主要防线,但根本办法仍是只用可信来源的服务器。

示例

三个示例来自同一个场景:一个Web项目团队,要让Claude Code接入GitHub、项目数据库和公司内部API。

第一步,接GitHub,HTTP传输加Bearer token。示例代码:

1
2
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_TOKEN"

默认写入local范围,只对当前项目、当前用户生效。添加后三类能力全部就位:让Claude"把刚才的报错整理成issue提交"走的是工具调用;@github:issue://123把一条issue精确拉进上下文;/mcp__github__list_prs直接执行服务器预置的提示。

第二步,接项目数据库,用项目范围让全组共享。示例代码:

1
2
claude mcp add --scope project \
mydb -- npx -y @bytebase/dbhub --dsn '${DB_URL:-postgresql://readonly@localhost:5432/appdb}'

--scope project把配置写进项目根目录的.mcp.json,提交后同事克隆仓库即用;--之后是stdio服务器的启动命令,单引号防止shell提前展开,让${DB_URL:-...}字面量原样写进.mcp.json,运行时再按上文的环境变量展开规则取值:设置了DB_URL环境变量的人连自己的库,没设的用默认的本地连接串,真实凭证始终不进仓库。给Claude的数据库账号建议用只读账号,把风险从"会不会误操作"降为"最多读到什么"。

第三步,接公司内部API。它走SSO而非标准OAuth,手写.mcp.jsonheadersHelper。示例代码:

1
2
3
4
5
6
7
8
9
10
11
{
"mcpServers": {
"corporate-api": {
"type": "http",
"url": "https://internal.company.com/mcp",
"headersHelper": "/usr/local/bin/mcp-sso-headers.sh",
"timeout": 30000,
"alwaysLoad": true
}
}
}

headersHelper指向的脚本在标准输出打印一个JSON对象作为附加请求头(如{"X-Token": "..."}),token的获取与刷新逻辑都在脚本里,配置文件中不出现任何凭证;timeout按内网延迟收紧到30秒;alwaysLoad让这台高频服务器的工具始终加载。改完重启会话,claude mcp list确认三台服务器都在线。

经验

排障优先看这张表:

症状 原因 处理
提示"No MCP servers configured" local范围的服务器绑在别的项目上 --scope user重新添加,或回到原项目根目录运行claude
“Failed to connect"或"Connection error” HTTP端点404/502,或stdio命令不存在 远程用curl -I <url>检查端点;本地在终端直接运行该命令看报错
“Needs authentication” 服务器返回401/403,或必须OAuth /mcp面板选中服务器执行Authenticate,或claude mcp login <name>
启动超时 stdio服务器首次下载依赖太慢 MCP_TIMEOUT=60000 claude(毫秒)延长启动等待
工具输出过大的警告 单次返回超过10000 tokens 调大MAX_MCP_OUTPUT_TOKENS;同时让查询自带收敛条件(如LIMIT)
.mcp.json改动不生效 配置在会话启动时一次性读取 重启会话
项目服务器显示"Pending approval" 新的项目级配置未经批准 交互运行claude完成确认;需要重新决定时用claude mcp reset-project-choices

MCP相关的环境变量集中如下:

环境变量 作用
MCP_TIMEOUT 服务器启动超时(毫秒)
MAX_MCP_OUTPUT_TOKENS 工具输出token上限
ENABLE_TOOL_SEARCH 工具延迟加载策略(true/false/auto/auto:N
CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT 远程工具空闲超时(毫秒)
ENABLE_CLAUDEAI_MCP_SERVERS 设为false时不加载claude.ai连接器

范围的选择有个简单次序:个人通用工具放user,团队共享放project,单项目试验用默认的local;排障时先用claude mcp get <name>确认服务器到底登记在哪一层,再谈连接问题。

除本章的交互形态外,MCP还有两处延伸:Agent SDK可以在进程内直接定义MCP服务器、不需要独立进程,见《8.SDK》;MCP服务器也可以随插件打包分发、随插件启用自动加载,见《9.Plugins》

至此,工具调用循环的能力边界补齐了:数据库、Issue系统、浏览器都能以标准方式接进来。但这一切仍发生在有人守着的终端里——答权限提示、读输出、发下一轮指令。把人从循环里移出去,让Claude Code以Headless模式(非交互模式)在脚本与CI/CD中无人值守地运行(那里的MCP配置改由--mcp-config参数传入),是下一章《7.Headless》的主题。

文章作者: Kaka Wan Yifan
文章链接: https://kakawanyifan.com/128060
版权声明: 本博客所有文章版权为文章作者所有,未经书面许可,任何机构和个人不得以任何形式转载、摘编或复制。

留言板