深入理解 MCP (模型控制程序)

从 Function Calling 到智能自动化工作流的架构实践

引言:为何需要 MCP?

你可能已经熟悉大语言模型(LLM)的 Function Calling 功能。它能让 LLM 调用外部工具,极大地扩展了其能力范围。但是,当面对一个需要多个步骤、依赖前后结果、甚至包含条件判断复杂任务时,单次函数调用是远远不够的。

核心思想: MCP (Model Controlled Program/Process),并非一个新模型或服务器,而是一种架构模式编程范式。它利用 LLM 的规划和推理能力,结合 Function Calling 机制,像一个“智能项目经理”一样,指挥你的应用程序和后台服务,分步骤、有逻辑地完成复杂工作流。

MCP 的核心架构:Client 与 Server

MCP 模式的实现,关键在于理解其解耦的 Client/Server 架构。这比简单地认为有“协调者”和“执行者”更精确。

  1. 1. MCP Server (工具提供方 / 执行者)

    • 是什么: 您自己编写和部署的后台服务。这是所有工具的“家”
    • 干什么:
      • 包含实际执行具体操作的函数代码 (例如,操作数据库、调用第三方API的 Python 函数)。
      • 使用框架提供的装饰器(如 @mcp.tool)来“注册”这些函数。
      • 对外暴露两个核心能力:
        1. 提供一份所有已注册工具的详细描述清单 (Schema)
        2. 提供一个统一的 API 端点 (如 /execute),接收指令并安全地执行对应的函数,然后返回结果。
    • 在哪: 运行在您自己的基础设施上。您完全控制代码和执行环境。
  2. 2. MCP Client (业务逻辑 / 协调者)

    • 是什么: 您的主应用程序,它直接与用户和大模型交互。
    • 干什么:
      • 接收用户请求,并与大模型 API (如 GPT-4) 进行通信。
      • 在对话开始时,向 MCP Server 请求“工具描述清单”,并将其提供给大模型作为上下文。
      • 解析大模型返回的“工具调用”指令。
      • 向 MCP Server 发起“执行请求”
      • 接收 Server 返回的执行结果,并将其反馈给大模型。
      • 管理和维持整个“指令-执行-反馈”的循环,直到任务完成。
    • 在哪: 也运行在您自己的基础设施上。它可以是 Web 后端、命令行脚本等。

通信方式

Client 与 Server 之间的通信可以是:

从 Python 函数到 LLM 工具:转换的艺术

MCP 框架的核心魅力在于,开发者只需编写标准的 Python 函数,框架会自动将其“翻译”成大模型能理解的结构化工具定义。这遵循“单一事实来源”原则。

第一步:开发者编写 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}"

第二步:框架自动生成 StructuredTool 定义

当 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 风格) 中提取参数描述。

MCP 的核心工作流:一次完整的请求之旅

我们用一个实例 (“查天气并根据是否下雨创建日历提醒”) 来详细演示这个循环过程。整个过程由 Client 作为“协调者”来驱动。

  1. Step 0: 用户与 Client 交互

    用户向 Client (你的应用) 输入: "明天北京天气怎么样?如果下雨,帮我在日历上加个提醒带伞。" Client 初始化一个用于记录对话历史的 `messages` 列表。

  2. Step 1: Client LLM API (首次规划)

    Client 将用户消息和从 Server 获取的 `tools` 定义一起发送给 LLM API。

    LLM API 返回: 指示需要调用 `get_weather` 工具。

    { "tool_calls": [{ "id": "call_abc", "function": {"name": "get_weather", "arguments": "{\"location\": \"北京\"}"} }] }
  3. Step 2: Client MCP Server (执行工具 1)

    Client 解析指令,向 MCP Server 的执行端点发送请求。

    请求体: {"function_name": "get_weather", "arguments": {"location": "北京"}}

    Server 返回: (假设下雨) {"condition": "Rain", "temperature": 18}

  4. Step 3: Client LLM API (反馈结果,下一步决策)

    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": "..."} }] }

    循环继续!

  5. Step 4: Client MCP Server (执行工具 2)

    Client 再次调用 Server,执行 `create_calendar_event`,并获得成功结果。

  6. Step 5: Client LLM API (反馈结果,生成最终答案)

    Client 将第二个工具的执行结果(带着 ID `call_def`)再次反馈给 LLM。

    LLM API 返回: LLM 判断所有任务已完成,不再要求调用工具,而是直接生成自然语言回答。

    { "content": "好的,查询到北京明天会下雨...已为您创建日历事件。", "finish_reason": "stop" }

    Client 收到 `finish_reason: "stop"`。循环结束!

  7. Step 6: Client 用户 (显示结果)

    Client 将 LLM 返回的最终 `content` 显示给用户。

MCP 的工程价值:解决核心痛点

这种架构不仅仅是技术实现,更解决了软件工程中的几个关键问题:

深入细节:大模型看到的“工具全貌”

前面我们展示了单个工具的定义,但在实际应用中,框架会为 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={...}),
 # ... 更多工具
]

正是这样一份详尽、结构化、机器可读的“能力清单”,才使得大模型能够进行精确的规划和工具选择。

深入细节:Tool ID 的重要意义

总结:MCP 的力量

MCP 是一种将 LLM 作为智能调度中心来驱动复杂业务流程的架构模式

掌握 MCP 模式,意味着掌握了构建能解决现实世界复杂问题的、真正强大的 AI 应用的钥匙!