content/01-mcp/05-interview/mcp-5q.md

MCP 追问 · 5问

FC循环机制 · Prompt模板 · 动态注册弊端 · FC再理解 · Schema含义

Q1: AI 停止后谁触发代码去读取 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 服务,主控逻辑始终在你的代码里。"


Q2: Prompt 模板是不是就像 Claude Code 里的斜杠命令?

完全正确,就是同一个机制。 Claude Code 里的 /add-dir/review/clear 这些斜杠命令,就是 MCP Prompt 模板的具体体现。用户选命令,有些直接执行,有些需要填参数。

三者对应关系

概念Claude Code 里的例子你的 App 里可以做的
MCP HostClaude Code 本身你开发的 App
MCP Prompt 模板/review, /add-dir/词汇深度学习, /写作润色
参数填写/add-dir [路径]/词汇学习 [单词] [难度]

区别只是宿主不同

Claude Code 是 Anthropic 开发的 Host,它展示的是自己内置的命令列表。

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

用户体验完全一致:输入 /,弹出列表,选命令,有参数就填参数,确认后展开执行。机制完全相同,只是换了一个 Host 和一套模板内容。

Speakeasy 实战: 你可以在 Speakeasy 的 MCP Server 里定义一个 /深度学习 模板,参数是单词和难度级别,模板展开后自动生成:词源 + 例句 + 记忆口诀 + 相关词族——用户每次只需填一个单词,得到的是标准化的专家级学习内容。


Q3: 动态 Tool 注册有哪些弊端?

动态注册解决了"Tool 太多"的问题,但引入了新的复杂度。四个真实弊端,每一个都是工程上的实际痛点。

弊端 1:意图分类本身可能出错(高频) 用户说"查一下上个月的销售报表",意图分类触发了"客户查询"分组而不是"报表分析",正确的 generate_report Tool 根本没被暴露出来——任务失败,而且用户看不到任何错误提示,AI 只是告诉他"我没有这个能力"。

意图分类错了,比静态注册(至少 AI 能找到 Tool)还要糟糕。

弊端 2:跨场景任务无法处理(架构级) 用户说"帮我找到客户张三,查他所有订单,再生成一份报表发给他"——这个任务横跨"客户查询"、"订单管理"、"报表分析"三个 Tool 分组。

动态注册的两个选择都不好:

  • 一次性暴露全部分组 → 退化成静态注册,优势消失
  • 多轮切换分组 → 需要额外的状态管理,复杂度翻倍

弊端 3:引入额外延迟和成本(工程) 意图分类通常本身也是一次 LLM 调用(或者至少是一次向量检索),在真正回答用户问题之前多了一个网络请求。

用户感受到的延迟增加,API 成本增加。如果意图分类本身也不稳定,等于在不稳定的基础上又加了一层不稳定。

弊端 4:维护成本高(工程) Tool 分组逻辑需要随业务变化持续更新。新增一个 Tool,要决定它属于哪个分组,边界模糊时很容易被遗漏。

分组之间的边界本身也是模糊的("创建订单"是"订单管理"还是"销售流程"?),每次有争议都需要人工决策,增加了团队沟通成本。

什么时候值得用动态注册

适合用不适合用
Tool 数量超过 20 个Tool 数量少于 15 个(直接静态即可)
业务场景边界清晰(客服 vs 财务 vs 技术支持)用户任务复杂、跨业务域
用户角色固定(销售只用销售 Tool)对延迟敏感的场景
任务通常不跨场景团队没有人维护分组逻辑

Q4: 对 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 进一步规范了"如何通信"。


Q5: Schema 是什么,在 MCP 语境里指什么?

Schema = 数据结构的描述规范。 它本身不是数据,是数据的"说明书"——告诉你这份数据有哪些字段、每个字段是什么类型、哪些必填、取值范围是什么。

Schema 就像一张表格的表头设计图——不是表格里的数据,而是定义了:

  • 这张表有哪几列(字段名)
  • 每列填数字还是文字(类型)
  • 哪列不能为空(required)
  • 数字的合法范围是多少(minimum / maximum)

在 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 时没有 Schema 时
AI 知道 days 是整数,范围 1-7 → AI 填 3,合法,直接执行AI 可能把 days 填成 "三天"(字符串)→ 代码解析出错,Tool 调用失败
AI 知道 unit 只能是 celsius / fahrenheit → AI 不会填 "摄氏度" 或 "C"AI 可能把 unit 填成 "摄氏" 或 "°C" → API 不认识这个值,返回错误

一句话总结: Schema 是 MCP Tool 的"参数合同"——AI 读 description 知道"要不要调这个 Tool",读 Schema 知道"调的时候参数怎么填"。两者缺一不可,description 解决意图理解,Schema 解决参数格式。

评论