Function Calling是LLM调用工具的基础能力MCP是工具生态标准化的新尝试。两者不是竞争关系而是不同层次的解决方案。本文深度解析二者的本质区别、适用场景与架构选型。一、Function Calling的本质Function Calling也称Tool Use是2023年OpenAI引入的能力本质上是让LLM输出结构化的调用指令再由外部程序执行。用户: 帮我查下明天北京的天气 ↓LLM判断需要调用工具输出:{ tool: get_weather, parameters: { city: 北京, date: 2026-05-12 }} ↓应用层执行工具调用 → 获取真实天气数据 ↓将结果传回LLM → LLM生成最终回复关键理解LLM本身不执行任何代码它只是宣布打算调用什么真正的执行权在应用层。### 1.1 Function Calling的实现pythonfrom openai import OpenAIimport jsonclient OpenAI()# 定义工具tools [ { type: function, function: { name: get_weather, description: 获取指定城市和日期的天气信息, parameters: { type: object, properties: { city: { type: string, description: 城市名称如北京、上海 }, date: { type: string, description: 日期格式YYYY-MM-DD }, unit: { type: string, enum: [celsius, fahrenheit], description: 温度单位 } }, required: [city, date] } } }, { type: function, function: { name: send_notification, description: 发送通知消息, parameters: { type: object, properties: { recipient: {type: string}, message: {type: string}, channel: { type: string, enum: [email, slack, sms] } }, required: [recipient, message, channel] } } }]def run_tool(tool_name: str, tool_args: dict) - str: 工具执行层 if tool_name get_weather: # 实际调用天气API return json.dumps({ city: tool_args[city], date: tool_args[date], temperature: 22, condition: 晴天, humidity: 45 }, ensure_asciiFalse) elif tool_name send_notification: # 实际发送通知 return json.dumps({status: sent, message_id: msg_12345}) return json.dumps({error: Unknown tool})def agent_loop(user_message: str) - str: 基础Agent循环 messages [{role: user, content: user_message}] while True: response client.chat.completions.create( modelgpt-4o, messagesmessages, toolstools, tool_choiceauto ) message response.choices[0].message messages.append(message.model_dump()) # 没有工具调用直接返回 if not message.tool_calls: return message.content # 执行所有工具调用 for tool_call in message.tool_calls: tool_name tool_call.function.name tool_args json.loads(tool_call.function.arguments) print(f[调用工具] {tool_name}({tool_args})) result run_tool(tool_name, tool_args) messages.append({ role: tool, tool_call_id: tool_call.id, content: result })## 二、MCPModel Context Protocol的本质MCP是Anthropic在2024年底提出并开源的协议解决的是一个不同层次的问题工具生态的标准化与互操作性。### 2.1 MCP解决了什么Function Calling的痛点- 每个应用都要自己实现工具层天气API、数据库、文件系统…- 工具实现无法复用——A公司写的GitHub工具B公司无法直接用- 工具与应用强耦合迁移成本高MCP的解决思路定义一套标准协议让工具服务器MCP Server与AI应用MCP Client解耦。传统架构AI应用 ────────────── 直接调用 ──────────── 各种API/工具MCP架构AI应用MCP Client ↕ 标准MCP协议MCP Server工具实现 ↕ 实际服务GitHub/DB/FileSystem...### 2.2 MCP核心概念三种原语1. Tools工具可执行的函数等同于Function Calling2. Resources资源可读取的数据源文件、数据库记录、API响应3. Prompts提示模板预定义的提示词模板可参数化两种传输方式1. stdio本地进程间通信适合本地工具2. SSE/HTTP网络通信适合远程服务### 2.3 构建一个MCP Serverpython# 使用官方Python MCP SDKfrom mcp.server.fastmcp import FastMCPfrom mcp.types import TextContent# 创建MCP服务器mcp FastMCP(company-tools)mcp.tool()async def search_employee_database( name: str None, department: str None, employee_id: str None) - str: 搜索员工数据库 Args: name: 员工姓名支持模糊搜索 department: 部门名称 employee_id: 员工工号 Returns: 符合条件的员工信息JSON字符串 results db.query( SELECT * FROM employees WHERE (:name IS NULL OR name LIKE :name) AND (:dept IS NULL OR department :dept) AND (:eid IS NULL OR employee_id :eid), namef%{name}% if name else None, deptdepartment, eidemployee_id ) return json.dumps(results, ensure_asciiFalse)mcp.resource(file://{path})async def read_document(path: str) - str: 读取公司内部文档 # 安全检查只允许读取指定目录 allowed_base /company/docs full_path os.path.normpath(os.path.join(allowed_base, path)) if not full_path.startswith(allowed_base): raise PermissionError(Access denied: path traversal detected) with open(full_path, r, encodingutf-8) as f: return f.read()mcp.prompt()def hr_query_prompt(employee_name: str, query_type: str) - str: HR查询提示模板 return f你是一个HR助手。用户想要查询员工「{employee_name}」的{query_type}信息。请使用search_employee_database工具获取信息并以友好的方式回复。注意遵守数据隐私规定不要泄露薪资等敏感信息除非明确授权。# 启动服务器if __name__ __main__: mcp.run(transportstdio) # 本地进程模式 # 或: mcp.run(transportsse, port8080) # HTTP SSE模式### 2.4 在Claude应用中使用MCPpythonimport anthropicimport asynciofrom mcp import ClientSession, StdioServerParametersfrom mcp.client.stdio import stdio_clientasync def chat_with_mcp_tools(user_message: str): # 连接到MCP Server server_params StdioServerParameters( commandpython, args[company_mcp_server.py], env{DATABASE_URL: postgresql://...} ) async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: # 初始化 await session.initialize() # 获取可用工具列表 tools_result await session.list_tools() # 转换为Anthropic工具格式 claude_tools [] for tool in tools_result.tools: claude_tools.append({ name: tool.name, description: tool.description, input_schema: tool.inputSchema }) client anthropic.Anthropic() messages [{role: user, content: user_message}] while True: response client.messages.create( modelclaude-3-5-sonnet-20241022, max_tokens4096, toolsclaude_tools, messagesmessages ) if response.stop_reason end_turn: # 提取文本响应 return next( b.text for b in response.content if b.type text ) # 执行工具调用 messages.append({role: assistant, content: response.content}) tool_results [] for block in response.content: if block.type tool_use: # 通过MCP协议调用工具 result await session.call_tool( block.name, argumentsblock.input ) tool_results.append({ type: tool_result, tool_use_id: block.id, content: result.content[0].text }) messages.append({role: user, content: tool_results})## 三、核心区别对比| 维度 | Function Calling | MCP ||------|-----------------|-----||本质| LLM能力输出结构化工具调用 | 工具互操作协议 ||层次| 模型层 | 应用架构层 ||工具实现| 与应用代码耦合 | 独立Server可复用 ||跨应用复用| ❌ 需要重复实现 | ✅ MCP Server开箱即用 ||跨模型支持| 各厂商API不同 | ✅ 统一协议 ||部署复杂度| 低直接在应用内 | 中需要运行Server进程 ||安全控制| 应用层自己管 | Server端统一权限管理 ||适合场景| 简单工具、快速开发 | 工具多、需复用、多应用共享 |## 四、架构选型指南### 4.1 何时用纯Function Calling✅ 适合场景- 工具数量少10个- 工具与业务逻辑紧密耦合- 快速原型不考虑复用- 工具只在单一应用中使用- 对延迟极度敏感MCP有进程间通信开销典型例子- 客服机器人只调用自己公司的CRM、工单系统- 个人助手应用调用用户日历、Todo、邮件- 专项工具代码分析工具工具固定### 4.2 何时引入MCP✅ 适合场景- 工具需要被多个AI应用复用- 工具需要独立部署和版本管理- 企业希望建立工具中台- 工具由不同团队维护- 需要对外开放工具给合作伙伴典型例子- 企业AI平台多个业务线共用同一套工具- AI IDE插件Cursor等复用社区MCP Server- 开放工具生态开发者发布自己的MCP Server供他人使用### 4.3 混合架构pythonclass HybridToolSystem: 混合工具架构简单工具直接调用复杂工具走MCP DIRECT_TOOLS { get_current_time: lambda: datetime.now().isoformat(), calculate: lambda expr: str(eval(expr)), # 简单计算 } MCP_SERVERS { github: {command: npx, args: [modelcontextprotocol/server-github]}, postgres: {command: npx, args: [modelcontextprotocol/server-postgres]}, company-tools: {command: python, args: [company_mcp_server.py]}, } async def execute_tool(self, tool_name: str, tool_args: dict) - str: # 直接工具本地执行零延迟 if tool_name in self.DIRECT_TOOLS: return str(self.DIRECT_TOOLS[tool_name](**tool_args)) # MCP工具通过协议调用 server_name self._find_mcp_server(tool_name) if server_name: return await self._call_mcp_tool(server_name, tool_name, tool_args) raise ValueError(fUnknown tool: {tool_name}) def _find_mcp_server(self, tool_name: str) - Optional[str]: 根据工具名找到对应的MCP Server # 可以通过工具名前缀、注册表等方式路由 tool_server_map { github_: github, db_: postgres, hr_: company-tools, } for prefix, server in tool_server_map.items(): if tool_name.startswith(prefix): return server return None## 五、MCP生态现状2026### 5.1 主流MCP Server官方维护的服务器-modelcontextprotocol/server-github— GitHub操作-modelcontextprotocol/server-postgres— PostgreSQL查询-modelcontextprotocol/server-filesystem— 文件系统访问-modelcontextprotocol/server-brave-search— Brave搜索社区热门服务器- Playwright MCP — 浏览器自动化- Qdrant MCP — 向量数据库操作- Notion MCP — Notion内容管理支持MCP的客户端2026Claude Desktop、Cursor、Zed、VS Code通过扩展、Continue### 5.2 MCP的局限性当前已知问题1. 安全模型尚不完善恶意MCP Server可能读取敏感数据2. 工具发现机制依赖预配置无动态发现3. 跨Server的工具组合没有标准4. 版本管理和向后兼容性尚需完善5. 生产稳定性仍在验证中## 六、总结Function Calling和MCP解决的是不同层次的问题-Function Calling 如何让LLM调用工具能力层-MCP 如何让工具生态标准化和可复用协议层两者是互补关系不是替代关系。成熟的AI应用架构通常是用MCP组织工具用Function Calling触发执行。对于2026年的AI工程师建议1. 掌握Function Calling基础这是所有AI工具调用的根基2. 关注MCP生态企业级工具复用场景下MCP是未来方向3. 不要为了用MCP而用MCP简单场景直接实现即可4. 重点关注安全性无论哪种方案都需要严格的权限控制