从 @Tool 装饰器到 MCP,浅析大模型工具生态与 Function Calling 的底层逻辑

在开发 LLM Agent(大模型智能体)时,我们经常会遇到各种层出不穷的技术名词:Function Calling(函数调用)JSON Schema、LangGraph 中的 @tool 装饰器,以及最近大热的 MCP(Model Context Protocol,模型上下文协议)

初学者很容易陷入迷茫:

“既然我用几行 Python 代码加个 @tool 就能让大模型调用本地函数,为什么行业还在大费周章地推崇 MCP 协议?它们之间到底是什么关系?”

本文将以一个通俗易懂的视角,为你彻底拆解大模型工具生态的底层逻辑、演进过程以及它们在实际生产中的真实协作方式。

一、 核心概念:分清“点菜”与“做菜”

要理清这套生态,首先必须纠正一个常见的误区:@tool 或 MCP 并不等于 Function Calling。

它们处于整个交互流程的不同阶段。我们可以用一个“在餐馆点餐”的经典场景来做类比:

  • 菜单(工具定义 / JSON Schema):告诉客人店里有什么菜,需要什么配料。

  • 点菜(Function Calling):客人(大模型)看完菜单后做出决策,并喊出具体菜名和要求。

  • 后厨做菜(工具执行):服务员把订单传给厨房,厨房真正开火把菜做出来。

有了这个心智模型,我们再来看技术层面的具体定义:

1. 什么是 Function Calling?(大模型的“意图表达”)

大模型(LLM)本身是不能直接运行 Python 代码、也不能直接读写数据库的。当用户输入“帮我查一下明天北京的天气”时,大模型自己无能为力。

Function Calling 的本质是大模型的思考决策过程。 当它发现靠自身无法解决问题时,就会决定“召唤”外部工具。此时,它不执行任何代码,而是输出一段结构化的数据(通常是 JSON),告诉你的外围代码:“我选好工具了,请帮我用这些参数执行它”。

大模型吐出的 Function Calling 结果通常长这样:

JSON

{
  "name": "get_weather",
  "arguments": {
    "location": "北京",
    "date": "明天"
  }
}

2. JSON Schema:大模型看得懂的“说明书”

大模型既然要“做选择题”(选工具)和“填空”(填参数),它总得事先知道有哪些工具可选。JSON Schema 就是大模型唯一能读懂的“工具说明书”。

无论是 LangGraph 的 @tool 还是 MCP 工具,它们在底层都必须被翻译成标准化的 JSON Schema(包含工具名、功能描述、参数类型等)发送给大模型。大模型正是通过阅读说明书里的 description 来判断何时该用这个工具。

二、 本地 @tool vs 跨平台 MCP:单机开发与分布式生态

既然大模型对所有工具的调用最终都表现为 Function Calling,那么 @tool 和 MCP 的区别到底在哪里?区别在于“工具的包装、发布与运行方式”。

1. LangGraph 的 @tool:快捷的本地 App

当你写下如下代码时:

Python

@tool
def get_weather(city: str) -> str:
    """查询指定城市的天气预报。"""
    # 具体的查询逻辑
    return f"{city}明天晴天"

LangGraph 框架会在后台自动提取这个函数的名称、文档注释(Docstring)和参数类型,将其自动转化为 JSON Schema 发送给大模型。

  • 优势:极简。心智负担极低,非常适合单机开发或快速写个 Demo。

  • 劣势强绑定。这个工具被死死地绑在了当前的 Python 环境和 LangGraph 生态里。如果你明天想用 TypeScript 写一个新项目,或者想在另一个框架(如 AutoGen)或 Cursor 等 IDE 里复用这个工具,你就必须用对应的语言和框架把这段逻辑重写一遍。

2. MCP:万维网的 HTTP 协议

MCP(Model Context Protocol)由 Anthropic 提出,它的核心思想是将工具的“定义与运行”从 Agent 框架中完全剥离。

