从 Function Calling 到智能自动化工作流的架构实践
你可能已经熟悉大语言模型(LLM)的 Function Calling 功能。它能让 LLM 调用外部工具,极大地扩展了其能力范围。但是,当面对一个需要多个步骤、依赖前后结果、甚至包含条件判断的复杂任务时,单次函数调用是远远不够的。
核心思想: MCP (Model Controlled Program/Process),并非一个新模型或服务器,而是一种架构模式或编程范式。它利用 LLM 的规划和推理能力,结合 Function Calling 机制,像一个“智能项目经理”一样,指挥你的应用程序和后台服务,分步骤、有逻辑地完成复杂工作流。
MCP 模式的实现,关键在于理解其解耦的 Client/Server 架构。这比简单地认为有“协调者”和“执行者”更精确。
@mcp.tool)来“注册”这些函数。/execute),接收指令并安全地执行对应的函数,然后返回结果。Client 与 Server 之间的通信可以是:
stdio (标准输入/输出) 高效通信。MCP 框架的核心魅力在于,开发者只需编写标准的 Python 函数,框架会自动将其“翻译”成大模型能理解的结构化工具定义。这遵循“单一事实来源”原则。
我们只需关注业务逻辑,并使用标准的 Python 文档字符串 (docstring) 来描述函数的**整体功能**。
from some_mcp_framework import tool
@tool
def read_file(path: str, encoding: str = "utf-8") -> str:
"""从文件系统读取一个文件的完整内容。能处理多种编码。"""
try:
with open(path, 'r', encoding=encoding) as f:
return f.read()
except Exception as e:
return f"Error reading file: {e}"
当 Client 请求工具清单时,Server 上的框架会分析上面的函数,并生成类似下面的、大模型真正看到的详细 JSON 结构。框架会智能地提取函数名、文档字符串以及参数的名称、类型和是否必需。
{
"name": "read_file",
"description": "从文件系统读取一个文件的完整内容。能处理多种编码。",
"args_schema": {
"type": "object",
"properties": {
"path": {
"type": "string"
},
"encoding": {
"type": "string",
"default": "utf-8"
}
},
"required": ["path"]
}
}
重要观察: 在许多基础实现中,框架可能不会自动为每个**参数**生成独立的 `description`。因此,将关键信息写在函数的**主 `description`** 中至关重要。更高级的框架可能支持从特定格式的 docstring (如 reStructuredText 或 Google 风格) 中提取参数描述。
我们用一个实例 (“查天气并根据是否下雨创建日历提醒”) 来详细演示这个循环过程。整个过程由 Client 作为“协调者”来驱动。
用户向 Client (你的应用) 输入: "明天北京天气怎么样?如果下雨,帮我在日历上加个提醒带伞。" Client 初始化一个用于记录对话历史的 `messages` 列表。
Client 将用户消息和从 Server 获取的 `tools` 定义一起发送给 LLM API。
LLM API 返回: 指示需要调用 `get_weather` 工具。
{ "tool_calls": [{ "id": "call_abc", "function": {"name": "get_weather", "arguments": "{\"location\": \"北京\"}"} }] }
Client 解析指令,向 MCP Server 的执行端点发送请求。
请求体: {"function_name": "get_weather", "arguments": {"location": "北京"}}
Server 返回: (假设下雨) {"condition": "Rain", "temperature": 18}
Client 构造一个 `tool` 角色的消息,包含上一步的工具调用 ID (`call_abc`) 和 Server 返回的结果,**连同所有历史消息**再次发送给 LLM API。
LLM API 返回: LLM 看到下雨,决策需要调用第二个工具 `create_calendar_event`。
{ "tool_calls": [{ "id": "call_def", "function": {"name": "create_calendar_event", "arguments": "..."} }] }
循环继续!
Client 再次调用 Server,执行 `create_calendar_event`,并获得成功结果。
Client 将第二个工具的执行结果(带着 ID `call_def`)再次反馈给 LLM。
LLM API 返回: LLM 判断所有任务已完成,不再要求调用工具,而是直接生成自然语言回答。
{ "content": "好的,查询到北京明天会下雨...已为您创建日历事件。", "finish_reason": "stop" }
Client 收到 `finish_reason: "stop"`。循环结束!
Client 将 LLM 返回的最终 `content` 显示给用户。
这种架构不仅仅是技术实现,更解决了软件工程中的几个关键问题:
前面我们展示了单个工具的定义,但在实际应用中,框架会为 LLM 提供一份包含所有可用工具的完整清单。这是一个更真实的、包含多个工具的 `StructuredTool` 列表的片段,展示了其复杂度和信息密度:
Allowed directories: ['E:\\code\\test_mcp\\mcp']
[StructuredTool(name='read_file', description='从文件系统读取文件的完整内容...', args_schema={...}),
StructuredTool(name='read_multiple_files', description='同时读取多个文件的内容...', args_schema={...}),
StructuredTool(name='write_file', description='创建一个新文件,或用新内容完全覆盖一个现有文件...', args_schema={...}),
StructuredTool(name='edit_file', description='对文本文件进行基于行的编辑...', args_schema={...}),
StructuredTool(name='create_directory', description='创建一个新目录或确保一个目录存在...', args_schema={...}),
StructuredTool(name='list_directory', description='获取指定路径中所有文件和目录的详细列表...', args_schema={...}),
# ... 更多工具
]
正是这样一份详尽、结构化、机器可读的“能力清单”,才使得大模型能够进行精确的规划和工具选择。
MCP 是一种将 LLM 作为智能调度中心来驱动复杂业务流程的架构模式。
掌握 MCP 模式,意味着掌握了构建能解决现实世界复杂问题的、真正强大的 AI 应用的钥匙!