Function Call与MCP(区别、联系与实战)

Function Call 与 MCP:一个是"手",一个是"插座"

一句话总结 :Function Call 解决"模型怎么开口要工具" ------模型输出一段结构化 JSON,说"我要调 get_weather,参数是北京";MCP 解决"工具怎么被复用" ------它把工具、数据、提示词按统一协议暴露出来,让任何 AI 应用都能接任何 工具。两者不是替代关系,而是分层关系 :MCP 暴露的工具,最终还是通过 Function Call 交给模型去选 。一句话:Function Call 是模型的手,MCP 是墙上统一的插座。


📋 目录

  1. 先看一张图:它们根本不在同一层
  2. Function Call:模型如何"开口要工具"
  3. MCP:把 N×M 变成 N+M
  4. 关键澄清:MCP 不能替代 Function Call
  5. MCP 的三个核心概念 + 2026 年的重大变化
  6. 最小代码:一个工具,两种写法
  7. 三个最容易踩的坑
  8. 什么时候用哪个
  9. 总结

一、先看一张图:它们根本不在同一层

#mermaid-svg-NRBbuQdrGNzVD3MC{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NRBbuQdrGNzVD3MC .error-icon{fill:#552222;}#mermaid-svg-NRBbuQdrGNzVD3MC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NRBbuQdrGNzVD3MC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NRBbuQdrGNzVD3MC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NRBbuQdrGNzVD3MC .marker.cross{stroke:#333333;}#mermaid-svg-NRBbuQdrGNzVD3MC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NRBbuQdrGNzVD3MC p{margin:0;}#mermaid-svg-NRBbuQdrGNzVD3MC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC .cluster-label text{fill:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC .cluster-label span{color:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC .cluster-label span p{background-color:transparent;}#mermaid-svg-NRBbuQdrGNzVD3MC .label text,#mermaid-svg-NRBbuQdrGNzVD3MC span{fill:#333;color:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC .node rect,#mermaid-svg-NRBbuQdrGNzVD3MC .node circle,#mermaid-svg-NRBbuQdrGNzVD3MC .node ellipse,#mermaid-svg-NRBbuQdrGNzVD3MC .node polygon,#mermaid-svg-NRBbuQdrGNzVD3MC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NRBbuQdrGNzVD3MC .rough-node .label text,#mermaid-svg-NRBbuQdrGNzVD3MC .node .label text,#mermaid-svg-NRBbuQdrGNzVD3MC .image-shape .label,#mermaid-svg-NRBbuQdrGNzVD3MC .icon-shape .label{text-anchor:middle;}#mermaid-svg-NRBbuQdrGNzVD3MC .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NRBbuQdrGNzVD3MC .rough-node .label,#mermaid-svg-NRBbuQdrGNzVD3MC .node .label,#mermaid-svg-NRBbuQdrGNzVD3MC .image-shape .label,#mermaid-svg-NRBbuQdrGNzVD3MC .icon-shape .label{text-align:center;}#mermaid-svg-NRBbuQdrGNzVD3MC .node.clickable{cursor:pointer;}#mermaid-svg-NRBbuQdrGNzVD3MC .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NRBbuQdrGNzVD3MC .arrowheadPath{fill:#333333;}#mermaid-svg-NRBbuQdrGNzVD3MC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NRBbuQdrGNzVD3MC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NRBbuQdrGNzVD3MC .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NRBbuQdrGNzVD3MC .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NRBbuQdrGNzVD3MC .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NRBbuQdrGNzVD3MC .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NRBbuQdrGNzVD3MC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NRBbuQdrGNzVD3MC .cluster text{fill:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC .cluster span{color:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NRBbuQdrGNzVD3MC .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NRBbuQdrGNzVD3MC rect.text{fill:none;stroke-width:0;}#mermaid-svg-NRBbuQdrGNzVD3MC .icon-shape,#mermaid-svg-NRBbuQdrGNzVD3MC .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NRBbuQdrGNzVD3MC .icon-shape p,#mermaid-svg-NRBbuQdrGNzVD3MC .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NRBbuQdrGNzVD3MC .icon-shape .label rect,#mermaid-svg-NRBbuQdrGNzVD3MC .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NRBbuQdrGNzVD3MC .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NRBbuQdrGNzVD3MC .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NRBbuQdrGNzVD3MC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Function Call

