生产级 MCP Server 是受策略约束的能力服务,不是把任意函数套一层 Transport。按照 MCP 2026-07-28,每个 Request 都必须能够被独立路由、在需要时认证、逐项鉴权、限制资源、取消和审计;协议不再提供可以承载这些责任的握手或 Session ID。
本文假设读者已经了解 Host、Client、Server、Tool、Resource 与 Prompt。协议角色和生命周期可先阅读 MCP 协议深度解析,身份提供商集成则参考 远程 MCP 企业 OAuth 指南。
核心摘要
- 本地进程边界使用
stdio;远程 MCP Endpoint 使用 Streamable HTTP。 - 在
2026-07-28中,每条远程消息都是新的 POST,不再有initialize、notifications/initialized、Mcp-Session-Id、GET Stream 或 SSE Resume。 - 业务连续性使用显式 State Handle。Connection、Process 或 SSE Stream 都不是 User、Task、Tenant 或 Authorization Context。
- Request 按顺序进入 Transport Limit、Identity、Protocol Header、Schema、Object Authorization、Side-effect Policy 与 Execution Budget。
- Tool Definition、Arguments、Resource Content 和 Result Content 默认都不可信。
- 对高影响业务拆分 Read、Propose 与 Execute。Annotation 只能描述预期行为,不能授予权限。
- 只有安全性可证明时才重试。Dispatch 后丢失响应可能意味着 Unknown Effect,不等于执行失败。
- 大结果必须有界,Private Cache Key 必须绑定完整 Authorization Context。
- Legacy 协议放在显式兼容 Route 或 Adapter 中,不能由不可信 Request 选择更弱路径。
先定义生产契约
生产就绪意味着:不依赖隐藏的 Connection History,也能解释任意一次 Request 为什么被允许、如何执行以及产生了什么效果。
| 边界 | 必备证据 | 不安全捷径 |
|---|---|---|
| Protocol | Revision、Method、Name、Request ID、Descriptor Hash | 信任之前协商过的 Connection |
| Identity | Resource Server、Issuer、Principal、Tenant、Credential Age | 接受熟悉 IdP 签发的任意 Token |
| Authorization | Tool/Resource/Prompt、Object、Arguments、Purpose、Effect | 把 Scope 或 Schema 当成权限 |
| Execution | Deadline、Byte Budget、Concurrency Class、Idempotency Key | 所有 Tool 共用一个 Timeout 和 Retry |
| Result | Result Type、Output Validation、Provenance、Effect Status | 把 Transport Error 当成回滚证明 |
| Audit | Policy Revision、Decision、Latency、脱敏 Outcome | 记录原始 Token 或完整敏感 Payload |
MCP 只标准化协议边界,不提供 Tenant Isolation、Transaction Semantics、业务鉴权、Secret Management 或 Incident Response。即使 SDK 已处理 JSON-RPC Frame,这些责任仍属于应用。
按信任边界选择 Transport
MCP 2026-07-28 定义了两种标准 Transport,它们对应不同的运行模型。
本地 stdio
Host 启动本地 Server Process 时使用 stdio。每条 JSON-RPC Message 在标准输入或输出中占一行,日志只能写入标准错误。
本地不等于安全。进程可能继承 Environment Variable、File Permission、Network Access 和 Executable Path。应固定 Package 与 Command、验证来源、使用最小 OS Identity、限制目录与 Egress,并在安装前展示完整启动命令。恶意本地 Server 位于用户信任边界内,影响可能比远程 API 更大。
远程 Streamable HTTP
Server 独立部署时使用 Streamable HTTP。现代流程以单个 Request 为边界:
- Client 为每条 JSON-RPC Request 发起新的 HTTP POST。
- POST 携带
MCP-Protocol-Version与Mcp-Method。 tools/call、resources/read、prompts/get还必须携带Mcp-Name。- Body 的
_meta携带相同 Protocol Revision、Client Capabilities 与可选 Client Info。 - Server 返回单个 JSON Response,或以最终 Response 结束的 Request-scoped SSE Stream。
POST /mcp HTTP/1.1
Content-Type: application/json
Accept: application/json,text/event-stream
Authorization: Bearer <access-token>
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: reports.publish
{"jsonrpc":"2.0","id":42,"method":"tools/call","params":{"name":"reports.publish","arguments":{"reportId":"rpt_72","idempotencyKey":"pub_8f3"},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{},"io.modelcontextprotocol/clientInfo":{"name":"operations-host","version":"4.2.0"}}}}
JSON-RPC Body 仍是事实源。Dispatch 前必须拒绝 Header 与 Body 不一致的请求。存在 Origin Header 时必须校验,非法 Origin 返回 403。本地 HTTP Server 默认只绑定 Loopback,除非明确要开放远程访问。
SSE 只是发送相关 Progress 或 Logging Notification,并以最终 Result 结束的响应表示。关闭该 Response Stream 就是在取消当前 Request;Server 应尽快停止工作,并且不能继续发送消息。当前版本没有独立 GET Stream、Protocol Session、Last-Event-ID 恢复,也不能在 Stream 上发送独立 Server Request。
每个 Server 都必须实现 server/discover,但 Client 不需要先调用它才能执行 Business Method。Request 指定不支持的 Revision 时,应返回带 Supported Revision 的 UnsupportedProtocolVersionError,不能静默降级。
长期 List 与 Resource 变更通知使用显式 subscriptions/listen Request。Sampling、Elicitation 或 Roots 输入通过 MRTR 放入 InputRequiredResult,不会重新制造隐藏的双向 Session。
在没有 Protocol Session 的情况下管理状态
Stateless Core 消除的是 Transport Affinity,不是 Application State。Protocol Revision 和 Client Capabilities 随每个 Request 传递,因此普通 Round-robin Load Balancer 可以把请求发给任意兼容实例,无需 Sticky Routing 或共享 MCP Session Store。
Browser Automation Run、Draft、Cart、Export Job 或 Approval 仍可能跨越多次调用。Server 应由 Tool 返回显式 Opaque State Handle,并要求后续调用把它作为 Argument 传回。
import { createHash, randomBytes } from "node:crypto";
type HandleRecord = {
principalId: string;
tenantId: string;
workflowType: string;
policyRevision: string;
expiresAt: number;
};
const stateHandles = new Map<string, HandleRecord>();
function digest(value: string): string {
return createHash("sha256").update(value).digest("hex");
}
export function issueStateHandle(
record: Omit<HandleRecord, "expiresAt">,
ttlMs: number,
): string {
if (!Number.isSafeInteger(ttlMs) || ttlMs <= 0) {
throw new Error("invalid_ttl");
}
const handle = randomBytes(32).toString("base64url");
stateHandles.set(digest(handle), {
...record,
expiresAt: Date.now() + ttlMs,
});
return handle;
}
export function requireStateHandle(
handle: string,
principalId: string,
tenantId: string,
): HandleRecord {
const record = stateHandles.get(digest(handle));
if (
!record ||
record.expiresAt <= Date.now() ||
record.principalId !== principalId ||
record.tenantId !== tenantId
) {
throw new Error("state_handle_not_authorized");
}
return record;
}
这个内存实现只说明契约,不是分布式方案。真实存储还需要原子过期、撤销、有界容量和安全的并发更新。
即使 Handle 随机且不透明,也要把它视为攻击者可控的对象引用。可见值中不能放 Credential 或可信 Claim。存储记录应绑定 Principal、Tenant、Workflow Type、允许的 Operation、Policy Revision 和 Expiry,并在每次使用时重新鉴权。所有权、Consent 或 Credential 变化时立即轮换或撤销。
构建有序 Request Admission Pipeline
安全的 Request Path 会先拒绝成本低的错误,再进入昂贵执行,并准确记录哪一层做出了决策。
- **Transport Admission:**限制 Body Byte、解压后 Byte、Concurrent Stream 和 Header Count;在 Tool Lookup 前拒绝非法 Origin 与畸形 JSON。
- **Identity:**验证 Credential 是否面向当前 Resource Server,并派生最小 Principal;绝不能把原始 Token 传入 Tool。
- **Protocol:**比较
MCP-Protocol-Version、Mcp-Method、Mcp-Name与 Body;明确拒绝不支持的 Revision 和 Method。 - **Shape:**执行 JSON Schema 校验,拒绝未声明或畸形 Argument;默认关闭网络
$ref解析。 - **Business Policy:**鉴权 Tenant、Object、Action、Purpose、Data Class 与 Side Effect;Schema 合法不能证明对象所有权。
- **Execution:**应用 Tool 级 Deadline、Concurrency、Egress、Row 与 Cost Budget。
- **Result:**声明
outputSchema时校验structuredContent,限制全部 Content 并脱敏 Secret。 - **Audit:**记录稳定 Outcome,不保存无限制 Prompt、Token 或私有 Payload。
Policy Decision 与 Tool Handler 应相互分离。这样可以独立测试 Denial,也能防止模型生成的 Argument 静默进入管理员代码路径。
先认证 Resource,再授权 Operation
受保护的远程 MCP Server 是 OAuth Resource Server,Client 是 OAuth Client,Authorization Server 负责签发 Access Token。委托式 HTTP Access 使用 Protected Resource Metadata、Authorization Server Metadata、PKCE、RFC 9207 Issuer Validation 与 RFC 8707 Resource Indicator。
“OAuth 让 Tool 安全”是错误边界:
- Token 只能放在
Authorization: Bearer; - 拒绝签发给其他 Resource 或 Audience 的 Token;
- 不能把 Downstream Token 当作 MCP Credential 接受或透传;
- Client Credential 必须绑定签发它的 Issuer;
- 只 Challenge 当前 Operation 所需的 Scope;
- Token 缺失、无效或过期返回
401,权限不足返回403; - Token 验证后仍需授权 Tenant、Object、Argument、Purpose 与 Side Effect。
Authorization 在协议层是可选能力,因为本地 stdio 与私有 Workload Topology 不同。网络部署仍必须有明确 Identity 和 Authorization Boundary。若不使用 MCP OAuth Profile,应记录替代机制、Principal Mapping、Rotation、Revocation 和互操作成本。
OAuth Metadata 是不可信网络输入。需要验证 HTTPS Destination、Redirect 和最终解析地址;除非开发策略明确允许,否则阻断 Private、Loopback、Link-local 与 Cloud Metadata 地址。固定可信 Issuer,并使用受控 Egress 抵御 Metadata-driven SSRF。
远程 MCP 企业 OAuth 指南进一步解释 PKCE、JWKS Rotation、多 IdP Claim 与 Downstream Delegation。
按副作用设计 Tool
生产级 MCP Tool 应暴露一个可理解、权限边界窄的能力。
优先设计:
reports.read(reportId)
reports.preparePublication(reportId)
reports.publish(reportId, approvalId, idempotencyKey)
避免设计:
api.request(method, url, headers, body)
database.execute(sql)
shell.run(command)
通用 Proxy 把 Destination、Ownership 与 Effect Policy 压缩进模型生成的字符串,会放大 SSRF、Injection、Data Egress 与 Audit Ambiguity。
对高影响操作拆分 Read、Propose、Execute。Proposal 应展示精确 Object、Destination、Amount、Recipient 与不可逆 Effect。Approval 必须绑定这些关键参数、Principal、Tool Descriptor Hash、Policy Revision 和短 Expiry;任何重要字段变化都重新审批。
readOnlyHint、destructiveHint、idempotentHint、openWorldHint 是 Annotation,不是证据。存在 Bug 或恶意的 Server 可以错误标注;Policy Engine 必须按真实 Code Path 与 Backend Effect 分类。
明确 Retry 与 Unknown Effect
Transport Success 与 Business Success 是两件事。写操作到达 Backend 后,即使 Response 丢失,也不能证明副作用失败或已经回滚。
| 观察结果 | 含义 | 默认动作 |
|---|---|---|
| Dispatch 前拒绝 | Backend Effect 未开始 | 修复后按策略重试 |
| Read Timeout | Result Unknown,但没有预期写入 | 在总 Deadline 内有界重试 |
| Idempotency Store 拒绝写入 | 已知重复操作 | 返回已记录 Outcome |
| Dispatch 后 Write Timeout | Unknown Effect | 查询 Operation Status,不盲目重试 |
| 收到 Cancellation | 已请求停止 | 向下游传播,并核验真实 Effect |
| Connection Lost | Transport 终止 | 不推断回滚 |
高影响 Tool 应:
- 要求 Caller 或 Server 提供 Idempotency Key;
- 原子绑定 Principal、Tenant、Tool 与关键 Argument Digest;
- 存储
pending、succeeded、failed或unknown_effect; - 精确重复时返回原 Outcome;
- 相同 Key 携带不同 Argument 时拒绝;
- Backend 支持异步完成时提供 Status Lookup。
不能只因为 Annotation 声明 idempotentHint: true 就重试。需要验证 Backend Contract、Retention Window 与 Duplicate Behavior。每层 Retry Budget 都必须包含在总 Request Deadline 中,防止多层重试相乘。
让 Result 有界,并始终按数据处理
大 Result 会消耗 Memory、Network、Context Window 和 Disclosure Budget。应使用满足任务的最小表示:
- 对机器可校验字段返回有界
structuredContent; - 大列表返回 Summary 与 Opaque Cursor;
- 大 Artifact 使用经过授权的 MCP Resource 或 Resource Link;
- 产品拥有二进制交付通道时,使用短期 Application Download。
每个 Page、Resource Read 或 Download 都要重新检查 Principal、Tenant、Object 与 Expiry。Cursor 是对象引用,不是 Authorization;应绑定 Query Semantics 和 Policy Revision,并拒绝篡改与跨租户重用。
Tool 与 Resource Content 可能包含 Prompt Injection、恶意 URL、过期数据、Secret、Executable Code 或误导性指令。必须验证 Shape 与 MIME,限制 Nesting 与 Decompression,附加 Provenance,删除非必要字段,并明确标记外部文本是数据。Result 不能授权后续 Tool Call。
每个成功的 2026-07-28 Result 都声明 resultType: "complete" 或 resultType: "input_required"。后者表示协议步骤暂停,不代表业务操作已经完成;Client 使用所需 Input 重试原 Method 之前,不能记录成功 Outcome。为兼容旧 Revision,缺少 resultType 的历史 Result 按 Complete 处理。
Base64 只改变表示,不提供 Confidentiality,也不会改善尺寸成本。不能用 Base64 作为把无界文件塞入 JSON-RPC 的理由。
缓存与 Subscription 不能跨越租户边界
MCP 2026-07-28 的 List Result 与 Resource Read Result 可以携带 ttlMs 和 cacheScope。它们只是 Cache Hint,不是 Permission。
对 cacheScope: "private",Cache Key 至少包含:
已配置 Server Identity
Protocol Revision
Principal 与 Tenant
Authorization Context
Policy Revision
Method 与归一化 Arguments
Resource 或 Tool Descriptor Hash
不能因为两个 Payload 相同就把 Private Entry 降级为 Public。TTL 不能超过 Credential、Consent、Object 与 Policy Expiry;Permission 或 Descriptor 变化时立即失效。
subscriptions/listen 负责传递选定的 List 与 Resource Change Notification。Notification 只表示“缓存可能已过期”,不能授予新 Capability。使用前必须重新执行 Discovery Validation、Descriptor Review 与 Authorization。连接断开后创建新 Subscription;当前 Revision 不支持 Last-Event-ID Replay。
使用背压、Deadline 与 Cancellation
Agent Loop 即使由一个用户触发,也可能制造突发流量。应组合以下 Budget 保护稀缺依赖:
- Principal、Tenant、Server、Tool 级 Rate Limit;
- Tool 级 Concurrency 与 Queue Limit;
- Request Body、Response Body 与 In-flight Byte Limit;
- 一个 Total Deadline 与更短的 Downstream Timeout;
- Retry 与 Model Loop Budget;
- 按 Dependency 隔离的 Circuit Breaker 与 Bulkhead;
- Egress Allowlist 与 DNS Control;
- 先停止接收、再 Drain Work 的 Graceful Shutdown。
不能让一个慢 Tool 占满全局 Worker Pool。稳定的 Overload 或 Timeout Outcome 必须区分“尚未开始”与“Effect Unknown”。Cancellation 应传播到 Database Query、HTTP Call 和 Worker,并继续观测 Downstream 是否真正停止。
长业务任务不应无限保持 Request-scoped SSE Stream。只有 Client 支持对应 Extension 时才使用显式 Job 或 Task Extension,并把 Ownership、Status 与 Cancellation 保存在 Application State。
观测决策,不记录 Secret
有效 Telemetry 可以重建 Control Path,却不复制敏感内容。记录:
- Request 与 Trace ID;
- Protocol Revision、Method 与 Name;
- Client 与 Server Build;
- Hash 或 Tokenize 后的 Principal 与 Tenant;
- Descriptor、Argument 与 Policy Revision Hash;
- Authorization Decision 与 Reason Code;
- Deadline、Queue Time、Execution Time、Byte 与 Row;
- Idempotency State、Retry Count 与 Effect Status;
- Result Type、Cancellation 与 Error Class。
默认不记录 Bearer Token、Refresh Token、原始 Secret、无限制 Prompt、完整 Private Resource 或全部敏感 Argument。导出前就执行 Field-level Redaction,不能只在 Log Viewer 中隐藏。Audit Access 与 Retention 也应独立于业务数据治理。
Protocol Logging 在 2026-07-28 中已 Deprecated。新系统应使用 OpenTelemetry 等普通 Structured Telemetry,不能把 notifications/message 当作生产 Audit System。
隔离 Legacy Compatibility
Legacy Support 是独立信任边界。2025-03-26 至 2025-11-25 使用 initialize、可选 Mcp-Session-Id、独立 GET Stream 和 Server-initiated Request;HTTP+SSE 2024-11-05 使用分离的 SSE 与 Message Endpoint。
使用显式 Versioned Route、Adapter 或 Deployment:
/mcp -> 2026-07-28 Stateless Streamable HTTP
/legacy/mcp -> earlier Streamable HTTP adapter
/legacy/sse -> 2024-11-05 HTTP+SSE
不能让 Request Header 选择更弱的 Authentication 或 Authorization Policy。Legacy Traffic 不得进入现代 Cache 与 Subscription。Client 探测兼容性时应先解析 Structured JSON-RPC Error;仅凭 HTTP 400、404 或 405 不能确认 Server 是 Legacy。
按 Revision 统计使用量,发布 Retirement Date,测试 Downgrade Resistance,并在受支持 Client 完成迁移后再删除兼容层。
测试故障矩阵
只测正常 Tool Call 几乎不能证明生产安全。至少覆盖:
| 层级 | 必备负向测试 |
|---|---|
| Transport | 非法 Origin、超大 Body、畸形 JSON、不支持 Method、HeaderMismatch、SSE 断连 |
| Version | 不支持 Revision、缺少必需 Metadata、错误 Legacy Fallback |
| OAuth | 错误 Issuer、Resource、Audience、PKCE、过期 Token、Scope 不足、Metadata SSRF |
| Authorization | 跨 Tenant Object、Approval 参数变化、过期 Policy、撤销 Principal |
| Tool | 未知字段、边界值、错误 Annotation、禁止 Egress、投毒 Description |
| State | 猜测、过期、Replay、跨用户与跨 Operation Handle |
| Reliability | Overload、Dependency Timeout、Cancellation、重复写、Unknown Effect |
| Result | 超大、违反 outputSchema、投毒文本、危险 MIME、Decompression Bomb |
| Cache | Private 跨用户碰撞、TTL 超过 Credential Expiry、过期 Descriptor |
每个支持的 Protocol Revision 与固定 SDK Build 都要运行 Compatibility Test。Conformance 不能替代业务测试:格式完全正确的 tools/call 仍可能越权或重复扣款。
生产检查清单
- [ ] 固定受支持 MCP Revision 与 SDK Build。
- [ ] 现代 Streamable HTTP 使用带必需 Metadata 的独立 POST。
- [ ] 路由前交叉检查 Header 与 Body。
- [ ] Origin、Size、Concurrency、Deadline 与 Egress Control 在 Tool 执行前生效。
- [ ] Identity 映射到 Principal 与 Tenant;Token 绑定 Audience 且禁止透传。
- [ ] 每个 Tool、Resource、Prompt 与 Object 都有应用层授权。
- [ ] 业务连续性使用显式、可过期、可撤销 State Handle。
- [ ] 高影响场景拆分 Read、Propose 与 Execute。
- [ ] Approval 绑定精确参数、Descriptor 与 Policy Revision。
- [ ] Write 有真实 Idempotency 与 Status Query 契约。
- [ ] 显式表示 Unknown Effect。
- [ ] Result、Page、Cursor 与 Resource 有界且每次重新鉴权。
- [ ] Private Cache 包含完整 Authorization Context。
- [ ] Cancellation 传播至下游,并观测最终 Outcome。
- [ ] Log 记录 Decision 与 Effect,不保存 Token 或无限制 Private Content。
- [ ] Legacy Protocol 使用隔离 Route,并具备 Downgrade Test 与 Retirement Telemetry。
常见问题
MCP 2026-07-28 需要 Session Store 吗?
不需要。Core 已没有 Protocol Session。应用仍可保存 Workflow State,但必须返回显式 Opaque Handle,并在每次使用时鉴权该对象。隐藏 Connection State 既不可迁移,也不是身份边界。
生产 MCP Server 是否始终返回 SSE?
不是。简单 Result 返回 application/json;只有最终 Result 前需要相关 Progress 或 Logging Notification 时才使用 Request-scoped text/event-stream。选定的长期变更通知使用 subscriptions/listen。
有效 OAuth Token 足以调用 Tool 吗?
不够。它只证明已经验证的 Credential Contract。Server 仍需检查 Tenant、Object、Tool、Arguments、Purpose 与 Effect。Scope 只是粗粒度门禁,Token Passthrough 被明确禁止。
什么情况下 Retry 安全?
操作尚未开始、只读,或 Backend 提供可验证幂等契约时可以重试。写入发生歧义 Timeout 后,应按 Idempotency Key 查询状态或返回 Unknown Effect。
Server 应如何返回大文件?
返回有界 Summary,以及经过独立授权的 Resource 或 Download Reference。每次读取重新鉴权,限制 Byte 与 Lifetime,并把文件当作不可信数据。
总结
MCP 生产工程的起点,是从 Transport 中移除隐藏信任。2026-07-28 Request 携带足够协议信息,可以到达任意兼容实例;Server 仍需建立 Identity、授权精确 Effect、管理业务状态、限制执行并保留证据。
稳定架构依赖显式契约:显式 Revision、Principal、State Handle、Approval、Idempotency 与 Effect Status。这样既能水平扩展,也能在故障发生后解释真实结果,而不把 Connection 或 Schema 误当成安全边界。
延伸阅读
- MCP 协议深度解析:Stateless Core、Discovery、MRTR 与能力家族。
- 远程 MCP 企业 OAuth:PKCE、JWKS、Tenant Claim 与 Downstream Delegation。
- MCP Gateway 架构:Routing、Backpressure、Bulkhead 与双 Hop Authorization。
- MCP Server:Server 责任与生命周期边界。
- MCP Resource:URI、Read、Cache 与 Content Safety 契约。