最近在学习 AI Agent 相关内容时,遇到了几个高频概念:
- Function Calling
- Tools
- MCP(Model Context Protocol)
刚开始学习的时候,我一直有一个疑问:
大模型为什么可以调用工具?
它是怎么知道有哪些工具?
如果工具越来越多,大模型又怎么准确选择?
带着这些问题,我整理了一下自己的理解。
Function Calling:让 LLM 调用工具
大语言模型(LLM)本身只能处理文本。
例如:
用户:
帮我查询今天北京天气
LLM 本身并不知道实时天气。
因为:
- 它没有访问互联网能力
- 它不知道当前时间的数据
所以需要给 LLM 增加:
Tools(工具)
工具本质就是:
一个可以执行具体功能的函数。
例如:
scss
getWeather(city)
searchWeb(keyword)
queryDatabase(sql)
当用户提出问题时:
用户
↓
LLM
↓
判断自己无法完成
↓
调用工具
↓
获得结果
↓
生成最终回答
这个过程就是:
javascript
Function Calling
Function Calling 存在的问题
虽然 Function Calling 解决了:
LLM 如何调用工具?
但是随着工具越来越多,又出现了新的问题。
问题一:决策瘫痪
假设现在有很多工具:
scss
searchGoogle()
searchWeb()
searchInternet()
querySearch()
它们功能都类似:
搜索互联网
那么:
LLM 应该调用哪一个?
如果工具描述不够清晰:
模型很容易选择错误。
这就是:
决策瘫痪(Decision Paralysis)
问题二:上下文过载
为了让 LLM 知道有哪些工具可用。
我们需要把工具信息传递给模型:
例如:
工具名称
工具描述
参数
返回值
使用方式
如果只有几个工具:
没有问题。
但是如果:
yaml
100个工具
500个工具
1000个工具
这些工具描述都会进入:
Context(上下文)
导致:
- 占用大量 Token
- 减少模型推理空间
- 增加调用成本
最终:
工具越多,模型反而越难判断。
MCP 出现了
为了解决这些问题:
Anthropic 提出了:
MCP
Model Context Protocol
中文:
模型上下文协议
MCP 是什么?
MCP 本质是一套:
LLM 与外部工具交互的标准协议。
它规定:
- 工具如何暴露
- 工具如何发现
- 工具如何调用
- 数据如何传输
简单理解:
以前:
每个 AI 平台
都有自己的工具调用方式
现在:
所有工具
统一遵守 MCP 标准
MCP 的核心架构
MCP 中主要有三个角色:
arduino
MCP Client
MCP Server
Tool
关系:
arduino
用户
↓
MCP Client
↓
LLM
↓
MCP Server
↓
Tool
MCP Client
负责:
- 与 LLM 通信
- 管理工具调用流程
例如:
- Claude Desktop
- Cursor
- Trae
MCP Server
负责:
- 管理工具
- 暴露工具能力
例如:
一个 MCP Server 可以提供:
天气查询工具
数据库查询工具
文件读取工具
Tool
真正执行任务的函数。
例如:
scss
getWeather()
真正执行:
查询天气 API
MCP 提供了哪些能力?
MCP 主要解决三个问题。
1. 工具搜索(Tool Discovery)
MCP Client 可以向 MCP Server 请求:
有哪些工具?
MCP Server 返回:
css
[ { name:"getWeather", description:"查询天气", parameters:{} }]
LLM 就知道:
当前有哪些能力。
2. 程序化工具调用
LLM 不直接执行函数。
流程:
arduino
LLM
↓
MCP Client
↓
MCP Server
↓
Tool
MCP Server 负责真正调用工具。
3. 工具使用示例
除了告诉模型:
工具叫什么
还可以告诉模型:
什么时候使用
参数怎么传
返回什么格式
提高模型选择工具的准确率。
一个 MCP 请求流程
例如:
用户在 Trae 中输入:
帮我查询上海天气
流程:
arduino
用户
↓
Trae(MCP Client)
↓
LLM
↓
LLM 判断需要天气工具
↓
Trae 请求 MCP Server
↓
调用 weather Tool
↓
返回天气数据
↓
发送给 LLM
↓
LLM 生成答案
↓
展示用户
LLM 如何知道有哪些工具?
这是 MCP 最核心的问题。
答案:
arduino
MCP Client 主动向 MCP Server 获取工具列表。
流程:
第一步:
MCP Client 启动。
↓
第二步:
请求 MCP Server:
scss
list_tools()
↓
第三步:
MCP Server 返回:
工具名称
工具描述
参数 Schema
↓
第四步:
MCP Client 将这些工具信息配置到 LLM 的:
tools 参数
LLM 如何知道应该调用哪个工具?
LLM 并不是直接认识工具。
它依赖:
工具名称
工具描述
参数定义
例如:
工具:
getWeather
描述:
查询指定城市实时天气
用户:
北京今天温度多少?
LLM 推理:
用户需要天气信息
↓
getWeather 描述匹配
↓
返回调用请求
所以:
工具描述质量非常重要。
MCP 调用过程中的递归执行
实际 Agent 中:
一次任务可能需要多轮调用。
例如:
用户:
帮我分析最近销售数据
可能需要:
- 查询数据库
- 计算数据
- 生成报告
流程:
arduino
用户请求
↓
LLM
↓
需要数据库工具
↓
调用 MCP Server
↓
返回数据
↓
继续发送给 LLM
↓
LLM 判断下一步
↓
继续调用工具
↓
最终回答
这个过程会不断:
messages追加
↓
LLM重新推理
↓
工具调用
↓
messages合并
直到得到最终答案。
如何开发一个 MCP Server?
一个简单 MCP 服务开发流程:
第一步:安装 SDK
css
pnpm i @modelcontextprotocol/sdk zod
其中:
@modelcontextprotocol/sdk
MCP 官方开发 SDK。
zod
用于:
javascript
定义参数类型
↓
自动生成 JSON Schema
例如:
csharp
z.object({
city:z.string()
})
自动转换:
css
{
city:{
type:"string"
}
}
让 LLM 理解工具参数。
第二步:创建 MCP Server
创建一个服务:
arduino
MCP Server
作为工具管理中心。
第三步:注册 Tool
例如:
注册天气工具:
getWeather
包含:
- 名称
- 描述
- 参数
- 执行逻辑
第四步:启动 MCP Server
让 Client 可以连接。
例如:
css
Trae
Cursor
Claude Desktop
第五步:开发 MCP Client 测试
测试:
- 是否可以获取工具列表
- 是否可以调用工具
- 是否正确返回结果
面试回答:什么是 MCP?
如果面试官问:
MCP 是什么?
可以回答:
arduino
MCP 是 Model Context Protocol,
是一套标准化协议,用于统一 LLM 与外部工具、数据源、系统之间的交互方式。
它解决了传统 Function Calling 中工具管理困难的问题,
通过 MCP Server 暴露工具,让 MCP Client 获取工具定义并提供给 LLM,
最终实现模型对工具的发现和调用。
面试回答:MCP 有什么作用?
markdown
主要有三个作用:
1. 标准化工具调用方式
2. 让 LLM 可以动态发现工具
3. 提高工具选择和调用准确率,减少上下文占用
面试回答:你开发过 MCP 吗?怎么实现?
arduino
开发 MCP Server 时:
首先安装 @modelcontextprotocol/sdk 和 zod。
然后创建 MCP Server 实例。
接着通过 Server 注册 Tool,
使用 zod 定义工具参数,
自动生成 JSON Schema。
启动 MCP Server 后,
开发 MCP Client 获取工具列表并测试调用。
整个流程就是:
Client 获取 Tool 信息,
LLM 根据描述选择工具,
Client 调用 MCP Server,
Server 执行 Tool,
结果返回给 LLM。
总结
一句话理解:
javascript
Function Calling:
让 LLM 能调用工具。
MCP:
让 LLM 可以标准化、高效、准确地管理和调用大量工具。
未来 AI Agent 的核心能力:
不是单纯让模型变聪明。
而是:
diff
LLM
+
Tools
+
MCP
+
Agent Workflow
共同组成真正能够完成复杂任务的智能系统。