输出 tool_calls
MCP 协议

tools/call
结果
tool 消息
👤 用户提问
🧠 大模型

(判断:要不要调工具、调哪个)
🖥️ Host 应用

(执行调度)
🔌 MCP Server

(真正干活的工具)
✅ 最终回答

看这张图就能明白:

管什么 在哪一层
Function Call 模型**表达"我要调工具"**的语言 模型能力层
MCP 应用发现和调用工具的接口标准 工程集成层

它们解决的是完全不同的问题。 一个在"模型怎么说话",一个在"系统怎么接线"。


二、Function Call:模型如何"开口要工具"

2.1 一次完整的往返

Function Call 的本质是一个"三段式"循环 ,模型自己不执行任何东西:
真实函数 大模型 应用 真实函数 大模型 应用 #mermaid-svg-D2wM8SxIZ4wmktIv{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-D2wM8SxIZ4wmktIv .error-icon{fill:#552222;}#mermaid-svg-D2wM8SxIZ4wmktIv .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-D2wM8SxIZ4wmktIv .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-D2wM8SxIZ4wmktIv .marker{fill:#333333;stroke:#333333;}#mermaid-svg-D2wM8SxIZ4wmktIv .marker.cross{stroke:#333333;}#mermaid-svg-D2wM8SxIZ4wmktIv svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-D2wM8SxIZ4wmktIv p{margin:0;}#mermaid-svg-D2wM8SxIZ4wmktIv .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-D2wM8SxIZ4wmktIv text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-D2wM8SxIZ4wmktIv .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-D2wM8SxIZ4wmktIv .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-D2wM8SxIZ4wmktIv #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-D2wM8SxIZ4wmktIv .sequenceNumber{fill:white;}#mermaid-svg-D2wM8SxIZ4wmktIv #sequencenumber{fill:#333;}#mermaid-svg-D2wM8SxIZ4wmktIv #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-D2wM8SxIZ4wmktIv .messageText{fill:#333;stroke:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-D2wM8SxIZ4wmktIv .labelText,#mermaid-svg-D2wM8SxIZ4wmktIv .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .loopText,#mermaid-svg-D2wM8SxIZ4wmktIv .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-D2wM8SxIZ4wmktIv .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-D2wM8SxIZ4wmktIv .noteText,#mermaid-svg-D2wM8SxIZ4wmktIv .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-D2wM8SxIZ4wmktIv .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-D2wM8SxIZ4wmktIv .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-D2wM8SxIZ4wmktIv .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-D2wM8SxIZ4wmktIv .actorPopupMenu{position:absolute;}#mermaid-svg-D2wM8SxIZ4wmktIv .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-D2wM8SxIZ4wmktIv .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-D2wM8SxIZ4wmktIv .actor-man circle,#mermaid-svg-D2wM8SxIZ4wmktIv line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-D2wM8SxIZ4wmktIv :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} ① 用户问题 + 可用工具列表 ② tool_calls: {name: "get_weather", args: {city: "北京"}} ③ 应用去执行(模型不执行) ④ "北京 晴 25℃" ⑤ 把结果作为 tool 消息回传 ⑥ 基于结果生成最终回答

关键点:模型只负责"决定"和"填参数",执行永远是应用的事。

2.2 协议长什么样

第一步,把工具描述给模型:

json 复制代码
{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "北京天气怎么样?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "查询指定城市的实时天气",
      "parameters": {
        "type": "object",
        "properties": {
          "city": {"type": "string", "description": "城市名称,如 北京"}
        },
        "required": ["city"]
      }
    }
  }]
}

第二步,模型回一个"调用意图":

json 复制代码
{
  "choices": [{
    "finish_reason": "tool_calls",
    "message": {
      "role": "assistant",
      "tool_calls": [{
        "id": "call_abc123",
        "type": "function",
        "function": {
          "name": "get_weather",
          "arguments": "{\"city\": \"北京\"}"
        }
      }]
    }
  }]
}

第三步,应用执行完,把结果塞回去:

json 复制代码
{
  "role": "tool",
  "tool_call_id": "call_abc123",
  "content": "北京 晴,25℃"
}

模型拿到结果后继续生成,就得到了自然语言回答。

2.3 它有三个天然局限

