Appearance
MCP 无状态请求如何路由和缓存:Header Routing 与 Cacheable Lists
前置:MCP 如何表达内容与模板:Resources 与 Prompts
核心问题:无状态 MCP 请求如何携带足够路由信息,又怎样缓存 discovery/list 而不会把 tenant/session 的结果串错?
当请求不再依赖长生命周期 session 时,Gateway 必须从请求自身判断“这是什么操作、应该路由到哪里”;而 discovery/list 结果开始可缓存后,新的问题变成“这个结果允许在什么身份与版本范围内复用”。
Header Routing
Stateless MCP 的一个关键要求是:网关不能依赖“上一次连接还在某台 Server 上”才能知道请求该去哪里。请求需要携带足够的显式 routing metadata。
Header routing 的价值就在这里:Gateway 可以根据 method/name、Server identity、auth scope 等信息做路由、授权和缓存,而不是依赖长连接 affinity。
但 header 只是传递信息,不自动提供安全性。Proxy 必须防止客户端伪造受信 metadata,并确保 cache key 包含身份/权限/version,否则不同 tenant 的 list 结果可能被错误共享。
Cacheable List Results
在缓存/授权链路里,Mcp-Method / Mcp-Name 等自描述 header 可以让网关在不解析完整 JSON body 的情况下做路由或策略判断;ttlMs / cacheScope 则决定 list/discovery 结果何时、在什么范围可复用。
List/discovery 结果可以利用 ttlMs / cacheScope 减少重复请求,但 client 必须把 server identity、authorization scope、protocol/schema version 纳入 cache identity,并在版本/能力变化时失效。
Stateless 不等于“每次什么都重新算”
远程 MCP 请求可以尽量自描述,但生产 Host 仍会维护一些本地工程状态:连接池、授权 token、catalog cache、tenant/workspace routing metadata。关键是这些状态不能偷偷变成协议正确性所必需、却无法恢复的 server-side session。
一个典型 Host 路径是:
text
request context
→ resolve tenant/workspace/server
→ obtain credential
→ read cached capability list (if fresh)
→ make MCP request with required routing/auth metadata
→ normalize responseCatalog cache 的失效策略要和 capability version/freshness 绑定。缓存过久可能让模型继续看到已撤销 Tool;完全不缓存又会让每次 Run 都付 discovery latency。这个 trade-off 属于 Harness policy,而不是让 Model 自己决定“我猜这个工具还在不在”。
Failure Modes
Cache Scope 没有包含身份/版本
症状: 用户 A 的 tools/list 结果被用户 B 命中,或 Server schema 更新后仍命中旧目录。
为什么危险: 这既是功能错误,也可能直接造成越权 capability 暴露。
处理: 复用本节的 scoped cache identity;测试跨身份、跨版本请求不能命中同一条记录。
如何验证
| Case | 断言 |
|---|---|
| 不同身份请求同一 list endpoint | 不共享越权结果;版本变化后旧 cache 失效。 |
自测
- 同一 MCP endpoint 通过 header 路由不同 tenant/server 时,cache key 如果忽略 routing header 会发生什么?
- 哪些 discovery/list 响应适合缓存,哪些动态授权结果不应跨用户复用?