☰
MCP 面试高频考点:如何控制返回内容大小并降低上下文消耗
2026/10/19 3:26:28 网站建设 项目流程

MCP 面试高频考点:如何控制返回内容大小并降低上下文消耗

面试场景

候选人正在面试 AI 应用工程岗位,岗位要求能够基于 MCP(Model Context Protocol)把企业内部工具和知识库接入 Host,并在真实使用中控制成本、延迟和上下文窗口占用。面试官没有直接问定义,而是从一个很落地的问题切入:“你们在 MCP Server 里提供查询能力时,怎么避免一次返回太多内容,把模型上下文撑爆?”


基础问题:先讲清问题边界

面试官:我们先不聊优化技巧。假设你要实现一个 MCP Server,对 Host 暴露知识检索和若干业务查询 Tool,底层走 JSON-RPC 通信。你的目标是控制返回内容大小、降低上下文消耗。你会先怎么设计能力边界?

候选人:我会先做结论:优先把能力拆对,再谈压缩和裁剪。

MCP 的三类能力要按语义使用:Tools 是模型可调用的操作,Resources 是按 URI 读取的上下文,Prompts 是模板化工作流[资料1]。如果是“根据问题检索相关片段”,更适合设计成 Tool;如果是“读取某个已知文档或对象的详情”,更适合 Resource。不要把只读资料硬做成有副作用的 Tool,否则模型容易误调用,也不利于 Host 做缓存和权限控制[资料1]。

通信层上,MCP 客户端和服务端之间使用 JSON-RPC 编码消息,消息必须是 UTF-8;stdio 适合本机子进程,标准输出只能发协议消息,调试日志要写到标准错误;Streamable HTTP 适合远程部署,每个 JSON-RPC 请求或通知都是一次 HTTP POST,服务端可以返回单个 JSON 对象,也可以返回该请求范围内的 SSE 流[资料2][资料4]。这意味着“返回大小控制”既发生在应用层,也发生在传输层:应用层决定返回哪些字段、多少片段、是否分页;传输层决定是一次性返回还是流式返回。

如果一开始不做边界,常见问题是:Tool 直接把整份文档、整页数据库结果或超长 JSON 塞回结果,Host 再把它原封不动放进模型上下文,最后既浪费 token,又引入无关信息,还可能触发截断。


第一轮追问:具体怎么控制 Tool 返回大小

面试官:方向对。但如果我让你把“知识检索”做成一个 MCP Tool,你具体怎么控制返回大小?为什么不能只靠模型自己少要一点?

候选人:结论是:服务端必须主动限制结果规模,不能把裁剪责任完全留给模型。

原因有三点。第一,模型在调用 Tool 前并不知道底层库里有多少命中内容;第二,Tool 参数 schema 只是结构约束,不能替代服务端校验和授权[资料1];第三,MCP Server 返回的内容最终会进入上下文窗口,过大的结果会增加成本、延迟,并降低回答质量。

我的设计会包含几层:

  1. 输入参数显式支持范围控制
    检索类 Tool 至少要让调用方传入查询语句、期望返回片段数量上限、最大字符数或 token 预算、是否需要元数据等字段。注意这里不是让模型随意传很大的值,而是服务端设置硬上限,例如单次最多返回若干片段、单片段最大长度、总内容最大长度。这些阈值不能拍脑袋写死,要结合业务 SLA、上下文窗口和压测结果确定。

  2. 服务端做切块和召回裁剪
    RAG 链路里,切块要尽量保留语义完整性,同时避免不相关内容占用上下文;召回后应只返回少量相关片段,并带上来源元数据,便于引用和排错[资料1]。也就是说,MCP Server 不应该返回“所有命中文档”,而应返回经过排序、截断、去重后的 TopK 片段。

  3. 结构化内容优先,避免冗余自然语言
    如果 SDK 支持结构化返回,应优先返回结构化字段,例如片段列表、标题、URI、分数、摘要,而不是把所有内容拼成一大段自然语言。以 Python SDK 的风格为例,开发者可以通过类型标注描述 Tool 输入输出,由 SDK 处理协议和基础校验,业务代码只关注函数逻辑[资料3]。即使不依赖具体 SDK,接口设计上也应区分content、metadata、next_cursor、truncated等字段。

  4. 显式告知截断状态
    如果结果被裁剪,要在返回里明确标记truncated: true,并说明裁剪原因,例如“结果超过最大返回长度,已返回前 N 条”。否则 Host 和模型会误以为拿到了完整结果。

