MCP 工具如何用分页避免结果静默截断
MCP 工具一次返回过多记录,会受到传输、上下文窗口和客户端内存限制,导致截断或基于不完整结果作答。文章建议返回有界分页、显式游标与 hasMore 标记,并通过元数据明确披露截断。
AI 深度解读
把数据库查询结果一股脑塞给 AI,不一定能让它答得更全。MCP 工具返回太多数据时,传输、上下文和客户端内存都可能先碰到限制,更麻烦的是,模型可能把被截断的列表当成完整结果,继续给出结论。
作者主张把结果大小纳入工具接口设计:每次返回有上限的一页,用游标和 hasMore 明确告知是否还有数据;无法避免截断时,也要说明切在哪里、怎样继续取。对正在给 AI 接业务数据、搜索或日志工具的开发者,这比单纯扩大上下文更值得先处理。
数据返回成功,为什么结论仍然可能出错
作者把问题分成了几层:传输帧能容纳多少数据,模型上下文能放多少内容,客户端又能承受多少内存开销。它们不是同一个限制,排查时也不能只看响应有没有成功。
工具结果会进入模型的工作上下文,和用户指令、历史消息、其他工具结果争夺空间。返回的数据越多,不代表模型越能用好它们。作者列举了几种部署中的失败表现:只总结可见部分,却当作全部结果;漏掉截断位置之后的记录;遇到传输错误后,重复发起同样过大的请求。
其中最难察觉的是没有报错的情况。接口似乎正常,模型也正常回答,但它依据的集合已经不完整。
工具必须明确告诉调用方:眼前这些记录是否已经全部取完。
原文没有给出具体传输实现、上下文容量、内存阈值或实验数据。因此,这些是作者描述的工程故障模式,不能据此推导出所有 MCP 客户端统一适用的响应大小上限。
分页接口要让 Agent 知道怎样继续、何时停止
作者建议采用游标分页(cursor-based pagination),把输入和输出约定完整写进工具 schema。
输入包含 limit 和 cursor,分别表示请求的页大小和继续读取的位置。输出包含当前页的 items、下一页位置 nextCursor,以及布尔值 hasMore。接口还要声明页大小上限,让客户端和 Agent 对单次返回量有稳定预期。
这里最有价值的不是字段名字,而是循环有了明确规则:处理当前页,检查 hasMore;还有数据就沿游标继续,没有数据才结束。模型不用从列表长度猜测是否取完,也不用自行发明翻页参数。
作者推荐不透明游标(opaque cursor),也就是调用方只负责原样传回、不需要解析内部结构的续取凭据。对于会发生增删的数据,按位置计数的 offset 容易漂移:前面插入一条记录,后面记录的位置就变了,下一页可能重复或漏项。锚定最后一条已读记录的游标,可以减少这类位置变化带来的问题。
不过,原文把游标的稳定性讲得比较笼统。它没有说明排序规则、锚点被删除后的处理方式,也没有说明多页数据是否来自同一份快照。游标是合理方向,但完整性仍然依赖服务端怎样实现。
分页之外,还要考虑截断。某些工具包装的是固定数据块,例如日志文件或搜索响应,未必能直接按记录分页。作者建议限制输出,并附带 truncated 标记、截断位置等元数据,以及下一段的游标。
分页是预先设计好的遍历方式;截断则表示这次输出没有完整交付。两者都需要继续读取的路径。只返回一个 truncated: true,却不给后续获取办法,模型仍然无法补齐信息。
我的判断
我赞同把结果大小当作接口契约。对 Agent 来说,hasMore 和续取位置会直接影响结论是否可信。它们不是可有可无的辅助字段。
相比「全部返回,让模型自己筛选」,受控分页更容易限制单次开销,也更方便定位问题。但原文没有提供分页前后的准确率、延迟或成本对照,这部分应当视为工程经验,不能当成已量化验证的收益。
分页也有代价。多页读取会增加调用次数;如果任务只是找某条记录,或者计算一个统计值,让工具先筛选、聚合,通常比要求 Agent 翻完整个集合更直接。这是站内补充的取舍,原文没有展开。
还要区分「能取到全部」和「应该取到全部」。查询单条信息可以按需停止;声称覆盖整个集合的汇总,则必须有完整遍历的依据。接口提供了续取能力,不代表模型一定会正确使用它。
作者提出测试整个翻页行为,这一点很实用:单页返回正确,不足以证明多页之间没有遗漏或重复。
能拿来做什么
- 给 Node 实现的 MCP 列表工具检查一遍接口:输入是否有
limit、cursor,输出是否有items、nextCursor、hasMore,schema 是否说明页大小上限和游标含义。 - 为日志或搜索工具补齐截断信息。如果响应有长度限制,就明确返回
truncated、截断位置和续取方式,让 AI 知道当前内容是否完整。 - 测试真实调用循环,沿游标读取完整集合,核对是否重复或漏项,并确认调用方恰好在
hasMore为false时停止。 - 在日常 AI 编程中审查依赖工具列表的结论,尤其是「全部」「没有」「只有这些」等表述,检查工具是否还有未读取的数据。