MCP 追问 · 5问

FC循环机制 · Prompt模板 · 动态注册弊端 · FC再理解 · Schema含义
问题 ① — FC 输出后,谁触发代码去读取 JSON 执行请求
是你的代码自己在控制整个循环,不是 AI 主动通知。
AI 就是一个普通的 HTTP 接口——你调用它,它返回结果,你的代码判断返回类型决定下一步。AI 停止后什么都不做,就等着你的代码下一次调用它。
完整的控制流(你的代码主导)
// 1. 你的代码发起调用
const response = await anthropic.messages.create({
  model: "claude-sonnet-4-5",
  messages: conversation,
  tools: availableTools       // 告诉 AI 有哪些 Tool 可用
});

// 2. AI 返回响应(同步等待,就像普通 HTTP 请求)
// response.stop_reason 有两种值:
//   "end_turn"   → AI 直接回答了,展示给用户
//   "tool_use"   → AI 要调 Tool,你需要执行

// 3. 你的代码检查 stop_reason,自己决定下一步
if (response.stop_reason === "tool_use") {

  // 4. 从返回值里提取 Tool 调用信息
  const toolCall = response.content.find(b => b.type === "tool_use");
  const { name, input } = toolCall;
  // name = "get_weather", input = { city: "上海" }

  // 5. 你的代码执行对应函数(AI 完全不参与这一步)
  const result = await executeToolCall(name, input);
  // 比如:调天气 API,真的发了 HTTP 请求,拿到了数据

  // 6. 你的代码把结果拼回对话,再次调用 AI
  conversation.push({ role: "user", content: [{
    type: "tool_result",
    tool_use_id: toolCall.id,
    content: JSON.stringify(result)
  }]});

  // 7. 再次调用 AI,AI 用结果生成最终回答
  const finalResponse = await anthropic.messages.create({ ... });

} else {
  // AI 直接回答,展示给用户
  showToUser(response.content[0].text);
}
两个关键认知
AI 是被动的 HTTP 服务
每次"对话"对 AI 来说都是一次独立的 API 调用。AI 不持有连接,不主动推送,不知道上一次调用发生了什么——你的代码每次都要把完整的对话历史重新传给它。
你的代码是主控方
决定"要不要继续循环""执行哪个函数""结果怎么处理"的,全是你的代码。AI 只是在每次被调用时输出它的判断,从不主动触发任何事情。
面试一句话版:"Function Calling 不是 AI 主动调用工具,而是 AI 输出结构化的调用意图,由宿主代码(Host)拦截并执行,再把结果传回 AI。AI 是无状态的 HTTP 服务,主控逻辑始终在你的代码里。"
问题 ② — Prompt 模板 是不是就像 Claude Code 里的斜杠命令
完全正确,就是同一个机制。
Claude Code 里的 /add-dir/review/clear 这些斜杠命令,就是 MCP Prompt 模板的具体体现。用户选命令,有些直接执行,有些需要填参数。
三者对应关系
概念 Claude Code 里的例子 你的 App 里可以做的
MCP Host Claude Code 本身 你开发的 App
MCP Prompt 模板 /review, /add-dir /词汇深度学习, /写作润色
参数填写 /add-dir [路径] /词汇学习 [单词] [难度]
区别只是宿主不同
Claude Code 是 Anthropic 开发的 Host,它展示的是自己内置的命令列表。

你开发的 App 作为 Host,可以连接你自己的 MCP Server,展示你在 Server 里定义的 Prompt 模板。

用户体验完全一致:输入 /,弹出列表,选命令,有参数就填参数,确认后展开执行。机制完全相同,只是换了一个 Host 和一套模板内容。
Speakeasy 实战:你可以在 Speakeasy 的 MCP Server 里定义一个 /深度学习 模板,参数是单词和难度级别,模板展开后自动生成:词源 + 例句 + 记忆口诀 + 相关词族——用户每次只需填一个单词,得到的是标准化的专家级学习内容。
问题 ③ — 动态 Tool 注册有哪些弊端
动态注册解决了"Tool 太多"的问题,但引入了新的复杂度。四个真实弊端,每一个都是工程上的实际痛点。
弊端 1:意图分类本身可能出错 高频
用户说"查一下上个月的销售报表",意图分类触发了"客户查询"分组而不是"报表分析",正确的 generate_report Tool 根本没被暴露出来——任务失败,而且用户看不到任何错误提示,AI 只是告诉他"我没有这个能力"。

意图分类错了,比静态注册(至少 AI 能找到 Tool)还要糟糕。
弊端 2:跨场景任务无法处理 架构级
用户说"帮我找到客户张三,查他所有订单,再生成一份报表发给他"——这个任务横跨"客户查询"、"订单管理"、"报表分析"三个 Tool 分组。

动态注册的两个选择都不好:
· 一次性暴露全部分组 → 退化成静态注册,优势消失
· 多轮切换分组 → 需要额外的状态管理,复杂度翻倍
弊端 3:引入额外延迟和成本 工程
意图分类通常本身也是一次 LLM 调用(或者至少是一次向量检索),在真正回答用户问题之前多了一个网络请求。

