什么是MCP?
MCP(Model Context Protocol)是 2024 年底 Anthropic 提出的一套协议,让你通过一个配置文件接入别人写好的"工具服务器"(MCP Server),Agent 就能直接调用里面的工具。比如装一个 Playwright MCP Server,Agent 就会操作浏览器了;装一个 GitHub MCP Server,Agent 就能帮你管 PR 了。
听起来很美好。但用过之后你可能会发现两个奇怪的现象:
为什么接了几个 MCP Server 之后,Agent 变得明显迟钝了,回答质量也下降了?
为什么有时候 Agent 会做一些你完全没要求的事,好像被谁"操控"了?
MCP解决了什么问题?
MCP(Model Context Protocol)的核心贡献是标准化。在 MCP 之前,每个 AI 产品要接外部工具,都得自己实现一套:比如 Cursor 有自己的插件格式,ChatGPT 有自己的应用市场,Coze 也有自己的 Plugin,各有各的一套标准。
MCP 定义了一套 JSON-RPC 2.0 协议,让任何 MCP Server 能被任何支持 MCP 的 Agent 调用。也就是说,写一次 Server,到处能用。
协议设计上,MCP Server 可以暴露三种东西:
Tool:可以被模型调用的工具(最常用)。
Resource:可以被读取的数据源(文件、数据库记录等)。
Prompt:预设的提示词模板。
MCP背后的工程硬伤
硬伤一:Token占用
一个 MCP Server 暴露 15-20 个工具是常态。Playwright MCP 有 20+ 个浏览器操作工具,GitHub MCP 有 46 个。每个工具都有名称、描述、参数 Schema。
一个 Playwright MCP Server 接进来,光工具定义就吃掉 8,000-13,000 token。
如果你接了 3 个这样的 MCP Server,40,000 token 没了。200K 上下文窗口,五分之一直接消失,非常恐怖。
更要命的是,这些工具定义在 prompt 的前部——改了它们就没有了 KV Cache。所以你也不能"动态增删"来优化。
Speakeasy 团队做过实验,用动态工具集方案替代 MCP 的全量加载,Token 消耗降了 96%。这就侧面说明了 MCP 全量加载设计本身的问题。
硬伤二:安全风险-Prompt Injection的天然入口
这个问题比 Token 更严重,但很多人还没意识到。MCP Server 返回的工具结果直接进入 LLM 的上下文。这意味着,一个恶意的 MCP Server 可以通过工具返回值来"操控"你的 Agent。2025 年已经出了 CVE-2025-6515(MCP prompt hijacking),说明已经在生产环境遇到了一些风险了。核心问题是:MCP 的安全模型是给确定性程序设计的,但 LLM 是概率性的推理系统——用确定性的安全假设去保护概率性系统,先天就对不上。
硬伤三:复杂度
跑一个 MCP Server 需要:一个额外进程、一套配置、一条通信链路(stdio/SSE/HTTP)。如果涉及认证,还要处理 OAuth 流程。
这就会导致一个结果:调试链路变长了。你的 Agent 调工具,工具通过 MCP 协议发给 Server 进程,Server 再调外部 API,结果再原路返回。任何一环出问题,排查起来都比直接调函数复杂得多。
Claude Code 的MCP
命名空间隔离
Claude Code 给每个 MCP 工具加了一个三段式命名:
PLAINTEXT
mcp__<serverName>__<toolName>比如 Supabase MCP Server 的 execute_sql 工具,在 Claude Code 里变成了 mcp__supabase__execute_sql。这解决了一个很现实的问题:工具名冲突。如果你接了两个 MCP Server,都暴露了一个叫 search 的工具,没有命名空间就分不清了。更重要的是,内置工具永远优先——如果 MCP 工具和内置工具同名,内置工具覆盖 MCP 工具。Server 名称中的特殊字符会被清理(替换为下划线),确保工具名是合法的标识符。
默认全部延迟加载
上一篇讲的 Deferred Tool Loading,MCP 工具是最大的受益者。
源码里的判断逻辑是这样的:MCP 工具(tool.isMcp === true)一律延迟加载,除非工具通过alwaysLoad这个 flag 显式声明"我必须立即加载"。
这意味着你接了 3 个 MCP Server、50 个工具,初始 prompt 里只出现这些工具的名字列表,完整 Schema 不占上下文。模型需要某个 MCP 工具时,通过 ToolSearch 按需加载。
没有这个机制,MCP 基本不可用——几个 Server 就把上下文吃光了。
共享权限管线——MCP 工具不享受"特权"
前面讲的 7 步执行管线,MCP 工具走的是完全一样的流程:Zod 验证 → 业务校验 → 输入补全 → PreToolUse Hook → 权限检查 → 执行 → PostToolUse Hook。
MCP 工具不因为来自外部就跳过权限检查。该拦截的照样拦截,该问用户的照样问。
而且 Claude Code 对 MCP 工具有额外的策略层:
Server 级别的允许/拒绝:可以在配置里直接禁用某个 MCP Server 的所有工具
项目级 vs 用户级:不同来源的 MCP 配置有不同的信任级别
默认禁用的内置 Server:某些内置 MCP Server 默认是关闭的,需要用户显式启用
MCP 工具的结果处理
MCP 工具返回的结果走正常的截断流程——maxResultSizeChars 设为 100,000 字符,超了就持久化到磁盘。
但 MCP 工具的结果还有一个特殊处理:Claude Code 会检查结果内容的类型。MCP 协议支持返回多种内容类型(文本、图片、Resource Link),Claude Code 需要把这些转换成模型能理解的格式。图片会被压缩到合理尺寸,避免大图吃太多 token——模型处理图片是按像素数算 token 的,一张 4K 截图可能吃掉几千 token,压一下就可控了。
Token 占用和 Prompt Injection 这两个核心问题,协议层面很难彻底解决——前者需要应用层做延迟加载(上一篇讲过),后者需要从根本上重新思考"外部内容如何安全地进入 LLM 上下文"。
MCP擅长的场景
说了这么多问题,MCP 也不是一无是处。在某些场景下,它确实是非常合适的方案:
有状态的外部服务连接
数据库查询、API 调用——这些需要维护连接状态、处理认证、管理会话。MCP Server 作为一个独立进程,天然适合管理这些有状态的连接。比如 Stripe、Supabase 直接通过 OAuth 一键跳转到浏览器认证了,非常方便。
当然,在这个场景 MCP 并不能说比 Skills 更优,只能说是一种可选方式。因为对于 Skills 而言,也能通过 CLI 的方式来完成认证和授权流程。两者的上手难易程度差不多。
MCP Apps——协议驱动的 UI 应用
这是一个很多人还没注意到但非常重要的方向。MCP Apps 是指用 MCP Server 来驱动交互式 UI 应用——数据看板、可视化工具、表单交互等等。
你想想,一个 AI Agent 生成了一份数据分析结果,你想让用户在一个可视化界面里交互式地探索这些数据。这种场景需要的是标准化的双向通信协议——前端 UI 需要和后端 AI 服务实时交换消息,需要工具调用、需要资源读取、需要状态同步。
这恰恰是 MCP 天然擅长的。你用 Markdown 文件或者 CLI 脚本搞不定这种事——UI 应用需要协议化的东西来支撑,而 MCP 的 JSON-RPC + Streamable HTTP 正好就是干这个的。
MCP不适合场景
知识注入、最佳实践指导、工作流定义——这些不需要"实时连接",不需要"独立进程",不需要"协议通信"。一个 Markdown 文件就够了。
