$Wynn5a 技术博客 - AI编程与软件工程实践
~/blog/function-calling-and-mcp

Function-Calling 和 MCP 

引言#

让我们给现在的各种 LLM(如 GPT,Gemini,Claude,DeepSeek 等)画一个自画像,我会描述为一个装在罐子里的超级智能大脑,它从阅读过的所有书籍和网站中学到了很多知识,像一个全知全能的超级智囊,但如果你问它今天的天气,或者想让它查看你最新的邮件,甚至访问你开发的某个工具呢?他只能果断的拒绝你,因为这个罐子里的大脑无法自行接触外部世界。

于是我们开始思考:如何为这个"罐中大脑"装上四肢,让它不仅能思考,还能行动?这便是 Function Calling 和模型上下文协议(Model Context Protocol,简称 MCP)诞生的背景。Function Calling 使得模型能够在理解用户意图后,调用外部定义的函数,执行特定任务。而 MCP 则提供了一个标准化的接口,允许模型与外部数据源和工具进行交互,获取实时信息或执行操作。 

通过这两者的结合,原本封闭的语言模型得以突破限制,成为真正的智能代理——它们就像为模型装上了感官和四肢,使其不仅能"思考",还能"感知"和"行动"。

给 LLM 装上“手”,它能做的就更多了
给 LLM 装上“手”,它能做的就更多了

在接下来的内容中,我们将深入探讨函数调用与 MCP 的原理、区别与联系,以及它们在构建智能代理系统中的实际应用。

💡 Function Calling 在很多时候和 Tool Calling 是可以互换的,所以本文不在进一步区分这两者

Function calling(函数调用)#

定义与目的#

函数调用指的是让大语言模型在生成文本时,自动识别需要调用外部工具或 API,并输出结构化信息(如 JSON)来执行该函数的能力。通过函数调用,LLM 能够突破静态训练数据的限制,实时查询外部数据源、执行命令或调用各种服务,从而完成更复杂、动态的任务。换言之,函数调用让 AI 不仅能“说”,还能“做”:当模型遇到无法直接回答的问题(如天气查询、数据库查询、设备控制等)时,它可以生成一个预定义的函数名和参数列表,请外部系统执行,并将结果带回给模型。

典型使用场景#

函数调用常用于对话机器人和智能体中,为它们提供调用外部工具的能力。例如,对于问题“北京现在天气如何?”,模型会通过函数调用产生类似 get_current_weather(location="Beijing") 的输出,由后端代码接管该请求并调用真实的天气 API,最后将返回的天气信息反馈给模型,由模型生成自然语言回复。又如智能家居场景中,用户说“打开客厅灯”,模型可以输出调用智能家居接口的函数调用指令 。函数调用还能应用于数据处理:模型可将“从数据库检索订单总数”转化为调用执行 SQL 查询的函数,从而实时获取所需数据。只要任务可以通过一个明确的函数接口完成,函数调用机制就能使 LLM 轻松完成信息检索、指令执行、API 交互等操作。

特点#

  • 增强 LLM 的实时性和功能性:通过函数调用,模型可以查询最新数据或执行实时运算,例如调用股票行情、计算器、地图导航等服务,使回答更加准确和实用
  • 简化功能扩展的开发流程:开发者只需向模型注册可用的函数及其接口描述,模型即可在需要时调用它们,许多现代 LLM(如 GPT-4、Gemini)已经针对函数调用进行了专门优化,模型能够自动判定何时调用哪个函数
  • 高效交互:函数调用将自然语言请求转化为结构化指令,使得对外部系统的访问更加可靠和准确,避免模型直接生成不可靠的答案

MCP(模型上下文协议 / Model Context Protocol)#

定义与目的#

MCP(Model Context Protocol,模型上下文协议)是一套针对 LLM 与工具/服务器通信的开放协议标准。它是一套标准化的开放接口协议,并不直接增强模型的推理能力,而是规定了宿主应用(Host)、外部服务(Server)与 AI 模型之间如何交换“上下文”的通用语言。如果说 Function Calling 是模型的一项“技能”,那么 MCP 就是一套标准化的“接线板”,让开发者无需为每个模型重复编写工具集成代码,实现了一次开发、到处接入。

工作流程#

MCP 协议的工作流程大致包括以下几个阶段

  1. 初始化(Handshake):在宿主应用启动时,创建 MCP 客户端并与相应的 MCP 服务器建立握手,双方交换能力信息和协议版本,确认可用的工具列表及其接口格式。
  2. 发现(Discovery):客户端请求服务器公布可用的能力(包括工具、资源、预设的提示模板等),服务器返回一个带有名称和描述的工具清单供客户端参考。
  3. 上下文准备(Context Provisioning):宿主应用可以将用户输入以及这些工具的定义(Schema)注入到模型的上下文窗口中,同时宿主可将工具描述转换为 LLM 可识别的格式(例如转换为 JSON 函数调用签名)。
  4. 调用(Call):当 LLM 在生成回答时判断需要调用某个工具(例如基于用户请求“查询邮件列表”),MCP 客户端会向相应的 MCP 服务器发出调用请求,请求指定工具执行任务,此请求按照统一的 MCP 格式封装工具名和参数。
  5. 响应(Response):MCP 服务器接收请求后执行对应操作(可能是真实 API 调用或本地计算),得到结果后按 MCP 协议的格式将结果返回给客户端。
  6. 结果整合(Output Integration):MCP 客户端将服务器返回的结果融合回 LLM 的对话上下文,接着模型可以利用这些新获取的信息生成最终回复。

