MCP 原理与实战教程
Model Context Protocol(模型上下文协议) —— 打通大模型与外部世界的标准化桥梁
文章目录
一、什么是 MCP —— 大模型的 “USB-C 接口”
背景:大模型的能力边界
LLM(大语言模型)在文本生成、代码编写、逻辑推理方面已经非常强大。但它们有一个天生的短板:无法直接访问外部数据、调用外部工具、或与真实世界交互。模型的知识截止于训练数据,缺少实时信息,也无法执行"发一封邮件"、"查一下数据库"这样的操作。
MCP 要解决的问题
此前,开发者若想让 AI 连接外部系统,需要为每个模型、每个平台单独写一套适配层。这就像每种设备都需要一个专属充电口 —— 直到 USB-C 出现。
MCP 就是 AI 世界的 “USB-C 协议”。 它定义了一套标准化的接口规范,让任何 AI 应用(Host)都能以统一的方式与任何外部工具/数据源(Server)通信,彻底告别 N×M 的适配困境。
MCP 由 Anthropic 于 2024 年底开源发布,目前已经成为 AI 生态中增长最快的协议标准之一,被 OpenAI、Google、Microsoft 等主流厂商广泛采纳。
没有 MCP 之前:
模型A --自定义适配层1--> 工具/数据
模型B --自定义适配层2--> 工具/数据
... (M x N 种组合,每次都要重写适配层)
有了 MCP 之后:
任何 Host --[ MCP 协议 / JSON-RPC 2.0 ]--> 任何 Server
(只需实现一次协议,即可无限组合)
二、核心架构:三大角色与通信模型
三大角色
| 角色 | 说明 |
|---|---|
| MCP Host | AI 应用本身(如 Claude Desktop、WorkBuddy、VS Code 插件)。负责发起连接请求,将 Server 提供的能力注入 LLM 的上下文。 |
| MCP Client | 协议客户端,嵌入在 Host 内部。负责与 Server 建立通信通道、发送请求、接收响应,管理连接生命周期。 |
| MCP Server | 轻量级服务程序,暴露具体的工具/数据/提示词能力。每个 Server 专注一个领域,通过标准协议对外提供服务。 |
架构全貌
+-------------------------------------------+
| LLM(大语言模型) |
| Claude / GPT / DeepSeek |
+--------------------+----------------------+
|
+--------------------+----------------------+
| MCP Host |
| Claude Desktop / WorkBuddy |
+--------------------+----------------------+
|
+--------------------+----------------------+
| MCP Client |
| 协议编解码 & 连接管理 |
+--------+-----------+----------+-----------+
| | | JSON-RPC 2.0
+----+---+ +----+---+ +---+----+
| File | | DB | | API | ... 更多 Server
| Server | | Server| | Server |
+--------+ +-------+ +--------+
通信传输层
MCP 支持两种传输方式:
| 传输方式 | 说明 | 适用场景 |
|---|---|---|
| stdio | 通过标准输入/输出进行 JSON-RPC 消息交换,Client 作为子进程启动 Server | 本地工具、CLI 应用 |
| SSE (HTTP) | 基于 HTTP + Server-Sent Events,支持远程通信 | 远程服务、云端部署 |
设计哲学: 每个 MCP Server 应该是"小而美"的,专注于一个领域。不是一个大而全的巨型 Server,而是像微服务一样,按领域拆分成多个独立的 Server。这样既便于维护,也符合安全最小权限原则。
三、协议细节:JSON-RPC 消息格式与生命周期
消息格式
MCP 使用 JSON-RPC 2.0 作为消息编码协议。所有通信都是 JSON 对象,通过 Request / Response / Notification 三种模式交互。
请求(Request)
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "city": "北京" }
}
}
响应(Response)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{ "type": "text", "text": "北京当前天气:晴,26°C" }
]
}
}
通知(Notification)—— 无 id,不期待响应
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
连接生命周期
1. Initialize --> 2. List Capabilities --> 3. Invoke --> 4. Shutdown
(握手协商) (能力发现) (调用工具) (优雅关闭)
关键阶段说明:
- Initialize:Client 发送
initialize请求,Server 返回自身的能力清单(protocol version、capabilities) - Initialized:Client 发送
notifications/initialized通知,表示握手完成 - 正常工作:Client 可调用
tools/list、tools/call、resources/read等方法 - 关闭:在 stdio 模式下,关闭进程的 stdin;在 HTTP 模式下,发送 DELETE 或关闭 SSE 流
提示: 在 stdio 模式下,MCP Server 的标准输出完全被 JSON-RPC 消息占用。任何
print()或日志输出都会破坏协议。调试日志必须输出到 stderr。
四、核心概念:Tools / Resources / Prompts 三剑客
MCP Server 通过三种原语向 Host 暴露能力:
1. Tools(工具)—— “让 AI 动手做事”
Tools 是 MCP 最核心的概念。每个 Tool 是一个可由 LLM 调用的函数,有明确的名称、描述和参数 schema。当用户问"帮我查一下北京天气",LLM 会识别出需要调用 get_weather 工具,Host 通过 MCP Client 调用 Server 执行该函数,并把结果返回给 LLM。
# 定义一个 Tool
@server.tool()
async def get_weather(city: str) -> str:
"""获取指定城市的实时天气信息"""
# ... 调用天气 API
return f"{city}当前天气:晴,26°C"
2. Resources(资源)—— “让 AI 读取数据”
Resources 是只读的数据源,用 URI 标识。LLM 可以像"打开文件"一样读取资源内容。例如:file://docs/readme.md、db://users/list。
3. Prompts(提示词模板)—— “让用户快速上手”
Prompts 是预定义的对话模板,带有参数占位符。用户在 Host 中选择一个 Prompt,填入参数,即可生成结构化的对话。例如:"代码审查"模板,参数为文件路径。
三者对比
| 概念 | 类比 | 方向 | 典型场景 |
|---|---|---|---|
| Tool | 函数调用 | AI -> Server(读写) | 发送邮件、查询天气、操作数据库 |
| Resource | 文件读取 | AI <- Server(只读) | 读取文档、获取配置、查看日志 |
| Prompt | 对话模板 | User -> AI(输入) | 代码审查模板、翻译模板、摘要模板 |
五、环境准备与工具链
安装 MCP SDK
Anthropic 提供了官方的 Python SDK,一行命令即可安装:
pip install mcp
如果你使用 uv(推荐,更快的包管理器):
uv pip install mcp
# 或者创建独立项目
uv init my-mcp-server
cd my-mcp-server
uv add mcp
推荐的工具链
- mcp —— Anthropic 官方 Python SDK,提供
Server、Tool、Resource等装饰器 - Claude Desktop —— 现成的 MCP Host,用于测试你的 Server
- MCP Inspector —— 官方调试工具:
npx @anthropic-ai/mcp-inspector - WorkBuddy / Cursor / Windsurf —— 支持 MCP 的 IDE,直接在编程环境中使用
版本说明: MCP 协议正在快速迭代中,截至 2025 年 7 月,最新稳定版支持
mcp >= 1.0.0。本文代码基于 Python SDK 1.x 版本,建议使用pip install "mcp>=1.0"确保兼容性。
六、实战一:从零编写一个 MCP Server
我们来创建一个完整的 MCP Server —— 天气助手,提供两个 Tool:查询天气和获取城市建议。
项目结构
weather-server/
├── server.py # MCP Server 主程序
├── .env # API Key 等配置(可选)
└── pyproject.toml # 项目依赖
编写 Server 代码
#!/usr/bin/env python3
"""
天气查询 MCP Server
提供实时天气查询和城市建议功能
"""
import asyncio
import json
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationCapabilities
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
# 1. 创建 Server 实例
server = Server("weather-server")
# 2. 注册工具列表
@server.list_tools()
async def list_tools() -> list[Tool]:
"""返回此 Server 提供的所有工具列表"""
return [
Tool(
name="get_weather",
description="获取指定城市的实时天气信息,包括温度、湿度、天气状况",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称,如 '北京'、'上海'、'深圳'"
}
},
"required": ["city"]
}
),
Tool(
name="suggest_city",
description="根据用户的偏好推荐适合旅游的城市",
inputSchema={
"type": "object",
"properties": {
"preference": {
"type": "string",
"description": "用户偏好,如 '海滨'、'山景'、'美食'、'历史文化'",
"enum": ["海滨", "山景", "美食", "历史文化"]
}
},
"required": ["preference"]
}
)
]
# 3. 实现工具调用逻辑
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
"""处理工具调用请求"""
if name == "get_weather":
city = arguments["city"]
# 实际场景中应调用真实的天气 API
weather_data = await fetch_weather(city)
return [TextContent(
type="text",
text=f"坐标城市: {city}\n"
f"温度: {weather_data['temp']}°C\n"
f"湿度: {weather_data['humidity']}%\n"
f"天气: {weather_data['condition']}\n"
f"风速: {weather_data['wind']} m/s"
)]
elif name == "suggest_city":
suggestions = {
"海滨": ["三亚", "青岛", "厦门", "大连"],
"山景": ["丽江", "张家界", "黄山", "桂林"],
"美食": ["成都", "广州", "西安", "重庆"],
"历史文化": ["西安", "南京", "洛阳", "开封"]
}
cities = suggestions.get(arguments["preference"], ["暂无推荐"])
return [TextContent(
type="text",
text=f"偏好: {arguments['preference']}\n"
f"推荐城市:\n" + "\n".join(f" * {c}" for c in cities)
)]
raise ValueError(f"Unknown tool: {name}")
# 4. 模拟天气数据(实际项目应接入真实 API)
async def fetch_weather(city: str) -> dict:
"""模拟天气数据获取"""
# 实际项目中替换为: requests.get(f"https://api.weather.com/...")
import random
conditions = ["晴", "多云", "阴", "小雨", "阵雨"]
return {
"temp": random.randint(15, 35),
"humidity": random.randint(30, 90),
"condition": random.choice(conditions),
"wind": round(random.uniform(1, 10), 1)
}
# 5. 启动 Server(stdio 模式)
async def main():
async with stdio_server() as (read_stream, write_stream):
await server.run(
read_stream,
write_stream,
InitializationCapabilities(
sampling={},
experimental={},
roots={"listChanged": True}
),
notification_options=NotificationOptions(),
)
if __name__ == "__main__":
asyncio.run(main())
本地测试 Server
你可以直接用命令行测试 Server 是否能正常启动:
python server.py
# Server 会阻塞在 stdio,等待 JSON-RPC 消息
# 按 Ctrl+C 退出
提示: 如果遇到
ModuleNotFoundError: No module named 'mcp',请先执行pip install mcp安装 SDK。
七、实战二:让 Claude Desktop / WorkBuddy 连接你的 Server
配置 Claude Desktop
Claude Desktop 是目前最成熟的 MCP Host。配置非常简单 —— 编辑它的配置文件:
配置文件路径:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["D:/projects/weather-server/server.py"]
}
}
}
重启 Claude Desktop,在聊天框输入**“帮我查一下北京的天气”**,Claude 会自动识别并调用你的 MCP Server!
配置 WorkBuddy
WorkBuddy 的 MCP 配置位于 ~/.workbuddy/mcp.json:
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["D:/projects/weather-server/server.py"]
}
}
}
配置完成后,在 WorkBuddy 的"连接器管理"中找到新注册的 Server,点击"信任"即可启用。
调试技巧
使用 MCP Inspector 可以在不依赖 Host 的情况下独立测试 Server:
npx @anthropic-ai/mcp-inspector python server.py
这会启动一个 Web 界面(默认 http://localhost:5173),你可以在其中:
- 查看 Server 暴露的所有 Tool / Resource / Prompt
- 手动构造 JSON-RPC 请求并查看响应
- 模拟 LLM 的工具调用流程
八、总结与展望
核心要点
| 要点 | 说明 |
|---|---|
| 标准化协议 | MCP 用 JSON-RPC 2.0 统一了 AI 与外部工具的通信,像 USB-C 一样"插上即用"。 |
| 三大能力原语 | Tools(执行动作)、Resources(读取数据)、Prompts(对话模板),覆盖几乎所有交互场景。 |
| 清晰的架构 | Host -> Client -> Server 三层分离,职责清晰,支持 stdio 和 HTTP 两种传输。 |
| 生态繁荣 | 官方已有数百个开源 Server,覆盖文件系统、数据库、API、搜索引擎等各个领域。 |
下一步学习建议
- 阅读官方规范:modelcontextprotocol.io —— 协议的最新权威文档
- 浏览官方 Server 仓库:GitHub 上的
modelcontextprotocol/servers有大量生产级的 MCP Server 参考实现 - 动手写一个:从你最熟悉的领域开始 —— 封装一个你每天都在用的 API 或工具
- 关注 SDK 更新:Python SDK 和 TypeScript SDK 都在快速迭代,定期升级关注新特性
- 参与社区:MCP 有着非常活跃的开发者社区,讨论设计和最佳实践
MCP 正在重新定义 AI 与世界的交互方式。 它让大模型不再是"纸上谈兵"的思考者,而是能真正"动手做事"的行动者。学完这篇教程,你已经具备了从零搭建 MCP 应用的能力——现在就去写你的第一个 MCP Server 吧!
更多推荐


所有评论(0)