MCP 分页游标为何必须由服务端生成
MCP 分页游标不能由客户端按照“第几页”自行生成。正确做法是:第一次请求不带 cursor,服务端返回当前页和可选的 nextCursor;客户端下一次请求原样带回这个值,直到响应中不再出现 nextCursor。游标的格式、页大小以及它如何映射到数据位置,全部由服务端掌握。
官方地址:https://modelcontextprotocol.io/specification/2026-07-28
MCP 把游标定义成不透明令牌。客户端只负责保存和转发,不能解析、递增、拼接或猜测它;服务端用自己的规则生成并解释下一页位置。
先分清 cursor 和 nextCursor
一次分页请求里有两个方向相反的字段:
cursor出现在请求参数中,表示“从服务端给出的某个位置继续”。首个请求通常没有它。nextCursor出现在响应结果中,表示“还有下一页,以及下一页应该使用的令牌”。
因此,客户端并不拥有一个可以自由递增的页码。它只接力传递上一页的结果。服务端可以把令牌实现成数字偏移、最后一条记录的主键、带签名的编码值,或者带有效期的状态引用;这些实现细节都不应该泄露为客户端契约。

最小可用配方:原样回传上一页的令牌
下面的伪客户端只处理分页职责,不假设游标内容是什么。它先消费当前页,再判断是否还存在下一页,避免把最后一页的数据漏掉。
async def list_all(client):
# None 表示从第一页开始,不能自行写成 page-1 或 0。
cursor = None
items = []
while True:
# 请求只携带服务端上一次返回的游标。
page = await client.list_resources(cursor=cursor)
items.extend(page.resources)
# 先收集当前页,再用缺省 next_cursor 判断是否结束。
if page.next_cursor is None:
break
# 不解析、不拼接,原样交给下一次请求。
cursor = page.next_cursor
return items
这段写法有三个关键点:第一页的 cursor 是空值;每一页都先加入结果;结束条件是服务端不再返回游标,而不是“本页数量小于固定页大小”。即使最后一页刚好装满,也可能需要再请求一次才能知道分页已经结束。
为什么服务端必须生成游标
把游标交给服务端生成,不是为了增加神秘感,而是为了让分页策略与数据源保持一致。
- 页大小属于服务端约束。工具、资源或提示列表的单项大小不同,服务端需要控制响应体积,协议并没有要求客户端通过
limit指定服务端必须返回多少条。 - 排序和位置属于数据源语义。服务端可能按稳定主键、更新时间加主键,或数据库游标排序。客户端若把令牌当偏移量,无法理解这些规则。
- 部署方式可以变化。令牌可以携带签名、租户边界或短期状态;客户端只转发它,服务端才能在变更内部实现后保持外部契约。
- 错误处理集中。格式不合法、已过期或超出范围的令牌,应由服务端按自身 API 规则返回错误,而不是让不同客户端各自猜测修复方式。

