生产级 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 为边界:

  1. Client 为每条 JSON-RPC Request 发起新的 HTTP POST。
  2. POST 携带 MCP-Protocol-Version 与 Mcp-Method。
  3. tools/call、resources/read、prompts/get 还必须携带 Mcp-Name。
  4. Body 的 _meta 携带相同 Protocol Revision、Client Capabilities 与可选 Client Info。
  5. Server 返回单个 JSON Response,或以最终 Response 结束的 Request-scoped SSE Stream。
http
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 传回。

typescript
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 会先拒绝成本低的错误,再进入昂贵执行,并准确记录哪一层做出了决策。

flowchart LR A["HTTP 或 stdio 输入"] --> B["大小、速率与 Deadline"] B --> C["Identity 与 Tenant"] C --> D["Protocol 与 Header 校验"] D --> E["Schema 与业务校验"] E --> F["对象与副作用鉴权"] F --> G["有界执行"] G --> H["输出校验与脱敏"] H --> I["Result 与 Audit Event"]
  1. **Transport Admission:**限制 Body Byte、解压后 Byte、Concurrent Stream 和 Header Count;在 Tool Lookup 前拒绝非法 Origin 与畸形 JSON。
  2. **Identity:**验证 Credential 是否面向当前 Resource Server,并派生最小 Principal;绝不能把原始 Token 传入 Tool。
  3. **Protocol:**比较 MCP-Protocol-Version、Mcp-Method、Mcp-Name 与 Body;明确拒绝不支持的 Revision 和 Method。
  4. **Shape:**执行 JSON Schema 校验,拒绝未声明或畸形 Argument;默认关闭网络 $ref 解析。
  5. **Business Policy:**鉴权 Tenant、Object、Action、Purpose、Data Class 与 Side Effect;Schema 合法不能证明对象所有权。
  6. **Execution:**应用 Tool 级 Deadline、Concurrency、Egress、Row 与 Cost Budget。
  7. **Result:**声明 outputSchema 时校验 structuredContent,限制全部 Content 并脱敏 Secret。
  8. **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 应暴露一个可理解、权限边界窄的能力。

优先设计:

text
reports.read(reportId)
reports.preparePublication(reportId)
reports.publish(reportId, approvalId, idempotencyKey)

避免设计:

text
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 应:

  1. 要求 Caller 或 Server 提供 Idempotency Key;
  2. 原子绑定 Principal、Tenant、Tool 与关键 Argument Digest;
  3. 存储 pending、succeeded、failed 或 unknown_effect;
  4. 精确重复时返回原 Outcome;
  5. 相同 Key 携带不同 Argument 时拒绝;
  6. Backend 支持异步完成时提供 Status Lookup。

不能只因为 Annotation 声明 idempotentHint: true 就重试。需要验证 Backend Contract、Retention Window 与 Duplicate Behavior。每层 Retry Budget 都必须包含在总 Request Deadline 中,防止多层重试相乘。

让 Result 有界,并始终按数据处理

大 Result 会消耗 Memory、Network、Context Window 和 Disclosure Budget。应使用满足任务的最小表示:

  1. 对机器可校验字段返回有界 structuredContent;
  2. 大列表返回 Summary 与 Opaque Cursor;
  3. 大 Artifact 使用经过授权的 MCP Resource 或 Resource Link;
  4. 产品拥有二进制交付通道时,使用短期 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 至少包含:

text
已配置 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:

text
/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 误当成安全边界。

延伸阅读

一手资料