-
原生Function Calling: 就像你买了一辆原厂自带“车载导航”和“蓝牙音乐”功能的品牌车(比如特斯拉)。这些功能是车厂(OpenAI/Google)预装好的,你只需要在车机屏幕上按一下,告诉它“导航到公司”或“播放音乐”,车子自己就知道怎么做了。你是一个“司机”。
-
自建MCP服务: 就像你是一个专业的“汽车改装厂”。你买来一个强大的裸引擎(大模型),然后你自己设计并安装了一整套复杂的车载系统(MCP服务)。这套系统里,你自己造了导航模块(数据库查询服务)、娱乐模块(邮件发送服务),并且用一套自己定义的总线协议(MCP协议)把它们连接起来。引擎(大模型)只负责根据你的指令输出“该导航了”或“该放音乐了”,而具体怎么做,都是由你的改装系统完成的。你是一个“汽车工程师”+“司机”。
| 对比维度 | 原生Function Calling (开车) | 自建MCP服务 (造车) |
|---|---|---|
| 控制权 | 低。 你只能使用模型厂商提供的工具调用框架和协议。 | 极高。 从协议、安全、到工具的实现,一切都由你定义和控制。 |
| 安全性 | 依赖模型厂商。 数据是否会离开你的环境,取决于厂商的策略。 | 自主可控。 你可以设计让所有敏感数据和工具执行都留在你的私有网络内。 |
| 灵活性 | 中等。 可以在厂商的框架内定义工具,但受限于其能力。 | 极高。 可以集成任何系统(本地、云端、老旧系统),实现任意复杂的逻辑。 |
| 复杂性 | 低。 只需要调用一个API,并处理其返回的工具调用请求即可。 | 高。 需要搭建一整套后端服务,包括API网关、服务发现、安全认证等。 |
| 核心逻辑 | 模型驱动。 模型直接决定调用哪个工具和传入什么参数。 | 服务驱动,模型辅助。 模型更像一个“意图翻译器”,将自然语言翻译成服务指令,真正的执行和调度由你的MCP服务完成。 |
一句话总结二者关系:
自建MCP服务通常会“包含”Function Calling作为其内部的一个环节。 你的MCP Server接收到用户请求后,会利用大模型的Function Calling能力来“解析意图”,然后MCP Server再根据解析出的意图去执行真正的操作。
实现方案:一步步教你怎么做
方案一:原生Function Calling的实现 (简单直接)
这种方案适用于快速开发、对数据安全要求不是最高、或者工具逻辑比较简单的场景。
事件流程图/时序图:

sequenceDiagram
participant User as 用户
participant App as 你的应用 (前端/后端)
participant LLM_API as 大模型API (如OpenAI)
User->>App: "查一下北京今天的天气"
App->>LLM_API: 发送请求(prompt="查天气", tools=[{name:"get_weather", ...}])
LLM_API-->>App: 返回指令(tool_calls=[{name:"get_weather", args:{"city":"北京"}}])
App->>App: 在本地执行 get_weather("北京") 函数
Note right of App: 调用一个外部天气API
App->>LLM_API: 再次发送请求(附上工具执行结果: "北京天气晴朗,25度")
LLM_API-->>App: 返回最终答案("北京今天天气晴朗,气温25度。")
App->>User: 显示最终答案
实现步骤:
- 定义工具: 在你的代码里,按照OpenAI(或其他模型提供商)的格式,用JSON Schema定义一个或多个工具。
tools = [ { "type": "function", "function": { "name": "get_weather", "description": "获取一个城市的天气信息", "parameters": { "type": "object", "properties": { "city": {"type": "string", "description": "城市名称"}, }, "required": ["city"], }, }, } ] - 首次调用API: 将用户的prompt和定义好的
tools一起发送给大模型API。response = client.chat.completions.create( model="gpt-4-turbo", messages=[{"role": "user", "content": "查一下北京今天的天气"}], tools=tools, tool_choice="auto", ) - 解析并执行工具: 检查API的返回。如果包含
tool_calls,就说明模型决定调用工具了。你在本地代码里执行这个函数。# response_message.tool_calls[0].function.name 会是 "get_weather" # response_message.tool_calls[0].function.arguments 会是 '{"city": "北京"}' # 你的本地函数 def get_weather(city): # ... 调用真实的天气API ... return f"{city}天气晴朗,25度。" tool_result = get_weather("北京") - 二次调用API: 将工具的执行结果再次发回给API,让模型根据结果生成最终的自然语言回答。
方案二:自建MCP服务的实现 (专业强大)
这种方案适用于企业级应用,对安全、稳定、可控性要求高的场景。
事件流程图/时序图:

sequenceDiagram
participant User as 用户
participant MCP_Host as MCP主机 (IDE/桌面应用)
participant MCP_Client as MCP客户端 (代理)
participant MCP_Server as MCP服务器 (你的核心服务)
participant LLM_API as 大模型API
participant Local_Data as 内部数据库
User->>MCP_Host: "查上周A产品的销售额"
MCP_Host->>MCP_Client: 发送请求(含用户身份)
MCP_Client->>MCP_Server: 按MCP协议发送请求
Note over MCP_Server, LLM_API: MCP服务器开始处理
MCP_Server->>LLM_API: 调用FC (prompt="...", tools=[{name:"query_sales",...}])
LLM_API-->>MCP_Server: 返回指令(tool_calls=[{name:"query_sales", args:{...}}])
Note over MCP_Server, Local_Data: MCP服务器执行工具
MCP_Server->>Local_Data: 执行安全的SQL查询
Local_Data-->>MCP_Server: 返回结果(500000)
MCP_Server->>LLM_API: 二次调用(附上结果)
LLM_API-->>MCP_Server: 返回最终答案("销售额为50万元...")
MCP_Server->>MCP_Client: 返回答案
MCP_Client->>MCP_Host: 返回答案
MCP_Host->>User: 显示最终答案
实现步骤:
-
搭建MCP Server (核心!):
- 使用FastAPI、Flask或Django等Python框架创建一个后端服务。
- 创建一个API端点,比如
/api/v1/chat,它接收来自MCP Client的请求。 - 在这个端点内部,实现上面“方案一”的完整逻辑。也就是说,Function Calling在这里只是
MCP Server的一个内部步骤。
-
在MCP Server中定义和实现工具:
- 定义部分(JSON Schema): 和方案一一样,这部分是要给大模型看的。
- 实现部分(Python函数): 这里的函数不再是简单的本地调用,而是连接公司内部系统的“重武器”。
# 在你的 FastAPI 服务中 def query_sales(product_name, region): # 1. 权限校验:检查当前用户是否有权限查询 # check_permission(user_context) # 2. 安全地连接内部数据库 db_connection = connect_to_internal_db() # 3. 执行SQL查询 result = db_connection.execute(...) return result
-
实现MCP Client和Host (可选,但推荐):
- Client: 可以是一个轻量级的代理程序,负责安全地将
Host的请求转发到Server。它处理认证、加密、保持长连接等。 - Host: 你的前端应用,比如一个VS Code插件或一个桌面客户端。它只负责UI和与
Client的简单交互。
- Client: 可以是一个轻量级的代理程序,负责安全地将
总结一下两种方案的选择:
- 想快速验证一个想法,做一个小工具?用方案一 (原生Function Calling)。
- 想构建一个给企业用的、需要连接内部数据、对安全和权限有严格要求的正式产品?必须用方案二 (自建MCP服务)。
8786

被折叠的 条评论
为什么被折叠?



