MCP Server 与 Function Calling

MCP Server 与 Function Calling:AI 工具调用的两层架构

一篇讲清楚"模型怎么想调工具"和"工具怎么被真正执行"的区别。


1. Function Calling 与 Model Context Protocol

你跟 AI 说:"帮我查一下订单 NB-666 的状态。"

AI 看起来"自己调了工具、读了数据库、给了你答案"。这个过程里,至少藏着两套机制:

  1. Function Calling :模型输出一段结构化意图------"我要调 get_order,参数是 NB-1001"。
  2. MCP(Model Context Protocol):真正有个服务收到这个调用,去数据库查,把结果送回来。

很多人以为这是"同一个东西的两种说法",其实它们根本不在一层。

Function Calling 是模型"嘴上说要做什么";

MCP 是"旁边谁真的去把它做了,并且让所有 AI 应用都能复用这套做法"。


1.1. Function Calling(函数调用)

这是大模型自己的能力,不是协议。

流程很简单:

  1. 你给模型一份"工具清单"(名字 + 描述 + 参数 JSON Schema)
  2. 模型根据用户问题,决定调哪个、传什么参
  3. 模型输出一段结构化调用请求(不是真执行)
  4. 你的代码拿到请求,自己跑函数
  5. 把结果塞回对话,模型继续生成回答

模型侧看到的样子(以 OpenAI 风格为例):

json 复制代码
{
  "type": "function_call",
  "name": "get_order",
  "arguments": "{\"order_id\": \"NB-1001\"}"
}

关键点:模型永远不碰数据库。它只"提议",执行者是你写的应用代码。

特点:

  • 快、轻、简单
  • 工具定义跟着每次请求走(有上下文开销)
  • 各厂商 Schema 格式不完全兼容(OpenAI / Claude / Gemini 各一套)
  • 工具逻辑和你的应用强耦合,换一个应用就得重写

1.2. MCP Server(模型上下文协议服务)

MCP 是 Anthropic 在 2024 年提出的开放协议,现在已捐给 Linux 基金会旗下 Agentic AI Foundation,OpenAI、Google、Microsoft、AWS 都参与支持 。

它解决的是另一个问题:

工具那么多、AI 应用那么多,难道每个组合都要写一遍对接代码?

MCP 的答案是:把工具做成"标准插座"。

1.2.1 架构三角色
角色 是什么 例子
Host 用户直接用的 AI 应用 Claude Desktop、Cursor、VS Code、你自研的 Agent
Client Host 内部的小连接器,一对一连一个 Server Host 里每个 MCP Server 配一个 Client
Server 独立运行的服务,暴露工具/资源/提示词 数据库服务、文件系统服务、Jira 服务
1.2.2 MCP Server 能暴露三种能力
  • Tools(工具) :可执行的动作,模型主动调用
    query_db()、send_email()、search_code()
  • Resources(资源) :只读上下文数据,按 URI 标识
    file:///config.yaml、db://schema/users
  • Prompts(提示词模板) :可复用的交互模板
    "代码审查模板""周报生成模板"
1.2.3 通信底层
  • 消息格式:JSON-RPC 2.0
  • 传输方式:
    • stdio:本地进程,通过标准输入输出(默认、零部署)
    • Streamable HTTP:远端服务,走 HTTP + SSE

一次典型工具调用在协议层长这样:

json 复制代码
// Client → Server
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "get_order",
    "arguments": { "order_id": "NB-1001" }
  }
}

// Server → Client
{
  "jsonrpc": "2.0",
  "id": 7,
  "result": {
    "content": [{ "type": "text", "text": "{\"status\": \"shipped\"}" }]
  }
}

Server 自己从不跟模型对话,它只等调用、做事情、回结果 。


2. 核心关系:不是替代,是分层

这是全文最重要的图,建议直接记下来:

复制代码
┌─────────────────────────────────────────────┐
│                AI Host 应用                   │
│                                               │
│   模型(LLM)                                  │
│     │                                         │
│     │ ① Function Calling:我要调 get_order     │
│     ▼                                         │
│   适配器(把 MCP 工具转成模型能看的 Schema)     │
│     │                                         │
│     │ ② MCP Client                            │
│     ▼                                         │
│  ╔═══════════════════════╗                    │
│  ║      MCP Server        ║                    │
│  ║  - 工具发现            ║                    │
│  ║  - 真正执行业务逻辑     ║                    │
│  ║  - 调底层 API / DB      ║                    │
│  ╚═══════════════════════╝                    │
└─────────────────────────────────────────────┘

一句话:

Function Calling 是"模型到应用的契约";

MCP 是"应用到工具服务的协议"。

生产系统里,它们通常一起用:模型用 Function Calling 表达意图,Host 把它翻译成 MCP 调用。


3. 完整调用时序(真实发生的事)

以"查订单"为例,端到端走了这几步:

  1. 启动发现 :Host 启动 MCP Client,连上 Server,发 server/discover 或 tools/list
  2. 能力协商 :Server 返回"我有 get_order,参数长这样(JSON Schema)"
  3. 塞给模型:Host 把这个工具描述,转成当前模型支持的 Function Calling 格式,放进模型请求
  4. 模型决策 :用户问"订单咋样了",模型输出 function_call: get_order(NB-666)
  5. 协议转发 :Host 收到后,通过 MCP Client 发 tools/call
  6. 执行:MCP Server 真去查库
  7. 回传:Server 返回结果,Client 交给 Host
  8. 二次推理:Host 把结果塞回对话,模型生成自然语言回答

模型从头到尾不知道数据库密码,也不知道 MCP 存在。


4. 、写一个最小可运行的 MCP Server

用官方 Python SDK(FastMCP 风格),十几行就能跑起来:

python 复制代码
# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("order-server")

ORDERS = {
    "NB-1001": {"status": "shipped", "items": 2},
    "NB-1002": {"status": "processing", "items": 1},
}

@mcp.tool()
def get_order(order_id: str) -> dict:
    """根据订单号查询订单状态"""
    return ORDERS.get(order_id, {"status": "not_found"})

@mcp.resource("order://{order_id}")
def order_resource(order_id: str) -> str:
    """把订单暴露成可读资源"""
    return str(ORDERS.get(order_id, {}))

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

运行:

bash 复制代码
pip install "mcp[cli]"
python server.py

在支持 MCP 的客户端(Cursor / Claude Desktop / Cherry Studio)里配一下:

json 复制代码
{
  "mcpServers": {
    "order": {
      "command": "python",
      "args": ["/绝对路径/server.py"]
    }
  }
}

AI 应用启动后会自动发现 get_order 工具,模型就能自己决定什么时候调它。

💡 SDK 会根据函数名、docstring、类型注解自动生成 JSON Schema,你不用手写。


5. 两者对比一览

维度 Function Calling MCP Server
本质 模型能力(输出格式) 通信协议 + 服务形态
所在层 模型 ↔ 应用 应用 ↔ 工具服务
工具定义在哪 每次请求里塞给模型 Server 启动后自动暴露
执行位置 你的应用代码里 独立的 MCP Server 进程/服务
跨应用复用 差,要重写 好,一次写好处处连
跨模型兼容 各厂商格式不同 协议统一,Client 做适配
上下文开销 工具越多,每次请求越重 按需发现,不占主对话
运行状态 无状态、请求级 可保持连接、连接池、缓存
部署成本 零额外组件 要跑/管一个服务进程

6. 选型建议

✅ 只用 Function Calling 就够

  • 工具只有 2~5 个,且只在你自己的应用里用
  • 不打算给别的 AI 客户端复用
  • 快速原型、单一模型、单一业务

✅ 值得上 MCP

  • 多个 AI 应用(IDE、客服、运营后台)要共用同一批工具
  • 工具要连数据库、文件系统、内部微服务,需要独立鉴权
  • 工具多(几十个以上),Function Calling 的 Schema 上下文成本扛不住
  • 想做"工具产品化",给别人或其他 Agent 用