局限 后果
工具定义要写在每次请求里 工具一变,所有应用的 prompt 都要改
各家格式不统一 OpenAI / Claude / Gemini 的 schema 有差异,换模型要重写
工具和执行绑在应用里 你写的天气工具,别人的应用用不了

🎯 这三个局限,正好就是 MCP 要解决的问题。


三、MCP:把 N×M 变成 N+M

3.1 没有 MCP 的世界

假设你有 3 个 AI 应用 (IDE、客服机器人、个人助手)和 4 个工具(数据库、文件系统、GitHub、搜索)。

每一个应用都要为每一个工具写一遍适配代码:
#mermaid-svg-nbsOFgdHod05xbc4{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-nbsOFgdHod05xbc4 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-nbsOFgdHod05xbc4 .error-icon{fill:#552222;}#mermaid-svg-nbsOFgdHod05xbc4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-nbsOFgdHod05xbc4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-nbsOFgdHod05xbc4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-nbsOFgdHod05xbc4 .marker.cross{stroke:#333333;}#mermaid-svg-nbsOFgdHod05xbc4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-nbsOFgdHod05xbc4 p{margin:0;}#mermaid-svg-nbsOFgdHod05xbc4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-nbsOFgdHod05xbc4 .cluster-label text{fill:#333;}#mermaid-svg-nbsOFgdHod05xbc4 .cluster-label span{color:#333;}#mermaid-svg-nbsOFgdHod05xbc4 .cluster-label span p{background-color:transparent;}#mermaid-svg-nbsOFgdHod05xbc4 .label text,#mermaid-svg-nbsOFgdHod05xbc4 span{fill:#333;color:#333;}#mermaid-svg-nbsOFgdHod05xbc4 .node rect,#mermaid-svg-nbsOFgdHod05xbc4 .node circle,#mermaid-svg-nbsOFgdHod05xbc4 .node ellipse,#mermaid-svg-nbsOFgdHod05xbc4 .node polygon,#mermaid-svg-nbsOFgdHod05xbc4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-nbsOFgdHod05xbc4 .rough-node .label text,#mermaid-svg-nbsOFgdHod05xbc4 .node .label text,#mermaid-svg-nbsOFgdHod05xbc4 .image-shape .label,#mermaid-svg-nbsOFgdHod05xbc4 .icon-shape .label{text-anchor:middle;}#mermaid-svg-nbsOFgdHod05xbc4 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-nbsOFgdHod05xbc4 .rough-node .label,#mermaid-svg-nbsOFgdHod05xbc4 .node .label,#mermaid-svg-nbsOFgdHod05xbc4 .image-shape .label,#mermaid-svg-nbsOFgdHod05xbc4 .icon-shape .label{text-align:center;}#mermaid-svg-nbsOFgdHod05xbc4 .node.clickable{cursor:pointer;}#mermaid-svg-nbsOFgdHod05xbc4 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-nbsOFgdHod05xbc4 .arrowheadPath{fill:#333333;}#mermaid-svg-nbsOFgdHod05xbc4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-nbsOFgdHod05xbc4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-nbsOFgdHod05xbc4 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nbsOFgdHod05xbc4 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-nbsOFgdHod05xbc4 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nbsOFgdHod05xbc4 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-nbsOFgdHod05xbc4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-nbsOFgdHod05xbc4 .cluster text{fill:#333;}#mermaid-svg-nbsOFgdHod05xbc4 .cluster span{color:#333;}#mermaid-svg-nbsOFgdHod05xbc4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-nbsOFgdHod05xbc4 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-nbsOFgdHod05xbc4 rect.text{fill:none;stroke-width:0;}#mermaid-svg-nbsOFgdHod05xbc4 .icon-shape,#mermaid-svg-nbsOFgdHod05xbc4 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-nbsOFgdHod05xbc4 .icon-shape p,#mermaid-svg-nbsOFgdHod05xbc4 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-nbsOFgdHod05xbc4 .icon-shape .label rect,#mermaid-svg-nbsOFgdHod05xbc4 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-nbsOFgdHod05xbc4 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-nbsOFgdHod05xbc4 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-nbsOFgdHod05xbc4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用1
工具1
工具2
工具3
应用2
应用3

3 × 4 = 12 份适配代码。 加一个应用就是 4 份新代码,加一个工具就是 3 份新代码。

