MCP 入门:给 Agent 装上「USB-C」的开放协议
- MCP 把工具集成的 M×N 变成 M+N:应用实现一次客户端、数据源实现一次 server;它已是捐入中立基金会的事实标准。
- 架构三角色:Host(宿主)协调多个 Client(客户端),Client 与 Server(服务器)一一对应;本地 stdio、远程 Streamable HTTP,消息都是 JSON-RPC。
- 三原语按控制权划分:tools 归模型管、resources 归应用管、prompts 归用户管;MCP tools 最终仍走 function calling——标准化的只是工具的供给方式。
- 把每个第三方 server 当不可信输入源:最小权限、人工确认、警惕工具描述注入;只在自家单个 Agent 里用的话,function calling 更简单。
上篇回顾:上一篇我们手搓了整套工具层——schema、并行、确认门控。但如果每个应用都要为每个数据源这么手搓一遍,集成的复杂度就是 M×N:5 个 Agent 框架对接 20 个系统,要写 100 个连接器。本篇讲把这个等式改成 M+N 的开放协议。
一、M×N 地狱,与一根 USB-C
2024 年 11 月,Anthropic 开源了 Model Context Protocol(模型上下文协议,MCP),定位是一句很朴素的话:「连接 AI 助手与数据所在系统的标准」[3]。官方文档里那个流传更广的类比是:它是「AI 应用的 USB-C 接口」——设备与外设不再需要一对一的专用线缆,一根标准线解决所有连接。思路与当年数据库的 ODBC、Web 世界的 HTTP 一脉相承:把私有集成变成公共协议。
两年过去,它已经从一家厂商的开源项目长成行业事实标准:早期 Block、Apollo 把它集成进系统,Zed、Replit 等工具厂商跟进支持,预置的 Google Drive、Slack、GitHub、Postgres 等 server 覆盖了最常见的对接场景 [3];此后 OpenAI 等厂商相继宣布支持,2025 年底,协议被捐入 Linux Foundation 旗下新设的中立基金会(与 Block、OpenAI 等共同创立),彻底坐实了「公共标准」的身份 [6]。对你我的意义很实际:学它不是学某家 API,是学一个像 HTTP 一样会长期存在的地基。
可能有读者会问:企业系统早就有 OpenAPI/REST 文档了,为什么不直接让模型读接口文档调 REST?试过就知道差距在哪:REST 文档是写给程序员看的,而工具定义是写给模型「读」的——哪个参数必填、什么时候该用、出错怎么办,这些恰恰是 description 层面的事(第 5 篇的「实习生测试」还作数);而且模型要的不只是「能调」,还有发现、鉴权、确认、审计这些横切能力。MCP 把这一整套都标准化了:同一个 server,换一个 Host 接入,安全策略和审计点原样复用。
二、架构与三原语:谁控制什么
MCP 的架构是三个角色:Host(宿主)是「协调并管理一个或多个 MCP client 的 AI 应用」——Claude Code、IDE、桌面助手都属于这类;Client(客户端)是 Host 内部的连接器,与每个 server 一一对应;Server(服务器)则是「向 client 提供上下文与能力的程序」[1]。顺便纠正一个常见误解:stdio 传输的 server 是跑在本机的子进程,所以「MCP server」不等于「远程服务」——本地与远程只是运行位置不同;stdio 通常一夫一妻服务单个 client,Streamable HTTP(流式 HTTP)的远程 server 则可以同时服务多个 [1]。
协议分两层:数据层是 JSON-RPC 2.0,定义工具发现、调用与通知这些消息;传输层是通道,stdio 走标准输入输出直连本地进程,Streamable HTTP 走 HTTP POST 加可选的流式响应、支持标准认证 [1]。同一套消息跑在任意传输上,所以从本地迁到远程,server 的业务代码几乎不用动。
Server 能提供的东西分成三个原语,而区分它们的关键是控制权归谁 [1]:
| 原语 | 是什么 | 谁控制 | 例子 |
|---|---|---|---|
| Tools(工具) | 可执行的动作 | 模型(官方措辞是 model-controlled) | |
| Resources(资源) | 可读取的数据 | 应用决定何时读取并注入 | |
| Prompts(提示模板) | 可复用的交互模板 | 用户主动选择(如斜杠命令) |
然后是本篇最重要的技术澄清:MCP tools 最终仍走 function calling。协议标准化的是工具的「发现与描述」——client 调 tools/list 拿回的 name、description、inputSchema,就是我们在第 5 篇手写的 JSON Schema;Host 把它们合并进模型的工具注册表,模型发起调用时仍走普通的 function calling,Host 拦截调用、路由到对应 server、再把结果作为对话的一部分送回模型 [1]。官方也划了边界:「MCP 只关注上下文交换的协议,不规定 AI 应用如何使用 LLM 或管理这些上下文」[1]。一句话:MCP 改变的是工具的供给方式,不是模型的推理方式——前五篇的知识一个字都不作废。(小提示:经典教程讲的 initialize 握手,在 2026 年中的新规范里已收敛为无状态的发现请求——对着老教程学习时不必慌,流程心智不变。)
新手最容易纠结的是「我的能力该写成哪个原语」。判据就一句,跟着控制权走:需要模型自己决定何时调用的,写成 tool(比如「查订单」);需要应用每次都带上的背景数据,做成 resource(比如数据库 schema、项目约定文档——注入时机是应用的事,不该劳模型操心);需要用户手动触发的快捷入口,注册成 prompt(比如 /review-pr 这种斜杠命令)。拿不准就问自己:这个动作由谁发起?答案落在哪一列,原语就是哪个。
回望本系列,MCP 的出现恰好给前五篇标了坐标:第 5 篇手搓工具层,等于「自己给自己写 server」——你知道工具定义长什么样,读 tools/list 的返回就不会陌生;第 5 篇的确认门控,本来就是 client 侧的安全职责,MCP 文档只是把它写成了 SHOULD 条款;第 4 篇的上下文预算,决定你能同时挂多少个 server 的工具描述而不撑爆窗口。协议没有推翻这个系列的任何一层,它只是把「工具从哪来」这件最脏最累的活,标准化了。
三、动手:十五行写一个 MCP server
用官方 Python SDK(包名 mcp),把上一篇手搓的笔记工具发布成一个 MCP server,核心代码只有十几行 [4]:
# notes_server.py —— pip install "mcp[cli]"(v2 写法;老教程的 FastMCP 是 v1,别混)
from pathlib import Path
from mcp.server import MCPServer
mcp = MCPServer("Notes")
@mcp.tool()
def list_notes() -> str:
"""列出 notes/ 目录下所有 .txt 笔记的文件名。"""
names = sorted(p.name for p in Path("notes").glob("*.txt"))
return "\n".join(names) if names else "(空目录)"
@mcp.tool()
def read_note(note_name: str) -> str:
"""按文件名读取单篇笔记,返回前 1500 字。"""
path = Path("notes") / Path(note_name).name # 防呆:第 5 篇同款
return path.read_text(encoding="utf-8")[:1500]
if __name__ == "__main__":
mcp.run() # 等价于 transport="stdio";远程部署:mcp.run(transport="streamable-http")
盯着这段代码看十秒,你会发现本系列最妙的一次「回收」:类型注解 + docstring,就是上一章手写的 JSON Schema。框架接管了 schema 生成、消息序列化和传输细节,你写的仍然只是「业务逻辑住在工具函数里」。调试用官方 Inspector(mcp dev server.py),部署为远程服务时换一行传输参数即可 [4]。一个提醒:网上大量教程还是 v1 的 FastMCP 写法,新 SDK 已更名为 MCPServer——对着报错查资料时先看版本。工具之外,resource 和 prompt 也有对称的装饰器写法(@mcp.resource("greeting://{name}") 这类 URI 模板),Inspector 里可以逐个试调用——本地的工具生态,第一次有了「包管理器 + 试吃装」的体验。最后是工具粒度的收束:server 的工具集同样要「少而精」,把十个 REST 端点原样包成十个 tool 是最常见的反模式——第 2 篇那个 schedule_event 合并三连调的例子,在这里一字不差地再次成立:一个面向任务的高层工具,胜过一排面向接口的低层工具。
四、接入:一行命令与两个坑
server 写好了,怎么让 Claude Code 这样的 Host 用上它?命令行一步:
# 远程 HTTP server:一行接入
claude mcp add --transport http notes https://notes.example.com/mcp
# 本地 stdio server:注意「--」分隔符,漏了它,参数会被 Claude Code 自己吃掉
claude mcp add --transport stdio notes -- python notes_server.py
# 会话内用 /mcp 查看连接状态、完成 OAuth、重新连接
两个高频坑都在官方文档里明码标价 [5]:一是 stdio 命令的 -- 分隔符,漏了它,server 的参数会被 Host 自己吞掉,你只会看到莫名其妙的启动失败;二是团队共享的项目级配置文件(.mcp.json)里,HTTP 型 server 必须同时写 url 和 "type": "http",只写 url 会被按 stdio 处理,状态检查时报错跳过。配置的作用域分 local、project、user 三级,优先级依次递减——个人调试用 local,团队共享用 project。「即插即用」不是修辞:同一个 server,今天接 Claude Code,明天接任何支持 MCP 的 Host,一行配置的事。
传输怎么选?同样跟着场景走:能力长在本机上(读本地文件、跑本地命令),选 stdio——零网络开销、天然隔离在本机权限内;要给团队共享、部署成 SaaS、或者 server 本身就要访问云端数据,选 Streamable HTTP,认证走标准 OAuth。折中情形也常见:先 stdio 起步验证工具设计,等真有第二个 Host 或第二台机器要接,再切 HTTP——反正业务代码不用动,这是两层架构送的福利。顺带一提,远程 server 的认证在主流 Host 里已经几乎无感:首次连接时 /mcp 会引导你走完 OAuth,token 由 Host 保管,server 拿到的 scope 就是它申请的最小集合——比把 API key 明文抄进配置文件体面得多。
五、安全:每个第三方 server 都是不可信输入源
便利的背面是新的攻击面,官方文档对安全的要求相当直白:server 必须「校验所有工具输入、实现访问控制、限流、净化输出」;client 应该「在敏感操作上请求用户确认、调用前把工具输入展示给用户、为审计记录工具使用」;并且「除非来自可信 server,否则应把工具注解视为不可信」[2]。展开成三层:
- 最小权限 + 人工在环:官方原话是「应当始终有人类在环,并保留拒绝工具调用的能力」[2]——第 5 篇的确认门控在这里从「最佳实践」升级为「协议要求」;装 server 时按最小权限给目录、给凭据,文件系统 server 没必要给整块盘;
- 供应链:安装一个 npm/PyPI 上的第三方 server,等于把一段任意代码跑在你本机。凭据用环境变量注入,警惕配置文件里的明文 key;来源不明的 server,先读代码再谈接入 [5];
- 工具描述注入:别忘了第 4 篇的判断——工具描述是要进入模型上下文的。恶意 server 可以在 description 里藏指令,诱导模型越权。接入任何第三方 server 前先读一遍它暴露的工具描述;生产环境固定 server 白名单,别让 Agent 随手
mcp add。
审计落地到具体动作,就是一本流水账:每次 tools/call 记下时间、server 名、工具名、参数摘要与结果状态,定期回看「到底装了哪些 server、它们被用过多少次」——三个月没被调用过的 server,就是该下线的权限尾巴。而「最小权限」也别停在口号:目录级授权(只给 notes/,不给整块盘)、只读优先(能暴露 resource 就别暴露写 tool)、给每个调用设超时——三条都是几分钟能做完、出事时能救命的动作。协议给了你确认的抓手,纪律得自己长在流程里。
小结
- MCP 把集成的 M×N 变成 M+N,且已是厂商中立的公共标准——学它是在给未来几年铺路;
- Host/Client/Server 三角色,Client 与 Server 一一对应;stdio 与 Streamable HTTP 只是运行位置不同;
- 三原语按控制权分家:tools 归模型、resources 归应用、prompts 归用户;tools 最终仍走 function calling,协议管供给不管推理;
- 类型注解 + docstring 就是 schema,十几行一个 server;第三方 server 一律按不可信输入源对待:最小权限、人工确认、读它的工具描述。
下一篇预告:工具的问题解决了,状态的问题还欠着一笔——第 2 篇说过「跨会话还记得用户」才需要长期记忆,但真要做,写入、检索、遗忘该怎么设计?下一篇《记忆系统实战》给 Agent 装上「越用越懂你」的那一半。
参考来源
- Architecture overview, MCP 官方文档, 2026,modelcontextprotocol.io
- Tools, MCP 官方文档, 2026,modelcontextprotocol.io
- Introducing the Model Context Protocol, Anthropic, 2024,anthropic.com
- modelcontextprotocol/python-sdk, GitHub, 2025-2026,github.com
- MCP — Claude Code 文档, Anthropic, 2026,code.claude.com
- Donating the Model Context Protocol / Agentic AI Foundation, Anthropic, 2025,anthropic.com