MCP(Model Context Protocol)详解

引言

Model Context Protocol(模型上下文协议,简称 MCP)由 Anthropic 于 2024 年 11 月发布,是 AI 生态里连接”模型”与”外部世界”的事实标准之一。做 Agent、做 AI 应用的人都会遇到它。

本文是 MCP 的专题详解,读完你会掌握:

  • MCP 到底解决了什么痛点;
  • Host / Client / Server 三角色与 Tools / Resources / Prompts 三类原语;
  • 一条请求从模型到外部工具完整走一遍的生命周期;
  • 它支持哪些传输方式、版本如何演进;
  • 一个可直接运行的最小 MCP Server 示例。

前置知识:了解 LLM 的基本概念即可。文中事实以官方规范为准,个人理解处会明确标注。

要解决的问题:告别”每家一套适配层”

在 MCP 出现前,让模型调用外部能力主要靠两种方式:

  1. Function Calling:模型按 JSON Schema 声明想调的函数,应用端手写逻辑去执行。问题是每接一个工具都要写一遍适配代码,且只在单个应用内有效。
  2. 各家私有集成:每个数据源(数据库、GitHub、Slack、日历)给每家 AI 应用各做一套对接,重复劳动严重。

MCP 的出发点很朴素:与其让”每个 AI 应用 × 每个数据源”都单独对接,不如规定一个统一的”插头标准”。任何一个遵循 MCP 的 Server(数据源/工具),可以被任何遵循 MCP 的 Host(AI 应用)直接使用,无需为每家平台重写。

一个生活化比喻:MCP 就像统一电源插头。过去每个家电都造自己的插孔,不同房间(应用)还得配不同转换头;MCP 规定大家用同一套插头插孔,于是”电器”(MCP Server)与”插排”(Host)之间即插即用。

比喻的边界:插头插上就通电,但 MCP Server 是被动的——它不会主动找上门,需要 Host 侧配置并主动发起连接。

核心架构:Host / Client / Server 三角色

MCP 架构由三层组成,分别对应插排、插孔、电器:

  • Host(主机):用户直接交互的 AI 应用,内含 LLM。例如 Claude Desktop、Cursor、自建的聊天机器人。它是整套系统的”消费者”。
  • Client(客户端):Host 内部的轻量翻译器,负责把 Host 的请求翻译成 MCP 协议消息,并把 Server 的返回翻译回去。一个 Host 可以持有多个 Client,分别连接不同的 Server。
  • Server(服务端):暴露特定能力、托管并执行工具的程序,例如文件系统 Server、数据库 Server、GitHub Server。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<svg viewBox="0 0 600 300" xmlns="http://www.w3.org/2000/svg" width="100%">
<rect x="20" y="20" width="230" height="200" rx="8" fill="#eef2f7" stroke="#4a5568"/>
<text x="135" y="48" text-anchor="middle" font-size="16" fill="#1a202c">Host(AI 应用 + LLM)</text>
<rect x="45" y="70" width="180" height="46" rx="6" fill="#ffffff" stroke="#2b6cb0"/>
<text x="135" y="98" text-anchor="middle" font-size="14" fill="#2b6cb0">Client 1</text>
<rect x="45" y="130" width="180" height="46" rx="6" fill="#ffffff" stroke="#2b6cb0"/>
<text x="135" y="158" text-anchor="middle" font-size="14" fill="#2b6cb0">Client 2</text>
<text x="135" y="210" text-anchor="middle" font-size="13" fill="#718096">内含 LLM,向多个 Client 派发请求</text>

<line x1="225" y1="93" x2="350" y2="93" stroke="#2b6cb0" stroke-width="2" marker-end="url(#arr)"/>
<line x1="225" y1="153" x2="350" y2="183" stroke="#2b6cb0" stroke-width="2" marker-end="url(#arr)"/>

<rect x="360" y="60" width="220" height="66" rx="8" fill="#ffffff" stroke="#38a169"/>
<text x="470" y="88" text-anchor="middle" font-size="14" fill="#1a202c">MCP Server 1</text>
<text x="470" y="108" text-anchor="middle" font-size="12" fill="#718096">文件系统 / 工具</text>
<rect x="360" y="150" width="220" height="66" rx="8" fill="#ffffff" stroke="#38a169"/>
<text x="470" y="178" text-anchor="middle" font-size="14" fill="#1a202c">MCP Server 2</text>
<text x="470" y="198" text-anchor="middle" font-size="12" fill="#718096">数据库 / 资源</text>

<defs>
<marker id="arr" markerWidth="8" markerHeight="8" refX="6" refY="3" orient="auto">
<path d="M0,0 L6,3 L0,6 Z" fill="#2b6cb0"/>
</marker>
</defs>
</svg>

图 1:MCP 三角色架构——一个 Host 通过多个 Client 连接多个 Server,通信基于 JSON-RPC 2.0。

三类原语:Tools / Resources / Prompts

MCP 把”模型需要的外部能力”抽象成三种原语,每种都有配套的发现(*/list)与获取(*/get、*/call)方法:

