AI Agent 实战(二):MCP 协议深度解析——让 AI 拥有“万能工具箱”

MCP 协议工作流示意图

图 2-1:Model Context Protocol (MCP) 标准交互流程示意图

第二章:MCP 协议深度解析——让 AI 拥有“万能工具箱”

2.1 MCP 是什么?

MCP(Model Context Protocol) 是由 Anthropic 在 2024 年底推出的开源协议,旨在解决 AI 应用中的一个核心痛点:如何让 LLM 灵活、安全地调用外部工具?

在 MCP 出现之前,AI 调用工具的方式五花八门:

  • 有的通过 HTTP API。
  • 有的通过命令行参数。
  • 有的通过数据库查询。
  • 有的甚至直接操作文件系统。

这种碎片化导致:

  1. 开发成本高:每新增一个工具,都要为 LLM 编写专门的调用逻辑。
  2. 维护困难:工具接口变更时,LLM 的调用逻辑也要同步更新。
  3. 安全性差:缺乏统一的权限控制和错误处理机制。

MCP 的核心思想是“标准化”

  • 工具定义:所有工具遵循统一的描述格式(JSON Schema)。
  • 工具调用:LLM 通过标准协议发起调用,无需关心底层实现。
  • 错误处理:统一的错误格式,便于 LLM 理解和恢复。

类比

  • 没有 MCP:就像你每次买新电器,都要重新学习如何使用插头和开关。
  • 有 MCP:就像所有电器都使用标准插座,你只需学会一次,就能插拔任何电器。

2.2 MCP 的核心组件

MCP 协议由三个核心组件构成:

2.2.1 MCP Server(工具提供者)

MCP Server 是工具的“宿主”,负责:

  • 暴露工具:将本地功能(如文件操作、数据库查询、API 调用)封装为 MCP 工具。
  • 处理请求:接收 LLM 的调用请求,执行工具逻辑,返回结果。
  • 错误反馈:如果工具执行失败,返回结构化的错误信息。

示例halo-mcp-server 是一个 MCP Server,它暴露了以下工具:

  • list_my_posts:列出博客文章。
  • create_post:创建新文章。
  • publish_post:发布文章。
  • delete_post:删除文章。

2.2.2 MCP Client(工具调用者)

MCP Client 是 LLM 的“代理”,负责:

  • 发现工具:向 MCP Server 查询可用工具列表。
  • 发起调用:将 LLM 的意图转换为 MCP 工具调用请求。
  • 处理结果:将 MCP Server 的返回结果传递给 LLM。

在 OpenClaw 中,mcporter 就是 MCP Client 的实现。它负责:

  • 读取 ~/.mcporter/mcporter.json 配置文件,找到所有已注册的 MCP Server。
  • 通过 mcporter call <server> <tool> <params> 命令调用工具。

2.2.3 工具描述(Tool Schema)

每个 MCP 工具都有一个JSON Schema描述,包括:

  • 名称:工具的唯一标识(如 create_post)。
  • 描述:工具的用途(LLM 据此判断何时调用)。
  • 参数:工具的输入参数及其类型、必填项。
  • 返回格式:工具的输出格式。

示例

{
  "name": "create_post",
  "description": "创建一篇新的博客文章",
  "parameters": {
    "type": "object",
    "properties": {
      "title": {"type": "string", "description": "文章标题"},
      "content": {"type": "string", "description": "文章内容(Markdown 格式)"},
      "category": {"type": "string", "description": "文章分类"}
    },
    "required": ["title", "content"]
  }
}

2.3 实战:编写一个自定义 MCP Server

现在,让我们动手编写一个自定义 MCP Server,演示如何暴露一个简单功能给 LLM。

2.3.1 场景设定

假设我们想做一个**“天气查询工具”**,让 LLM 能够查询任意城市的天气。

2.3.2 实现步骤

步骤 1:创建项目结构

mkdir -p weather-mcp-server
cd weather-mcp-server
touch main.py requirements.json

步骤 2:编写 MCP Server 代码(Python + FastAPI)

# main.py
from fastapi import FastAPI
from pydantic import BaseModel
import requests
from typing import Optional

app = FastAPI(title="Weather MCP Server", version="1.0.0")

# 工具参数定义
class WeatherQuery(BaseModel):
    city: str
    unit: Optional[str] = "celsius"  # celsius 或 fahrenheit

