
🎁个人主页:我滴老baby
🎉欢迎大家点赞👍评论📝收藏⭐文章
🔍系列专栏:AI


文章目录:
- [工具调用全景解析:从Function Calling到MCP协议,让智能体真正动手干活的完整实践](#工具调用全景解析:从Function Calling到MCP协议,让智能体真正动手干活的完整实践)
-
- [一、Tool Use:Agent的核心能力](#一、Tool Use:Agent的核心能力)
- [二、Function Calling详解](#二、Function Calling详解)
-
- [2.1 原理](#2.1 原理)
- [2.2 完整实现](#2.2 完整实现)
- 三、并行工具调用
- 四、自定义工具最佳实践
-
- [4.1 工具设计原则](#4.1 工具设计原则)
- [4.2 工具质量评分表](#4.2 工具质量评分表)
- 在这里插入图片描述
- [五、从Function Calling到MCP协议](#五、从Function Calling到MCP协议)
-
- [5.1 MCP(Model Context Protocol)简介](#5.1 MCP(Model Context Protocol)简介)
- [5.2 MCP vs Function Calling](#5.2 MCP vs Function Calling)
- [5.3 创建MCP工具服务器](#5.3 创建MCP工具服务器)
- 六、工具安全性深度防护
-
- [6.1 常见安全威胁](#6.1 常见安全威胁)
- [6.2 安全工具包装器](#6.2 安全工具包装器)
- 总结
工具调用全景解析:从Function Calling到MCP协议,让智能体真正动手干活的完整实践
不会用工具的AI只是个聊天机器人。本文全面解析Agent工具调用的技术演进与实践。

一、Tool Use:Agent的核心能力
AI Agent之所以从"聊天机器人"进化为"智能体",关键在于能够使用工具。Tool Use让Agent从被动回答变为主动执行。
Agent工具使用能力演进
| 阶段 | 时间 | 特点 | 代表 |
|---|---|---|---|
| 纯文本生成 | 2022前 | 只能生成文本建议 | GPT-3 |
| 插件系统 | 2023初 | 预定义的插件接口 | ChatGPT Plugins |
| Function Calling | 2023中 | 结构化函数调用 | GPT-4 |
| 多模态工具 | 2024 | 图片/音频/视频处理 | GPT-4V |
| MCP协议 | 2025+ | 标准化工具接口 | Claude MCP |

二、Function Calling详解
2.1 原理
Function Calling的工作流程:
1. 开发者定义工具描述(JSON Schema)
2. 将工具描述和用户消息一起发送给LLM
3. LLM判断是否需要调用工具
4. 如果需要,返回工具名和参数(JSON格式)
5. 开发者执行工具,将结果返回给LLM
6. LLM基于工具结果生成最终回答
2.2 完整实现
python
# tool_use/function_calling.py
import json
from openai import OpenAI
client = OpenAI(api_key="your-api-key")
# ===== 步骤1:定义工具 =====
tools = [
{
"type": "function",
"function": {
"name": "get_stock_price",
"description": "获取指定股票的实时价格信息",
"parameters": {
"type": "object",
"properties": {
"symbol": {
"type": "string",
"description": "股票代码,如 AAPL, TSLA, 600519"
},
"include_history": {
"type": "boolean",
"description": "是否包含历史数据",
"default": False
}
},
"required": ["symbol"]
}
}
},
{
"type": "function",
"function": {
"name": "calculate_portfolio",
"description": "计算投资组合的预期收益率和风险指标",
"parameters": {
"type": "object",
"properties": {
"holdings": {
"type": "array",
"items": {
"type": "object",
"properties": {
"symbol": {"type": "string"},
"weight": {"type": "number",
"description": "权重(0-1)"}
}
},
"description": "持仓列表"
},
"risk_free_rate": {
"type": "number",
"description": "无风险利率",
"default": 0.03
}
},
"required": ["holdings"]
}
}
},
{
"type": "function",
"function": {
"name": "send_notification",
"description": "向用户发送通知消息",
"parameters": {
"type": "object",
"properties": {
"message": {"type": "string", "description": "通知内容"},
"priority": {
"type": "string",
"enum": ["low", "medium", "high"],
"description": "优先级"
}
},
"required": ["message"]
}
}
}
]
# ===== 步骤2:工具实现 =====
def get_stock_price(symbol: str, include_history: bool = False) -> str:
# 模拟数据
stocks = {
"AAPL": {"price": 198.50, "change": "+2.3%", "volume": "52M"},
"TSLA": {"price": 245.20, "change": "-1.1%", "volume": "89M"},
"600519": {"price": 1680.00, "change": "+0.8%", "volume": "12M"},
}
data = stocks.get(symbol, {"error": f"未找到股票 {symbol}"})
return json.dumps(data, ensure_ascii=False)
def calculate_portfolio(holdings: list, risk_free_rate: float = 0.03) -> str:
# 模拟计算
expected_return = sum(h["weight"] * 0.12 for h in holdings)
risk = sum(h["weight"] ** 2 * 0.25 for h in holdings) ** 0.5
sharpe = (expected_return - risk_free_rate) / risk if risk > 0 else 0
return json.dumps({
"expected_return": f"{expected_return*100:.1f}%",
"volatility": f"{risk*100:.1f}%",
"sharpe_ratio": round(sharpe, 2)
}, ensure_ascii=False)
def send_notification(message: str, priority: str = "medium") -> str:
return json.dumps({
"status": "sent",
"message": message,
"priority": priority,
"timestamp": "2026-04-26 15:00:00"
})
tool_map = {
"get_stock_price": get_stock_price,
"calculate_portfolio": calculate_portfolio,
"send_notification": send_notification
}
# ===== 步骤3:Agent主循环 =====
def agent_chat(user_message: str) -> str:
messages = [
{"role": "system", "content": "你是一个专业的投资顾问AI助手。"},
{"role": "user", "content": user_message}
]
# 第一次调用:LLM决定是否需要工具
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)
message = response.choices[0].message
# 如果不需要工具,直接返回
if not message.tool_calls:
return message.content
# 执行工具调用
messages.append(message)
for tool_call in message.tool_calls:
func_name = tool_call.function.name
func_args = json.loads(tool_call.function.arguments)
print(f"🔧 调用: {func_name}({func_args})")
result = tool_map[func_name](**func_args)
print(f"📤 结果: {result}")
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
})
# 第二次调用:LLM基于工具结果生成回答
final_response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
return final_response.choices[0].message.content
# 运行
print(agent_chat("帮我看看苹果和特斯拉的股价,然后分析如果我50%持有苹果、50%特斯拉的组合表现如何"))

三、并行工具调用
python
# tool_use/parallel_calls.py
def agent_chat_parallel(user_message: str) -> str:
"""支持并行工具调用的Agent"""
messages = [
{"role": "system", "content": "你是投资顾问AI。"},
{"role": "user", "content": user_message}
]
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto",
parallel_tool_calls=True # 启用并行调用
)
message = response.choices[0].message
if message.tool_calls:
messages.append(message)
# 并行执行所有工具调用
import concurrent.futures
def execute_tool(tc):
func_name = tc.function.name
func_args = json.loads(tc.function.arguments)
result = tool_map[func_name](**func_args)
return {
"tool_call_id": tc.id,
"result": result,
"func_name": func_name
}
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = [executor.submit(execute_tool, tc)
for tc in message.tool_calls]
for future in concurrent.futures.as_completed(futures):
tool_result = future.result()
messages.append({
"role": "tool",
"tool_call_id": tool_result["tool_call_id"],
"content": tool_result["result"]
})
final_response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
return final_response.choices[0].message.content
四、自定义工具最佳实践
4.1 工具设计原则
| 原则 | 说明 | 示例 |
|---|---|---|
| 单一职责 | 每个工具只做一件事 | search_web 而非 search_and_summarize |
| 描述精确 | 让LLM准确理解工具用途 | 详细的description和参数说明 |
| 错误友好 | 返回有用的错误信息 | "未找到股票AAPL"而非"Error" |
| 幂等性 | 相同输入返回相同结果 | GET请求应可重复调用 |
| 安全边界 | 限制危险操作 | 数据库工具禁止DROP操作 |
4.2 工具质量评分表
python
# tool_use/tool_quality.py
class ToolQualityChecker:
"""评估工具定义的质量"""
@staticmethod
def check(tool_definition: dict) -> dict:
issues = []
score = 100
func = tool_definition["function"]
# 检查描述
desc = func.get("description", "")
if len(desc) < 20:
issues.append("描述太短,LLM可能无法准确理解")
score -= 20
if len(desc) > 300:
issues.append("描述过长,可能影响token效率")
score -= 10
# 检查参数
params = func.get("parameters", {}).get("properties", {})
for pname, pdef in params.items():
if "description" not in pdef:
issues.append(f"参数 '{pname}' 缺少描述")
score -= 15
# 检查必要性
if not func.get("parameters", {}).get("required"):
issues.append("未定义required参数列表")
score -= 10
return {
"score": max(0, score),
"issues": issues,
"quality": "优秀" if score >= 80 else "良好" if score >= 60 else "需改进"
}
五、从Function Calling到MCP协议
5.1 MCP(Model Context Protocol)简介
MCP是Anthropic提出的开放标准协议,旨在统一AI模型与外部工具/数据源的交互方式。
5.2 MCP vs Function Calling
| 特性 | Function Calling | MCP |
|---|---|---|
| 标准化 | 各厂商自定义 | 开放标准协议 |
| 工具发现 | 手动定义 | 自动发现 |
| 跨模型 | 不通用 | 统一接口 |
| 安全性 | 依赖开发者 | 内置权限模型 |
| 生态 | 封闭 | 开源社区 |
5.3 创建MCP工具服务器
python
# tool_use/mcp_server.py
from mcp.server import Server
from mcp.types import Tool, TextContent
app = Server("financial-tools")
@app.list_tools()
async def list_tools():
return [
Tool(
name="get_stock_price",
description="获取股票实时价格",
inputSchema={
"type": "object",
"properties": {
"symbol": {"type": "string", "description": "股票代码"}
},
"required": ["symbol"]
}
)
]
@app.call_tool()
async def call_tool(name, arguments):
if name == "get_stock_price":
symbol = arguments["symbol"]
price_data = get_stock_price(symbol)
return [TextContent(type="text", text=price_data)]
# 启动服务器
if __name__ == "__main__":
import asyncio
asyncio.run(app.run())

六、工具安全性深度防护
6.1 常见安全威胁
| 威胁 | 攻击方式 | 防御措施 |
|---|---|---|
| Prompt注入 | 在用户输入中嵌入恶意指令 | 输入验证、角色分离 |
| 工具滥用 | 诱导Agent调用危险工具 | 权限分级、确认机制 |
| 数据泄露 | 通过工具调用泄露敏感信息 | 输出过滤、访问控制 |
| 拒绝服务 | 大量无意义工具调用 | 频率限制、预算控制 |
6.2 安全工具包装器
python
# tool_use/secure_tool.py
class SecureToolWrapper:
"""安全工具包装器"""
def __init__(self, tool_func, max_calls=10, timeout=30):
self.tool_func = tool_func
self.max_calls = max_calls
self.timeout = timeout
self.call_count = 0
def __call__(self, **kwargs):
# 频率检查
if self.call_count >= self.max_calls:
raise PermissionError(f"工具调用次数超过限制({self.max_calls})")
# 输入验证
for key, value in kwargs.items():
if isinstance(value, str) and len(value) > 10000:
raise ValueError(f"参数 {key} 过长")
self.call_count += 1
return self.tool_func(**kwargs)
总结
Tool Use是Agent从"聊天"到"执行"的关键跨越:
- Function Calling是目前最成熟的工具调用方式
- 并行调用可以显著提升多工具场景的效率
- MCP协议代表着工具调用的未来方向------标准化和互操作
- 安全性 不容忽视------任何工具都应该有防护措施


