你好啊,我是雨飞,见字如面。感谢阅读,期待我们下一次的相遇。
昨天,给大家直播分享了一次 MCP 的基本概念,其中有几个人私聊我问到关于 MCP 和 Function calling 的区别,今天和大家分享下这方面的知识,内容非常多,建议收藏后仔细阅读。市面上有很多分析 MCP 和 Function calling 的文章,但是说的并不对,如果只能用一句话来总结这两者的区别。那么相对比较准确的说法应该是 MCP 是封装了提示词、上下文资源和工具调用为一起的协议,功能更强,更具有规范性。其中工具调用可以用 Function calling 实现,也可以单纯依赖提示词。
首先,Function calling 是 OpenAI 在很早之前就提出来的一种方式,主要用于让大模型可以识别外部工具,然后让我们的程序可以和外部的 API 进行交互,从而实现更多复杂的功能,比如发送邮件、查看今天的天气,进行知识库搜索等等。在 OpenAI 后期的文档中,这个接口的入参名字改为了 tools,为此我们一般统称为工具调用,至于更细节的历史,大家不必追究,记住这几个都指的是一个东西就好了。
下面这个示例,就是 OpenAI 官方提供的,如何使用 Python 代码去调用我们定义的一个获取天气的函数。在这个 tools 变量里面,我们定义了当前函数的名字、功能描述,所需要的参数。
最终结果。GPT 返回了一个类型为 function_call 的对话信息,里面包括调用的函数名字,然后要传递给当前函数的参数。注意,这个地方类型并不是 Function calling,OpenAI 在概念和术语上并没有对齐,会导致很多新手、小白弄不清楚相关概念。
在这之后,我们就需要自己编写代码,去根据 AI 返回的函数名去调用这个函数,然后将入参传递过去,得到函数的结果。到这一步之后,我们才真正获得了天气的信息,这样就可以继续和 GPT 进行对话,让 GPT 根据获取到的信息,总结和归纳最终的答案。
整个过程可以用下面这个图进行描述,可以看到整体会分为 5 个步骤。其中,第一步、第三步、第四步这些环节都需要我们自己编写代码去完成,整个流程相对比较麻烦。另外,各个工具或者函数都需要我们自己实现或是调用第三方的服务,这也会导致各家实现的风格、方式各不相同,适配起来非常吃力。
很重要的一点,大模型需要具有识别和调用工具的能力才能正常给我们返回类似步骤 2的信息。因为这种能力需要依赖数据进行训练和微调,因此有很多大模型或者 API 是不支持工具调用的。
MCP 就是实现了一套服务端、客户端以及他们之间的协议,更详细一点,MCP 的服务端定义了自己对外提供的工具类型和描述信息,客户端通过 LLM 根据用户的指令,判断当前的指令需要调用哪个 MCP 服务器,并生成固定格式的请求参数去请求服务器,获得结果。
而 MCP 协议就是规定了客户端和服务端如何进行通信,并提供了三大原语,包括提示词、资源以及工具。提示词就是用户控制的,如何和服务器交互的提示词,如果你去看一些 MCP Client 的实现代码,他们会内置自己优化好的提示词,以便取得更好的结果。资源就是包括每次交互的上下文数据,响应信息等,也都会存储到服务器中。工具就是服务端可以提供的函数,让 LLM 去执行。
上图就是 MCP 官方的项目文档,在这里面其实我们就能看到, MCP 原语里面就包括了工具调用,也就是 Function calling 这个功能。只不过 MCP 的优势就是把之前复杂的步骤给封装好了,我们就不需要自己去实现上面复杂的代码,只需要简单调用 MCP 的 SDK 就能完成任务。
在官方的示例代码中,我们也只需要执行 call_tool 这个方法,就可以调用 MCP Server 所提供的工具并得到结果,非常方便。这个地方,同样需要 LLM 的参与,我们需要 LLM 去判断用户的输入究竟调用哪一个工具,也就是 OpenAI Function calling 中的第一步。然后后面的步骤,MCP 全给我们搞定了,就不需要我们自己再写代码。
Function calling 功能单一,不具备上下文管理能力,一次只执行一个任务,一般是同步进行调用。没有特定的标准,需要厂商或者我们自己去开发实现。生态相对封闭,没有多少开源项目,定制化比较多。
MCP 功能复杂,可以支持多轮对话,一次能调用多个任务,也可以异步执行。有统一的标准,只要是适配了 MCP 的 Server 都可以用统一的代码去调用。而且 MCP 本身的社区生态更繁荣,现在已经 2000+ 以上的 MCP Servers 供大家使用。
Function calling 需要大模型具有工具调用的能力,能识别出来当前用户请求是需要调用哪个工具去完成任务。而且并不是所有的大模型都会支持工具调用。比如在 Coze 中提供的 DeepSeek 模型,就有很多不支持工具调用(Coze 叫做 funcionCall 是一回事)。
MCP 则更加灵活,可以借用 Function calling 的方式去进行工具调用,也可以使用自然语言描述的提示词去告诉 LLM,提供了哪些工具供他使用,应该以何种格式返回结果这种就更依赖大模型的语言理解能力,比如 Claude 就要更好用。最简单的例子,你告诉大模型要求返回 JSON 格式的信息,它给你返回的并不是JSON结构,那就导致 MCP 会解析失败,直接完蛋。
这种提示词的描述带来的潜在问题就是传输给大模型的上下文会非常长,假如我们现在有几个 MCP,一次调用可能消耗几十万的 token。更离谱的,你去看下 Cline 的源码中,他们直接把 MCP 相关的内容全扔进提示词里面,导致使用 Cline 消耗的 token 会非常多。
最后,太长看不懂的朋友们可以看下面这张图。Function calling 就是各自为战,直接和大模型进行对接。而 MCP 则更为复杂,Client 和 Server 直接使用标准化的协议进行链接,Server 并不会直接和大模型进行交互,而是通过 Client 链接到后面的大模型。
https://platform.openai.com/docs/guides/function-calling?api-mode=responses
https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#writing-mcp-clients
https://github.com/cline/cline/blob/main/src/core/prompts/system.ts
有想一起交流学习 Cursor 的可以添加下方的微信,备注「编程」,邀你一起学习。
加微 1060687688,备注「公众号」,送你一份「AI工具与副业变现指南」
「雨飞同行」这是雨飞的介绍(第8版,交个朋友,限时送福利)