MCP:给 Agent 装上标准化的工具接口

MCP:给 Agent 装上标准化的工具接口

目录

MCP是什么

MCP(Model Context Protocol,模型上下文协议)是 Anthropic 在 2024 年底发布的一个开放协议。它给 LLM 连接外部工具和数据定义一套标准接口

为什么需要一套标准?在 USB-C 出现之前,充电口五花八门,有USB、Lightning、各种厂商自己的私有接口。每换一个设备可能就得换一根线。后来出现了USB-C 统一了这个接口,一根线就能充电、能传数据、能接显示器,统一一种线之后消除了差异所带来的不便。MCP 在做的事情也是这样,它就是AI 领域的 USB-C:不管你是 Claude、GPT 还是其他模型,不管你是查数据库、调 API 还是读文件,都通过同一套协议来连接。

为什么需要MCP

回到我们已经讲过的 Tool Use 机制。在那篇文章里我们说过,Agent 调用工具的核心是一个注册表:工具名映射到执行函数。这个机制本身没问题,但有一个实际的痛点:每个 Agent 项目都要从零开始定义自己的工具

假设我们想给 Agent 加一个"查询天气"的能力:

python 复制代码
# 项目 A 的写法
weather_tool = {
    "name": "get_weather",
    "input_schema": {
        "properties": {
            "city": {"type": "string"}
        }
    }
}

# 项目 B 的写法
weather_tool = {
    "name": "query_weather",
    "input_schema": {
        "properties": {
            "location": {"type": "string"},
            "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
        }
    }
}

同样的功能,工具名、参数名、参数数量都不同。如果你想把项目 A 的天气工具搬到项目 B 里用,不能直接拿来就跑,需要改代码适配。

那如果有一个标准:所有天气类的 MCP Server 都叫 get_weather,参数都用 city,返回值格式都一样,那么任何支持 MCP 的 Agent 都能直接用,不用改一行代码。这就是 MCP 的核心价值:一次实现,到处可用

MCP的架构

MCP 采用 Client-Server 架构,涉及三个角色:

复制代码
用户
  │
  ▼
Host(宿主应用)
  │
  ├── Client A ──── Server 1(文件系统)
  ├── Client B ──── Server 2(数据库)
  └── Client C ──── Server 3(GitHub API)

Host 是用户直接交互的应用,比如 Claude Desktop、Cursor、或者开发者自己写的 Agent 程序。它负责管理整个生命周期:创建 Client、协调通信、控制权限。

Client 是 Host 内部的协议代理,由 Host 创建。每个 Client 和一个 Server 之间是一对一的有状态连接。它负责和 Server 做协议协商、消息路由。

Server 是提供具体能力的服务端。它把自己能做的事情(查数据库、读文件、调 API)通过 MCP 协议暴露出来,任何 Client 都能连接并使用。

为什么要分 Client 和 Server 两层?因为一个 Host 可能同时需要多种能力。查数据库是一个 Server,读文件是另一个 Server,调 GitHub API 是第三个 Server。每个 Client 只管和自己对应的 Server 通信,Host 负责统筹调度。

MCP的三大能力

MCP Server 可以向 Client 暴露三种类型的能力:

Tools(工具)

工具是 Server 提供的可执行操作。Agent 可以调用工具来完成具体任务,比如执行 SQL 查询、发送消息、创建文件。

python 复制代码
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather-server")

@mcp.tool()
def get_weather(city: str) -> str:
    """查询指定城市的天气"""
    # 实际实现:调用天气 API
    return f"{city}:晴,25°C"

这部分和我们之前讲的 Tool Use 最像,区别在于工具的定义格式是 MCP 统一规定的,不是各项目自己定的。

Resources(资源)

资源是 Server 提供的可读取数据。和工具不同,资源是"只读"的,Agent 可以获取资源的内容,但不能通过资源去执行操作。

python 复制代码
@mcp.resource("config://database")
def get_db_config() -> str:
    """返回数据库连接配置"""
    return "host=localhost port=5432 dbname=myapp"

资源用 URI 来标识(比如 config://database),Client 可以通过 URI 列出可用资源、读取资源内容。

Prompts(提示模板)

提示模板是 Server 预定义的交互模板,告诉 Agent"在这种场景下你应该怎么组织 prompt"。

python 复制代码
@mcp.prompt()
def review_code(code: str) -> str:
    """生成代码审查的 prompt"""
    return f"请审查以下代码,关注安全性和性能:\n\n{code}"

三种能力的定位不同:

能力 方向 作用 类比
Tools Agent → Server 执行操作 调用函数
Resources Server → Agent 提供数据 读取文件
Prompts Server → Agent 引导交互 提供模板

MCP的两种传输方式

Client 和 Server 之间怎么通信?MCP 支持两种方式:

stdio(标准输入输出):Client 启动 Server 进程,通过 stdin/stdout 交换 JSON-RPC 消息。这种方式适合本地场景,比如 Agent 在你电脑上运行一个本地的文件系统 Server。

复制代码
Client
  │
  ├── 启动 Server 子进程
  ├── 通过 stdin 发送请求
  ├── 通过 stdout 接收响应
  └── 进程退出时断开连接

Streamable HTTP:Client 通过 HTTP 请求和远程 Server 通信。这种方式适合远程场景,比如连接一个部署在服务器上的数据库 MCP Server。

对于 Agent 初学者来说,先理解 stdio 就够了。你写一个本地 MCP Server,Agent 启动它、调用它的工具、拿到结果,整个过程都在本机完成。

MCP 和 Tool Use 的区别

这是一个比较容易混淆的点:MCP 和我们之前讲的 Tool Use 是什么关系?

Tool Use 是 LLM 调用工具的底层机制,模型输出一个结构化的工具调用请求,代码端执行并返回结果。MCP 是在此之上的一层标准化协议,它解决的不是"Agent 怎么调工具",而是"工具怎么定义、怎么发现、怎么复用"。

维度 Tool Use MCP
层级 底层机制 上层协议
解决的问题 Agent 怎么调工具 工具怎么标准化
工具定义 各项目自己定 协议统一规定
复用性 需要手动适配 一次实现到处可用
能力范围 只有工具 工具 + 资源 + 提示模板

Agent 侧怎么接入MCP

Host 应用(比如 Claude Desktop)内置了 MCP Client。用户在配置文件里声明要用哪些 MCP Server:

json 复制代码
{
  "mcpServers": {
    "filesystem": {
      "command": "python",
      "args": ["filesystem_server.py"]
    }
  }
}

Host 启动时会为每个 Server 创建一个 Client,通过 stdio 启动 Server 进程,完成协议握手和能力协商。之后 Agent 在推理过程中如果需要文件操作,就会通过 Client 调用 Server 的工具,拿到结果后继续推理。

小结

MCP 给 Agent 连接外部世界定义了一套标准接口。Server 把自己的能力(工具、资源、提示模板)按照协议暴露出来,Client 按照协议去连接和调用。一次实现,任何支持 MCP 的 Agent 都能直接用。