3.2 有 MCP 的世界

工具只需要按 MCP 标准做成一个 Server,应用只需要实现一个 MCP Client:
#mermaid-svg-rsuvXibeJahCjzw8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-rsuvXibeJahCjzw8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-rsuvXibeJahCjzw8 .error-icon{fill:#552222;}#mermaid-svg-rsuvXibeJahCjzw8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-rsuvXibeJahCjzw8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-rsuvXibeJahCjzw8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-rsuvXibeJahCjzw8 .marker.cross{stroke:#333333;}#mermaid-svg-rsuvXibeJahCjzw8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-rsuvXibeJahCjzw8 p{margin:0;}#mermaid-svg-rsuvXibeJahCjzw8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-rsuvXibeJahCjzw8 .cluster-label text{fill:#333;}#mermaid-svg-rsuvXibeJahCjzw8 .cluster-label span{color:#333;}#mermaid-svg-rsuvXibeJahCjzw8 .cluster-label span p{background-color:transparent;}#mermaid-svg-rsuvXibeJahCjzw8 .label text,#mermaid-svg-rsuvXibeJahCjzw8 span{fill:#333;color:#333;}#mermaid-svg-rsuvXibeJahCjzw8 .node rect,#mermaid-svg-rsuvXibeJahCjzw8 .node circle,#mermaid-svg-rsuvXibeJahCjzw8 .node ellipse,#mermaid-svg-rsuvXibeJahCjzw8 .node polygon,#mermaid-svg-rsuvXibeJahCjzw8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-rsuvXibeJahCjzw8 .rough-node .label text,#mermaid-svg-rsuvXibeJahCjzw8 .node .label text,#mermaid-svg-rsuvXibeJahCjzw8 .image-shape .label,#mermaid-svg-rsuvXibeJahCjzw8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-rsuvXibeJahCjzw8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-rsuvXibeJahCjzw8 .rough-node .label,#mermaid-svg-rsuvXibeJahCjzw8 .node .label,#mermaid-svg-rsuvXibeJahCjzw8 .image-shape .label,#mermaid-svg-rsuvXibeJahCjzw8 .icon-shape .label{text-align:center;}#mermaid-svg-rsuvXibeJahCjzw8 .node.clickable{cursor:pointer;}#mermaid-svg-rsuvXibeJahCjzw8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-rsuvXibeJahCjzw8 .arrowheadPath{fill:#333333;}#mermaid-svg-rsuvXibeJahCjzw8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-rsuvXibeJahCjzw8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-rsuvXibeJahCjzw8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rsuvXibeJahCjzw8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-rsuvXibeJahCjzw8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rsuvXibeJahCjzw8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-rsuvXibeJahCjzw8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-rsuvXibeJahCjzw8 .cluster text{fill:#333;}#mermaid-svg-rsuvXibeJahCjzw8 .cluster span{color:#333;}#mermaid-svg-rsuvXibeJahCjzw8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-rsuvXibeJahCjzw8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-rsuvXibeJahCjzw8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-rsuvXibeJahCjzw8 .icon-shape,#mermaid-svg-rsuvXibeJahCjzw8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-rsuvXibeJahCjzw8 .icon-shape p,#mermaid-svg-rsuvXibeJahCjzw8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-rsuvXibeJahCjzw8 .icon-shape .label rect,#mermaid-svg-rsuvXibeJahCjzw8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-rsuvXibeJahCjzw8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-rsuvXibeJahCjzw8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-rsuvXibeJahCjzw8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 应用1
🔌 MCP
应用2
应用3
Server: 工具1
Server: 工具2
Server: 工具3

3 + 4 = 7 份代码。 加一个应用只写 1 份 Client,加一个工具只写 1 个 Server。

💡 这就是 MCP 被叫做"AI 界的 USB-C"的原因 :它不是让你多一个选择,而是让接口形状统一。

3.3 三个角色

角色 是什么 例子
Host 用户直接用的 AI 应用 Claude Desktop、Cursor、你的 Agent
Client Host 内部与 Server 一一对应的连接器 SDK 里的 ClientSession
Server 真正暴露工具/数据的一方 你写的天气服务、GitHub 官方 Server

关系:一个 Host 可以挂多个 Client,每个 Client 连一个 Server。


