MCP(Model Context Protocol)
问题
MCP 如何标准化 AI 应用与工具、数据源和工作流的连接?Host、Client、Server、Tools、Resources、Prompts、Sampling、Elicitation、Roots 和 Tasks 分别是什么?如何安全地开发与接入 MCP?
MCP 是基于 JSON-RPC 2.0 的上下文交换协议。它解决的是“AI 应用如何发现和调用外部能力”,不规定模型如何推理,也不等于 Agent 框架。
- Host:AI 应用,负责用户体验、权限、模型与多个连接。
- Client:Host 内与某一个 Server 维持一对一会话的协议组件。
- Server:提供 Tools、Resources、Prompts。
- 本地传输:stdio。
- 远程传输:Streamable HTTP;旧 HTTP+SSE 仅用于兼容历史实现。
- 安全核心:能力协商、最小权限、参数校验、用户确认、OAuth 2.1、PKCE、token audience 校验和禁止 token passthrough。
一、MCP 的边界
MCP 负责:
- 初始化、版本和能力协商。
- 工具、资源和提示模板的发现与调用。
- 日志、进度、通知、用户补充输入和长任务状态。
- 传输与远程授权规范。
MCP 不负责:
- 替你决定用哪个模型。
- 自动保证工具安全或结果正确。
- 定义完整 Agent 规划、记忆和评估框架。
- 替代业务 API 的授权、审计和数据隔离。
二、参与者与连接关系
| 参与者 | 职责 | 典型例子 |
|---|---|---|
| Host | 管理用户、模型、权限、多个 Client | IDE、桌面助手、企业 Agent 平台 |
| Client | 与一个 Server 协商能力并路由请求 | Host 内部的 MCP 会话对象 |
| Server | 暴露上下文和操作能力 | Git、数据库、知识库、监控平台 |
一个 Host 通常为每个 Server 创建一个 Client。不要把“浏览器里的用户”“模型”“MCP Client”混为一谈:用户授权由 Host 驱动,模型只是提出使用工具的建议,Client 才负责协议通信。
三、能力分类
1. Server Primitives
Server 向 Client 暴露三类核心原语:
| 原语 | 用途 | 是否可能产生副作用 |
|---|---|---|
| Tools | 执行查询、计算或动作 | 取决于工具,可能有 |
| Resources | 读取文件、Schema、文档或状态 | 通常只读 |
| Prompts | 提供可复用的提示模板 | 通常无 |
2. Client Features
| 能力 | 方向 | 用途 |
|---|---|---|
| Sampling | Server → Client | 请求 Host 使用模型生成内容 |
| Elicitation | Server → Client | 请求用户补充结构化信息或确认 |
| Roots | Client → Server | 告知 Server 可操作的文件系统边界 |
| Logging | Server → Client | 发送结构化日志 |
3. Utilities
- Notifications:工具、资源或提示列表发生变化时主动通知。
- Progress:报告长操作进度。
- Tasks:为延迟执行、轮询和长任务提供实验性封装。
Host 决定是否展示请求、展示哪些字段以及用户是否同意。Server 不能假设用户一定会提供敏感信息,也不能把密码、密钥等字段偷偷塞入通用表单。
四、生命周期与版本协商
初始化顺序:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-11-25",
"capabilities": {
"elicitation": {},
"roots": { "listChanged": true }
},
"clientInfo": {
"name": "knowledge-app",
"version": "1.0.0"
}
}
}
远程 HTTP 请求应携带协商后的 MCP-Protocol-Version。双方没有兼容版本时应终止连接,而不是静默猜测;只调用对端声明支持的能力。
五、Tools
工具发现
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
工具描述应做到:名称稳定、描述具体、输入 Schema 严格、副作用明确。不要把一个万能 execute(command: string) 暴露给模型。
工具调用
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "issue_get",
"arguments": { "issueId": "FE-1024" }
}
}
工具安全设计:
- Client/Host 先按用户、租户和会话过滤允许工具。
- Server 再做真正的鉴权,不能信任模型或 Host 传来的用户 ID。
- JSON Schema 只验证形状,资源归属和状态必须单独检查。
- 读写工具拆开,例如
issue_get与issue_update。 - 写操作支持幂等键、预览、确认和审计。
- 设定超时、并发、结果大小和网络出站限制。
六、Resources 与 Prompts
Resource 使用 URI 标识内容:
{
"jsonrpc": "2.0",
"id": 4,
"method": "resources/read",
"params": { "uri": "docs://frontend/auth-design" }
}
适合 Resource 的内容:数据库 Schema、只读文档、日志片段、代码文件、业务对象快照。资源列表不等于授权列表,读取时仍要逐资源检查权限。
Prompt 是由 Server 管理的参数化模板。它适合团队共享工作流入口,但不应隐藏危险操作,也不构成不可覆盖的系统安全策略。
七、传输层
| 传输 | 场景 | 关键点 |
|---|---|---|
| stdio | Host 启动本地子进程 | stdout 只写协议消息,日志写 stderr;限制环境变量和文件权限 |
| Streamable HTTP | 多用户远程服务 | HTTPS、Origin 校验、会话管理、授权、可恢复流和负载均衡 |
对于本地 HTTP 服务,需要绑定 loopback、校验 Origin 并防止 DNS rebinding。对于远程服务,需要把会话状态放到可共享存储或使用无状态设计,不能依赖某一台实例内存。
WebSocket 可以作为应用自己的传输选择,但不是核心规范规定的默认远程传输;不要把推测中的路线图写成既定能力。
八、远程授权
当前规范采用 OAuth 2.1 的受约束方案。核心流程包括:
- Client 从 MCP Server 的 Protected Resource Metadata 发现授权服务器。
- 通过 OAuth Authorization Server Metadata 或 OIDC Discovery 获取端点。
- 使用 Authorization Code + PKCE;公开客户端必须安全处理刷新 token。
- 授权请求和 token 请求包含目标
resource。 - MCP Server 校验 token audience、scope、有效期和签名。
- MCP Server 调用下游 API 时使用自己的下游凭据,禁止转发收到的用户 token。
MCP Server 不能把 Client 给它的 access token 原样转发给 GitHub、数据库或其他下游。这会破坏 token audience 边界并造成 confused deputy。Server 应作为独立 OAuth Client 获取下游 token。
九、前端如何展示 MCP 执行过程
前端不应该只显示“AI 正在处理”。建议使用类型化状态:
type MCPActionState =
| { type: 'approval-required'; tool: string; summary: string }
| { type: 'running'; tool: string; startedAt: string }
| { type: 'progress'; tool: string; current: number; total?: number }
| { type: 'completed'; tool: string; resultSummary: string }
| { type: 'failed'; tool: string; errorCode: string };
- 对写操作展示工具名、目标资源、关键参数和预期副作用。
- 用户确认后生成不可重放的 approval token,Server 仍要再次鉴权。
- 工具结果做摘要和大小限制,原始数据通过受权资源链接查看。
- 取消只表示 Host 不再等待;还需要向 Server 传播取消并确认后台任务状态。
十、服务发现与供应链
不要在教程中维护“官方 MCP Server 大全”。生态变化快,部分早期 @modelcontextprotocol/server-* 包已废弃。推荐流程:
- 从 MCP Registry 或供应商官方页面发现 Server。
- 核对发布者、源码、包签名、权限与维护状态。
- 固定版本和完整性,生成 SBOM,先在隔离环境运行。
- 审查工具清单变化;新增高风险工具不能自动进入允许列表。
- 企业内优先维护经过审核的私有目录。
十一、MCP 与 Function Calling、A2A 的区别
| 技术 | 解决的问题 |
|---|---|
| Function Calling | 某个模型 API 如何表达“想调用函数” |
| MCP | AI 应用如何发现、连接和调用外部上下文能力 |
| A2A | 独立 Agent 之间如何发现能力、委派任务和交换结果 |
| AG-UI | Agent 与用户界面如何同步事件、状态和人工操作 |
MCP 工具最终常被转换成模型供应商的 Function Calling 描述,但它还包含资源、提示、生命周期、通知、授权和传输,不等同于 Function Calling。
常见面试问题
Q1: MCP 的 Host、Client、Server 分别是什么?
答案:Host 是完整 AI 应用;Client 是 Host 内与单个 Server 建立会话的协议组件;Server 提供 Tools、Resources 和 Prompts。一个 Host 通常有多个 Client,每个 Client 对应一个 Server。
Q2: MCP Server 到底暴露几种核心原语?
答案:Server Primitives 是 Tools、Resources、Prompts 三类。Sampling、Elicitation、Roots、Logging 属于 Client 能力或双向能力,不能统称为 Server 暴露的五种原语。
Q3: Tools 和 Resources 如何选择?
答案:有参数、需要执行并可能产生副作用的能力用 Tool;可寻址、以读取内容为主的数据用 Resource。不要为了让模型“看见数据”就把所有读取都做成高权限工具。
Q4: stdio 和 Streamable HTTP 有什么区别?
答案:stdio 适合 Host 管理的本地进程,安全边界依赖操作系统和进程权限;Streamable HTTP 适合远程多用户服务,需要 HTTPS、授权、Origin 校验、会话和横向扩展设计。
Q5: MCP 的能力协商有什么价值?
答案:初始化时双方交换协议版本和 capabilities,避免调用对方不支持的功能,也让客户端知道工具列表是否会变化、是否支持 Elicitation、Roots 等能力。
Q6: 为什么 MCP 工具仍要在 Server 端鉴权?
答案:模型、Prompt、Client 传入的用户信息都不可信。只有 Server 掌握真实资源和授权策略,因此必须对每次调用校验主体、租户、资源和操作权限。
Q7: 为什么禁止 token passthrough?
答案:上游 token 的 audience 只应指向 MCP Server。原样转发会让下游误信不属于自己的 token,引发 confused deputy。Server 应用独立凭据访问下游。
Q8: Elicitation 和普通工具确认有什么区别?
答案:Elicitation 是协议化的“向用户补充信息或请求确认”;Host 控制展示和同意。它可以用于工具前确认,但不能代替 Server 最终授权。
Q9: Tasks 适合什么场景?
答案:适合耗时较长、需要延迟获取结果或跟踪状态的操作。它仍是实验性能力,应做能力检测和降级,不要假设所有 Client/Server 都支持。
Q10: 如何防止恶意 MCP Server?
答案:审查来源和权限、固定版本、隔离进程、限制文件和网络、过滤工具列表、要求高风险操作确认、监控工具变化,并避免把环境中的全部凭据传给本地进程。
Q11: MCP 能替代 REST API 吗?
答案:不能。REST/GraphQL 是业务系统的确定性接口,MCP 是让 AI 应用发现和消费这些能力的适配层。业务授权、事务和一致性仍应留在 API 服务中。
Q12: 前端接入 MCP 最重要的体验是什么?
答案:可理解的工具状态、明确的副作用确认、取消与失败恢复、结果来源和权限解释。不要只显示模糊的“思考中”,也不要把工具原始 JSON 全部倾倒给用户。