这里有个关键取舍:返回片段过少会漏信息,返回过多会污染上下文。我的做法是默认返回较小的高相关结果集,同时提供“继续获取更多”的能力,而不是第一次就把所有内容吐出来。

面试官:那“继续获取更多”你会怎么设计?是在同一个 Tool 里返回超大列表,还是另开接口?

候选人:我倾向于分页或分段读取,而不是一次性返回全量。

对于检索结果,可以返回next_cursor,模型或 Host 需要更多内容时再次调用 Tool,传入游标。对于已知资源,更适合用 Resource 按 URI 读取详情[资料1]。例如检索 Tool 只返回摘要和资源 URI,真正需要看全文某个章节时,再读取对应 Resource。这样可以把“粗召回”和“深读取”分开,降低无效上下文。


第二轮追问:传输、异常与安全边界

面试官:如果远程部署 MCP Server,走 Streamable HTTP。你刚才说可以流式返回,那是不是边查边往上下文里写,就不用控制大小了?如果中途异常呢?

候选人:不是。结论是:流式传输解决的是首包延迟和长结果递送问题,不解决上下文预算问题。

根据协议,Streamable HTTP 下每个请求都是一次 POST,服务端可以返回单个 JSON 对象,也可以返回该请求相关的 SSE 流,最后再给出最终响应;服务端到客户端的一些交互会嵌入结果中,长生命周期通知走专门的订阅机制[资料4]。这说明流式返回仍然是“同一个请求的结果”,如果服务端在流里持续吐出大量片段,Host 最终还是要消费这些内容,上下文消耗不会凭空消失。

流式更适合的场景是:结果可以逐步产出,Host 希望尽早展示或边收边处理;但服务端仍然要维护总预算,达到上限就停止发送并结束响应,不能无界输出。

异常处理上,我会关注几类问题:

  • 后端检索超时或部分失败:返回已成功获取的高相关片段,并标记部分失败,避免整个 Tool 调用失败导致模型无信息可用。
  • 结果超长:在达到硬上限时主动截断,并返回truncated和续取方式。
  • 传输中断:因为 Streamable HTTP 是请求范围内的 SSE 流[资料4],连接断开后客户端不应假设结果完整;可以通过游标或幂等参数重新请求。
  • 输入不可信:模型传入的查询词、资源 URI、过滤条件都要视为不可信输入,服务端必须校验,防止路径穿越、越权读取、注入等问题[资料1]。

安全上还有一个容易忽略的点:远程 MCP Server 不能只判断用户是否登录,而要对每次请求做授权检查;凭据不能出现在日志、Tool 返回值或模型上下文中;审计日志要记录谁在何时调用了哪个 Tool、访问了什么资源范围以及结果状态,敏感字段要脱敏[资料1]。如果为了“减少返回大小”而把内部 ID、权限字段、调试信息一起删掉不彻底,反而可能泄漏。


方案设计:一个可落地的接口设计

面试官:如果让你落地这个检索 Tool,不绑定具体 SDK 版本,你会怎么定义接口和返回?

候选人:我会做一个版本无关的 Tool 设计,核心是“小结果集 + 游标 + 明确截断 + 来源元数据”。