MCP 引入了标准的客户端-服务器(Client-Server)架构。你用任何语言(Python、Go、TypeScript 等)写一个 MCP 服务器,把它发布在网络上(通过 Stdio 或 SSE 传输)。任何支持 MCP 协议的客户端(无论是 LangGraph、LlamaIndex、Cursor 还是 Claude 官方客户端)都能直接插上使用,根本不需要重写代码。

3. 维度对比表

为了让你更直观地看出两者的适用场景,我们可以进行如下对比:

维度 LangGraph @tool MCP (Model Context Protocol)
开发体验 极简。直接写本地函数加个装饰器即可。 稍显繁琐。需要启动并维护一个集成了 MCP 协议的微服务。
跨语言/跨框架 强绑定。通常绑定在特定的语言和生态内。 完全通用。只要客户端和服务器都支持 MCP,技术栈完全无所谓。
安全性与架构 本地运行。工具代码和 Agent 逻辑混在一起,容易互相影响。 隔离运行。工具作为独立微服务运行,可具备独立的沙箱与权限控制。
生态复用 零散。很难直接拿别人写好的代码来用,通常需要复制粘贴。 开箱即用。社区有大量现成的 MCP 服务器(如 GitHub、Postgres),配置一下即可。

三、 工具爆炸的终极挑战:大模型如何动态发现工具?

在简单的 Demo 中,你只有 3 个工具,框架每次都会把这 3 个工具的 JSON Schema 全量塞进系统提示词(System Prompt)里。

但在实际的企业级生产中,你可能会面对成百上千个工具(例如公司内部的所有 API 接口、各种数据库连接器)。如果每次都全量注入,将带来两个灾难性的后果:

  1. Token 成本爆炸:光是工具说明书就会吃掉几万个 Token,每次对话都在无谓地烧钱。

  2. 注意力分散(Context Rot):工具太多,大模型会“挑花眼”,导致工具调用的准确率急剧下降。

为了解决这个问题,现代高级 Agent 系统绝不是把说明书一次性拍在大模型脸上,而是采用了“动态工具发现”的架构策略:

方案 1:工具检索器(Tool RAG)—— 当下的主流

将工具的“找寻”变成一个搜索过程。

  1. 开发人员将成百上千个工具的名称和描述转化为向量嵌入(Vector Embeddings),存入向量数据库。

  2. 用户输入:“帮我查一下昨天财务报表里的利润率。”

  3. 外围的传统代码(无需大模型)先去向量数据库里检索,找出与“财务、报表、利润”最相关的 3-5 个工具。

  4. 框架只把这几个被选中的工具的 JSON Schema 动态注入到当前的提示词中,再交由大模型做最后的 Function Calling 决策。

方案 2:分层/多 Agent 架构(Hierarchical Delegation)

不让一个大模型管所有的事,而是采用“总管 + 专家”的模式。

  • Router Agent(总管):只给它注入高层级的工具分类(如:[财务工具箱]、[日常办公工具箱])。

  • Specialist Agent(专家):当总管判断当前任务属于财务时,将任务指派给财务专家子 Agent。此时,财务专家的提示词里只会注入具体财务相关的 5 个工具

四、 总结:未来的主流架构

回到最初的问题:有了 @tool,我们还需要 MCP 吗?

答案是:它们在未来是共存且融合的。

你不需要在 LangGraph 和 MCP 之间二选一。在未来的复杂企业级 Agent 系统中,你的架构大概率是这样的:

  • 本地特异性工具:对于那些只跟当前项目状态(State)紧密关联、逻辑简单的本地操作,继续用 @tool 定义,图个方便快捷。

  • 企业基础设施与第三方生态:比如公司内部的数据库查询、GitHub 企业版对接、或者复杂的文档解析器,将它们做成 MCP 外部服务。然后让你的 LangGraph 作为 MCP 客户端,通过网络把这些外部工具动态拉进来。

通过将 Function Calling 作为核心大脑决策JSON Schema 作为沟通语言@tool 解决本地敏捷开发MCP 解决跨平台分布式生态,我们才真正拥有了一个可扩展、高可用的生产级 AI Agent 架构。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