# 工具实现
@app.post("/tools/weather_query")
async def weather_query(query: WeatherQuery):
    """查询指定城市的天气"""
    try:
        # 调用免费天气 API(示例使用 OpenWeatherMap)
        api_key = "YOUR_API_KEY"  # 实际使用时请替换为真实 Key
        url = f"http://api.openweathermap.org/data/2.5/weather"
        params = {
            "q": query.city,
            "appid": api_key,
            "units": "metric" if query.unit == "celsius" else "imperial"
        }
        response = requests.get(url, params=params)
        response.raise_for_status()
        data = response.json()

        # 构造返回结果
        result = {
            "city": data["name"],
            "temperature": data["main"]["temp"],
            "description": data["weather"][0]["description"],
            "humidity": data["main"]["humidity"],
            "wind_speed": data["wind"]["speed"]
        }
        return {"success": True, "data": result}
    except Exception as e:
        return {"success": False, "error": str(e)}

# MCP 协议要求:暴露工具列表
@app.get("/tools")
async def list_tools():
    return [
        {
            "name": "weather_query",
            "description": "查询指定城市的天气信息",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名称"},
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "default": "celsius"}
                },
                "required": ["city"]
            }
        }
    ]

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

步骤 3:安装依赖

pip install fastapi uvicorn requests pydantic

步骤 4:启动 MCP Server

python main.py
# Server 运行在 http://localhost:8000

2.3.3 验证工具

测试工具列表

curl http://localhost:8000/tools

返回:

[
  {
    "name": "weather_query",
    "description": "查询指定城市的天气信息",
    "parameters": {
      "type": "object",
      "properties": {
        "city": {"type": "string", "description": "城市名称"},
        "unit": {"type": "string", "enum": ["celsius", "fahrenheit"], "default": "celsius"}
      },
      "required": ["city"]
    }
  }
]

测试工具调用

curl -X POST http://localhost:8000/tools/weather_query \
  -H "Content-Type: application/json" \
  -d '{"city": "Beijing", "unit": "celsius"}'

返回:

{
  "success": true,
  "data": {
    "city": "Beijing",
    "temperature": 15.2,
    "description": "clear sky",
    "humidity": 45,
    "wind_speed": 3.2
  }
}

2.4 集成 OpenClaw:注册并调用自定义工具

现在,我们将这个天气 MCP Server 集成到 OpenClaw 中。

2.4.1 配置 mcporter

编辑 ~/.mcporter/mcporter.json,添加我们的 Server:

{
  "mcpServers": {
    "weather-mcp-server": {
      "command": "python3",
      "args": ["/path/to/weather-mcp-server/main.py"],
      "transport": "http",
      "url": "http://localhost:8000"
    }
  }
}

2.4.2 验证连接

mcporter list

输出应包含 weather-mcp-server

2.4.3 调用工具

mcporter call weather-mcp-server weather_query city="Shanghai" unit="celsius"

返回:

{
  "success": true,
  "data": {
    "city": "Shanghai",
    "temperature": 18.5,
    "description": "partly cloudy",
    "humidity": 62,
    "wind_speed": 2.8
  }
}

2.4.4 LLM 调用

现在,当你对 OpenClaw 说:

“帮我查一下上海的天气。”

OpenClaw 会:

  1. 解析意图,识别出需要调用 weather_query 工具。
  2. 通过 mcporter 调用 weather-mcp-server
  3. 将返回结果整理成自然语言回复: “上海当前天气:18.5°C,多云,湿度 62%,风速 2.8m/s。”

2.5 深度思考:MCP 如何改变 AI 工具生态?

2.5.1 从“硬编码”到“动态发现”

传统方式下,每新增一个工具,都要修改 LLM 的调用逻辑。而 MCP 让工具动态注册,LLM 只需知道“有哪些工具可用”,无需关心“工具如何实现”。

类比

  • 传统:就像你每次去新餐厅,都要重新学习菜单和点餐流程。
  • MCP:就像所有餐厅都用同一套点餐系统,你只需学会一次,就能在任何餐厅点餐。

2.5.2 从“孤岛”到“生态”

MCP 的标准化,让不同开发者编写的工具可以互操作。例如:

  • 一个开发者写了一个“博客发布工具”。
  • 另一个开发者写了一个“图片生成工具”。
  • LLM 可以同时调用这两个工具,完成“生成配图并发布博客”的复杂任务。

这将催生一个开放的 AI 工具生态,类似 npm、PyPI 这样的包管理器,但针对的是AI 工具

2.5.3 安全性与权限控制

MCP 协议本身不直接处理权限,但可以通过Server 端实现

  • 认证:API Key、OAuth2。
  • 授权:基于角色的访问控制(RBAC)。
  • 审计:记录所有工具调用日志。

未来展望: 随着 MCP 的普及,我们可能会看到:

  • MCP 应用商店:开发者发布工具,用户一键安装。
  • MCP 沙箱:工具在隔离环境中运行,防止恶意操作。
  • MCP 标准组织:制定更详细的协议规范,推动互操作性。

(第二章完)

下一章预告:第三章将深入解析 Agent Reach,教你如何配置和使用它来访问 Twitter、Reddit、YouTube、Bilibili 等平台,实现“互联网之眼”。