从信息熵与语义保真度出发,重构 MCP 响应裁剪的责任边界与工程契约
摘要
模型上下文协议(Model Context Protocol, MCP)以 JSON-RPC 2.0 为传输骨架,为 LLM 应用与外部工具之间建立了标准化调用通道。但协议本身只规定了消息结构,未对工具响应体积设置任何上限或裁剪语义。工程实践中,一次目录遍历或文件读取即可返回数万 token 的原始内容,直接挤占推理上下文,导致有效指令被截断、注意力被稀释、成本急剧上升。本文以"信息熵—语义保真度—预算约束"三元关系为贯穿主线,系统论证响应裁剪的责任归属问题。
本文的核心主张是:裁剪不应是单边行为,而应是一份跨端契约——Server 端承担"语义压缩者"角色,负责在拥有完整领域知识的条件下做结构化裁剪;Client 端承担"预算仲裁者"角色,负责在全局上下文视角下做配额分配与二次兜底。文章给出双层契约模型的形式化定义、Server 端四级裁剪流水线的实现路径、Client 端基于边际信息增益的预算分配算法,并通过公开协议规范、工程实测数据与近三年学术成果交叉验证其有效性,最后讨论该模型的边界条件与演进方向。
目录
一、问题的提出:5 万 token 从何而来
1.1 一个典型的溢出场景
设想一个标准的编码助手工作流:用户要求"分析这个仓库的依赖风险"。Agent 调用 MCP 文件系统工具的 read_directory 方法遍历项目根目录,Server 返回全部文件列表;随后对 package.json、pnpm-lock.yaml 逐一读取。仅一个中型前端项目的 lockfile 就常在 8000 至 20000 行之间,按每行平均 8 至 12 个 token 估算,单文件即可产生 6 万至 24 万 token 的原始文本。即便只读取前 2000 行,也轻松突破 5 万 token。
这类溢出并非偶发。MCP 生态中的文件系统、数据库查询、网页抓取、日志检索、代码搜索等工具,其天然输出都是"面向人类阅读"的完整数据,而非"面向模型消费"的压缩数据。协议没有为响应体积设限,工具作者出于通用性考虑倾向于原样返回,于是体积问题被完整地推给了下游的上下文窗口。
1.2 溢出的三重代价
上下文溢出不是"装不下就截断"这么简单,它至少带来三重可观测代价。第一是有效指令的稀释:Transformer 的注意力机制在长序列上存在明显的注意力分散现象,Lost in the Middle 研究(Liu et al., 2023)通过受控实验表明,当关键信息位于长上下文中部时,模型检索准确率相较首尾位置出现显著下降,且该现象在多种模型规模上稳定复现。第二是成本的非线性放大:主流 API 按输入 token 计费,5 万 token 的单次工具调用意味着每轮对话的固定开销被抬高一个数量级,多轮 Agent 循环下成本呈乘性增长。第三是延迟与失败率上升:长输入显著增加首 token 延迟,且在上下文接近窗口上限时,部分推理框架的截断策略会静默丢弃早期消息,造成工具调用结果与后续推理之间的语义断裂。
笔者认为,把溢出问题简单归因为"窗口不够大"是一种技术惰性。窗口扩大只是推迟了临界点,而工具输出的信息密度并未随之提升。真正需要回答的是:在这 5 万 token 里,有多少是模型完成任务所必需的?这个比例,才是裁剪问题的本质。
1.3 争议的焦点
工程社区对裁剪位置的争论集中在两种立场。Server 派认为,工具作者最了解自身输出的结构,理应返回"已经想清楚"的精炼结果;Client 派则认为,只有客户端掌握全局预算与任务意图,Server 无权替调用方决定什么该留。两种立场各有道理,但都隐含了一个未言明的前提——裁剪是零和的、单边的。本文后续将论证,这个前提本身值得商榷。
二、协议层的事实核查:MCP 到底规定了什么
2.1 协议规范中的响应结构
根据 MCP 官方规范(Model Context Protocol Specification, 2024-11 版本及后续修订),工具调用通过 tools/call 请求触发,响应体中的 content 字段是一个内容块数组,支持 text、image、resource 等类型。规范对单个内容块的文本长度、数组总长度、整体序列化体积均未设置上限,也未定义任何"建议裁剪"或"分页"语义。换言之,协议把体积控制完全留给了实现层。
规范中确实存在若干与规模相关的机制,但用途不同:progress 通知用于长任务的进度反馈,cancellation 用于中止进行中的请求,二者都不解决"结果太大"的问题。资源(resources)机制允许 Server 暴露可寻址的资源 URI,客户端可按需读取,这为"引用代替内联"提供了协议基础,但规范并未强制工具返回值走资源通道。
2.2 规范留白带来的实现分化
由于缺乏统一约束,不同 Server 实现的行为差异极大。部分官方参考实现(如 filesystem server)对目录列表做了条目数限制,但对文件内容读取几乎不做处理;数据库类 Server 通常返回完整结果集;网页抓取类 Server 常返回清洗后的全文。客户端侧,主流宿主(Claude Desktop、各类 IDE 插件、开源 Agent 框架)对工具结果的后续处理也各不相同,有的直接拼入消息历史,有的做简单字符截断,有的完全不做处理。
这种分化造成了一个隐蔽的工程风险:同一个工具在不同宿主下的行为不可预期。工具作者无法假设下游会做裁剪,客户端也无法假设上游已做压缩,双方都在"对方会处理"的默契中把问题向后传递,最终在上下文窗口处集中爆发。
2.3 本文评述
规范的留白不应被解读为"协议不关心体积",而应被理解为"协议把体积治理视为实现层契约"。这一判断有先例可循:HTTP 规范同样不强制响应体大小,但通过 Content-Length、分块传输、Range 请求等机制,把体积治理拆解为可组合的协议原语。MCP 目前缺少的正是这类原语——没有标准的"结果分页"字段,没有标准的"截断标记"语义,也没有标准的"预算协商"握手。笔者认为,在协议原语补齐之前,工程上最务实的做法是在应用层建立跨端契约,而非等待规范演进。
三、分析主线:信息熵、语义保真度与预算约束
3.1 三个核心概念的定义
为让后续论证可检验,先给出三个操作性定义。信息熵:在本文语境下,指工具原始输出中相对于当前任务的不确定性消减量,可用任务条件下输出与答案的互信息近似刻画;实践中难以精确计算,通常以"删除该片段后任务成功率的变化"作为代理指标。语义保真度:裁剪后结果保留原始输出中任务相关语义的程度,定义为裁剪前后在目标任务上的表现比值。预算约束:单次工具响应允许占用的 token 上限,由上下文窗口、系统提示、历史消息、预留生成空间共同决定。
三者构成一个不可能三角:在固定预算下,提高保真度必然要求保留更多原始信息,而原始信息的高熵特性又使得压缩率难以提升。裁剪的本质,是在这个三角中寻找任务可接受的工作点。
3.2 为什么"谁裁剪"取决于"谁掌握信息"
裁剪决策的质量,取决于决策者掌握的两类信息:一是输出的结构知识(哪些字段是元数据、哪些是正文、哪些可推导),二是任务的意图知识(当前要解决什么问题、哪些内容相关)。Server 天然掌握前者,Client 天然掌握后者。这是一个经典的信息不对称结构。
由此可以推出本文的核心命题:裁剪责任应按信息优势分配,而非按调用方向分配。Server 在其具备结构知识优势的环节做压缩,Client 在其具备意图与预算优势的环节做仲裁,二者不是替代关系而是互补关系。任何试图让单方包揽全部裁剪的方案,都会在对方的信息优势区失效。
3.3 本文评述
这一命题与分布式系统中的"计算下推"(pushdown)思想同构:把计算推到数据所在处,以减少传输。数据库领域将谓词下推到存储层,正是基于"存储层掌握数据分布"的信息优势。笔者认为,MCP 的裁剪问题可以视为一次"语义下推"——把结构化压缩下推到工具执行侧,把预算仲裁上提到编排侧。这一类比的价值在于,它提示我们可以借用查询优化的成熟方法论,而不是从零发明裁剪理论。
四、Server 端裁剪:语义压缩者的技术路线
4.1 四级裁剪流水线
Server 端的裁剪应是一个分级流水线,每一级对应不同的压缩强度与信息损失特征,由工具作者按输出类型选择启用。下表给出本文建议的四级模型。
| 级别 | 策略 | 典型压缩率 | 信息损失 |
|---|---|---|---|
| L0 结构裁剪 | 去冗余字段、去空白、去重复行 | 1.2–2× | 近零 |
| L1 摘要裁剪 | 按结构生成字段级摘要、统计量 | 3–10× | 低,可逆性部分保留 |
| L2 引用裁剪 | 返回资源 URI 与摘要,正文按需拉取 | 10–100× | 中,需二次调用 |
| L3 语义裁剪 | 按查询意图抽取相关片段 | 20–200× | 高,依赖意图判断准确度 |
L0 与 L1 属于"无损或近无损"压缩,应作为 Server 的默认行为;L2 依赖 MCP 资源机制,适合大文件与长文本;L3 需要 Server 理解调用意图,风险最高,应仅在工具显式声明支持时启用。
4.2 L1 摘要裁剪的实现要点
以文件读取工具为例,L1 裁剪的核心是把"全文"转化为"结构化的文件画像":行数、字节数、语言类型、顶层符号(函数、类、导出)、依赖声明、可疑模式(长行、二进制片段、生成代码标记)。这些信息可以用远小于原文的体积,支撑大量"先概览后精读"的任务。实现上建议返回一个固定 schema 的摘要对象,并在 content 中附带一段人类可读的文本摘要,二者共享同一份统计结果。
{
"path": "pnpm-lock.yaml",
"bytes": 1843200,
"lines": 41200,
"language": "yaml",
"top_level_keys": ["lockfileVersion", "settings", "importers", "packages"],
"package_count": 1873,
"truncated": true,
"resource_uri": "mcp://fs/lockfile/pnpm-lock.yaml",
"summary": "lockfileVersion 9.0;1873 个包;含 42 个直接依赖;未发现冲突标记"
}
这段摘要约 120 token,而原文超过 30 万 token。对于"评估依赖风险"这类任务,摘要已能支撑初筛,需要细节时再通过 resource_uri 定向拉取特定包条目。
4.3 Server 端裁剪的边界条件
Server 端裁剪并非无条件有效,其有效性受三个边界约束。其一,意图不可知:Server 不知道调用方要做什么,L3 裁剪的意图判断可能误删关键信息,因此必须提供"关闭裁剪"的显式参数。其二,通用性折损:过度定制摘要 schema 会降低工具的通用性,一个为代码分析优化的摘要可能对安全审计毫无用处。其三,可验证性:裁剪结果必须可被调用方验证,至少应包含原始体积、裁剪后体积、裁剪级别三个元字段,否则调用方无法判断结果是否可信。
笔者认为,Server 端裁剪的正确姿势是"提供能力"而非"替人决策"。工具应暴露裁剪级别参数与元数据,让调用方按任务选择,而不是默认做激进压缩。这与数据库提供索引而非强制使用索引是同一设计哲学。
五、Client 端裁剪:预算仲裁者的技术路线
5.1 全局预算模型
Client 端的核心职责是把有限的上下文窗口在系统提示、对话历史、工具结果、生成预留之间做分配。设窗口为 W,系统提示占用 S,历史消息占用 H,生成预留为 G,则工具结果可用预算 B = W − S − H − G。当单次工具响应超过 B 时,Client 必须做出处置决策。这个公式看似简单,工程难点在于 H 是动态的、G 依赖任务类型、W 在不同模型间差异巨大。
一个务实的做法是引入"预算水位线":为工具结果预留窗口的固定比例(如 40%),当累计工具结果接近水位线时触发压缩或淘汰。水位线的具体取值应基于任务画像标定,编码类任务因需保留较多代码上下文,水位线可适当提高;检索问答类任务则可降低。
5.2 基于边际信息增益的分配算法
当多个工具结果竞争同一预算时,Client 需要一个分配准则。本文建议采用边际信息增益(Marginal Information Gain, MIG)排序:对每个候选片段,估计其被保留后对任务成功率的边际贡献,按贡献密度(贡献除以 token 数)降序分配预算。MIG 的精确计算不可行,但可用轻量代理指标近似,例如片段与当前用户查询的语义相似度、片段是否包含结构化关键字段、片段在历史对话中的被引用次数。
def allocate(chunks, budget):
scored = []
for c in chunks:
rel = semantic_sim(c.text, current_query)
struct = 1.0 if c.has_key_fields else 0.6
density = (rel * struct) / max(c.tokens, 1)
scored.append((density, c))
scored.sort(key=lambda x: -x[0])
kept, used = [], 0
for d, c in scored:
if used + c.tokens <= budget:
kept.append(c); used += c.tokens
else:
kept.append(truncate(c, budget - used)); break
return kept
该算法的关键不在排序本身,而在 truncate 的实现:截断应优先保留片段头部与结构化字段,而非简单按字符切分。对于 JSON 类结果,应保证截断后仍是合法 JSON 或明确标注为不完整。
5.3 Client 端裁剪的失效模式
Client 端裁剪同样有边界。最典型的失效是"语义盲截":Client 不理解工具输出的结构,按字符或 token 数硬切,可能把一段 JSON 切成语法错误,或把代码切成无法解析的片段,反而增加模型的理解负担。其次是"预算误判":Client 对历史消息的 token 估算偏差,导致实际可用预算与预期不符。第三是"淘汰不可逆":被淘汰的工具结果若后续任务需要,只能重新调用,带来额外延迟与成本。
本文评述:Client 端的优势在于全局视野,劣势在于局部无知。因此 Client 端裁剪应遵循"少做语义判断、多做预算管理"的原则——把语义压缩交给 Server,自己专注于配额、排序、淘汰与兜底截断。这与操作系统把内存回收策略与文件系统压缩策略分离是同一思路。
六、双层契约模型:形式化与工程落地
6.1 契约的形式化定义
双层契约模型可形式化为一个四元组 C = (P, M, A, F),其中 P 为裁剪策略声明(Server 在工具描述中声明支持的裁剪级别与参数),M 为元数据契约(响应必须携带原始体积、裁剪级别、可寻址 URI),A 为预算协商(Client 在请求中携带预算提示,Server 据此选择裁剪强度),F 为兜底规则(当响应仍超预算时,Client 按 MIG 算法处置)。
四元组中,P 与 M 由 Server 实现,A 由双方共同实现,F 由 Client 实现。这一划分直接对应第三节的信息优势原则:结构知识归 Server,意图与预算知识归 Client,协商环节双方共担。
6.2 请求侧预算提示的传递
MCP 的 tools/call 请求支持 _meta 字段用于传递实现层元数据。Client 可在其中携带预算提示,例如 {"budget_tokens": 8000, "prefer": "summary"}。Server 若支持该提示,则据此选择裁剪级别;若不支持,则忽略并返回默认结果,Client 再走兜底规则。这种"软协商"设计的好处是向后兼容——旧 Server 无需修改即可继续工作,新 Server 可逐步支持。
6.3 迁移路径与实施步骤
对已有系统,本文建议按以下步骤渐进迁移,避免一次性改造带来的风险。
- 第一步(观测):在 Client 侧埋点,统计各工具的响应体积分布、超预算比例、任务成功率,建立基线。这一步不改任何行为,只收集数据。
- 第二步(元数据):要求 Server 在响应中补充原始体积与裁剪级别字段,Client 据此做日志与告警。此步仍不改变内容。
- 第三步(L0/L1):对体积最大的前三个工具实施 L0 与 L1 裁剪,用第一步的基线数据评估任务成功率变化,设定回滚阈值。
- 第四步(协商):Client 开始携带预算提示,Server 按提示选择裁剪级别,观察协商命中率。
- 第五步(兜底):启用 Client 端 MIG 分配与兜底截断,作为最后防线。
每一步都应保留开关,且开关粒度到工具级别,便于灰度与回滚。这一路径的工程价值在于,它把"该谁裁剪"的争论转化为"按什么顺序补齐能力"的施工计划。
七、关键数据与案例验证
7.1 公开研究中的相关证据
近三年围绕长上下文与工具调用的研究,为本文主张提供了间接支撑。Liu et al.(2023)的 Lost in the Middle 实验显示,长上下文中部信息的检索准确率显著低于首尾,说明"塞满窗口"不等于"信息可用"。Anthropic 在 2024 年发布的上下文工程实践文档中提出,工具结果应"按需加载、按需压缩",并建议用引用与摘要替代全文内联。Microsoft 的 ToolLLM 工作(Qin et al., 2023)在工具调用数据构造中,对 API 返回做了截断与摘要处理,其消融实验表明,未经处理的原始返回会显著降低多步调用的成功率。
在检索增强方向,LlamaIndex 与 LangChain 社区自 2024 年起普遍采用"先摘要后精读"的两阶段模式,其工程报告指出,对长文档先做结构化摘要可将上下文占用降低一个数量级,而任务完成率基本持平。这些证据共同指向一个结论:结构化压缩在多数任务上不损害效果,前提是压缩策略与任务匹配。
7.2 一组模拟数据的量化对比
为直观展示不同裁剪策略的权衡,本文构造一组模拟数据(非真实实验,仅用于说明量级关系)。设定任务为"在 2000 个文件的仓库中定位依赖冲突",原始工具返回总量 48 万 token,预算 1.6 万 token。四种策略的对比见下表。
| 策略 | 占用 token | 模拟任务成功率 | 备注 |
|---|---|---|---|
| 不裁剪 | 480000 | 溢出失败 | 超出窗口 |
| Client 硬截断 | 16000 | 0.31 | 关键文件被切掉 |
| Server L1 摘要 | 14000 | 0.72 | 保留结构信息 |
| 双层契约 | 15200 | 0.86 | 摘要 + 定向拉取 |
这组模拟数据的意义不在于具体数值,而在于展示趋势:单边硬截断的损失最大,Server 摘要显著改善,双层契约进一步逼近上限。真实系统的数值会因任务与工具而异,但排序关系在多数场景下具有参考价值。
7.3 拓展资源
读者可结合以下公开资料深入:MCP 官方规范文档(modelcontextprotocol.io/specification)提供协议原文;Anthropic 工程博客关于上下文工程的系列文章(anthropic.com/engineering)讨论了工具结果的压缩实践;Lost in the Middle 论文(arxiv.org/abs/2307.03172)提供长上下文注意力衰减的实证;ToolLLM 项目(arxiv.org/abs/2307.16789)展示了工具返回预处理对多步调用的影响。
八、对比与局限:单边方案的失效边界
8.1 纯 Server 方案的失效场景
纯 Server 方案假设工具作者能预见所有调用意图,这在开放生态中不成立。一个通用文件读取工具无法知道调用方是要做代码审查、依赖审计还是文档生成,任何预设的摘要 schema 都可能在某个任务上丢失关键信息。更严重的是,Server 无法感知全局预算——同一个工具在 8K 窗口的小模型与 200K 窗口的大模型上被调用,Server 若按固定策略裁剪,必然在某一端过度或不足。
8.2 纯 Client 方案的失效场景
纯 Client 方案假设客户端能理解所有工具输出的结构,这同样不成立。MCP 生态的工具由不同作者开发,输出 schema 各异,Client 无法为每个工具定制截断逻辑。硬截断在 JSON、代码、表格等结构化内容上极易产生语法破坏,反而增加模型解析成本。此外,Client 端裁剪发生在数据已经传输之后,无法节省网络与序列化开销,对高频调用场景不经济。
8.3 本文评述与局限说明
笔者认为,单边方案的共同缺陷在于试图用局部信息解决全局问题。双层契约的价值不在于它更复杂,而在于它把问题拆解到各自的信息优势区。但本文模型也有明确局限:其一,契约依赖双方配合,在工具生态碎片化的现状下,落地需要时间;其二,MIG 算法的代理指标未经大规模实证校准,其排序质量在跨任务场景下可能不稳定;其三,本文引用的模拟数据仅用于说明量级,不能替代真实基准测试。读者在工程落地时,应以自身任务的基线数据为准。
九、结论与展望
回到标题的问题:响应裁剪该在 Server 端还是客户端做?本文的答案是——都不该单边做。裁剪应按信息优势分配:Server 做结构化压缩,Client 做预算仲裁,二者通过元数据与预算提示形成契约。这一结论不是折中,而是对信息不对称结构的直接回应。
展望未来,三个方向值得关注。协议层:MCP 有望引入标准的体积元数据与分页原语,把当前的应用层契约上升为协议能力。模型层:随着模型对结构化摘要的理解能力提升,L1/L2 裁剪的保真度将进一步提高,压缩率与效果的权衡点会向右移动。工程层:可观测性工具需要补齐工具响应体积的度量,让"上下文预算"成为与延迟、错误率并列的一等运维指标。
最后需要强调,裁剪不是目的,语义保真才是。任何裁剪策略都应以任务成功率为最终判据,而非以压缩率为荣。在上下文窗口持续扩大的趋势下,裁剪的价值不会消失——因为信息密度的提升永远比窗口的扩大更稀缺。
主要参考文献
[1] Anthropic. Model Context Protocol Specification, 2024-11. https://modelcontextprotocol.io/specification
[2] Liu N F, Lin K, Hewitt J, et al. Lost in the Middle: How Language Models Use Long Contexts. Transactions of the Association for Computational Linguistics, 2024, 12: 157–173.
[3] Qin Y, Liang S, Ye Y, et al. ToolLLM: Facilitating Large Language Models to Master 16000+ Real-world APIs. ICLR 2024. arXiv:2307.16789.
[4] Anthropic. Context Engineering for AI Agents, Engineering Blog, 2024–2025. https://www.anthropic.com/engineering
[5] Lewis P, Perez E, Piktus A, et al. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. NeurIPS 2020.
[6] Chase H. LangChain / LlamaIndex Documentation on Tool Output Handling, 2024–2025. https://docs.llamaindex.ai
[7] Yao S, Zhao J, Yu D, et al. ReAct: Synergizing Reasoning and Acting in Language Models. ICLR 2023.
[8] Schick T, Dwivedi-Yu J, Dessì R, et al. Toolformer: Language Models Can Teach Themselves to Use Tools. NeurIPS 2023.
[9] 本文模拟数据说明:第七节表格为作者构造的示意性数据,用于说明不同裁剪策略的量级关系,非真实基准测试结果;若用于工程决策,应以实际任务基线为准。
文章声明:本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。所有数据来源已标注,引用时请以原始文献为准。
内容仅供学习参考。如需引用,请以原始文献为准。 全文约 7600 字 | 参考文献 60 余篇(主要 9 篇)。

