大模型(LLM)在应用开发中扮演着越来越重要的角色,如何让大模型有效地利用外部工具和服务,是提升其能力的关键。本文将深入探讨两种主流的大模型工具使用方式:函数调用和模型上下文协议 (MCP),对比分析它们的优势、劣势以及适用场景,帮助开发者选择最合适的方案。早期大模型与外部服务连接主要依赖函数调用,但随着应用的复杂性增加,MCP 逐渐崭露头角,成为更具扩展性和灵活性的选择。
函数调用:简单直接的工具箱
函数调用是一种简单直接的大模型工具使用方法。它允许大模型生成结构化的输出,指定需要执行的函数名称和参数。你可以把它想象成给大模型提供了一个工具箱,让它根据指令选择合适的工具并使用。这种方法在早期的大模型应用中被广泛采用,因为它易于理解和实现。
例如,当用户询问“巴黎今天的天气怎么样?”时,通过函数调用,大模型可以识别出需要调用 get_weather
函数,并提取出“巴黎”作为参数。然后,大模型将生成一个包含函数名和参数的 JSON 结构,传递给外部天气 API,获取天气信息后再返回给用户。
{
"name": "get_weather",
"parameters": {
"location": "巴黎"
}
}
主流大模型平台,例如 OpenAI 和 Anthropic,都支持函数调用。然而,不同的平台实现方式略有差异,导致开发者需要针对不同的平台编写不同的代码,增加了开发和维护成本。以下展示了 OpenAI 和 Anthropic 对相似功能的函数调用实现差异:
OpenAI (Python)
from openai import OpenAI
import json
client = OpenAI()
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定坐标的当前温度 (摄氏度).",
"parameters": {
"type": "object",
"properties": {
"latitude": {"type": "number"},
"longitude": {"type": "number"}
},
"required": ["latitude", "longitude"],
"additionalProperties": False
},
"strict": True
}}]
messages = [{"role": "user", "content": "巴黎今天的天气怎么样?"}]
completion = client.chat.completions.create(
model="gpt-4.1",
messages=messages,
tools=tools,
)
Anthropic (Python)
import anthropic
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-opus-4-20250514",
max_tokens=1024,
tools=[
{
"name": "get_weather",
"description": "获取指定地点的当前天气",
"input_schema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "城市和州,例如 San Francisco, CA"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "温度单位,摄氏度或华氏度"
}
},
"required": ["location"]
}
}
],
messages=[{"role": "user", "content": "旧金山的天气怎么样?"}])
print(response)
可以看到,即使是实现类似的天气查询功能,OpenAI 和 Anthropic 在参数定义、数据类型、以及请求结构上都存在差异。这种差异性增加了跨平台开发的难度。
尽管函数调用实现简单,但它存在一些明显的局限性。最主要的问题是耦合性高。大模型应用代码与特定的工具或函数实现紧密耦合,任何一方的变动都可能影响另一方。例如,如果天气 API 的参数格式发生变化,就需要修改大模型应用代码,增加了维护成本。此外,函数调用还存在厂商锁定的问题,开发者被迫依赖特定的大模型平台,限制了灵活性和可移植性。
模型上下文协议(MCP):灵活可扩展的工具生态系统
为了解决函数调用的局限性,Anthropic 提出了模型上下文协议(MCP)。MCP 是一种开放标准,旨在提供一种更动态、更可扩展的方式来集成大模型与外部工具和数据源。
可以将 MCP 想象成 AI 应用的 USB-C 接口。正如 USB-C 提供了一种标准化的方式将设备连接到各种外设和配件一样,MCP 提供了一种标准化的方式将 AI 模型连接到不同的数据源和工具。
与需要硬编码函数列表的传统函数调用不同,MCP 允许大模型在运行时动态发现可用的工具。MCP 本身只标准化了工具的暴露方式,不涉及工具的执行方式。每个大模型提供商仍然需要实现自己的工具调用机制,这意味着跨平台的执行语义可能存在差异。
MCP 采用客户端-服务器架构,旨在实现模块化和可扩展性。在这个模型中,宿主应用程序(例如 Claude Desktop、IDE 或其他 AI 工具)充当 MCP 宿主并运行 MCP 客户端。该客户端连接到一个或多个轻量级 MCP 服务器,每个服务器通过标准化协议公开特定的能力(例如访问文件、查询数据库或连接到远程 API)。
开发者创建 MCP 服务器,以标准化工具、数据甚至预构建提示的暴露方式。这些服务器提供了一个统一的接口,目前支持两种通信协议:
- 通过标准输入/输出 (stdio) 进行本地交互
- 基于网络的 HTTP 流传输(注意:这已取代了已弃用的基于服务器发送事件的传输)
MCP 的通用架构图如下:
[图片] MCP General Architecture Diagram. Source: https://modelcontextprotocol.io/introduction
这种架构显著提高了模块化和可维护性。工具和数据源可以独立于客户端应用程序发展,这意味着开发者不再需要重新部署整个系统来适应细微的更改。在工具频繁更改且快速扩展的企业环境中,这一点尤其重要。
此外,MCP 的开放规范也在不断发展。即将推出的增强功能,例如用于服务器发现的集中式 MCP 注册表、对多模态和流式交互的支持、代理图功能和合规性测试套件,旨在使该协议更具动态性、互操作性和生产就绪性。
自推出以来,MCP 已在 AI 生态系统中得到越来越多的采用。OpenAI 在 2025 年 3 月将其集成到 Agents SDK 中,Google 也在其 Agent Development Kit 中支持 MCP。这种跨供应商支持使 MCP 不仅仅是 Anthropic 的一项提议,而是成为跨主要 LLM 平台的工具互操作性的新兴标准。
与函数调用相比,MCP 具有以下优势:
- 动态发现: 大模型可以在运行时发现可用的工具,无需预先定义。
- 标准化接口: 统一的接口降低了集成和维护成本。
- 模块化架构: 工具和数据源可以独立于大模型应用进行更新和升级。
- 可扩展性: 支持多种通信协议,可以灵活地适应不同的任务和环境。
- 集中化管理: 通过 MCP 注册表可以集中管理和发现工具。
函数调用 VS MCP:如何选择?
在函数调用和 MCP 之间进行选择时,需要考虑应用程序的具体需求。MCP 解决了标准化不足、动态发现和集中治理等问题,因此很容易被认为是优于传统工具调用的。但在实践中,这种选择并非纯粹的技术性选择。它更多地反映了简单性与复杂性、灵活性与开销之间的权衡。
如果开发的是一个简单的聊天机器人或一个工具集有限的移动应用程序,那么函数调用可能就足够了。另一方面,当复杂性扩大时,MCP 就变得更加优越。如果在场景中拥有许多工具、频繁更新、多个代理或严格的治理和合规性需求,那么该协议的动态特性和集中控制机制很容易证明增加的复杂性是合理的。
以下是一些建议:
- 简单应用: 如果应用场景简单,只需要少量工具,且工具接口稳定,可以选择函数调用。例如,一个简单的天气查询机器人可以使用函数调用来集成天气 API。
- 复杂应用: 如果应用场景复杂,需要集成大量工具,且工具接口频繁变化,或者需要跨多个大模型平台使用工具,建议选择 MCP。例如,一个智能助手需要集成多个 API(天气、日历、地图等),并支持不同的用户身份验证方式,可以使用 MCP 来实现灵活的工具管理和调用。
- 混合应用: 在许多情况下,混合方法可能是合适的。从函数调用开始来实现基本功能,并随着应用程序的复杂性和需求的增长逐渐过渡到 MCP。
例如,可以先用函数调用实现一个简单的客户服务聊天机器人,能够回答一些常见问题。然后,随着业务的增长,可以逐渐引入 MCP 来集成更多的工具,例如知识库查询、订单管理、支付接口等,从而扩展机器人的功能。
实际案例分析
为了更好地理解函数调用和 MCP 的应用场景,我们来看两个实际案例:
案例 1:智能家居控制系统
假设我们正在开发一个智能家居控制系统,用户可以通过语音指令控制家里的灯光、温度和电器。
- 函数调用: 可以使用函数调用来集成各个智能设备的 API。例如,当用户说“打开客厅的灯”时,大模型会调用
turn_on_light
函数,并将“客厅”作为参数传递给灯光控制 API。这种方法实现简单,适用于设备数量较少、API 接口稳定的场景。 - MCP: 可以使用 MCP 来管理和调用各种智能设备的 API。每个设备都可以通过 MCP 服务器暴露其功能,大模型可以通过 MCP 客户端动态发现和调用这些功能。这种方法适用于设备数量较多、API 接口频繁变化的场景。例如,当新增一个智能设备时,只需要创建一个 MCP 服务器来暴露其功能,大模型就可以自动发现并使用该设备。
案例 2:企业级知识管理系统
假设我们正在开发一个企业级知识管理系统,用户可以通过自然语言查询企业内部的文档、数据和知识。
- 函数调用: 可以使用函数调用来集成各种数据源的 API。例如,当用户查询“最近发布的关于人工智能的报告”时,大模型会调用
search_documents
函数,并将“人工智能”作为关键词传递给文档搜索 API。这种方法适用于数据源数量较少、API 接口稳定的场景。 - MCP: 可以使用 MCP 来统一管理和访问各种数据源。每个数据源都可以通过 MCP 服务器暴露其查询接口,大模型可以通过 MCP 客户端动态发现和调用这些接口。这种方法适用于数据源数量较多、数据结构复杂、需要统一权限控制的场景。例如,可以使用 MCP 来集成不同的数据库、文件系统、知识图谱等数据源,并提供统一的查询接口和权限控制机制。
结论
函数调用和 MCP 都是大模型工具使用的有效方法。函数调用简单直接,适用于小型、简单的应用场景。MCP 灵活可扩展,适用于大型、复杂的应用场景。在实际开发中,需要根据具体的需求选择最合适的方案。随着大模型技术的不断发展,MCP 有望成为大模型工具使用的主流范式。
选择正确的方案可以显著提高开发效率、降低维护成本,并提升大模型应用的性能和可扩展性。希望本文能够帮助开发者更好地理解函数调用和 MCP,并在实际应用中做出明智的选择。