GitHub 官方的 MCP 服务器从一开始就做了分页——perPage 最多 100,较新的工具还带 after 游标——可它的 issue 列表里照样堆满了单次调用就撑爆上下文窗口的报告:30 个提交超过 64k token,30 个拉取请求 508KB,50 个项目条目约 100K token。分页限制的是返回多少条记录。上下文窗口却是一笔 token 预算,而一条记录多重都有可能。按 token 来数你的分页,先裁字段再分页,并且要假定:你的用户实际在用的宿主,处理溢出的方式和你测试时用的那个不一样。
一览
github/github-mcp-server 上的溢出报告,截至 2026 年 10 月。大小均为各报告者自己测得,唯一的例外是 PR #2563,那是维护者测的。
| 提交日期 | 工具 | 报告的大小 | 后续处理 |
|---|---|---|---|
| 2025-04-06(#142) | list_commits | 30 个提交,>64k token;每个提交约 5–6KB | 报告者要求支持字段过滤 |
| 2025-05-22(#425) | get_pull_request_comments | 26,688 token,而 Claude Code 的上限是 25,000 | 随后出现了分页需求(#567、#625) |
| 2025-06-29(#608) | get_job_logs | 完整日志「很容易超出 LLM 的上下文上限」 | 新增 tail_lines 参数 |
| 2026-02-02(#1934) | list_pull_requests | 30 个 PR,508KB;每个 PR 约 17KB,另一次查询中达 36KB | 仍未关闭;PR #2675 让 search_pull_requests 默认返回精简结果 |
| 2026-03-02(#2122) | pull_request_read | 超过约 50–100KB 的载荷会让 Cursor 和 VS Code 的 CPU 跑满 100% | PR #2489 补上了缺失的 after 游标 |
| 2026-04-24(#2383) | projects | 50 个条目,约 400KB,约 100K token | PR #2563 引入精简类型:每个条目 −93% |
| 2026-09-07(#3236) | pull_request_read get_files | 总是返回完整补丁 | 仍未关闭;#3286 要求支持字段过滤 |
一台服务器留下的一串记录
大多数撑爆上下文窗口的 MCP 服务器都没留下任何记录。GitHub 的留下了十八个月的记录,因为它的用户会提 issue,维护者也会公开回复。按时间顺序读下来,这些 issue 每一次讲的都是同一个故事。
第一份是 2025 年 4 月的 #142,一次针对 zalando/skipper 的 list_commits 调用。三十个提交在下一次模型调用时产生了超过 64k token,每个提交约 5–6KB。报告者是 OpenAI 的 tier-1 用户,收到了一个 429:这次请求需要 68,490 token,而限额是每分钟 30,000 token。这是整个故事里唯一一个硬性的成本数字。这次调用完全在页大小范围之内,却还是发不出去。
这个模式一直延续下去。2025 年 5 月,get_pull_request_comments 给一位上限为 25,000 的 Claude Code 用户返回了 26,688 token(#425)。6 月,一份报告指出完整的作业日志「很容易超出 LLM 的上下文上限」,由此催生了 tail_lines 参数(#608)。2026 年 2 月,list_pull_requests 为 30 个 PR 返回了 508KB——每个约 17KB,另一次查询中每个 36KB——报告者希望加上 search_repositories 早已具备的 minimal_output 选项(#1934,仍未关闭)。4 月,50 个项目条目合计约 400KB,大约 100K token,报告者称这「大约是一个典型 LLM 上下文窗口的一半」;两页 50 条就能把一个窗口填满(#2383)。
问题出在记录本身,而不是条数
GitHub 的 REST 对象是为那些会忽略无用字段的程序设计的:一个用户对象就带着十五个以上的 URL 模板,外加模型永远用不上的 reactions 和元数据。原样透传的话,每条记录五到十七 KB,乘以 perPage 上限 100,就是一页任何模型都装不下的数据。这台服务器的页大小对 HTTP 客户端来说很合理,对上下文窗口来说却大得离谱。
每一次真正奏效的修复都是投影。2026 年 5 月 28 日合并的 PR #2563 为项目条目加上了精简类型。维护者对五个线上条目做了测量:修改前约 12,875 token,修改后 901——削减 93.0%,每个条目从约 2,575 token 降到 180。按一页 50 条换算,就是从 128,750 token 降到 9,010。页大小没变,每条记录都变小了。同样的修复如今正在一个端点一个端点地铺开:issue 和拉取请求的列表与搜索工具新增了 fields 参数,其 README 写道「省略 body 就去掉了每条结果中最大的那部分数据」;PR #2675 让 search_pull_requests 默认返回紧凑结果,需要原始对象时传 minimal_output: false;精简类型则集中放在 pkg/github/minimal_types.go 里。截至 2026 年 10 月,下一个排队的是 pull_request_read,它的 get_files 仍然返回完整补丁(#3236)。
够不着的分页不算分页
2026 年 3 月的 issue #2122 展示了按记录分页失效的另一种方式。pull_request_read 的 get_review_comments 方法宣称支持游标分页,但工具的 schema 里根本没有 after 参数,而且有三个方法会悄无声息地忽略 page 和 perPage。模型没法请求第二页,因为 schema 里没有任何东西允许它这么做。超过约 50–100KB 的结果会让 Cursor 和 VS Code 的 CPU 飙到 100%,只能强制重启。PR #2489 补上了 after,这个 issue 在 5 月关闭。游标只有在模型能从 schema 里看到它时才管用,也只有在每一页都装得下时才有帮助。
为什么记录条数框不住窗口
Datadog 从截然相反的一类数据出发,得出了同样的结论:「一条 Datadog 日志消息可能只有 100 个字符,也可能有 1 MB」,没有哪个条数能框住这种情况。于是他们改变了一页的含义——「服务器在达到一定 token 数后截断响应,并返回一个用于获取更多内容的游标」——剩下的交给游标。
一个感知大小的分页写成代码是什么样子,MCP 中的大结果与分页的 Step 4 有完整的说明,并以 MotherDuck 和 Grafana 的服务器为实例。只按条数分页的服务器,把剩下的事全丢给了宿主,而协议并没有给宿主任何可依据的东西。
协议分页的是目录,不是调用
MCP 有分页,但只针对 tools/list 这类列表方法。tools/call 没有游标、没有大小上限、也没有分块,所以每一台对工具结果做分页的服务器,都得像 GitHub 那样自己发明 page、perPage、after 或 cursor 参数。想改变这一点的提案提过、也关过,路线图上可能有帮助的条目都没有日期;规范的规则和这段历史见MCP 中的大结果与分页。
两种膨胀,只解决了一种
过去一年那些广为人知的上下文节省,大多落在这条线的另一边。工具搜索、代码模式的目录、同步到文件夹里的工具描述,缩小的都是模型在调用任何东西之前要读的工具定义;没有一个能让单次 list_pull_requests 的响应变小。协议分页的是目录,业界大部分优化工作针对的也是目录。具体数字,以及为什么它们不该为结果侧的修复买单,见当 MCP 结果撑爆上下文。
于是由宿主说了算,而宿主们各执一词
协议里什么都没规定,每个宿主就各自设定上限,以及越过上限之后的行为,而且连单位都不统一:有的数 token,有的数字符。服务器作者为某一个宿主调好的页,换到另一个宿主上可能超线好几倍。各宿主当前的上限,以及运维方能调的旋钮,统一列在当 MCP 结果撑爆上下文的 Step 2。
落盘不是分页
落盘看起来像是宿主把问题解决了:结果保住了,窗口省下了。Datadog 的文章提到 Cursor 和 Claude Code 现在都这么做,同时也指出这「还没有写进 MCP 规范」。只有当模型能读取文件的一部分、并根据读到的内容采取行动时,这个文件才有用;针对 Notion、Atlassian 和 VS Code 集成的公开报告,展示了这几步各自怎么断掉,它们作为宿主侧的测试用例收录在运维指南的 Step 3。每个宿主都按自己的节奏修自己的落盘逻辑,所以服务器不能指望其中任何一个。
服务端该怎么做
服务器是唯一知道一条记录里装了什么、哪些字段重要的地方。GitHub 这十八个月可以归结为四条做法;包括参数、信封和尺寸在内的完整契约,见MCP 中的大结果与分页。
按 token 来数一页
设一个预算,而不只是一个条数:不断加入记录,直到下一条会越过预算,然后返回一个游标,条数上限则留作兜底。这正是 Datadog 做出的改变,也是 GitHub 那些按记录数计算的页从来没做的事。
先投影,再分页
默认只返回智能体会据以行动的字段,完整对象则让它主动去要,同时留下后续调用需要的标识符。GitHub 的 −93% 全部来自这一点,页大小一点没动。
把截断标记和补救办法放进结果
模型永远不该去猜自己是否拿到了全部。多取一条来判断,在一个字段里明说,再加一句下一步该怎么做;Anthropic 的工具编写指南要求截断提示文字引导智能体去做「许多小而有针对性的搜索」。一个完整的信封示例——游标放在参数里,标记放在结果里——见深入解析的 Step 4。
为最小的宿主而设计
按你的用户在用的最严格的宿主来定默认页大小,而不是按你桌上那一个;某个宿主按工具放宽上限的设置,只能当逃生口,不能当解决方案。眼下定出这条天花板的两个数字,见深入解析的 Step 3。
常见问题
MCP 支持对工具结果分页吗?
不支持。MCP 分页只覆盖 tools/list 这类列表方法,所以要对工具结果分页的服务器只能自己定义游标参数;具体规则见MCP 中的大结果与分页。
GitHub 的 MCP 服务器明明做了分页,为什么还会撑爆上下文窗口?
它的页是按记录数计算的,而它的记录很大——在已报告的案例中,每个提交 5–6KB,每个拉取请求 17–36KB。解决问题的是精简响应类型,而不是更小的页:PR #2563 把项目条目削减了 93%。
在 Claude Code 中,MCP 工具结果太大会怎样?
Claude Code 会先发出警告,然后把超限的成功结果存到文件、把路径交给模型,而超大的错误结果只保留开头和结尾。当前的各项阈值列在当 MCP 结果撑爆上下文里。
一个 MCP 工具的页应该多大?
用 token 或字符来设定,而不是记录数,按用户在用的最严格的宿主来定大小,并同时返回截断标记和游标。完整的契约见MCP 中的大结果与分页。
MCP 规范会加入工具结果分页吗?
短期内不会:路线图计划重新设计 tools/call 的结果形态,但没有日期,关于流式返回部分结果的提案也已被关闭。详情见MCP 中的大结果与分页。
延伸阅读
本站相关:
- MCP 中的大结果与分页——规范里的分页规则,以及一份工具层面的分页契约。
- 当 MCP 结果撑爆上下文——从宿主运维方的角度看同一个问题:上限、驱逐与告警。
- 塑形工具返回值——通用的结果信封,以及如何裁剪它。
- 设计 MCP 工具——MCP 服务器的工具粒度与 schema。
- 上下文窗口详解——这笔预算是什么,以及它为什么会被填满。
资料来源:
- github/github-mcp-server 的 issue #142、#425、#608、#1934、#2122、#2383,以及 PR #2563
- Datadog:为智能体设计 MCP 服务器工具
- motherduckdb/mcp-server-motherduck;grafana/mcp-grafana
- MCP 规范 2026-07-28:分页;MCP 路线图
- Claude Code:MCP 输出上限;Claude 连接器:大小与超时限制
- Codex 配置参考;Gemini CLI 配置;Cursor:Dynamic context discovery
- notion-mcp-server #206;atlassian-mcp-server #106;microsoft/vscode #311068
- Anthropic:Writing effective tools for agents