MCP tool server、browser/python 工具与工作流接口#
前面的结构化生成与 API 章节已经覆盖了 function calling、tool parser 和 Responses API 的 background 语义,但如果没有一章把“工具到底怎样进入工作流”单独讲透,第 6 节对外部接口的覆盖仍然会缺一条关键支线。很多读者会自然把工具系统理解成“模型输出一个函数调用 JSON,再去执行一下”。当前实现已经明显比这更厚:
- 有
MCPToolServer - 有内建
browser/python工具人格 - 有 tool session
- 有把工具描述注入请求上下文的流程
- 还有 background / streaming 场景下的模式限制
这章真正要补齐的,就是这条“工具工作流接口”本身,而不是再重复一遍 parser 或 tool-call schema。
先把工具放回 Responses 工作流,而不是函数调用 JSON#
如果只站在 function calling 角度看,工具似乎只是模型输出的一种结构化结果;从 Responses API 的实现看,工具实际上在更早就进入了工作流。下面这张图的价值就在于把这一点明确画出来:
flowchart LR
Req["ResponsesRequest + tools"] --> Server["tool_server / MCPToolServer / DemoToolServer"]
Server --> Session["tool session(s)"]
Session --> Ctx["HarmonyContext / StreamingHarmonyContext"]
Ctx --> Resp["Responses API generation workflow"]图里最重要的一点是:工具不是在模型之外平行运行的插件,而是会在请求开始前就被准备成上下文资源。只要这一点稳住,读者就不再会把“工具工作流”误读成 parser 的附属品。
tool_server.py 才是这条链最值得先读的入口#
这棵树特别适合作为代码阅读起点,因为它把工具接口的两种主要人格都直接摆出来了:
ToolServer抽象基类MCPToolServerDemoToolServer
这说明系统并不是把所有工具逻辑硬编码进某个 handler,而是先抽象出一层正式的工具接口。对系统书来说,这层抽象特别值钱,因为它能把“工具从哪里来”这个问题从 execution 主线里拆开:
- 有的工具来自远端 MCP server
- 有的工具是本地内建人格
来源不同,但都会在更下游被折成同一套 request-scoped session 和上下文能力。
MCPToolServer 真正做的事情,比“连一下 MCP”要厚得多#
它至少承担这些动作:
- 通过 SSE +
ClientSession连接 MCP server - 调
initialize()/list_tools() - 把 MCP 的 schema 修整成 Harmony 所需形式
- 为每个 tool name 维护 URL 和描述
- 提供
get_tool_session(...)
这说明 MCP 接入并不是“把远端工具列表原样抄过来”,而是要做一次正式的 schema 适配和 session 生命周期管理。也正因为如此,把它放在结构化生成与 API 章节里,比放在某个附录更合理:这里已经是系统正式对外暴露的工作流接口,而不是外围脚本。
DemoToolServer 说明工具并不等于外部 MCP#
这一点对读者尤其重要。DemoToolServer 明确提供了本地内建工具人格:
browserpython
这意味着工具工作流的核心问题不是“有没有外部 MCP server”,而是“工具能力怎样被抽象成统一接口,再按请求注入工作流”。只要这一点说清楚,读者就更容易理解为什么 built-in tool 和 MCP tool 看起来差异很大,却仍然会在 Responses API 里共享同一条上下文进入路径。
serving_responses.py 把工具真正接进请求,而不是等模型输出后再拼#
这一层非常关键。create_responses() 的真正价值不只是构造 GenerateReqInput(...),而是在更早的地方显式处理:
- 根据 request 里的 tool types 决定是否启用
browser/python - 用
tool_server.get_tool_session(tool_name)建 session - 把 tool description 注入系统消息或开发者消息
- 在
HarmonyContext/StreamingHarmonyContext里把这些 session 一起带进去
这说明工具不是在模型输出后才突然出现,而是在生成前就已经被作为上下文资源准备好了。对技术书来说,这一层特别重要,因为它能把“工具工作流”从 parser 和 schema 章节里真正解放出来,成为一条独立可理解的工作流接口。
为什么 background / streaming 模式下有些工具会被拒绝#
源码里有一条很值得系统书明确指出的保护逻辑:
- 如果
tool_server是MCPToolServer - 并且 request 是 background 或 streaming
- 又用了某些特定工具类型
系统会直接返回错误。
这说明工具工作流不是“只要接上就到处都能用”。不同工具接口和不同运行模式之间其实存在明确的兼容边界。换句话说,这里讲的不只是“能不能接工具”,还包括“在哪些工作流人格下不该接工具”。这类模式限制特别像成熟系统书该主动替读者讲透的边界。
HarmonyContext / StreamingHarmonyContext 把工具能力真正变成 request-scoped 资源#
这是这一章特别值得强调的另一点。工具 session 最终不是挂在某个全局单例里,而是作为请求上下文的一部分进入具体工作流。这意味着工具能力在这里有几个很清晰的特征:
- 按请求注入
- 生命周期跟着请求或 background task 走
- 和 request identity 天然绑定
这是一种非常健康的系统设计,因为它避免了“工具能力是全局环境”的模糊状态。对于读者来说,这也能直接改变对工具工作流的理解:它不是系统外的脚本能力,而是 request-scoped capability。
这条链和 parser / Responses / maintainer 视角天然会回扣#
工具工作流很适合作为一本系统书里的桥章节,因为它天然连接三块内容:
- 结构化生成:tool-call constraint 和 parser
Responses API:background task、retrieve / cancel、session 生命周期- 维护层:工具工作流出问题时,应该先怀疑 session、tool server,还是 parser
这正是一本“像书”的技术作品会有的咬合感:同一能力不是只在一章出现,而是在不同章节从不同层次被照亮。
最容易出现的三种误判#
第一,误把工具系统理解成纯 function calling JSON 解析。
实际上它还包括 tool server、session、schema trimming 和上下文注入。
第二,误以为 MCP 工具和内建工具没本质区别。
源码里两者在生命周期和模式支持上是明确分开的。
第三,误以为工具只是结果生成后的附加动作。
事实上它们在请求生成前就已经作为上下文资源进入工作流。
真正顺着这条链读源码时,更稳的顺序#
建议按下面顺序:
- 先读
tool_server.py - 再看
serving_responses.py里如何创建 tool session - 再看
HarmonyContext/StreamingHarmonyContext - 最后再回到 parser / tool-call constraint 章节看“模型怎样输出工具调用”
这样读,你会更容易把这条链看成“工具工作流接口”,而不是“再多几个工具相关文件”。
小结#
这一章真正补齐的,是第 6 节里很容易被忽略的一层:工具不是只靠 parser 和 JSON schema 就能工作,它们还需要 tool server、session 和请求上下文这层工作流接口。
把这一层讲清之后,Responses API 和工具工作流才真正像一个完整系统,而不是几个功能点的拼接。
叶王 © 2013-2026 版权所有。如果本文档对你有所帮助,可以请作者喝饮料。