✅ 生产系统常见做法:两者叠加

  • 模型侧:用 Function Calling 表达意图
  • 架构侧:Host 把 MCP 工具映射成 Function,调用转发给 MCP Server
  • 这样既保留模型原生能力,又获得标准化工具治理

7. 工程与安全注意点(踩坑必看)

MCP 不是"接上就安全",它本质是能执行代码的代理,权限越大风险越高。

  • 最小权限

    Server 不要直连 root 数据库。单独建账号,只给必要表、必要操作。

  • 写操作必须加确认

    send_email / delete_record / create_ticket 这类动作:

    • 要求 confirm=true 显式参数
    • 或在 Host 层弹确认框,不让模型"顺手就发"
  • 超时与降级

    MCP Server 是独立进程,会挂、会卡。Client 一定加 timeout,Server 返回结构化错误,让模型能自我恢复,而不是无限等待 。

  • 把工具返回当"不可信输入"

    第三方 Server 返回的内容可能是注入载荷。别直接拼进系统提示,要做清洗。

  • 环境隔离

    stdio 模式启动子进程时,工作目录、环境变量、配置文件路径要用绝对路径。一个相对路径错误,可能让 tools/list 返回空,排错排到怀疑人生。

  • 密钥隔离

    API Key 放 Server 侧,别散落在 Host 和各模型请求里。


8. 一个更直白的类比

把整套体系想象成公司协作:

  • 模型(LLM):老板,只会说"我要这份数据"
  • Function Calling:老板在群里 @你 的那句话
  • Host:项目经理,听懂老板意思,安排人干活
  • MCP Client:项目经理手里的对讲机
  • MCP Server:各个专业小组(财务组、IT 组、法务组)
  • Tools/Resources:小组能提供的服务

没有 MCP 时:老板每换一个项目,项目经理就得重新教一遍"财务组怎么对接"。

有 MCP 后:财务组装好对讲机,所有项目经理都能直接呼叫。


9.总结

  • Function Calling ≠ MCP,它们是不同层。
  • Function Calling 解决"模型怎么表达想调工具"。
  • MCP 解决"工具怎么被标准化发现、连接、执行、复用"。
  • 真实生产架构里,它们通常一起出现:模型用 Function Calling 决策,MCP 负责落地。
  • 小项目先用 Function Calling;工具要跨应用、要治理、要规模化,再抽成 MCP Server。
  • MCP 不自带安全,权限、确认、超时、审计都得自己设计。

模型负责"想",MCP 负责"做",Function Calling 是它们之间那句"我来安排"。


这篇文章的基础框架已经完整,接下来可以选一个方向继续深化:

相关推荐
猫头_4 小时前
MCP 开发实战:把你自己的后端 API 接入 Agent
人工智能·typescript·mcp
第404块砖头9 小时前
Spring Boot 4.1 + Spring AI 2.0:我如何用 Java 微服务把 RAG、知识图谱和 MCP 协议串成一个 Agent 平台
知识图谱·知识库·graph·rag·mcp·spring boot 4.1·spring ai 2.0
xrlfreedom9 小时前
MCP 面试高频考点:把知识库 RAG 封装成 Tool 时,提示注入防护与人机协同确认怎么答?
mcp·提示注入防护·人机协同确认
情 九18 小时前
MCP 实战 06:把 HTTP 接口接成工具,让 AI 帮你查数据
人工智能·网络协议·http·mcp
lgcgkCQ1 天前
【AI 转型实战 1】SpringAI 入门:搭建基础大模型对话能力
java·ai·agent·rag·spring ai·mcp·langchain4j
情 九1 天前
MCP 实战 04:把自己的工具接进 Cherry Studio
mcp
念念不忘 必有回响1 天前
从0到1:搭建你的第一个 MCP 服务器实战
agent·mcp
情 九1 天前
MCP 工具开发实战:参数校验、结构化输出与错误处理
mcp
xrlfreedom2 天前
MCP 面试高频考点:桌面客户端 stdio 连接失败,如何用 Resources、结构化输出与 OpenTelemetry 排查?
resources·opentelemetry·结构化输出·mcp