四、关键澄清:MCP 不能替代 Function Call

这是最容易搞混的一点,也是面试常问的。

很多人以为上了 MCP 就不需要 Function Call 了。错。

真实链路是这样的:
#mermaid-svg-kQXkS1KdjBp1K5WI{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kQXkS1KdjBp1K5WI .error-icon{fill:#552222;}#mermaid-svg-kQXkS1KdjBp1K5WI .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kQXkS1KdjBp1K5WI .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kQXkS1KdjBp1K5WI .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kQXkS1KdjBp1K5WI .marker.cross{stroke:#333333;}#mermaid-svg-kQXkS1KdjBp1K5WI svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kQXkS1KdjBp1K5WI p{margin:0;}#mermaid-svg-kQXkS1KdjBp1K5WI .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI .cluster-label text{fill:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI .cluster-label span{color:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI .cluster-label span p{background-color:transparent;}#mermaid-svg-kQXkS1KdjBp1K5WI .label text,#mermaid-svg-kQXkS1KdjBp1K5WI span{fill:#333;color:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI .node rect,#mermaid-svg-kQXkS1KdjBp1K5WI .node circle,#mermaid-svg-kQXkS1KdjBp1K5WI .node ellipse,#mermaid-svg-kQXkS1KdjBp1K5WI .node polygon,#mermaid-svg-kQXkS1KdjBp1K5WI .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kQXkS1KdjBp1K5WI .rough-node .label text,#mermaid-svg-kQXkS1KdjBp1K5WI .node .label text,#mermaid-svg-kQXkS1KdjBp1K5WI .image-shape .label,#mermaid-svg-kQXkS1KdjBp1K5WI .icon-shape .label{text-anchor:middle;}#mermaid-svg-kQXkS1KdjBp1K5WI .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kQXkS1KdjBp1K5WI .rough-node .label,#mermaid-svg-kQXkS1KdjBp1K5WI .node .label,#mermaid-svg-kQXkS1KdjBp1K5WI .image-shape .label,#mermaid-svg-kQXkS1KdjBp1K5WI .icon-shape .label{text-align:center;}#mermaid-svg-kQXkS1KdjBp1K5WI .node.clickable{cursor:pointer;}#mermaid-svg-kQXkS1KdjBp1K5WI .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kQXkS1KdjBp1K5WI .arrowheadPath{fill:#333333;}#mermaid-svg-kQXkS1KdjBp1K5WI .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kQXkS1KdjBp1K5WI .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kQXkS1KdjBp1K5WI .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kQXkS1KdjBp1K5WI .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kQXkS1KdjBp1K5WI .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kQXkS1KdjBp1K5WI .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kQXkS1KdjBp1K5WI .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kQXkS1KdjBp1K5WI .cluster text{fill:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI .cluster span{color:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kQXkS1KdjBp1K5WI .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kQXkS1KdjBp1K5WI rect.text{fill:none;stroke-width:0;}#mermaid-svg-kQXkS1KdjBp1K5WI .icon-shape,#mermaid-svg-kQXkS1KdjBp1K5WI .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kQXkS1KdjBp1K5WI .icon-shape p,#mermaid-svg-kQXkS1KdjBp1K5WI .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kQXkS1KdjBp1K5WI .icon-shape .label rect,#mermaid-svg-kQXkS1KdjBp1K5WI .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kQXkS1KdjBp1K5WI .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kQXkS1KdjBp1K5WI .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kQXkS1KdjBp1K5WI :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} MCP Server 声明工具
Host 拉取 tools/list
Host 把 MCP 工具

转成模型的 tool schema
模型用 Function Call 选择
Host 用 tools/call 执行
结果回传给模型

拆开看:

环节 谁负责
工具有哪些、怎么调 MCP
模型选哪个、填什么参数 Function Call
真正执行 MCP Server

🎯 一句话 :MCP 是"工具的目录和插头",Function Call 是"模型点菜的动作"。

目录再标准,也得模型自己点。

一个反证:如果模型没有 function calling 能力,你接再多 MCP Server 也没用------它根本不会发起调用。


五、MCP 的三个核心概念 + 2026 年的重大变化

5.1 三个原语

