Skip to main content
Model Context Protocol (MCP) 支持对部分结果进行缓存。这允许客户端缓存响应,并减少不必要的重复获取。缓存与变化通知互为补充,二者可以共存。

可缓存结果

服务器 MUST 在以下操作返回的结果中包含缓存提示:
  • server/discover
  • tools/list
  • prompts/list
  • resources/list
  • resources/templates/list
  • resources/read

缓存模型

MCP 中的可缓存结果使用两个字段向客户端提供缓存提示:
  • 生存时间 (TTL) 字段 ttlMs 是以毫秒为单位的整数值,指定客户端 MAY 将结果视为新鲜的时长。
  • 缓存作用域字段 cacheScope 指示缓存响应的预期作用域,可以是 "public""private"

Time-to-Live (TTL) 字段

ttlMs 字段是服务器给出的提示,表示客户端 MAY 将结果视为新鲜的毫秒数。其语义类似于 HTTP Cache-Control: max-age
  • 如果 ttlMs0,响应 SHOULD 被视为立即过期。客户端 MAY 在每次需要结果时重新获取。
  • 如果 ttlMs 为正数,客户端 SHOULD 在收到响应后的相应毫秒数内将结果视为新鲜。
  • 如果缺少 ttlMs,客户端 SHOULD 假定默认值为 0(立即过期),并依赖自身缓存启发式规则或通知。这只应出现在较旧的服务器版本中。
  • 如果 ttlMs 为负数,客户端 SHOULD 忽略它并将其视为 0
服务器 MUST 提供 >= 0ttlMs 值。
TTL 是新鲜度提示,不是保证。服务器 MAY 在 TTL 过期前更改底层数据。 TTL 告诉客户端它可以合理地避免重新获取多久,而不是保证数据会保持不变多久。

新鲜度计算

客户端记录收到响应时的本地时间(t_received)。当满足以下条件时,响应被视为新鲜
一旦 TTL 过期,响应即为过期,客户端 SHOULD 在下次访问时重新获取。 客户端 SHOULD NOT 将 TTL 视为触发自动后台重新获取的轮询间隔。TTL 是新鲜度提示:客户端在需要数据时检查新鲜度,并且仅在过期时重新获取。选择轮询的实现 MUST 应用抖动和退避。 如果客户端有理由相信数据已发生变化(例如,在工具调用上收到意外错误,表明方法未找到或参数无效),客户端 MAY 在 TTL 过期前重新获取。 如果重新获取期间发生错误(例如网络问题、服务器停机),客户端 MAY 提供过期响应。

缓存作用域字段

cacheScope 字段控制谁可以缓存响应,类似于 HTTP Cache-Control: publicCache-Control: private

选择缓存作用域

  • 当工具、提示和资源模板列表对所有用户都相同时,"public" 是合适的。
  • 对于依赖已认证用户的 resources/read 结果,或按用户变化的过滤列表结果,"private" 是合适的。

与通知的交互

TTL 与服务器推送通知互为补充:
  • 服务器 MAY 在其能力中不公告 listChanged: true 的情况下提供 ttlMs。在这种情况下,客户端完全依赖基于 TTL 的新鲜度。
  • 服务器 MAY 同时公告 listChanged: true 并提供 ttlMs。在这种情况下,客户端可以使用 TTL 来避免在通知之间进行不必要的重新获取,而通知则作为立即失效信号。
当缓存响应仍然新鲜时收到相关通知,该通知会使缓存响应失效,并应将其视为立即过期。

与分页的交互

当列表结果被分页时,每一页都是可独立缓存的响应,这与 HTTP Cache-Control 处理分页资源的方式一致。
  • 每个页面响应都携带自己的 ttlMs 值。每页的新鲜度时钟从收到该页的时间开始。
  • 服务器 MAY 在不同页面上返回不同的 ttlMs 值(例如,对稳定列表的早期页面使用较长 TTL,对最后一页使用较短 TTL)。
  • 当缓存页过期时,客户端 SHOULD 使用其游标重新获取该页。
  • 不保证跨页面一致性。如果底层数据在页面获取之间发生变化,客户端可能会观察到重复或缺口。
  • 需要完整列表一致快照的客户端 SHOULD 从头开始重新获取(不带游标)。
  • 如果游标变为无效(例如,服务器对先前有效的游标返回错误),客户端 SHOULD 丢弃所有缓存页并从头开始重新获取。
对于给定列表请求,服务器 MUST 对所有响应页面应用相同的 cacheScope。例如,如果 tools/list 响应的第一页具有 cacheScope: "private",则该请求的所有后续页面也 MUST"private"

安全注意事项

cacheScope"public" 表示响应不包含用户特定数据,可以安全共享。服务器 MUST 意识到,即使结果来自已认证端点,具有 "public" cacheScope 的响应也可能在调用方之间共享。例如,带有 "public" cacheScope 的已认证 tools/list 调用结果可能被客户端缓存,并可能在初始请求授权上下文之外共享。(即,不同访问令牌可以利用同一缓存。) 服务器实现者:
  • 应确保 cacheScope 正确反映原语的预期可见性。
  • MUST 应用适当的逐原语访问控制,且 MUST NOT 仅依赖 cacheScope 来防止对原语的未授权访问。