通过以上流程,MCP 协议使得 LLM 与外部能力的交互不再是一次性的“问-答”调用,而是一种持续的、可追踪的会话流程。这种架构可以灵活支持多步任务和多工具协作。例如,在自动驾驶、游戏开发、设计创作等复杂场景中,用户一句话指令就可以通过 MCP 调用多个协同工具来完成复杂任务

Function Call 与 MCP 的关联#

MCP 是 Function Call 的升华#

MCP 并非要取代函数调用,而是对其进行了协议级的升华。在 MCP 架构中,函数调用从一种“点对点”的私有实现,转变为协议驱动的标准行为:模型通过函数调用产生意图输出,MCP 框架则负责工具的发现、路由与执行。这种解耦让开发者不再受限于特定模型的 API 格式,实现了“模型意图生成”与“后端工具执行”的标准对接。你可以理解为:函数调用是模型向外伸出的“手”,而 MCP 是连接万千工具的“通用接口”。

虽然 MCP 是一套独立的协议,但函数调用依然是其核心的触发机制。在实际运行中,函数调用是模型表达意图的“语言”,而 MCP 则充当了“翻译官”与“物流系统”,负责将这些指令标准化,并精准投递至对应的服务器。简而言之,函数调用解决了模型“想做什么”的问题,而 MCP 则规范了“如何安全、标准地做到”。

多步思维链规划的体现#

在多步任务执行中,模型往往需要先进行“思考”(生成执行步骤),再逐步调用工具。这个过程通常被称为多步思维链规划(Plan-and-Execute 模式)。MCP 协议正好支持这样的多轮交互:模型可以在生成的上下文(Context)中一次调用一个工具,然后根据返回结果更新状态,再决定下一步调用哪个工具,直到任务完成。例如,一个计划型智能 Agent 会先调用 MCP 中的规划器工具生成步骤列表,然后再通过 MCP 客户端逐个调用执行工具来完成每一步。需要强调的是,多步思维链规划本身是一种 Agent 设计模式,任务的分步规划、逻辑跳转和状态记忆是由 Agent 框架或宿主逻辑控制的,而非协议本身。MCP 协议的作用是提供一个稳定、标准化的“管道”,确保在多轮交互中,模型调用的每一步工具都能通过统一的格式与外部系统交换数据

工具生态与集成#

使用函数调用时,开发者需手动将函数定义嵌入到模型的提示词中,这会导致不同模型平台使用不同格式,维护成本高。而 MCP 则通过标准协议统一了这一过程:模型只需知晓 MCP 协议和工具能力,MCP 客户端就能自动发现和加载适配于各种模型的工具接口,简化了跨模型和跨平台的对接工作 。可以说,函数调用关注单次对接,MCP 则关注建立长期稳定的对接方案,两者在体系上互为补充。

Function Call 和 MCP 的区别#

两者在抽象层次、应用范围和复杂度等方面存在明显不同

抽象层次#

函数调用是一种较低层次的机制,聚焦于“在当前对话生成中调用一个函数”,类似于给模型一个明确的“工具箱”并让它选取工具。而 MCP 是一个更高层次的通信协议,它不仅包含具体的调用指令,还规定了发现工具、管理上下文、维护会话等流程。可以理解为:函数调用相当于向下的 API 请求,而 MCP 则是一整套协议和中间层,负责协调多个函数调用和数据流。

调用流程#

在传统的函数调用中,一次用户请求对应一次模型调用,然后一次函数调用(或多个函数依次调用)并返回结果,通常是“单阶段(一问一答式)”的交互。若函数调用失败,流程就终止。相比之下,MCP 支持多阶段、状态化的任务执行:任务可以分解为多个子任务,模型和工具之间可以交互多轮,每轮都在 MCP 协议下有明确的请求和响应。这一特性使 MCP 更适合处理长时间运行或需要检查进度、调整策略的任务。

工具发现与描述#

函数调用需要在对话上下文中预先定义函数签名,模型才能识别并调用;这些定义通常是静态的、与具体模型平台绑定的,而 MCP 引入了工具发现机制,客户端可以查询服务器获取可用工具列表和描述。这样,模型不必事先知道所有工具的细节,只需在对话中按照 MCP 协议询问合适的功能即可,从而大大降低了跨平台对接的复杂度。

数据流与上下文管理#

函数调用往往是一种“写死”的调用逻辑,模型生成调用请求后,大部分与工具的交互不再体现在对话文本中。MCP 则支持更动态的数据交互:工具运行的状态和结果可以实时反馈到对话中,并被模型利用,进而影响后续决策,此外,MCP 客户端会维护对话历史和中间变量,使模型能够将外部工具的返回结果无缝纳入自身的推理过程。

适用任务复杂度#

对于轻量级、高频的任务(如调用计算器、简单天气查询),直接使用函数调用往往更快速简便,而对于需要跨多个步骤协调和大量工具协作的复杂任务,MCP 提供了更完整的支撑。从实现角度看,函数调用体系在设计上较为简单,但在规模化和多样化任务场景下的可扩展性有限;MCP 则专为规模化、多模型和多工具场景设计,虽然引入了更多复杂度(如握手、发现等步骤),但能够显著提升工程效率与系统可靠性。

总结#

简单任务那么直接用 Function Calling,快。复杂任务那么要多用 MCP ,协调多步、多工具,可靠。两者并不冲突,组合起来用才是正经的 Agent 系统该有的样子。

我一直推崇奥卡姆剃刀:没必要的复杂度,不要引入。能用函数调用搞定的,不要套一层 MCP;真的需要多工具协作、状态管理,再上 MCP。选最简单的方案,够用就好。