核心摘要
MCP 是协议边界,不是授权系统或自主 Agent 框架。在 MCP 2026-07-28 中,每个 Request 都是 Self-describing:它携带 Protocol Version 与相关 Client Capabilities,任意兼容 Server Replica 都能独立处理,不依赖 Protocol Session。Host 使用一个或多个 Client 连接 Server,Server 则暴露 Tool、Resource 与 Prompt。应用仍然负责:
- 认证调用者;
- 针对精确的 Tool、Resource、Tenant 和对象执行授权;
- 校验参数和结果大小;
- 限制成本、并发和副作用;
- 审计并删除敏感数据。
本文解释基础词汇和生命周期。生产安全可阅读 MCP 生产实践,远程 OAuth 边界可阅读 企业 OAuth 集成指南。
为什么需要协议边界
没有共享协议时,每个 Host 都要用不同 Adapter 接入每个外部能力。MCP 不能消除应用工作,但提供了共同的生命周期和消息模型:
| 关注点 | MCP 提供 | 应用仍负责 |
|---|---|---|
| Connection | stdio 与 Streamable HTTP Binding | TLS、Proxy、进程和网络策略 |
| Message | JSON-RPC Framing、Per-request Metadata、Result Type | 校验、限制和错误映射 |
| Discovery | server/discover 与 Capability List Method |
来源、审批和清单治理 |
| Tool | 名称、描述、输入 Schema | 身份、授权和副作用 |
| Resource | URI 形式的数据引用 | 所有权、新鲜度、分类和删除 |
| Prompt | 可复用消息模板 | 内容审查、注入控制和策略 |
互操作性不等于权限可迁移。一个 Server 可以被多个 Host 使用,但每个部署仍需要自己的授权模型。
协议角色与外部系统
Host
Host 是面向用户的应用或 Agent Runtime,通常负责:
- 接收用户请求;
- 选择或路由模型;
- 管理一个或多个 Client;
- 把发现到的能力呈现给模型;
- 执行 Host 侧审批和展示策略。
Host 不应把 Server 的描述当成可信指令。描述、Resource 和 Result 都是跨信任边界的数据。
Client
MCP Client 是由 Host 管理的协议适配器。常见拓扑是一个 Client 对应一个 Server,以隔离 Credential、Capability Catalog、Cancellation 和故障。可以保留 Dedicated Connection,但它不是 Protocol Session、Conversation、User 或 Task。Host 也可以使用 Gateway,这会增加新的路由、身份、缓存和策略边界。
Server
Server 暴露能力并在自己的策略下执行。它可以访问文件系统、数据库、API 或进程内服务。“Server”描述的是协议角色,不保证一定是独立 OS 进程、沙箱或安全边界。
External System
数据库、文件存储、SaaS API 或本地操作系统才是业务数据的权威。MCP Server 是 Adapter 和策略执行点,不能替代外部系统的访问控制。
无状态请求与 Discovery
MCP 2026-07-28 没有 initialize / notifications/initialized 握手,也没有 Mcp-Session-Id。每个 Request 都在 _meta 中携带选定 Revision 和相关 Client Capabilities。clientInfo 可用于展示和调试,但它是 Self-reported Metadata,不能充当认证身份。
每个 Server 都必须实现 server/discover,但 Client 也可以先调用其他 Method,并处理 UnsupportedProtocolVersionError(-32022)。Discovery 返回支持版本、Server Capabilities、Identity Metadata 与 Cache Hint,只能证明协议兼容,不能证明 Endpoint 来源、可信度或权限。
精简后的 Discovery Request 展示了 Self-describing Contract:
{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": {
"name": "acme-host",
"version": "4.2.0"
},
"io.modelcontextprotocol/clientCapabilities": {
"elicitation": {}
}
}
}
}
Capability Discovery 不是权限授予。列表可以按当前 Request 携带的 Credential 变化,但不能因其他 Request 复用了同一 Connection 而变化。可靠 Client 还应处理:
- Protocol Version 不匹配;
- Discovery 超时与过期 Cache Hint;
- 畸形或超大消息;
- 取消和断连;
- 已订阅的 Capability 变化;
- Server 关闭与 Stream 重连;
- 重复请求和幂等。
JSON-RPC 边界
MCP 使用 JSON-RPC 的请求、响应、通知和错误概念。Request ID 用于关联响应,不负责认证请求。
type RequestId = string | number;
type JsonRpcRequest = {
jsonrpc: "2.0";
id: RequestId;
method: string;
params?: {
_meta: {
"io.modelcontextprotocol/protocolVersion": string;
"io.modelcontextprotocol/clientCapabilities": Record<string, unknown>;
};
[key: string]: unknown;
};
};
type JsonRpcError = {
code: number;
message: string;
data?: unknown;
};
function requireRequest(value: unknown): JsonRpcRequest {
if (!value || typeof value !== "object") throw new Error("invalid_request");
const request = value as Record<string, unknown>;
if (request.jsonrpc !== "2.0" ||
(typeof request.id !== "string" && typeof request.id !== "number") ||
typeof request.method !== "string") {
throw new Error("invalid_request");
}
if (request.params !== undefined &&
(!request.params || typeof request.params !== "object")) {
throw new Error("invalid_params");
}
return request as unknown as JsonRpcRequest;
}
这段代码只校验部分 Framing。真实实现还要校验固定版本的 Protocol Schema、非 Null 且唯一的 Request ID、必需 _meta、Result resultType、Method-specific Data、Byte / Depth Limit 与 Extension Negotiation。JSON Schema 未声明时默认 Draft 2020-12;默认不得解析网络 $ref,复杂 Composition 也需要资源上限。
三类核心能力
Tools
Tool 是 Model-controlled Operation,Client 可以请求 Server 执行。Definition 包含 Name、Description、必需 inputSchema、可选 outputSchema 与不可信 Annotation。tools/list 支持分页与缓存;tools/call 可返回 Text、Media、Resource Link、Embedded Resource 或经过 Schema 校验的 structuredContent。模型发出的调用应视为提议:
模型提出 Tool Call
-> Host/Client 执行审批和预算策略
-> Server 认证并授权
-> Server 校验参数
-> Server 执行操作
-> Server 返回有界 Result
好的 Tool 应明确:
- 做什么以及不做什么;
- 输入限制和默认值;
- 读写行为;
- Resource 与 Tenant 范围;
- 超时、重试、幂等和输出限制。
除非整个能力已被有意沙箱化并授权,否则不要暴露通用 run_command、任意 SQL、无限制 HTTP Client 或“管理一切”的 Tool。严格 Schema 不能让危险能力自动安全。
Resources
Resource 是 Application-controlled、由 URI 标识的数据。resources/list、resources/templates/list 与 resources/read 分别负责发现或读取;RFC 6570 Template 描述参数化 URI Space。URI 是标识符,不是读取权限证明。Server 必须执行 Scheme 校验、Tenant / Object Authorization、Freshness、MIME、Byte、Decompression、Path 与 Egress Limit。
Resource Link 可以避免把大 Artifact 嵌入 Tool Result,但后续读取必须重新鉴权。不要假定可信 Server 返回的 Resource 适合直接放入 Prompt,它可能包含指令或敏感数据。
Prompts
Prompt 是由 Server 编写、由用户选择使用的模板。prompts/list 返回 Descriptor 与 String Argument Metadata,prompts/get 渲染 user 或 assistant Message。获取 Prompt 不会调用模型,Assistant-role Message 也不会变成 System Instruction。Prompt Content、Argument 与链接或嵌入的 Resource 都是不可信数据。
| Primitive | 主要控制约定 | 核心 Method | 安全边界 |
|---|---|---|---|
| Tool | Model 提议 | tools/list、tools/call |
校验 Schema、领域规则、授权、副作用与输出 |
| Resource | Application 选择 | resources/list、resources/templates/list、resources/read |
授权 URI / Object,限制 Byte、MIME、Freshness、Traversal 与 SSRF |
| Prompt | User 选择 | prompts/list、prompts/get |
校验 Argument 与内容,保留 Provenance,防御 Prompt Injection |
List 与 Resource Read Result 携带 ttlMs 和 cacheScope。只有所有调用方得到相同且可共享的内容才可使用 public;按 User、Tenant、Role 或 Token 过滤的结果必须使用 private,并让 Cache Key 绑定 Authorization Context。Notification 只能让 Cache 失效,不能授予权限。
Result、MRTR 与 Notification
每个成功的 2026-07-28 Result 都声明 resultType。"complete" 表示最终结果;"input_required" 表示符合条件的 prompts/get、resources/read 或 tools/call 需要额外 Client Input 才能完成。
{
"jsonrpc": "2.0",
"id": 8,
"result": {
"resultType": "input_required",
"inputRequests": {
"approval": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "是否批准发布这份报告?",
"requestedSchema": {
"type": "object",
"properties": { "approved": { "type": "boolean" } },
"required": ["approved"]
}
}
}
},
"requestState": "opaque-integrity-protected-state"
}
}
MRTR 不是 Server-initiated JSON-RPC Request。初始 Request 已结束;Client 只收集自己支持的输入,再使用新的 JSON-RPC ID、inputResponses 和原样不透明 requestState 重试原 Method。Server 按攻击者可控输入处理 State,把它绑定 Principal、Method、关键参数、Policy Revision 与短 Expiry;若 Replay 可能重复副作用,还要保证单次消费。
长生命周期变更事件使用 subscriptions/listen。Client 选择 toolsListChanged、promptsListChanged、resourcesListChanged 或具体 Resource Subscription 等 Filter;Server 确认接受的子集,并用 Subscription ID 标记每个 Notification。断线后创建新 Subscription;Event 可以让 Cache 失效,但不能携带 Permission。
Transport 选择
stdio
Host 启动本地进程时可使用 stdio。仍需审查继承的环境变量、文件系统、网络外发、Shell、OS 用户和进程生命周期。本地进程并不天然沙箱化。
Streamable HTTP
面向 2026-07-28 的新远程部署应使用 Streamable HTTP。每条消息都是发往单一 MCP Endpoint 的独立 POST;Request 的响应是单个 JSON Object,或只承载相关 Notification 与最终 Response 的 Request-scoped SSE Stream。关闭该 Stream 表示取消,但不能证明下游副作用已回滚。
每个 POST 都包含 MCP-Protocol-Version 与 Mcp-Method;tools/call、resources/read 与 prompts/get 还包含 Mcp-Name。JSON-RPC Body 是权威数据,Server 必须拒绝 Header / Body 不一致。还应校验 Origin、认证每个 Request、为 SSE 关闭 Proxy Buffering,并禁止把 Secret 放进 Mcp-Param-* Header。
POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json,text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: reports.read
{"jsonrpc":"2.0","id":42,"method":"tools/call","params":{"name":"reports.read","arguments":{"reportId":"rpt_72"},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}
旧式 SSE 兼容
MCP 2025-11-25 及更早版本使用 Connection-scoped Initialization,可能包含 Mcp-Session-Id,并允许 Server-initiated Request。2024-11-05 HTTP+SSE Transport 则使用独立 SSE Endpoint 与 POST Message Endpoint。若必须兼容:
- 隔离并标记兼容路由;
- 按目标 Revision 实施 Initialize、Session 与 Message Direction;
- 对 SSE 和每个消息请求执行认证;
- 限制事件队列和结果大小;
- 明确顺序、取消、重连和重复行为;
- 通过真实 Proxy 路径测试。
不得把 Legacy Capability State 泄漏到现代路径,也不要把旧式 SSE 称为当前 Streaming Model。
HTTP 授权边界
Authorization 在 MCP 中是可选能力,但受保护的 Streamable HTTP Server 扮演 OAuth Resource Server,Client 扮演 OAuth Client。Client 发现 Protected Resource 与 Authorization Server Metadata,通过 Client ID Metadata Document 或预注册取得 Client ID,使用 PKCE 与 State,校验 Authorization Response Issuer,并在 Authorization 与 Token Request 中携带 RFC 8707 Resource Indicator。
Server 在每个 Request 上校验 Token Issuer、Audience、Expiry、Signature 与 Challenged Scope。Token 只能通过 Authorization: Bearer Header 传输,不能进入 URI。协议禁止 Token Passthrough:Server 不得接受或转发签发给其他 Resource 的 Token。
OAuth Scope 只是粗粒度门禁。Server 仍需授权具体 Principal、Tenant、Tool / Resource、Object、Argument、Purpose 与 Side Effect。Credential 缺失或无效使用 401;已认证但缺少当前操作 Scope 时,使用带 insufficient_scope Challenge 的 403。HTTP Profile 不适用于 stdio;本地 Server 从受限执行环境获取 Credential。
安全模型:MCP 不保证什么
MCP 标准化通信,但不保证:
- 用户认证;
- 租户隔离;
- 对象所有权;
- Tool 行为安全;
- Prompt Injection 抵抗能力;
- Transport 或 Telemetry 机密性;
- 缓存和日志中复制数据的删除。
远程 Server 至少需要:
- 可信 Token 或 Workload 认证;
- Issuer、Audience/Resource、Expiry、Algorithm 和 Key Rotation 校验;
- 逐调用 Scope 和对象级授权;
- 请求、结果、并发、超时和成本限制;
- 副作用的幂等与取消;
- 脱敏审计事件和 Trace Context;
- 跨租户、Tool Result Injection 和重放测试。
Read-only 或 Destructive 等 Annotation 可以帮助 Host 展示风险,但 Server 必须独立验证真实行为并执行策略。
最小 Server 设计
把协议适配、Policy 和业务逻辑分开:
Transport Adapter
-> JSON-RPC 与 Method 校验
-> Principal 与 Tenant Context
-> Tool/Resource Policy
-> Domain Service
-> 有界 Result 与 Audit Event
Domain Service 应接收可信 Context,而不是从模型参数推断身份:
type ExecutionContext = {
requestId: string;
principalId: string;
tenantId: string;
scopes: ReadonlySet<string>;
};
type ReportRequest = {
reportId: string;
};
async function getReport(
context: ExecutionContext,
request: ReportRequest,
authorize: (context: ExecutionContext, reportId: string) => Promise<boolean>,
repository: { read: (tenantId: string, reportId: string) => Promise<unknown> },
) {
if (!context.scopes.has("reports.read")) throw new Error("insufficient_scope");
if (!(await authorize(context, request.reportId))) throw new Error("access_denied");
const report = await repository.read(context.tenantId, request.reportId);
return { status: "ok", report };
}
这是核心片段,不是完整 SDK 接入。实际应用还要增加 Repository 级 Tenant 约束、结果脱敏、大小限制、Trace、错误映射和取消。
测试与运维
从五层测试契约:
| 层级 | 示例 |
|---|---|
| Protocol | server/discover、Per-request _meta、版本不匹配、Result Type、畸形 JSON-RPC |
| Policy | 缺少 Scope、错误 Tenant、对象所有权、过期 Token |
| Reliability | 超时、取消、SSE 中断、Subscription 重连、队列溢出、重复副作用 |
| Abuse | Tool / Prompt / Resource 注入、超大 Schema、SSRF、路径穿越、Token Passthrough |
| Compatibility | Modern-to-modern、Modern Probe Legacy、Legacy Fallback、不支持的 Revision |
观测低基数事件:
- Protocol 和 SDK 版本;
- Request、Subscription 和 Trace 标识;
- Method、稳定 Server Identity 和 Capability Revision;
- 参数摘要、结果类别和字节数;
- Policy、Approval、Cache 和 MRTR Decision;
- Queue / Upstream Latency、Retry、Cancellation、Budget 与最终 Effect Status。
默认不要保存原始 Token、私有 Prompt、完整 Tool Result 或隐藏推理。
如何选择 SDK
选择覆盖目标版本、Transport、取消、Capability 协商、授权 Hook 和安全更新的维护中 SDK。手写 Adapter 可以用于学习或狭窄的兼容边界,但会产生长期一致性和事故响应责任。
评估 SDK 时检查:
- Protocol 一致性测试;
- 依赖和发布历史;
- Transport 与 Proxy 行为;
- 错误和取消语义;
- 授权和脱敏扩展点;
- 观测和删除支持;
- 升级和回滚策略。
生产检查清单
- [ ] 固定 MCP 版本和 SDK。
- [ ] 记录 Host、Client、Server、外部系统和信任边界。
- [ ] 每个 Request 携带 Version 与 Client Capabilities,并支持或探测
server/discover。 - [ ] 使用 stdio 或当前 Streamable HTTP,隔离 Legacy Initialize、Session、GET Stream 与 HTTP+SSE。
- [ ] 校验 JSON-RPC Framing、Result Type、Routing Header 与 Method-specific Schema。
- [ ] 对每个操作执行认证和授权。
- [ ] 将 Resource 和 Tool 绑定到 Tenant 与对象策略。
- [ ] 按 Server、Revision、Authorization Context 与
cacheScope隔离缓存。 - [ ] 保护 MRTR
requestState,把 Sampling 与 Roots 作为 Deprecated 迁移路径。 - [ ] 限制请求、结果、队列、并发、超时和成本。
- [ ] 定义 Cancellation、Subscription Reconnect、Duplicate Effect 与 Shutdown 行为。
- [ ] 将描述、Prompt、Resource 和 Result 视为不可信数据。
- [ ] 脱敏 Telemetry,并测试删除传播。
常见问题
MCP 是什么?
它是 Host 连接面向模型的 Client 与暴露能力的 Server 的开放协议。它标准化生命周期和消息,但不标准化业务授权。
Host、Client、Server 有什么区别?
Host 协调用户和模型,Client 为一个 Server 适配协议,Server 在自己的策略下声明并执行能力。Connection 是 Transport Resource,不是 Protocol Session 或认证身份。
MCP Tool 是 Function Calling 吗?
两者在结构化调用边界上有交集,但 MCP 还定义跨进程发现、生命周期、Transport 和结果交换。Server 仍要校验和授权每次调用。
新的远程 Server 应该使用什么 Transport?
所有 Peer 支持时,使用 2026-07-28 Streamable HTTP:独立 POST Request 与 JSON 或 Request-scoped SSE Response。旧 Streamable HTTP 与 HTTP+SSE 应放在明确的兼容路由。
MCP Sampling 仍适合新实现吗?
不适合。MCP Sampling 在弃用窗口内仍可运行,但新实现应直接接入 LLM Provider API。现有 2026-07-28 兼容路径使用 MRTR,不再发送未经请求的 Server JSON-RPC Request。
总结
MCP 2026-07-28 是 Stateless Context-exchange Protocol:每个 Request 声明 Revision 与 Client Capabilities,Server 提供可发现的 Tool、Resource 与 Prompt,需要多次交互的流程使用显式 MRTR 或 Subscription。无状态化简化了水平扩展,却不会自动建立信任。应固定 Revision、校验每个边界、保留 Server Authorization、隔离 Legacy 行为,并把所有 Descriptor 与 Payload 视为不可信输入。