Model Context Protocol(MCP) 提供了一种标准化方式,让 AI 应用能够通过统一接口连接到工具、数据源和服务。开发者不再需要为每一个宿主应用单独构建一套集成逻辑,而是只需要在一个 MCP server 中实现一次功能,就可以在任何兼容 MCP 的客户端中复用。MCP 正是为了解决这一类集成难题而诞生的。这个抽象层带来了互操作性、可移植性以及生态系统增长。在 Claude Code 的语境下,MCP 尤其重要,因为它让开发者能够以结构化、可复用的方式,为这个编码智能体扩展更多工具、能力与集成。
在本章中,你将学习 MCP 是什么、它为什么会被创造出来,以及它在实践中是如何工作的。你会了解 MCP 所解决的集成问题,并考察它的核心架构组件:host、client 和 server。通过实际演示,你会把 MCP server 连接到 Claude 和 Cursor 这样的 AI 应用上,配置本地与远程 MCP server,并理解工具是如何通过这个协议暴露出来并被调用的。
你还会看到一些重要的运行层面考量。MCP 很强大,但它也会带来与上下文管理、性能和执行效率相关的挑战。本章会介绍一些上下文工程策略,用于减少上下文污染、正确限定 MCP 配置范围,并在一个会话中动态管理 server。此外,你还会学习 Claude Code plugin 如何把 MCP server 以及相关组件打包成可复用、可分享的单元,从而实现团队范围内的标准化。
本章的整体目标,是帮助你在 MCP 上建立一个扎实的概念基础与实践基础。到最后,你不仅会理解 MCP 如何实现跨平台工具集成,还会知道如何在真实 AI 系统中,以负责任的方式去配置和管理它。
这项知识之所以重要,是因为 MCP 正在迅速成为 agent-based architecture(基于智能体的架构)中的基础层。随着 AI 开发转向工具增强型系统与自主系统,理解 MCP 的架构、优势和取舍,将让你能够设计出可扩展、高效率、可互操作的 AI 应用。
本章将涵盖以下主题:
- 为什么需要 MCP
- MCP 核心架构
- MCP 的实际运行方式
- 将 Claude Code 连接到 MCP server
- MCP scope 速查表
- MCP 生态中的上下文工程
- 项目级 MCP 配置
- MCP 当前的局限
- 使用 Claude Code plugin 管理配置
虽然本书以 Claude Code 为中心,但 MCP 是一个跨平台协议,已经被多个 AI 开发工具支持。为了演示方便,本章在某些例子中会使用 Cursor。不过底层概念是一样的,在 Claude Code 中同样适用。
为什么需要 MCP?
MCP 在短时间内获得了快速普及,如今围绕它的讨论非常广泛,也已经出现了大量 MCP server 的实现。很多 AI 应用,包括 Claude Code 和 Cursor 这样的工具,都已经把 MCP 集成进自己的系统中。
在正式定义 MCP 之前,先理解它所解决的需求,会更重要。
集成问题
设想这样一个 AI agent:它需要执行发送 Slack 消息、读取和发送邮件,或者查询数据库这类操作。为了让它具备这些能力,你就必须亲自实现对应功能。这意味着你需要对接 Slack 或 Gmail 这类 API,并编写自定义代码,把这些集成封装成 agent 可调用的 tools。
图 4.1 —— Agent 通过 API 与 Slack、Gmail 和数据库集成
在很多场景中,自定义实现是必要的。比如,某个邮件集成可能会故意不暴露 Gmail API 的 delete endpoint,以防止意外删数据。于是,这套集成逻辑就会根据具体需求被手工定制实现。
某些框架会提供内置 tools。比如,一个框架可能已经内建了 Gmail 集成,并覆盖了整个 API 能力面。这种现成工具对于通用需求是可以开箱即用的。但无论你用的是内置工具还是自定义工具,这些功能最终都必须被集成到某个特定的 agent 环境里。
一旦这些能力被实现,这个 agent 就能够发邮件、发 Slack 消息、执行数据库查询。问题是:这套集成只在那个特定 agent 环境中有效。
可移植性挑战
假设这个 agent 变得很受欢迎,其他团队也希望在不同环境里复用它的功能。
比如,最初这个 agent 是为了跑在 Cursor 环境中而构建的。在这个设定下,它通过各自的 API 与 Slack、Gmail 和数据库集成。下图展示了这种架构。
图 4.2 —— 与 Cursor 环境及其 API 集成强耦合的 Agent
在这种情况下,这个 agent 与 Cursor 环境是强耦合的。它对 Slack、Gmail 和数据库的集成,都是专门为这套环境实现的。
现在假设我们希望把同样的 agent 能力接入 Claude Code。虽然从概念上看,功能并没有变化,但原有集成并不能直接复用。因为那套实现是专门写给原来的 agent 环境的,所以要接入 Claude Code,就必须重新做一遍集成。
结果就是,类似“发送 Slack 消息”“操作 Gmail”“执行数据库查询”这种能力,都要为新环境重新实现。再往后想一层:如果还想把这套能力接到别的环境,比如 Cursor、Bolt、GitHub Copilot 或其他 AI 编码助手中,你就得一次次重复这个过程。
图 4.3 —— 为 Claude Code 环境重新实现 Agent 集成
每增加一个新环境,都会新增一轮实现工作。同样一套功能,必须为每一个目标系统单独适配。
MCP 作为抽象层
这个可移植性问题,本质上会不断重复出现:每当同样的功能要在另一个环境里复用时,开发者都必须从头重做集成。
MCP 通过引入一个额外的抽象层来解决这个问题。软件工程中有一句很著名的话:
“我们可以通过再加一层间接层,解决任何问题。”
—— Andrew Koenig
这个思想和软件工程基本定理是相通的:很多复杂系统问题,都可以通过加一层抽象来简化。MCP server 就扮演了这样一个角色。
与其把功能分别集成进每个 agent,不如把这套功能实现一次,并放进一个 MCP server 里。随后,所有支持 MCP 的 agent 都可以直接连接到这个 MCP server。
图 4.4 —— 作为统一集成层的 MCP server,连接外部服务
这样一来,兼容性只需要实现一次。只要某项能力通过一个 MCP server 暴露出来,它就能被所有支持该协议的平台使用。原本只为 Cursor 实现的能力,也就自然变得可以被 Claude Code 和其他 MCP 环境调用,而不需要再写额外的集成逻辑。
开发者不再需要为每个平台重写或复制集成代码。任何支持 MCP 的系统,都可以无缝接入并使用这些能力。
网络效应与生态增长
MCP 的增长呈现出一种类似社交平台的网络效应。一个用户很少的社交产品,本身价值有限;但随着用户增多、内容变丰富,整个系统就会越来越有价值,从而进一步强化增长循环。
MCP 身上也在发生类似的事情。随着采用率上升、越来越多的 MCP server 被开发出来,整个生态也在不断扩展。实现数量越多,可用的集成和能力就越丰富,协议本身的总体价值也随之提升。
在理解了这一点之后,接下来就该进入 MCP 的核心架构,看看它在实践中究竟是如何运作的。
MCP 核心架构
MCP 标准化了应用向大语言模型(LLM)提供上下文的方式。上下文可以有多种形式。它可能是附加到 Prompt 后面的额外信息,也可能是一个要调用的工具定义,甚至 Prompt 本身也可以被视为上下文。
图 4.5 —— 连接 host、client 与 MCP server 的 MCP 核心架构
从这个角度看,所谓上下文,不仅包括辅助性数据,还包括会影响 LLM 响应方式的操作性指令。
一旦这样的标准被广泛采用,它就能在 AI 应用之间催生出强大而可扩展的集成能力。
MCP 的优势
MCP 官方文档(https://modelcontextprotocol.io/)强调了若干采用 MCP 的优势:
第一,MCP 支持一个广泛的集成生态,涵盖工具、数据源和各种服务,这些都可以用模块化方式接入 LLM 驱动的应用。举例来说,Claude Code 作为一个 AI 编码智能体,就利用 MCP 通过结构化的工具集成来扩展自己的能力。
第二,MCP 降低了系统对特定 LLM 厂商或 AI 应用提供方的耦合。开发者可以把核心能力实现成 tools,并通过 MCP server 暴露出来。随后,这些工具就能跨不同厂商和 host 应用复用,而不需要改动。
像 LangChain 这样的开源框架,也在解决 AI 工程中某些相邻的问题。不过,MCP 和 LangChain 看待这些问题的方式并不相同,它们的解决方案也不直接重叠。比如,它们都可能支持扩展性,但具体机制和架构含义是不同的。
MCP 的核心组件
MCP 的架构由三个主要组件构成:MCP host、MCP server 和 MCP client。
MCP hosts
MCP host 是指支持 MCP 的 AI 应用。典型例子包括 Claude Desktop、Claude Code 或 Cursor 这样的开发环境,以及各种专门化 AI agents。通过连接额外的工具、数据源或产品,这些应用能够被 MCP 增强,从而获得原生不具备的能力。
图 4.6 —— MCP host 通过 MCP client 连接到 MCP server
MCP servers
MCP server 用来向 MCP host 暴露功能。这些功能可能包括:
- 调用外部工具,例如通过 API 获取天气信息
- 数据库搜索能力
- 知识资源,例如 PDF 或大段文本内容
图 4.7 —— MCP server 向 MCP host 暴露工具、数据库和外部 API
MCP server 本质上是一个 gateway 或 proxy,它按照 MCP 规范,把这些 tools、resources 和 prompts 暴露出去。
图 4.8 —— 作为网关的 MCP server,为外部资源提供标准化访问方式
为了符合协议,一个 MCP server 需要实现特定方法,例如:
listPromptsgetPromptlistToolscallToollistResourceTemplates- 进度通知机制
一旦这些方法被实现,这个 MCP server 就可以连接到任何支持该协议的 MCP host。也就是说,一次实现,多端复用。这种复用性正是 MCP 的核心架构优势之一。
MCP clients
MCP client 位于 MCP host 内部。它负责让 host 和 MCP server 通过 MCP 进行通信。
图 4.9 —— 位于 host 内部、负责与 MCP server 通信的 MCP client
例如,如果要把一个 weather MCP server 接入 Claude Desktop,那么 Claude Desktop 内部就会有一个 MCP client 来管理与该 server 的交互。client 和 server 之间的通信完全遵循协议本身。
这里有一个重要细节:一个 MCP client 与一个 MCP server 是一对一关系。一个 MCP client 不能同时与多个 MCP server 通信。因此,如果一个 MCP host 需要连接多个 MCP server,它就必须为每个 server 各自实例化一个 MCP client。
图 4.10 —— 多个 MCP client 将一个 host 连接到不同的 MCP server
至此,MCP 的核心架构就完整了,也为构建可互操作、可扩展的 AI 应用打下了基础。
MCP 的实际运行方式
接下来我们通过一个实际例子,走一遍添加和配置 MCP server 的过程。这个演示展示了 MCP 带来的能力,以及这些能力在实践中是如何表现的。例子中,我们将一个实现天气查询功能的 MCP server,接入到两个不同客户端:Claude Desktop 和 Cursor。
这两个场景用的是同一个 MCP server。配置细节会分别处理,这里更关注的是:server 接入之后,系统会表现出什么行为。任何支持 MCP 协议的客户端都可以使用这项能力,包括 Claude Code、Claude Desktop、Cursor、Lovable 以及其他兼容客户端。
没有 MCP server 时的行为
在 Claude Desktop 中,起初并没有在 Developer 设置里配置任何 MCP server。比如,如果你问旧金山的天气,而系统还没接入 MCP server,那么语言模型通常会回答:它无法访问实时天气信息。有时它可能会尝试调用一个 search 工具去获取摘要化信息。
没有 MCP 时,模型只能依赖训练数据,无法直接获取实时数据;最多只能借助一些通用内置工具,例如搜索。
连接 MCP server
当 weather MCP server 被配置好之后,它就会出现在 Claude 的 Developer 设置中,并显示运行时细节。
图 4.11 —— 在 Claude Developer 设置中配置好的 Weather MCP server
这时你再问一次旧金山天气,系统就会弹出权限请求,询问是否允许在本地执行 weather tool。之所以需要批准,是因为工具调用可能涉及本地代码执行。相关安全问题我们后面单独讨论。
安全警告:MCP server 可以在你的机器上运行代码
MCP server 会在本地运行,并继承与你当前用户账户相同的权限。这意味着它可以访问你的文件、环境变量和网络资源。
在添加 MCP server 之前,你需要意识到这些风险:
- MCP server 可以在你的机器上执行命令,包括读取、修改甚至删除文件
- 恶意 server 可能把敏感信息(例如源码、环境变量或 API Key)发送到外部服务
- 来自 MCP server 的 tool response 里,可能携带隐藏指令,从而影响模型行为
因此,MCP server 应该被视为一种第三方依赖。尽量审查源码,只安装来自可信维护者的 server,并避免使用高权限运行它们。
一旦你允许 Claude Code 调用 MCP 工具,执行序列就会是这样:
- MCP server 内部包含获取天气数据的逻辑
- 它暴露了一个名为
getForecast的函数 getForecast接收两个参数:纬度和经度- 语言模型(这里是 Claude Sonnet 3.7)先判断出旧金山对应的经纬度
- 然后模型发起一次对
getForecast的 MCP 调用 - MCP server 执行该函数并返回响应
- 最后,语言模型处理响应并生成最终答案
图 4.12 —— Claude 调用 Weather MCP 工具并返回天气预报
得到的结果,就是基于 MCP server 实时拉取数据生成的天气报告。
虽然天气查询只是一个简单示例,但底层机制支持的是任意逻辑。任何功能都可以被实现成一个 MCP server。只要实现了 MCP 协议,兼容客户端就能通过工具调用来执行这些功能。这样,AI agent 的能力就不再局限于静态模型本身,而能够真正运行外部逻辑。
在多个客户端之间复用同一个 MCP server
同样的 weather MCP server 也可以接入 Cursor。配置完成后,它会出现在 Cursor 设置中的 MCP 标签页里。
图 4.13 —— 同一个 Weather MCP server 在 Cursor 中可用
连接后的 server 会显示它暴露的工具:
GetAlertsGetForecast
配置中还会展示启动这个 server 的命令。在这个例子里,它是一个 Node.js server。在 Cursor Chat 中,MCP 功能可以在 agent mode 下使用。
图 4.14 —— 在 Cursor 的 Agent Mode 中调用 Weather MCP 工具
这时再问旧金山天气,agent 会带上正确参数调用 GetForecast。在这里,Cursor 运行在 YOLO mode 下,也就是说工具会自动执行,而不再需要手工批准。虽然这样更方便,但也确实有安全代价。
整个过程中,agent 会:
- 用纬度与经度参数调用
GetForecast - 从 MCP server 获取天气数据
- 判断天气预警信息也可能相关
- 再调用
GetAlerts查询旧金山是否存在天气告警 - 最后把两个响应组合成一个最终答案,既包含天气情况,也包含告警信息
在这个例子里,一个 Prompt 之下调用了两个工具。agent 自主判断该调用哪些工具,并决定如何把它们的结果组织成一份连贯回答。
天气示例展示的是一个普遍模式:MCP 让 AI agent 能够执行定义在 MCP server 中的外部逻辑。 任何支持 MCP 的客户端,都能连接这些 server 并调用其中的工具。
只要开发者在 server 中实现 MCP 协议,它的功能就会自动对所有兼容客户端开放。这样,系统就摆脱了静态模型知识的限制,agent 得以执行动态、实时、定制化的操作。
将 Claude Code 连接到 MCP server
我们从一个空项目开始,并使用本书 GitHub 仓库中的一个空分支 project/MCP。仓库链接可通过前言中 Download the example code files 一节获取。接着,我们使用 /mcp 这个斜杠命令查看当前可用的 MCP server。此时列表中还没有任何 MCP server。
图 4.15 —— 在 Claude Code 中使用 /mcp 查看可用 MCP server
这里会提供一个链接,带你进入 MCP 文档,说明如何添加 MCP server。添加方式有多种:
- 通过文件添加 MCP server
- 通过 CLI 添加 MCP server
虽然可以通过文件配置,但更推荐使用 CLI。因为 CLI 通常是最新的;如果格式变化或者 API 发生变化,CLI 往往能更好地保证兼容性。
通过 CLI 添加 Context7 MCP Server
Context7(https://context7.com/)提供大量包的最新文档。尤其是在 AI 生态里,很多包(例如 LangGraph)变化很快,而拥有最新文档,意味着生成出来的代码能和最新 API 保持一致。
Context7 索引了将近 30,000 个包(https://github.com/upstash/context7),在写作本书时,该仓库大约有 49,200 个 stars。
要在 Claude Code 中使用 Context7,需要做 Claude Code integration。命令如下:
claude mcp add --transport http context7 https://mcp.context7.com/mcp
这条命令做了以下几件事:
- 使用
claude mcp add - 指定传输协议为 HTTP
- 指定 MCP 名称为
context7 - 提供 MCP server 的 URL
这是一个远程 MCP server,也就是说 server 并不运行在本地,而是运行在 Context7 的服务器上。
每一次调用,都会向远端 server 发起请求。这种方式有几个优点:
- 服务端更容易扩展
- 同一个 MCP 可以被多个客户端复用
关于 HTTP transport 和 remote MCP server,更深入的说明可以参考 Udemy 上的 MCP 课程:
https://www.udemy.com/course/model-context-protocol/
你可以把这条命令复制粘贴到终端里。执行前,可以先加上 --help 看看可用参数。
MCP server 的 scope 与配置
帮助输出会显示:MCP server 可以配置在不同 scope 下。可选 scope 包括:
- User scope
- Project scope
- Session scope
你也可以额外提供环境变量或 HTTP headers。
图 4.16 —— 使用 mcp add 命令向项目添加 MCP server
在这个例子中,我们选择 project scope 来添加 MCP server。
执行后,会生成一个新文件,其中包含 Context7 MCP 的配置。配置内容大致如下:
{
"mcpServers": {
"context7": {
"type": "http",
"url": "https://mcp.context7.com/mcp"
}
}
}
如果希望本地运行这个 MCP server,而不是用远程方式,也可以使用如下替代命令:
claude mcp add context7 -- npx -y @upstash/context7-mcp
这条命令会用 npx 下载对应仓库并在本地执行。
重启 Claude Code 并启用 MCP server
安装完 MCP server 后,需要重启 Claude Code。退出当前会话,清空终端,然后重新启动 Claude。
图 4.17 —— Claude Code 启动后检测并启用配置好的 MCP server
启动时,Claude 会检测到 mcp.json 文件,并询问你是否允许连接其中配置的 MCP server。这里选择第一个选项,允许连接。
随后,Claude 会为当前用户会话创建一个 settings.local.json 文件。打开这个文件,就能看到 Context7 MCP server 已经被启用,Claude 后续就可以在需要时调用它。
列出并检查已安装的 MCP server
现在就可以列出 MCP server 了。我们能看到 Context7 已经接入。
图 4.18 —— 列出已安装的 MCP server,并查看已连接的 Context7
点进去之后,可以看到它暴露了两个工具:
resolve-library-idget-library-docs
这些工具的描述会成为 agent 上下文的一部分,使得 agent 能够在运行时按需调用它们。比如,当你让系统获取最新版 LangGraph 文档时,它会先调用 resolve-library-id 获取合适的上下文 ID,然后再调用 get-library-docs 把最新文档拉回来。
通过 Context7 MCP server 查询 LangGraph
我们可以问这样一个问题,并明确指定希望使用 Context7 MCP server:
What is the latest version of LangGraph?
Claude Code 会请求权限调用 Context7 MCP 工具。批准后,这个权限会被写入 settings.local.json。
图 4.19 —— 调用 Context7 MCP 工具获取最新的 LangGraph 版本
MCP server 会先解析 library ID,然后再发出一次请求以获取文档。
根据 Context7 返回的文档,当时 LangGraph 的最新版本是 1.2。
LangGraph 是一个快速演进中的框架。你在实际使用时看到的版本,可能会比书里的示例更新;不过,这里讨论的架构概念和设计模式仍然成立。
将 MCP server 的使用习惯持久化到项目 Memory 中
我们可以进一步配置:以后每次问到 LangGraph 时,都自动使用 Context7。为此,我们把这条指令写入项目 memory,让它在跨会话场景下持续生效。
这条指令会被记录下来,并写入一个 Claude.md 文件,内容类似:
When discussing LangGraph, always use context7 MCP
验证持久化后的 MCP 行为
接着我们可以重启 Claude,清空会话,再问:
What is a LangGraph interrupt?
Claude Code 会自动选择 Context7 MCP server。它会解析 LangGraph 对应的库、获取相关文档和代码片段,然后返回关于 LangGraph interrupt 的解释。
图 4.20 —— Claude 自动使用 Context7 MCP server 解释 LangGraph interrupt
由于 Context7 提供的是最新文档与 API,生成出来的代码也会更贴近当前真实用法。
将 MCP 产物提交到版本控制中
我们可以把这些生成出的文件加入 GitHub 仓库。使用如下 commit message 提交:
git commit -m "context7 mcp"
然后再 push 到远端仓库。这个 commit 可以在本书 GitHub 仓库中找到。获取仓库链接的方式同样请参考前言中的 Download the example code files。
MCP Scope 速查表
正确选择 scope,有助于保持环境整洁,并避免无关配置泄漏到不相关项目中。下表总结了每种 MCP scope 的适用场景:
| 维度 | Project-scope | User-scope | Session-scope |
|---|---|---|---|
| 配置位置 | 项目根目录下的 .mcp.json | ~/.claude/settings.json | 使用 --mcp-config 启动,或在会话中途添加 |
| 可见范围 | 项目内所有人 | 只有你自己,跨所有项目 | 仅当前会话 |
| 是否提交到 Git | 是 | 否 | 否 |
| 是否跨会话持久化 | 是 | 是 | 否 |
| 是否与团队共享 | 是 | 否 | 否 |
表 4.1 —— MCP scope 对比:project、user 与 session
每种 MCP Scope 适合在什么时候使用?
Project-scope(.mcp.json)
当某个 MCP server 属于项目共享开发环境的一部分时,就用 project scope:
- 只服务于这个项目的数据库工具(例如项目自己的 Postgres MCP)
- 项目特定 API,例如内部服务或 staging 环境
- 整个团队都需要的定制工具,例如部署脚本或测试执行器
- 与项目技术栈绑定的文档 server
User-scope(~/.claude/settings.json)
当某个工具是个人性质的,或者绑定的是你自己的凭证时,用 user scope:
- 个人效率工具(Slack、Linear、Notion)
- 与你个人凭证绑定的工具,例如带你自己 PAT 的 GitHub,或者邮箱访问
- 你希望跨所有项目都可用的通用型 server(例如 Tavily 搜索或 Context7 文档)
- 那些依赖 secrets、且你不希望把它们提交到仓库里的 server
Session-scope(--mcp-config / 临时配置)
当配置是临时性的、实验性的,或者不该持久化时,用 session scope:
- 一次性调试用的 server,例如临时 proxy 或 mock API
- 你正在评估的实验性或不可信 server
- 依赖短时 token 的 server(OAuth 会话或临时凭证)
- 在 CI/CD 环境中动态启动的 server
MCP 生态中的上下文工程
这一节讨论的是 MCP 生态中的上下文工程。虽然示例基于 Claude Code,但这些概念适用于任何支持 MCP 的 agentic system。
图 4.21 —— 在有限 LLM context window 中,好的上下文使用与坏的上下文使用
在 agentic system,尤其是 agentic coding workflow 中,上下文是最昂贵、也最有限的资源。上下文会直接影响 agent 的表现。上下文质量差,agent 的性能就差。这里我们只讨论性能层面的影响,故意不涉及价格和延迟。
图 4.22 —— 上下文工程:只加载必要上下文,从而减少 token 消耗
一个很隐蔽、但影响极大的上下文低效来源,就是 MCP 配置方式。MCP 很强,但如果使用不当,它会严重拖垮上下文效率。核心问题在于:MCP 可能会把大量当前任务根本不需要的工具定义塞进 context window,从而浪费大量 token。
问题所在:过于泛化的 MCP 配置
上下文低效的根本原因,是 过于宽泛的 MCP 配置。当 MCP server 被配置得太泛时,agent 会在处理任何请求之前,就把所有可用工具全部加载进上下文窗口。
这会在推理开始之前,先消耗掉大量宝贵 token,让真正任务可用的空间被压缩。
图 4.23 —— 过宽 MCP 配置导致的 context window 浪费
在 Claude Code 中,MCP server 常常会通过项目级 mcp.json 文件进行配置。这个文件会同时加载多个 MCP server,以及它们关联的全部工具。
图 4.24 —— 启动时一次性加载所有工具的通用 MCP 配置
绝大多数人都会这样配置:用一个通用型 MCP 配置,去加载所有 MCP server 和所有 tools。出发点通常是“先把所有可能会用到的能力都给 agent 备齐”。
问题在于:这样一来,每次会话都会加载所有 MCP server 和全部工具,即便它们和当前任务毫不相关。在你还没写下第一个 Prompt 之前,这种配置就可能已经吃掉几万 token。
这一节的目标,就是把这个问题拆开讲清楚,并通过上下文工程技术展示如何修复它。
示例仓库与 MCP server
这一节使用的代码可以在本书 GitHub 仓库中的 context-engineering-mcp 分支找到。我们从第一个 commit 开始,以便准确复现整个 setup。
仓库中包含了一个用 verbose_mcp_server.py 实现的简单 MCP server。它使用 FastMCP 编写,并暴露了大量 MCP tools,例如:
add_two_numberssubtract_two_numbersmultiply_two_numbers
这个 server 故意包含了很多根本用不到的 MCP tools。每个 tool 还都带有很详细的描述。如下图所示:
图 4.25 —— 详细冗长的 MCP tool 定义如何推高上下文体积
这些描述确实有助于 MCP client 判断是否要调用某个 tool,但它们也会直接增加上下文体积。
运行这个 MCP server
这个 MCP server 使用 UV 包管理器运行。仓库中已经包含 uv.lock 文件,其中定义了 FastMCP 依赖(https://github.com/PrefectHQ/fastmcp)。操作步骤如下:
运行 uv sync,然后激活虚拟环境:
source .venv/bin/activate
环境激活后,就可以使用 FastMCP CLI(https://github.com/jlowin/fastmcp)。我们通过以下命令启动 MCP server:
fastmcp run verbose_mcp_server.py --transport http
这个 verbose mathematical operations MCP server 现在会通过 streamable HTTP transport 运行,并在 http://127.0.0.1:8000/mcp 暴露出来。
将这个正在运行的 MCP server 接入 Claude Code
接下来,我们需要观察:一旦 MCP server 和它的 tools 被加载进会话之后,它们究竟会如何影响上下文。
在本地 MCP server 已经运行的前提下,我们打开 Claude Code,并把这个 MCP server 添加进去。
为此,我们创建一个项目级 MCP 配置文件 .mcp.json。
如果回到仓库查看这个分支,你会发现有一个名为 Add project-based MCP configuration 的 commit,其中已经给出了完整配置。你可以直接复制,并根据实际情况填入 API Key。书中示例里的 API Key 都做了脱敏处理。
项目级 MCP 配置
这个项目级 MCP 配置一共定义了 4 个 MCP server:
- 一个本地运行的 verbose MCP server
- Context7(前面已经讲过,
https://context7.com/) - Tavily(
https://tavily.com/),用于联网搜索、网站抓取与网页提取 - Playwright MCP,用于浏览器自动化
图 4.26 —— 在 mcp.json 中定义多个 server 的项目级 MCP 配置
因为这是项目级配置,所以每次从该项目目录启动 Claude Code 时,这 4 个 MCP server 都会自动加载。
示例中的 API Key 同样做了脱敏。
为了确认配置已经正确应用,可以这样验证:
- 打开终端
- 切换到项目目录
- 确认当前位于
context-engineering-mcp分支 - 启动 Claude Code
- 运行
/mcp,确认 4 个 MCP server 都已连接
图 4.27 —— Claude Code 中已连接多个 MCP server
检查上下文使用情况
然后运行 /context,查看当前会话的上下文占用情况。
这个时候,即便你一个 Prompt 都还没写,context window 已经差不多被吃掉了一半。/context 输出会显示可用 token 是如何被分配的。
图 4.28 —— MCP tools 占据 context window 大量空间
占用情况大致如下:
- 约 2,000 tokens 用于 Claude Code 的 system prompt
- Claude Code 自带 system tools 大约消耗了 12,000 tokens
- MCP tool descriptions 消耗了接近整个上下文窗口的 20%
- 此时还没有任何消息、没有 memory file、也没有配置 sub-agent
如果此时还配了 sub-agents,它们的说明也会进入上下文,包括“什么时候该用它们、如何使用它们”的指令。
也就是说,在你真正开始工作之前,差不多已经有 50% 的 context window 被吃掉了。
而根据具体任务来看,其中很多 MCP server,尤其是那些 verbose mathematical MCP tools,其实是完全没必要存在的。
通过收窄 MCP 配置来减少上下文占用
要减少上下文占用,就必须把 MCP 配置范围收窄。
操作步骤如下:
- 删除项目级
.mcp.json文件 - 创建一个新文件,命名为
.mcp.json.tavily - 从仓库中复制 Tavily MCP 配置
- 粘贴到
.mcp.json.tavily中
图 4.29 —— 使用 mcp.json.tavily 进行范围收窄的 MCP 配置
这样,这个配置里就只剩下 Tavily MCP server。
接下来,用这个收窄后的配置启动 Claude Code:
claude --mcp-config .mcp.json.tavily
这里的 --mcp-config 参数支持传入多个空格分隔的 MCP 配置文件路径。
Claude 启动后,再次运行 /mcp 检查 MCP server。
图 4.30 —— 使用 scoped config 后仍处于活跃状态的 MCP server
此时你会看到 Tavily MCP——这是预期内的。但你也可能仍会看到 verbose MCP 和 Context7,而 Playwright 已经不见了。
原因在于:Claude Code 仍然会从用户级 MCP 配置中加载 server,而用户级配置里还包含 Context7、Tavily 和 verbose MCP。
强制启用严格 MCP 配置
如果想确保只加载你指定的那份 MCP 配置,就必须启用严格模式。
运行以下命令:
claude --mcp-config .mcp.json.tavily --strict-mcp-config
--strict-mcp-config 的含义是:让 Claude Code 忽略默认 MCP 层级体系,只加载你在指定配置文件中显式写出来的 MCP server。
验证方式如下:
- 运行
/mcp,确认只剩 Tavily MCP - 再运行
/context,确认 MCP 工具带来的上下文占用显著下降,因为此时只有 Tavily MCP 处于活跃状态
图 4.31 —— 开启 strict MCP 配置后的上下文使用情况
MCP 相关上下文占用会从接近 20%,下降到大约 2.4% 。
这样,agent 就能更专注于当前任务,而不会背着一堆与当前目标无关的工具上下文前进。在这个例子里,当前任务是研究,因此只保留 Tavily 就足够了。
在会话中动态管理 MCP
除了通过配置文件收窄范围,还可以在一个会话内部动态启用或禁用 MCP server。
做法如下:
- 恢复原来那个通用项目级
.mcp.json配置 - 重启 Claude Code
- 禁用 verbose MCP server
- 禁用 Playwright MCP server
- 运行
/mcp,确认这两个 server 已被禁用 - 再运行
/context
图 4.32 —— 禁用部分 MCP server 后的上下文占用
这时,MCP 相关的上下文占用大约会下降到 3.2% 。
这种方式的好处是:你可以直接在一个会话中通过 CLI 启用或禁用某些 MCP server,而不必去改 MCP 配置文件本身。
MCP 当前的局限
MCP 的设计初衷,是标准化 agent 与数据、工具之间的连接方式。但它当前的实现方式,也引入了一些明显缺点。它们主要来自两个方面:LLM 上下文管理与agent 任务执行方式。
图 4.33 —— LLM 与外部 API 之间的 MCP 抽象层
结果就是,agent 可能会比预期更慢、更贵,也更不稳定。不存在完美协议,MCP 也不例外。
上下文污染(Context Pollution)
MCP 最严重的问题,就是上下文污染。因为 MCP 要求在使用前,先把 tool definition 预加载进模型上下文。这些定义——包括所需参数和预期输出——都会被放进 system prompt 中。
图 4.34 —— 预加载 MCP 工具定义引发的上下文污染
因为所有工具定义都必须事先加载,这本身就会带来非常可观的 token 开销。要使用某个 MCP server,agent 就必须先拿到它全部可用工具的定义。
比如,一个配置中如果包含 GitHub MCP、Slack MCP 和 Central MCP 等 58 个工具,仅仅这些 tool definitions 本身,就可能在对话开始之前占掉 55,000 tokens。某些情况下,这个数字甚至可能膨胀到几十万 tokens。
在 LLM 应用和 agent 系统中,上下文是最应该被优化的首要资源。一旦上下文被大量工具定义塞满,agent 就会一直背着大堆无关信息工作。
例如,一个 agent 明明只是在改前端页面,但它却同时携带着数千行和数据库工具、PDF 阅读器等完全不相关的上下文。这些无关数据会在对话的每一步、每一次迭代中持续存在。
图 4.35 —— 过多 MCP 工具导致的“大海捞针”问题
随着上下文被越来越多无关定义填满,模型性能会下降。模型不得不在大量无关内容中寻找所需信息,从而更容易出现幻觉、指令跟随失败,或错误选工具。上下文污染越严重,模型就越难在其中找到真正相关的信息。
Agent 执行效率低下
除了上下文问题,MCP 还会引入执行层面的低效。
图 4.36 —— 多次 MCP tool 调用导致的低效 agent 执行
传统 MCP 用法依赖一种“乒乓球式”的交互模式。每个动作都需要完整往返一轮:
- 模型先请求一个工具
- 工具执行
- 执行结果被追加到对话历史中
- 更新后的完整历史再次发回模型,由模型决定下一步
一旦任务需要多个工具调用,这个过程就会迅速膨胀。大量中间结果会不断堆进 context window,即便它们对最终答案并不总是必要。虽然按理说某些中间结果后面是可以被移除的,但当前 MCP 实现通常会把它们一直保留下来,从而继续污染上下文。
图 4.37 —— 模型、client 与 server 之间的 MCP 工具往返调用
每一次往返,都需要多做一次 LLM inference。推理次数越多,延迟和成本就越高。随着工具调用次数增长,模型调用次数也同步增长,最终表现为更慢执行和更高开销。
“母语问题”:JSON vs Code
MCP 还有一个更底层的问题:它迫使 LLM 以一种并不贴近其训练分布的方式工作。
图 4.38 —— LLM 训练分布 vs 工具调用格式
MCP 协议高度依赖结构化 tool-call token 和 JSON schema。但 LLM 的主要训练材料其实是自然语言和代码,而不是这种专门化的工具调用 token。
虽然各家模型厂商已经显著提升了 tool calling 的可靠性,但这种格式终究不是模型最自然的工作方式。对 LLM 来说,文本和代码才是更“原生”的表达形式。尤其是代码,比 JSON 式工具调用机制更接近它的训练数据和能力边界。
这就造成了一种摩擦:模型的训练分布,与 MCP 所要求的结构化交互方式之间并不完全对齐。
工具定义与 Schema 的局限
MCP 中的 tool definition 和 JSON schema,只能描述一个工具“长什么样”:它有哪些参数、输入与输出。
图 4.39 —— JSON schema 在描述工具使用方式上的局限
但它们无法表达“怎么用、什么时候用、什么时候不该用”这类使用模式。
即便你可以额外写指令去约束工具使用方式,schema 本身也无法编码这种行为约束。换句话说,协议定义了工具的结构,却没有定义意图和正确应用方式。
Cloudflare 的 CodeMode
Cloudflare 在一篇博客中首次提出了 CodeMode(https://blog.cloudflare.com/code-mode/)。这是一个试图改变 agent 与 MCP tools 交互方式的执行模型。
它的出发点,就是前面提到的 MCP 问题,尤其是上下文膨胀,以及多次 LLM 调用造成的额外延迟。
与传统 MCP 用法不同,Cloudflare 的思路是:把 MCP 中所有的 tool definitions、tool interfaces 和 tool implementations,都转换成一个 TypeScript API。然后,不是让 LLM 去“选工具并调用”,而是让 LLM 直接写代码,并通过这套 TypeScript API 使用这些工具。
图 4.40 —— Cloudflare Code Mode:用代码执行取代直接工具调用
在这种模型里,LLM 会一次性生成完整可执行代码。代码里包含多个工具调用,以函数调用形式表达。随后,这段代码会在沙箱中执行一次。
这种方式可以显著减少工具调用中的往返轮数。传统模式下,模型要调一个工具、拿结果,再调下一个工具,如此反复;而在 CodeMode 下,模型直接把整套调用流程写成代码,在内部完成。Cloudflare 给出的核心理由是:LLM 非常擅长写代码。 写代码是它训练里极其常见的任务,数据量远超工具调用样例。由于代码只生成一次、执行一次,因此 tool definitions 也不用反复发送,从而减少 token 占用。
核心观察
Cloudflare 认为,MCP 过去往往是“直接把工具暴露给 LLM 来调用”。而在 CodeMode 中,MCP tools 会先被转成 TypeScript API,再由 LLM 写代码来调用它。
他们声称,这样 agent 能处理更多工具,也能处理更复杂的工具。传统 MCP 的一个问题是:工具一多,上下文就变大,成本和延迟上升,性能也会下降。而如果工具是以 TypeScript API 的形式呈现,而不是直接暴露为工具定义,那么性能就会更好。理由是:LLM 训练中见过大量真实 TypeScript 代码,却只见过极少量刻意构造的 tool-call 样例。
这种方法尤其适合多工具链式调用场景。传统 MCP 里,每一个工具输出都要回送给 LLM,再决定下一步;这种重复会持续消耗时间、能量和 token。而在 CodeMode 中,LLM 直接写出完成整条调用链的代码,只把最终结果返回出来。
所以 Cloudflare 的结论是:LLM 更擅长“写代码去调用 MCP”,而不是“直接调用 MCP 工具”。
Tool Calling 及其限制
传统 MCP 用法中,LLM 会生成表示工具调用的特殊 token。系统解析这些 token,提取函数名和参数,然后执行函数并返回结果。
但这种特殊 tool-call token,并不常见于真实世界数据。它们是训练阶段人为引入的语法构造。虽然模型厂商已经大幅提升了 tool calling 的效果,但这种机制本质上仍是“人工语法”。
一旦工具太多,或者工具本身太复杂,LLM 就可能难以选中正确工具,或者使用方式出错。因此,MCP server 设计者通常会被迫去简化 API,让它更适合 LLM 调用。
相比之下,LLM 对完整编程 API 的处理能力往往更强。面对复杂 API,它们可以分析、理解并生成对应代码,而不需要人为简化。根本区别在于:LLM 见过海量真实代码,却几乎没见过真实世界中的 tool calls。
Cloudflare 还给出了一个类比:让 LLM 做 tool calling,就像“把莎士比亚送去参加一个短期中文速成班,然后要求他用中文写戏剧”。含义非常明确:tool calling 并不是模型最擅长的领域。
MCP 的角色仍然重要
即便如此,MCP 仍然有价值。因为它依然提供了一种统一方式,让 agent 能够连接到 tools。MCP tools 本质上是一个带文档的 RPC 接口,而大多数 MCP server 本身也只是对已有传统 API 的包装。
CodeMode 的思路,不是直接把 MCP tools 以“工具”暴露出去,而是把它们转成编程语言 API。虽然底层传统 API 本来也存在,但 MCP 提供的是一种统一的接入与发现机制,这一点在 agent-based system 中依然非常有意义。
集成 CodeMode
Cloudflare 已经扩展了自己的 Agent SDK,以支持 CodeMode。在一个典型的 AI SDK 配置中,通常你会设置 model、system prompt、user message 和 tools。例如:
const stream = streamText({
model: openai("gpt-5.3"),
system: "You are a helpful research assistant.
Your job is to help the user…",
messages: [
{ role: "user", content: "Research on deep agents" }
],
tools: {
research agent's tool definition
}
})
而在 CodeMode 中,system prompt 和工具定义会先被 codemode helper 包装,再传给应用:
import { codemode } from "agents/codemode/ai";
const { system, tools } = codemode({
system: " You are a helpful research assistant.
Your job is to help the user…",
tools: [
research agent's tool definition
],
})
这样改完之后,应用就不再直接进行 tool calling,而是生成并执行调用这些工具(包括 MCP server)的 TypeScript 代码。
将 MCP 转成 TypeScript
当 CodeMode 连接到 MCP server 时,Agent SDK 会抓取这个 MCP server 的 schema,并将其转换成 TypeScript API。生成出的 API 会包含 TypeScript 类型定义,以及从 schema 派生出来的文档注释。
这些 TypeScript 定义会被加载进 agent 的上下文。目前,整个 API 仍然是一次性整体加载进去;未来可能会支持动态搜索或按需浏览。
虽然整套 API 加载也会增加上下文体积,但这只发生在初始化阶段。随后 LLM 读取 API,并生成代码。由于 LLM 很擅长处理代码,这种方案实际上是在利用它的优势。
在沙箱中执行
在 CodeMode 下,agent 不再直接面对一堆 MCP tools,而是只拥有一个“执行 TypeScript 代码”的工具。
生成出的代码会运行在一个安全沙箱中,与互联网隔离。这个沙箱只能通过提供给它的 TypeScript API 来访问外部系统,而这些 API 对应的正是已经连接好的 MCP servers。
当沙箱中的代码调用某个 API 函数时,这个调用会通过 RPC binding 回路由回 MCP server。沙箱通过 console.log() 返回结果;等执行完成后,这些日志再返回给 agent。
于是,传统 MCP 流程和 CodeMode 的差异就很清楚了:
传统 MCP:
- agent 从 MCP server 获取 tool schema
- LLM 调用中包含这些 tool definitions
- LLM 输出特殊 token 形式的函数调用
- agent 解析并执行这些调用
- 这一流程不断重复
CodeMode:
- agent 同样先从 MCP server 获取 tool schema
- LLM 调用中包含从这些 schema 推导出的 TypeScript API
- LLM 直接针对这个 API 写 TypeScript 代码
- 代码在沙箱中执行
- 沙箱通过 RPC 绑定与 MCP server 通信
- 最终日志返回给 agent
下图展示了传统 MCP 与 CodeMode 的执行架构对比。
图 4.41 —— Traditional MCP vs CodeMode 的执行流对比
CodeMode 被呈现为一种替代执行模型:它保留 MCP 作为统一集成层,但把执行方式建立在“LLM 擅长写代码”这一能力之上。
使用 Claude Code Plugins 管理配置
这里请参考 Claude Code 官方文档:
https://code.claude.com/docs/en/plugins
Plugins 可以把 slash commands(skills)、sub-agents、MCP servers 和 hooks 打包成一个统一、可分享的原语。它们可以在团队内部共享,也可以发布到开源社区中,从而帮助不同环境实现复用与一致性。
在 plugins 出现之前,复用配置是一件非常麻烦的事。比如,如果你想使用某个开源仓库里的 slash command,就得先去那个仓库,找到对应命令,复制出来,再粘贴进本地 .claude 目录。sub-agent 和 hook 也是类似流程。虽然 MCP server 的安装方式略有不同,但整体上仍然是手工、割裂、零散的。
Claude Code plugins 的出现,就是为了改善这个问题:它把所有这些组件统一打包成一个 plugin,让安装和集成变得顺畅。Plugin 可以来自开源仓库,也可以来自企业内部仓库,适合跨团队共享。
Claude Code 为此提供了一套基于 CLI 的 plugin system,操作直观、也很容易上手。
Plugin 系统的价值
Plugin 的一个核心价值,是让整个团队拥有统一的 Claude Code setup。比如,当一个新开发者加入团队时,我们希望他一上来就能拥有和其他人一样的工具、一样的 agents / sub-agents、一样的 MCP servers。Plugin 就提供了一种标准化 Claude Code 开发环境的机制。
另外,plugin 还支持细粒度安装。你不一定非要装完整 plugin,也可以只安装其中某个具体组件,比如一个单独的 MCP server。
Claude Code 还引入了一个新的原语:marketplace。它本质上是一个 JSON 文件,用来描述当前有哪些 plugin 可以安装。
值得一提的是,Google 的 Gemini CLI 也引入了一个类似概念,叫 Gemini Extensions。Gemini Extensions 发布于 2025 年 10 月 8 日,而 Claude Code plugins 发布于 2025 年 10 月 9 日。这个仅差一天的发布时间,很难不让人猜测:要么 Claude Code 团队迭代极快,要么两个团队几乎是在同时实现同一类思路。
查看官方 Plugin Marketplace
为了理解 plugin 是如何工作的,我们从 Claude Code 课程仓库开始看。
在 Claude Code 的开源仓库里,有一个 .claude-plugin 目录。这个目录里有一个 marketplace.json 文件。
它定义了官方 plugin marketplace,列出了所有可用 plugin,并包含对应元数据和 source 路径。
例如,marketplace 中列出的 plugin 包括:
pr-review-toolkitcommit-commandsagent-sdk-devfeature-devSecurity guidelines
这个 marketplace 本质上就是一个 registry,Claude Code 读取它之后,就知道有哪些 plugin 可供发现与安装。
将 Marketplace 添加到 Claude Code 中
在安装 plugin 之前,必须先把一个 marketplace 加到 Claude Code 里。
步骤如下:
- 打开 Claude Code,运行命令:
/plugin
2. 选择 Browse and install plugins
-
因为起初还没有配置 marketplace,所以选择 Add Marketplace
-
输入以下任意一种:
- 一个 GitHub 仓库 URL
- 或一个直接指向
marketplace.json的链接
在这个例子里,我们提供的是官方 Claude Code 仓库的 base URL。Claude Code 会自动检测 marketplace 文件,并加载所有可用 plugin。
加载完成后,就能看到 plugin 列表及其描述。
图 4.42 —— Claude Code plugin marketplace 中展示的可用 plugins
查看 Plugin 源码与安全考量
在这个阶段,你看到的仍然只是 plugin 描述。想真正知道某个 plugin 安装了什么,就必须去检查它的源码。
marketplace.json 中每个 plugin 条目都有一个 source 字段。这个字段指向 plugin 实现所在的位置。
在安装前审查这个 source 非常重要。从安全角度看,这和安装 MCP server、使用别人写的 system prompt 或 agent 没有本质区别。不看源码就安装 plugin,是有风险的。
查看 plugin source 的步骤如下:
- 打开
marketplace.json - 找到目标 plugin 条目
- 查看
source字段 - 跳转到仓库中的对应路径
例如,agent-sdk-dev 这个 plugin 指向仓库中的某个目录。要检查它:
- 打开仓库
- 进入
plugins/目录 - 再进入
agent-sdk-dev/ - 再进入
.claude-plugin/ - 查看其中的
plugin.json文件
plugin.json 会包含这个 plugin 的元数据,并定义它要安装的 agent 和 slash commands(skills)。
另一个例子是 feature-dev。这个 plugin 包含多个 agent,例如:
- code reviewer
- code explorer
- code architect
它还包含一个定义在 feature-dev.md 中的 slash command,用于描述待实现 feature,并引导整个工作流。
安装与管理 Plugins
一旦 marketplace 被添加,plugin 就可以被安装和管理了。
安装一个 Plugin
步骤如下:
- 用
/plugin打开 plugin 界面 - 选择 Browse and install plugins
- 找到
commit-commands这个 plugin - 打开 plugin 详情页
- 选择 Install
- 等待安装完成
安装完成后,这个 plugin 会出现在已安装列表里。
验证安装
为了确认 plugin 已成功安装并启用,可以:
- 打开已安装 plugin 列表
- 找到
commit-commands - 确认它显示为 installed
- 同时确认它处于 enabled 状态
更新 Plugin
Plugin 背后绑定的是仓库,因此它们可以随着时间持续更新。更新方式如下:
- 选择一个已安装 plugin
- 找到 Update 选项
- 应用更新
从概念上看,更新 plugin 很像对着插件仓库的最新版本做一次 rebase。
尝试卸载 Plugin
插件界面里也有 uninstall 选项。操作步骤如下:
- 选中一个已安装 plugin
- 找到 Uninstall
- 尝试卸载它
目前,这个卸载功能并不能如预期那样工作。执行卸载之后,plugin 并不会真正消失。这看起来像是当前版本的一个限制,或者一个 bug。
图 4.43 —— 尝试卸载 Claude Code plugin
使用 feature-dev Plugin
接下来,我们用 feature-dev plugin 演示一个完整工作流。
开始之前,请先确认这个 plugin 已经安装并启用。
图 4.44 —— Claude Code 中 feature-dev plugin 的详情
启动工作流
步骤如下:
- 打开 Claude Code,运行命令:
/feature-dev
2. 等待 plugin 初始化
命令执行后,Claude 会进入一个discovery phase(探索阶段) 。这时它会开始提问,以弄清楚你到底想实现什么 feature。
feature-dev 工作流中的 Git 状态处理
在切分支之前,Claude Code 会先检查当前仓库的 Git 状态。
在这个阶段,仓库很可能存在尚未提交的本地改动。如果不处理这些改动就直接切分支,可能会引发冲突,甚至丢失工作内容。
检查 Git 状态
在这个流程中,Claude 会自动完成:
- 检查当前 working tree 状态
- 发现存在本地未提交改动
- 判断此时直接切分支是不安全的
暂存本地改动
为了安全推进流程,Claude 会使用 git stash 保存当前工作状态。
在这一步中,Claude 会:
- stash 当前工作目录中的改动
- 确认 working tree 已经干净
- 然后继续执行 branch 切换
这样就能确保本地改动不会丢失。
切回原分支并恢复状态
在检查完 feature branch 之后,Claude 会回到原分支,并恢复之前的 Git 状态:
- 切回 main branch
- 重新应用刚才 stash 的改动
- 确认 working directory 已恢复原状
这时,仓库就回到了最初状态,本地改动也都还在。
提供 Feature 细节
在这个示例里,要完成的任务是:更新仓库的 README 文件。
README 里有一张课程章节表格。现在 GitHub 上已经有一个新分支 context-engineering-mcp,因此需要把这个新分支对应的课程条目补进表格。仓库链接同样可从前言的 Download the example code files 一节获得。
在 Claude 提问时,你需要:
- 描述要做的改动
- 提供
context-engineering-mcp分支的 URL
在 feature branch 中检查 README
Claude 会进入 feature branch,检查 README 文件。它会:
- 切换到
context-engineering-mcp分支 - 打开 README
- 识别表格结构
图 4.45 —— 在 feature branch 中检查 README
切回主分支
完成检查后,Claude 会:
- 切回 main branch
- 准备应用变更
- 提出一条新的表格条目
审查并微调拟议变更
Claude 会先生成一个 README 新条目的初稿描述。这时你需要:
- 检查描述
- 找出不准确之处
- 微调措辞
图 4.46 —— 审查并微调拟议的 README 变更
这个例子里,Claude 的描述已经接近正确,只需要稍作调整即可继续。
提交、推送并验证变更
一旦变更被批准,接下来会发生:
- Claude 创建 commit
- Claude 把 commit push 到远程仓库
- 你刷新仓库
- 打开 README
- 检查新课程条目是否已经出现在表格里
图 4.47 —— commit 后验证 README 更新
这就说明整个工作流已经顺利跑完。
Plugin Marketplace 与企业使用
Claude Code 支持第三方 plugin marketplace。
例如,一个 DevOps automation marketplace 可以提供一组与基础设施工作流相关的 plugins,其中包含 slash commands、agents 和 MCP servers。组织也可以构建自己的私有 marketplace,专门服务于内部工具和团队。
很有可能像 Supabase 这样的基础平台公司,将来也会发布自己的 marketplace 和 plugins,以提升与 Claude Code 的集成体验。
Plugins 还支持细粒度安装。你可以只安装一个单独组件,比如一个 slash command 或一个 MCP server,而不需要把整个 plugin 整体装进来。这个 plugin 生态预计会持续增长,并在企业级 Claude Code 采用中扮演重要角色。
总结
在本章中,你学习了 MCP 为什么会被创造出来,以及它是如何解决 AI 系统中的集成问题的。你考察了它的核心架构:host、client 和 server,并看到了 MCP 如何实现可复用、跨平台的工具集成。通过实战例子,你配置并使用了 Context7 MCP,把 server 接入 Claude,并通过 CLI 管理 MCP 设置。
你还学习了:糟糕的 MCP 配置如何污染上下文窗口、拖垮性能,以及如何通过上下文工程与 scoped configuration 优化使用方式。最后,你还考察了 Claude Code plugins,理解了 MCP 的局限,并了解了 CodeMode 这种替代执行模型。
理解 MCP 之所以重要,是因为它正在成为 agent-based AI 开发中的一个基础集成层。知道如何高效使用它,以及在什么情况下应该反过来质疑它,都会帮助你构建出更可扩展、更有效的 AI 系统。
在下一章中,我们将讨论 GitHub 仓库配置、Pull Request 与 Issue 自动化,以及如何借助 GitHub Actions 执行工作流。