MCP:宿主、客户端、服务器

P3
深入解析 · 协议与互操作

模型上下文协议:宿主、客户端、服务器,以及三种原语。

MCP(由 Anthropic 于 2024 年 11 月推出,由一份开放规范治理)标准化了智能体与其所用工具、数据和提示之间的那条边。本文覆盖它的参与者模型、它的三种服务器原语——资源、工具、提示——它的 JSON-RPC 消息层,以及它的传输方式,并附小型在线示例。

STEP 1

参与者模型:宿主、客户端、服务器。

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 论证的协议化表达——把每个系统包装一次为服务器,教会宿主客户端一次。

STEP 2

三种服务器原语:资源、工具、提示。

一个 MCP 服务器可提供三类能力。区分在于谁掌握控制权

资源(Resources)是应用控制的上下文:宿主可读取并放入模型上下文的类文件数据——文件内容、数据库行、API 响应。每个资源有一个 URI(例如 file:///repo/README.md 或自定义协议)。资源在意图上是面向读取且无副作用的;宿主决定何时呈现它们。

工具(Tools)是模型控制的动作:模型可选择调用的函数,每个用一份 JSON Schema 输入描述(与"工具调用标准"一文同一底层)。工具可有副作用——写文件、开 PR、跑查询——故 MCP 期望在执行前由宿主居中获取用户同意。

提示(Prompts)是用户控制的模板:服务器发布的可复用、可参数化的提示/工作流片段,宿主可将其呈现为命令("总结这个 PR")并用参数展开。它们让服务器交付的是专长,而不只是原始能力。

控制轴助记:资源 = 应用选择加载什么上下文;工具 = 模型选择采取什么动作;提示 = 用户选择运行哪个工作流。同一协议,三种意图。

STEP 3

在线格式: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 把它烘焙进了生命周期。

STEP 4

传输方式,以及安全在哪里进入。

MCP 把消息格式(JSON-RPC)与承载它的传输分离。规范定义两种传输:

  • stdio。宿主把服务器作为子进程启动,通过其标准输入/输出交换 JSON-RPC。适合本地工具(你机器上的文件系统或 Git 服务器):无网络面,生命周期绑定进程。
  • 可流式 HTTP。服务器是一个远程 HTTP 端点;客户端 POST 请求,服务器可流式返回响应及服务器发起的消息(以服务器发送事件作为流式机制)。这是托管的、多客户端服务器的路径,也是认证(规范将远程认证对齐到 OAuth 2 风格的授权)与传输安全所在。

还有一个能力值得点名,因为它反转了通常方向:采样(sampling)。服务器可请求宿主代它运行一次模型补全(在 initialize 能力中声明)。这让服务器无需自带模型就能"智能体化",但也是宿主必须以用户同意居中处理的控制流反转。

MCP 标准化的是通道,不是信任。被连接的服务器可返回模型将读取的内容——一个提示注入面——且一次工具调用可有真实副作用。协议的职责是让同意点显式(宿主把守工具执行与采样);授予什么由你决定。威胁模型、能力范围与来源溯源防御见"安全、对齐与智能体安全"深入探讨系列。把"服务器讲 MCP"当作描述形状,永远不是授权。

主线:MCP 是一个参与者模型(宿主/客户端/服务器)加三种意图类型化原语(资源/工具/提示)加一个可插拔传输(stdio 或可流式 HTTP)之上经过协商的 JSON-RPC 生命周期。这就是全部架构;本系列其余部分考察它的各部分——结构化 I/O、发现、智能体间扩展——如何泛化。