原语 是什么 谁来决定
Tools 可执行的函数(查天气、发邮件) 模型决定调用
Resources 可读取的数据(文件、数据库记录) 应用/用户决定加载
Prompts 预置的提示词模板 用户主动选择

区别很关键:Tools 是"模型想用就用",Resources 是"应用决定给不给",Prompts 是"用户点了才用"。

📌 做 RAG 或工具集成,90% 的场景只用 Tools。

5.2 ⚠️ 2026-07-28 规范:一次大改

如果你的参考资料是 2025 年的,现在大概率已经过时了。 当前规范是 2026-07-28,最重要的变化:

变化 说明
协议变无状态 initialize 握手被移除,Mcp-Session-Id 也被移除;协议版本、客户端信息改放在每次请求的 _meta 里
新增 server/discover 客户端需要预先了解服务端能力时用它(非必需)
Streamable HTTP 必带两个头 Mcp-Method 和 Mcp-Name,方便网关/限流器直接路由,不用解析 body
列表可缓存 tools/list 等结果带上 ttlMs 和 cacheScope
Roots / Sampling / Logging 已弃用 还能用,至少再撑 12 个月,但新项目别再用
HTTP+SSE 传输已弃用 改用 Streamable HTTP

为什么"无状态"是件大事?

以前:客户端要先 initialize 拿 Mcp-Session-Id,之后每个请求都要带这个 ID,被钉死在某一台服务器实例上------所以你需要 sticky session、共享 session 存储。

现在:每个请求自带全部上下文,任何一个实例都能处理。 直接扔到普通轮询负载均衡后面就行。

🎯 这一改动让 MCP Server 从"能跑"变成"能上生产"。

5.3 生态现状

  • 官方 TypeScript / Python / Go / C# 四个一级 SDK 均已支持 2026-07-28
  • 一级 SDK 月下载量接近数亿次,TS 与 Python 累计都过了 10 亿
  • 2025 年起 OpenAI、Google、Microsoft 陆续宣布支持,已成事实标准

六、最小代码:一个工具,两种写法

6.1 纯 Function Call 写法

python 复制代码
import json
from openai import OpenAI

client = OpenAI()

def get_weather(city: str) -> str:
    """查询指定城市的实时天气"""
    return f"{city} 晴,25℃"

TOOLS = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "查询指定城市的实时天气",
        "parameters": {
            "type": "object",
            "properties": {
                "city": {"type": "string", "description": "城市名称"}
            },
            "required": ["city"],
        },
    },
}]

messages = [{"role": "user", "content": "北京天气怎么样?"}]
resp = client.chat.completions.create(
    model="gpt-4o", messages=messages, tools=TOOLS
)

msg = resp.choices[0].message
if msg.tool_calls:
    messages.append(msg)
    for call in msg.tool_calls:
        args = json.loads(call.function.arguments)
        result = get_weather(**args)          # ← 应用自己执行
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": result,
        })

final = client.chat.completions.create(model="gpt-4o", messages=messages)
print(final.choices[0].message.content)

注意 :get_weather 是写死在这个应用里的,别人拿不走。

6.2 MCP Server 写法

python 复制代码
# 以官方 Python SDK 为例
# 注意:2026-07-28 规范下 SDK 有迁移,具体 API 以官方 README 为准
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather")

@mcp.tool()
def get_weather(city: str) -> str:
    """查询指定城市的实时天气。这段 docstring 会成为工具描述。"""
    return f"{city} 晴,25℃"

if __name__ == "__main__":
    mcp.run()

区别在哪?

Function Call 写法 MCP Server 写法
工具在哪 写死在应用里 独立进程/服务
谁能用 只有这个应用 任何 MCP Client
换应用 重写一遍 不用改
换工具 改 prompt 改 Server,应用不动

💡 一行总结 :Function Call 是"函数调用",MCP 是"函数即服务"。


七、三个最容易踩的坑

坑 1:以为 MCP 能替代 Function Call

不会。 MCP Server 暴露的工具,Host 仍然要转成模型的 tool schema,模型仍然用 function call 来选。

MCP 让工具"可复用",但没有让模型"会调用" ------那还是模型自身的能力。

坑 2:照抄 2025 年的 MCP 教程

2026-07-28 规范是破坏性变更。 如果你看到教程里出现这些,说明它过时了:

过时写法 现状
method: "initialize" 握手 ❌ 已移除
Mcp-Session-Id 请求头 ❌ 已移除
HTTP + SSE 传输 ⚠️ 已弃用,用 Streamable HTTP
用 Sampling / Roots / Logging ⚠️ 已弃用,新项目别用

坑 3:工具描述写得太随意

这一点和 Function Call 完全一样:

工具名 + docstring + 参数说明,会直接变成模型提示词的一部分。

所以:

  • ❌ def f(a, b): ...
  • ✅ def search_flights(origin, destination, date): """查询指定日期从出发地到目的地的航班。"""

另外:参数越少、越扁平越好。 嵌套三层对象,模型填错的概率会明显上升。


八、什么时候用哪个

你的场景 建议
就一个应用、几个内部函数 Function Call 够了,别上 MCP
工具要被多个应用/多个模型复用 上 MCP
要做成给别人用的产品/插件 上 MCP
需要标准化地接外部数据源 上 MCP
只是本地跑个 demo Function Call 更快

🎯 一个务实的判断 :

工具只有你自己用 → Function Call;工具要让别人也能用 → MCP。

不要因为 MCP 火,就给一个只有三个函数的小脚本套一层 Server。


九、总结

三句话记住区别

  1. Function Call 是模型的能力 :它学会"举手说我要调工具",并填对参数。
  2. MCP 是工程的协议 :它让工具只用写一次,任何 Host 都能接。
  3. 两者是叠在一起的:MCP 提供目录,Function Call 完成点菜,Server 负责上菜。

✅ 应该做的

  • 记住 Host / Client / Server 三个角色
  • 新项目按 2026-07-28 规范开发(无状态、Streamable HTTP)
  • 工具描述当成 prompt 来写,名字要语义化
  • 工具参数尽量少而扁平
  • 先用 Function Call 跑通,再考虑抽成 MCP Server

❌ 不要做的

  • ❌ 以为上了 MCP 就不需要 Function Call
  • ❌ 照着 2025 年教程写 initialize + Mcp-Session-Id
  • ❌ 新项目继续用 Sampling / Roots / Logging
  • ❌ 给三个函数的小脚本套 MCP Server
  • ❌ 把工具描述写成 def f(a, b)

🎯 最后一句

Function Call 让模型"能用手",MCP 让全世界的手"能插同一个插座"。

前者是模型能力的里程碑,后者是工程标准化的里程碑------它们不是一代淘汰一代,而是两层叠在一起。


📚 参考资料

版本说明 :本文 MCP 部分基于 2026-07-28 规范 (2026-10 核对)。该版本为破坏性变更 :移除 initialize 握手与 Mcp-Session-Id、新增 server/discover、Streamable HTTP 强制 Mcp-Method / Mcp-Name 头、Roots / Sampling / Logging 已弃用。如果你参考的是 2025 年的资料,请务必核对版本。SDK 的 Python API 在该版本下有迁移,示例代码以官方 README 为准。


如果这篇对你有帮助,欢迎点赞 + 收藏。下一篇可以写 怎么 10 分钟写一个自己的 MCP Server ,或者 MCP 的 Resources 和 Tools 到底怎么分工------评论区告诉我。

相关推荐
略略略咯咯2 小时前
啊啊啊啊啊
java·服务器·数据库
木子欢儿2 小时前
Debian 13 + vsftpd 搭建FTP服务
linux·服务器·前端·网络·debian
SL_staff2 小时前
运维救火实战:钉钉API变更致薪资计算中断,如何用可视化逻辑引擎5分钟热修复
java·开源·全栈
猫猫.1533 小时前
HashTable、HashMap、ConcurrentHashMap 核心区别总结
java·开发语言·java-ee
达~熊迪3 小时前
IP 分配前核查:把在线状态和使用登记一起看
服务器·网络·tcp/ip
qq_谁赞成_谁反对3 小时前
甲方IT的成长之路--SG TCP网络优化工具--20261026
运维·服务器·udp·tcp
郭小李3 小时前
spring mvc 工作流程
java·spring·mvc
SL_staff4 小时前
BI大屏嵌入MES的登录态难题:JVS统一账号体系实战解法
java·数据分析·数据可视化
乌暮4 小时前
综合案例:宠物电商系统
java·开发语言·spring·mvc·restful·1024程序员节