Tool 名称可以是search_knowledge,输入包括:

  • query:检索问题;
  • top_k:期望返回片段数,服务端设置最大值;
  • max_chars_per_fragment:单片段最大长度;
  • max_total_chars:本次返回总内容上限;
  • cursor:可选,分页游标;
  • include_metadata:是否返回标题、来源、更新时间等元数据。

返回结构建议包含:

  • fragments:片段数组,每项包含text、source_uri、title、score;
  • truncated:是否因预算限制被截断;
  • next_cursor:如果有更多结果,返回游标;
  • warnings:例如“部分数据源不可用”“结果已按权限过滤”。

如果使用 Python SDK,开发者通常只需要写带类型标注的函数和文档字符串,SDK 会处理协议解析、基础 schema 生成和调用分发[资料3]。但要强调:类型标注只能描述结构,不能代替权限、长度、业务范围校验[资料1]。

架构上的职责分工是:

  • MCP Server:负责参数校验、权限检查、召回、重排、裁剪、分页、审计日志;
  • JSON-RPC/传输层:负责按 stdio 或 Streamable HTTP 编码消息、递送请求与响应[资料2][资料4];
  • Host/Client:负责决定何时调用 Tool、是否继续分页、如何把结果放入模型上下文、是否向用户展示来源。

我不会在 Server 端替 Host 拼最终提示词,因为 Prompt 模板属于 Host 侧工作流能力;Server 只返回可信、精简、可追溯的结果。


面试官点评

考察点:这道题表面问“如何减小返回内容”,实际考察三层能力。第一,是否理解 MCP 的客户端—服务端架构、三类能力的语义边界,以及 JSON-RPC/传输层的职责[资料1][资料2];第二,是否能把 RAG 场景下的切块、召回、裁剪、来源保留落实到 Tool 设计中[资料1];第三,是否考虑远程部署下的安全、授权、异常、流式返回和分页取舍[资料1][资料4]。

合格回答:能够明确说出不能把全量内容直接返回;能区分 Tool、Resource、Prompt 的使用场景;能提出 TopK、截断、分页、结构化返回、来源元数据等基本手段;知道 schema 校验不等于安全校验,服务端必须做授权和输入校验[资料1]。

加分项:能够说清 stdio 与 Streamable HTTP 在输出日志、消息方向、流式响应上的差异[资料2][资料4];能够解释“流式不等于省上下文”;能够给出truncated、next_cursor、warnings这类可观测字段;能够意识到检索文档是不可信数据,其中内容不应覆盖系统规则[资料1]。


总结与容易踩坑的细节

控制 MCP 返回内容大小,本质上不是做字符串压缩,而是做上下文预算管理:在能力设计阶段选对 Tool/Resource/Prompt,在服务端阶段做强约束的召回、裁剪、分页和授权,在传输阶段正确处理 JSON-RPC 消息与流式边界,在 Host 阶段决定何时继续取数、如何组织上下文。

有一个非常容易踩坑的细节:stdio 模式下把调试日志写到标准输出。MCP 规定 stdio 传输通过标准流传递换行分隔的协议消息,服务端标准输出只能用于协议消息,调试日志必须写到标准错误;否则日志内容会混入 JSON-RPC 消息,造成客户端解析失败[资料1][资料2]。远程 Streamable HTTP 下也有类似问题:如果在 SSE 流中写入非协议内容,同样会破坏消息边界。

另一个常见取舍是:返回更多原始内容能减少二次调用,但会抬高上下文成本;返回更激进的摘要能省 token,但可能丢失可追溯性。更稳妥的做法是默认返回少量高相关片段和来源 URI,需要时再按游标或 Resource 深入读取,而不是追求一次返回“完整答案”。阈值如 TopK、最大长度、超时、重试策略等,都应结合业务 SLA、风险评估和压测确定,而不是照搬固定数字。

参考资料

  • [MCP 基础知识]
  • MCP Protocol Overview and Schema
  • MCP Python SDK
  • Streamable HTTP

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询