服务端设计时要固定的三个边界
实现 MCP 的 tools/list、resources/list、prompts/list 或相近的列表操作时,可以把选择集中在服务端处理器:
- 页大小:根据单条数据的体积和上游限制设定,不把它伪装成客户端必须理解的协议字段。
- 令牌格式:只要服务端能在下一次请求中识别即可。若采用偏移量,也应把它当作服务端内部实现,而不是允许客户端依赖数字含义。
- 数据稳定性:分页期间如果数据会插入、删除或更新,要选择稳定排序,并决定令牌是否绑定查询条件、租户和有效期。
服务端返回下一页时,可以是下面这种严格 JSON 结构。JSON 本身不插入注释,字段含义写在代码块后方,避免破坏可解析性。
{
"resources": [
{"uri": "books://catalog/book-11", "name": "book-11"}
],
"nextCursor": "opaque-token-from-server"
}
nextCursor 存在时,客户端把它放回下一次请求的 cursor;最后一页则省略该字段或使用 SDK 约定的空值。不要把一个空字符串擅自解释为结束,是否还有下一页应遵循目标 SDK 与服务端实现的明确约定。
三个容易写错的变体
| 写法 | 问题 | 改法 |
|---|---|---|
cursor = "page-" + str(page_no) | 客户端假定服务端使用页码,换实现就失效 | 直接使用上一页的 nextCursor |
| 先判断游标,再处理当前页 | 最后一页有数据但没有下一页游标,结果会被跳过 | 先追加当前页,再判断结束 |
| 把空字符串固定当作结束 | 空字符串可能仍是服务端发出的游标值 | 按 SDK/服务端约定判断缺省或空值语义 |
落地前的速查清单
- 首个请求没有人为构造的页码或游标。
- 客户端没有解码、递增或重写服务端游标的逻辑。
- 每次循环都先处理本页,再检查
nextCursor。 - 服务端的排序、页大小、令牌有效期和错误策略能够独立调整。
- 分页条件不会在下一页请求中被客户端悄悄改变。
如果只记住一句话,就是“客户端传递位置,服务端定义位置”。这让 MCP 客户端保持简单,也让服务端可以在数据库偏移、稳定键集和签名令牌之间演进,而不把内部实现变成跨客户端的隐性协议。
相关问题
MCP 的分页一定要使用数据库游标吗?
不一定。数据库游标、主键锚点、偏移量或编码令牌都可以,关键是由服务端生成并能在后续请求中解释。
客户端能不能保存 nextCursor?
可以保存和原样重放,但不要把它拆开修改。是否允许跨会话、跨用户或长时间重放,应由服务端的令牌策略决定。
没有 nextCursor 是不是代表本页没有数据?
不是。最后一页可以包含数据,只是服务端没有继续提供下一页的令牌,所以客户端必须先处理当前页。
OpenJDK 虚拟线程与 JFR 观测如何协同
- 上一篇
- OpenJDK 虚拟线程与 JFR 观测如何协同
- 下一篇
- mifun乐园隐私政策里的设备信息有哪些?Android ID、日志与SDK边界说明
-
- 科技周边 · 业界新闻 | 1小时前 | 虚拟线程 · 虚拟线程 OpenJDK JFR VirtualThreadPinned Java Flight Recorder
- OpenJDK 虚拟线程与 JFR 观测如何协同
- 480浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 |
- 浏览器 View Transition 跨文档能力为何值得关注
- 338浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | python · 版本迁移 · 兼容性 C扩展 free-threaded Python 3.15 abi3t free-threading
- Python 3.15 free-threaded 扩展兼容要先检查什么
- 300浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | 命令行 · 性能优化 · python · Python教程 · 语言特性 · Python 3.15 PEP 810 lazy imports CLI启动 启动性能
- Python 3.15 lazy imports 对 CLI 启动优化有什么启发
- 404浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 |
- Redis 哈希字段过期能力怎样改变缓存键设计
- 187浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | Redis · 消费组 Redis Streams Redis 8.2 XACKDEL XDELEX
- Redis 8.2 Stream 命令细粒度确认适合哪些消费组场景
- 153浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 |
- MCP 规范新增缓存元数据后客户端如何处理 TTL
- 406浏览 收藏
-
- 科技周边 · 业界新闻 | 1小时前 | 开发工具 · 业界新闻 · Go工具链 Go 1.27 go doc 可执行示例 go doc -ex
- Go 1.27 的 go doc -ex 如何改变示例检索体验
- 119浏览 收藏
-
- 科技周边 · 业界新闻 | 2天前 | 人工智能 · 业界新闻 · 开发实践 Stack Overflow Survey AI信任 代码助手
- Stack Overflow 2026 调查中的 AI 信任与开发实践
- 120浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 452次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 520次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 536次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 483次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 304次使用
-
- golang实现分页算法实例代码
- 2022-12-27 385浏览
-
- 用泛型方法封装类型安全的分页结果映射
- 2026-10-08 402浏览
-
- MySQL排序与分页讲解
- 2023-02-17 408浏览
-
- MySQL用limit方式实现分页的实例方法
- 2023-01-07 318浏览
-
- Kotlin+Vue+Spring Data JPA+MySQL 增查改删
- 2023-01-20 488浏览

