模型上下文协议:宿主、客户端、服务器,以及三种原语。
MCP(由 Anthropic 于 2024 年 11 月推出,由一份开放规范治理)标准化了智能体与其所用工具、数据和提示之间的那条边。本文覆盖它的参与者模型、它的三种服务器原语——资源、工具、提示——它的 JSON-RPC 消息层,以及它的传输方式,并附小型在线示例。
参与者模型:宿主、客户端、服务器。
MCP 定义三种角色。把它们理清就是全部心智模型:
- 宿主(Host)。用户交互且内嵌模型的应用——IDE 助手、桌面聊天应用、智能体运行时。宿主管理模型、强制用户同意、并协调一个或多个客户端。
- 客户端(Client)。宿主内部的连接器,与单个服务器严格一对一。若宿主连三个服务器,就跑三个客户端。客户端讲协议并隔离该服务器的会话。
- 服务器(Server)。一个独立程序,通过协议暴露能力——工具、资源、提示。服务器包装一个系统(文件系统、数据库、SaaS API),可被任何支持 MCP 的宿主复用。
┌─ Host (the agent app) ─────────────────────┐
│ model + consent + orchestration │
│ ├── Client A ───stdio───> Server: files │
│ ├── Client B ───HTTP────> Server: github │
│ └── Client C ───HTTP────> Server: db │
└─────────────────────────────────────────────┘
one client ⇄ one server (1:1, isolated)
客户端对服务器 1:1 隔离是有意为之:它按连接界定信任。恶意或有缺陷的服务器看不到另一个服务器的会话,宿主决定哪些服务器对某个模型上下文可见。这是"互操作问题"一文 M+N 论证的协议化表达——把每个系统包装一次为服务器,教会宿主客户端一次。
三种服务器原语:资源、工具、提示。
一个 MCP 服务器可提供三类能力。区分在于谁掌握控制权:
资源(Resources)是应用控制的上下文:宿主可读取并放入模型上下文的类文件数据——文件内容、数据库行、API 响应。每个资源有一个 URI(例如 file:///repo/README.md 或自定义协议)。资源在意图上是面向读取且无副作用的;宿主决定何时呈现它们。
工具(Tools)是模型控制的动作:模型可选择调用的函数,每个用一份 JSON Schema 输入描述(与"工具调用标准"一文同一底层)。工具可有副作用——写文件、开 PR、跑查询——故 MCP 期望在执行前由宿主居中获取用户同意。
提示(Prompts)是用户控制的模板:服务器发布的可复用、可参数化的提示/工作流片段,宿主可将其呈现为命令("总结这个 PR")并用参数展开。它们让服务器交付的是专长,而不只是原始能力。
控制轴助记:资源 = 应用选择加载什么上下文;工具 = 模型选择采取什么动作;提示 = 用户选择运行哪个工作流。同一协议,三种意图。
在线格式:JSON-RPC 2.0,带生命周期。
MCP 消息是 JSON-RPC 2.0:带 id 期待响应的请求、结果、错误,以及单向通知。每个会话以一次 initialize 握手开始,双方交换协议版本与一个能力对象——这就是让 M+N 图无需"统一切换日"即可演进的版本协商。
# 1. Client opens the session and declares itself {"jsonrpc":"2.0","id":1,"method":"initialize", "params":{"protocolVersion":"2025-06-18", "capabilities":{"roots":{},"sampling":{}}, "clientInfo":{"name":"my-host","version":"1.0"}}} # 2. Server responds with its own capabilities {"jsonrpc":"2.0","id":1,"result":{ "protocolVersion":"2025-06-18", "capabilities":{"tools":{"listChanged":true}, "resources":{},"prompts":{}}, "serverInfo":{"name":"github","version":"2.1"}}} # 3. Client confirms it is ready (a notification: no id) {"jsonrpc":"2.0","method":"notifications/initialized"}
握手之后,客户端用列举方法发现服务器提供什么,再用调用方法使用它:
tools/list -> [{name, description, inputSchema}, …]
tools/call -> run a tool by name with arguments
resources/list -> [{uri, name, mimeType}, …]
resources/read -> fetch a resource's contents by uri
prompts/list -> [{name, arguments}, …]
prompts/get -> expand a prompt template with args
notifications/* -> listChanged, progress, cancelled, …
因此能力发现是运行时的,不是构建时的:宿主通过调用 tools/list 得知服务器的工具,而一条 listChanged 通知让服务器告诉宿主集合已变。能力发现有专文;这里要点是 MCP 把它烘焙进了生命周期。
传输方式,以及安全在哪里进入。
MCP 把消息格式(JSON-RPC)与承载它的传输分离。规范定义两种传输:
- stdio。宿主把服务器作为子进程启动,通过其标准输入/输出交换 JSON-RPC。适合本地工具(你机器上的文件系统或 Git 服务器):无网络面,生命周期绑定进程。
- 可流式 HTTP。服务器是一个远程 HTTP 端点;客户端 POST 请求,服务器可流式返回响应及服务器发起的消息(以服务器发送事件作为流式机制)。这是托管的、多客户端服务器的路径,也是认证(规范将远程认证对齐到 OAuth 2 风格的授权)与传输安全所在。
还有一个能力值得点名,因为它反转了通常方向:采样(sampling)。服务器可请求宿主代它运行一次模型补全(在 initialize 能力中声明)。这让服务器无需自带模型就能"智能体化",但也是宿主必须以用户同意居中处理的控制流反转。
MCP 标准化的是通道,不是信任。被连接的服务器可返回模型将读取的内容——一个提示注入面——且一次工具调用可有真实副作用。协议的职责是让同意点显式(宿主把守工具执行与采样);授予什么由你决定。威胁模型、能力范围与来源溯源防御见"安全、对齐与智能体安全"深入探讨系列。把"服务器讲 MCP"当作描述形状,永远不是授权。
主线:MCP 是一个参与者模型(宿主/客户端/服务器)加三种意图类型化原语(资源/工具/提示)加一个可插拔传输(stdio 或可流式 HTTP)之上经过协商的 JSON-RPC 生命周期。这就是全部架构;本系列其余部分考察它的各部分——结构化 I/O、发现、智能体间扩展——如何泛化。