用户感受到的延迟增加,API 成本增加。如果意图分类本身也不稳定,等于在不稳定的基础上又加了一层不稳定。
弊端 4:维护成本高 工程
Tool 分组逻辑需要随业务变化持续更新。新增一个 Tool,要决定它属于哪个分组,边界模糊时很容易被遗漏。

分组之间的边界本身也是模糊的("创建订单"是"订单管理"还是"销售流程"?),每次有争议都需要人工决策,增加了团队沟通成本。
什么时候值得用动态注册
✓ 适合用

Tool 数量超过 20 个
业务场景边界清晰(客服 vs 财务 vs 技术支持)
用户角色固定(销售只用销售 Tool)
任务通常不跨场景
✗ 不适合用

Tool 数量少于 15 个(直接静态即可)
用户任务复杂、跨业务域
对延迟敏感的场景
团队没有人维护分组逻辑
问题 ④ — 对 Function Calling 的理解是否正确
✓ 你的理解现在完全正确,可以直接用于面试。
你说的:"FC 是对 AI 输出结果的结构化,AI 做了意图识别,输出对工具使用的决策,然后代码执行决策"——这个表述准确且清晰。
补充一个细节让表述更完整
AI 做的不只是"要不要调",还包括"填什么参数"——这也是 AI 推理的一部分,不是代码自动填的。

完整的说法:
AI 做意图识别 + 参数推断,输出结构化的调用决策(工具名 + 参数值);代码拦截这个决策并执行真实操作,再把结果传回 AI 继续推理。
FC 在整个知识体系里的位置
Function Calling(LLM 原生能力)
  │  ← AI 输出结构化意图,代码执行
  ├── MCP Tools(对 FC 的标准化封装)
  │     ← 统一协议、服务发现、跨模型复用
  ├── ReAct 模式(使用 FC 的推理范式)
  │     ← Reasoning(思考)+ Acting(调用 Tool)循环
  └── Agent Loop(多轮 FC 调用的完整循环)
        └── Multi-Agent(多个 Agent 互相调用)
从 FC 到 MCP 的升级逻辑:FC 解决了"AI 能调工具"的问题,但每个模型格式不同,每个应用都要自己定义工具——生态碎片化。MCP 在 FC 之上加了标准协议,让一个工具 Server 写一次,所有支持 MCP 的模型和应用都能用。就像 HTTP 解决了"计算机能通信",REST 进一步规范了"如何通信"。
问题 ⑤ — Schema 是什么,在 MCP 语境里指什么
Schema = 数据结构的描述规范。
它本身不是数据,是数据的"说明书"——告诉你这份数据有哪些字段、每个字段是什么类型、哪些必填、取值范围是什么。
类比理解
Schema 就像一张表格的表头设计图——

不是表格里的数据,而是定义了:
· 这张表有哪几列(字段名)
· 每列填数字还是文字(类型)
· 哪列不能为空(required)
· 数字的合法范围是多少(minimum / maximum)

表头设计图 = Schema;表格里的数据 = 实际的 JSON 数据。
在 MCP 里,JSON Schema 用来描述 Tool 的参数结构
{
  "name": "get_weather",
  "description": "查询指定城市的天气预报",

  "parameters": {               ← 这整块就是 JSON Schema
    "type": "object",
    "properties": {
      "city": {
        "type": "string",       ← city 是字符串
        "description": "城市名,如:上海、北京"
      },
      "days": {
        "type": "integer",      ← days 是整数
        "description": "预报天数",
        "minimum": 1,           ← 最少1天
        "maximum": 7,           ← 最多7天
        "default": 1
      },
      "unit": {
        "type": "string",
        "enum": ["celsius", "fahrenheit"],  ← 只能是这两个值
        "description": "温度单位"
      }
    },
    "required": ["city"]        ← city 必填,days 和 unit 选填
  }
}
Schema 里每个关键字的含义
"type"
字段的数据类型。常用:string(文字)、integer(整数)、number(小数)、boolean(是/否)、array(列表)、object(嵌套对象)
"description"
用自然语言解释这个字段的含义和用法——这是 AI 理解参数语义的关键,写得越清楚 AI 填参越准确
"required"
数组形式,列出必须提供的字段名。AI 生成调用时会确保这些字段一定有值,其余字段可以省略
"enum"
枚举值,限定这个字段只能填固定的几个值之一。AI 不会乱填,会从列表中选择
"minimum" / "maximum"
数字字段的取值范围。AI 生成参数时会遵守这个范围,不会填超出范围的值
"default"
用户没有提供该字段时使用的默认值。AI 在没有明确信息时会使用默认值
为什么 Schema 对 MCP 如此重要
有 Schema 时

AI 知道 days 是整数,范围 1-7
→ AI 填 3,合法,直接执行

AI 知道 unit 只能是 celsius / fahrenheit
→ AI 不会填 "摄氏度" 或 "C"
没有 Schema 时

AI 可能把 days 填成 "三天"(字符串)
→ 代码解析出错,Tool 调用失败

AI 可能把 unit 填成 "摄氏" 或 "°C"
→ API 不认识这个值,返回错误
一句话总结:Schema 是 MCP Tool 的"参数合同"——AI 读 description 知道"要不要调这个 Tool",读 Schema 知道"调的时候参数怎么填"。两者缺一不可,description 解决意图理解,Schema 解决参数格式。