原语定位模型如何使用典型例子
Tools(工具)可执行的操作模型自主决定调用查数据库、发消息、调支付 API
Resources(资源)供读取的上下文数据模型按需读取文件内容、数据库记录、API 返回
Prompts(提示词模板)可复用的交互模板应用/模型套用system prompt、few-shot 示例

区分 Tools 与 Resources 的关键:Tools 是”动作”(会触发副作用),Resources 是”数据”(只读)。比如”查询订单”是 Resource,”发起退款”是 Tool。这个区分帮助 Server 决定权限边界——只读资源可以放宽,有副作用的工具要收紧。

生命周期:一条请求怎么走

MCP 的连接不是一次 HTTP 请求就完事,它有一个明确的生命周期管理流程。

1. 初始化(initialize 握手)

建立连接后,Client 必须先向 Server 发送 initialize 请求,双方完成三件事:

  • 确认协议版本兼容(例如 2025-06-18);
  • 交换并协商能力(Server 声明自己支持 tools / resources / prompts 中的哪些);
  • 交换实现信息。

只有握手成功后,后续的 tools/list、tools/call 等请求才被允许。这保证了跨版本、跨实现的互操作安全。

2. 能力发现

Client 通过 tools/list、resources/list、prompts/list 向 Server 询问”你能做什么”,把能力清单交给模型。这避免了模型凭空编造工具名。

3. 工具调用

模型根据清单决定调用哪个工具,Client 发出 tools/call 请求,Server 执行并把结构化结果返回给模型。一次典型调用:

1
2
3
4
5
6
7
8
9
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "query_order",
"arguments": { "order_id": "20261029-001" }
}
}
sequenceDiagram
    participant LLM as LLM(Host 内)
    participant C as Client
    participant S as MCP Server
    C->>S: initialize(版本与能力协商)
    S-->>C: initialize 响应
    C->>S: tools/list(发现能力)
    S-->>C: 返回工具清单
    LLM->>C: 决定调用 query_order
    C->>S: tools/call(携带参数)
    S-->>C: 返回结构化结果
    C-->>LLM: 结果交给模型继续推理

图 2:MCP 一次工具调用的完整时序——握手 → 发现 → 调用。

传输方式:stdio 与 Streamable HTTP

MCP 支持两类传输:

  • stdio:Client 以子进程方式启动 Server,通过标准输入/输出通信。适合本地、单机、进程内的场景(如 IDE 内置的本地工具)。
  • Streamable HTTP:通过 HTTP 端点通信,Client 在请求中携带 MCP-Protocol-Version 头标明协议版本,Server 据此选择行为。适合远程、跨机器、多客户端共享的场景。

选型原则(个人理解):本地单体应用或调试阶段优先 stdio,部署为共享服务或需要被多个客户端调用时用 Streamable HTTP。

一个最小 MCP Server 示例

用官方 Python SDK(mcp)可以几行写出一个可运行的 Server:

1
2
3
4
5
6
7
8
9
10
11
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("demo-server")

@mcp.tool()
def add(a: int, b: int) -> int:
"""两个整数相加。"""
return a + b

if __name__ == "__main__":
mcp.run() # 默认通过 stdio 提供 MCP 服务

安装依赖并运行:

1
2
pip install "mcp[cli]"
python server.py

该 Server 向客户端暴露一个 add 工具,任何支持 MCP 的 Host 都能发现并调用它,无需为具体 Host 定制代码。这就是 MCP 的核心价值——一次实现,处处复用。

版本演进

MCP 规范迭代较快,主要版本包括:

  • 2025-03-26:早期稳定规范;
  • 2025-06-18:统一传输为 Streamable HTTP,引入 MCP-Protocol-Version 头;
  • 2025-11-25:架构与生命周期文档逐步完善;
  • 2026-07-28:演进为更无状态、面向长任务的架构,强化安全隔离与跨客户端复用。

写代码时注意在初始化请求中声明你支持的协议版本,避免与老版本 Server 不兼容。

适用场景

MCP 最适合以下情况:

  • 给一个 LLM 应用接数据库、文件系统、GitHub、Slack、日历等具体数据源和工具;
  • 想把某套工具集成做成可复用、跨平台的能力,而不是绑定单一应用;
  • 架构上是”应用(Host)↔ 工具(Server)”的主从接入关系,由模型直接驱动工具调用。

典型例子:一个客服 Agent 通过 MCP 连接 CRM、订单库、退换货接口,在单一 Host 内完成查询、处理与反馈。

总结

  • MCP 由 Anthropic 于 2024 年 11 月提出,目标是统一”模型 ↔ 外部工具/数据”的接入标准。
  • 架构上分为 Host / Client / Server 三角色,能力抽象为 Tools / Resources / Prompts 三类原语。
  • 连接遵循 initialize 握手 → 能力发现 → 工具调用 的生命周期,基于 JSON-RPC 2.0,支持 stdio 与 Streamable HTTP 两种传输。
  • 它的价值是让工具接入一次实现、处处复用,做单 Agent 的能力底座时优先选它。

参考链接