理解 MCP
目录
理解 MCP #
MCP 概述 #
MCP(模型上下文协议)是一个开源标准协议,让 AI 应用(如 Claude、ChatGPT)能够统一连接外部数据源、工具和工作流。类比 USB-C 接口——为 AI 与外部系统的交互提供标准化的连接方式。MCP 专注于上下文交换协议本身,不干涉 AI 应用如何使用 LLM 或管理上下文,保持了高度的灵活性与可扩展性。

MCP 能做什么:
- AI 助手接入日历、笔记等个人数据
- 根据 Figma 设计稿直接生成网页应用
- 企业聊天机器人连接多个数据库进行数据分析
- AI 操控 Blender 建模并驱动 3D 打印机
为什么重要:
- 开发者:降低 AI 应用的开发复杂度
- AI 应用:接入更丰富的数据和工具生态,提升能力
- 终端用户:获得能访问个人数据、代为执行任务的更强大 AI
重要资源:
- 官方文档 — MCP 官网,含架构说明、规范和教程
- 示例服务器 — 官网提供可直接使用的服务器示例,覆盖数据库、文件系统、Web API 等场景
- 社区精选服务器 — GitHub 上的
awesome-mcp-servers,持续更新的各类 MCP 服务器合集 - MCP 客户端列表 — GitHub 上的
awesome-mcp-clients,多语言、多框架的客户端实现参考 - MCP For Beginners — 微软出品的MCP入门教程,通过Rust、Python和TypeScript等语言的实践代码示例学习MCP
- 探索更多的MCP服务器:
- https://glama.ai/, 一个集成的多模态 AI 客户端与开源工具平台。它提供了一个统一的聊天界面,让用户可以同时对比、调用多个主流人工智能模型,并以拥有大量 MCP(模型上下文协议)服务器资源而知名。
- https://mcp.so/,一个社区驱动的平台,旨在收集和整理第三方 MCP(Model Context Protocol)服务器资源。
- https://mcpservers.org/,一个专注于 MCP服务器的资源平台
- https://www.reddit.com/r/mcp/,reddit的MCP资源频道
- https://lobehub.com/zh/mcp,lobehub的MCP服务器市场
MCP的架构 #
参与者 #
MCP Host(AI 应用)
├── MCP Client 1 ──→ MCP Server A(本地,如文件系统)
├── MCP Client 2 ──→ MCP Server B(本地,如数据库)
└── MCP Client 3 ──→ MCP Server C(远程,如 Sentry)
- MCP Host:AI 应用本体(如 Claude Desktop、VS Code、Cursor等)
- MCP Client:由 Host 创建,每个 Server 对应一个专属 Client
- MCP Server:提供上下文数据的程序,可以在本地或远程运行
两层协议 #
| 层次 | 职责 |
|---|---|
| 数据层 | 基于 JSON-RPC 2.0,定义消息结构、生命周期管理、原语(Tools/Resources/Prompts)、通知机制 |
| 传输层 | 负责通信信道与认证,屏蔽底层细节 |
传输层两种方式:
- Stdio:标准输入输出,用于本地进程通信,性能最优
- Streamable HTTP:HTTP POST + SSE,用于远程服务器,支持 OAuth 认证
核心设计原则 #
- 一个 Host → 多个 Client → 多个 Server
- 数据层协议统一,传输层可替换
- 有状态协议,需要生命周期管理(初始化 → 能力协商 → 通信 → 终止)
JSON-RPC 2.0 #
JSON-RPC 是一个无状态、轻量级的远程过程调用(RPC)协议,使用 JSON(RFC 4627)作为数据格式。这个规范简洁而强大,广泛应用于各种 API 和微服务架构中。详细规范:https://www.jsonrpc.org/specification。
基本概念 #
核心特点:
- 简单轻量:规范精简,易于实现和理解
- 传输无关:可在 HTTP、WebSocket、TCP 等任何传输协议上使用
- 无状态:每个请求独立完整,不依赖上下文
- 支持批量:可一次发送多个请求,提高效率
消息分类:
├─── 请求/响应模型
│ ├─── 请求对象 (Request),需要服务器响应的调用
│ ├─── 响应对象 (Response),对请求的响应,可以响应结果或者错误
│ └─── 通知对象 (Notification),不需要响应的单项请求
└─── 批量处理
└─── 批量调用 (Batch),多个请求和响应一起发送
角色定义:
- 客户端(Client):发起请求对象,处理响应对象
- 服务器(Server):处理请求对象,发起响应对象
通信流程:
数据结构 #
使用JSON数据结构,用对象封装消息。
请求对象(Request Object) #
示例:
{
"jsonrpc": "2.0",
"method": "subtract",
"params": [42, 23],
"id": 1
}
字段说明:
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| jsonrpc | String | ✓ | 协议版本,必须是 “2.0” |
| method | String | ✓ | 要调用的方法名 |
| params | Array/Object | ✗ | 方法参数(结构化值) |
| id | String/Number/Null | ✗ | 请求标识符,通知时省略 |
响应对象(Response Object) #
成功响应示例:
{
"jsonrpc": "2.0",
"result": 19,
"id": 1
}
字段说明:
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| jsonrpc | String | ✓ | 必须是 “2.0” |
| result | Any | ✓ | 方法返回的结果 |
| id | String/Number/Null | ✓ | 与请求对应的 ID |
错误响应示例:
{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 1
}
字段说明:
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| jsonrpc | String | ✓ | 必须是 “2.0” |
| error | Object | ✓ | 错误对象 |
| id | String/Number/Null | ✓ | 与请求对应的 ID |
错误对象(Error Object)
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
| code | Number | ✓ | 错误代码(整数) |
| message | String | ✓ | 错误简短描述 |
| data | Any | ✗ | 附加错误信息 |
预定义错误码
| 代码 | 消息 | 含义 |
|---|---|---|
| -32700 | Parse error | 解析 JSON 失败 |
| -32600 | Invalid Request | 请求对象无效 |
| -32601 | Method not found | 方法不存在 |
| -32602 | Invalid params | 参数无效 |
| -32603 | Internal error | 内部错误 |
| -32000 至 -32099 | Server error | 服务器自定义错误 |
通知(Notification) #
通知是不需要响应的特殊请求,通过省略 id 字段来标识:
{
"jsonrpc": "2.0",
"method": "update",
"params": [1, 2, 3, 4, 5]
}
批量调用(Batch) #
可以将多个请求对象放在一个数组中发送:
批量请求:
[
{"jsonrpc": "2.0", "method": "sum", "params": [1,2,4], "id": "1"},
{"jsonrpc": "2.0", "method": "notify_hello", "params": [7]},
{"jsonrpc": "2.0", "method": "subtract", "params": [42,23], "id": "2"}
]
批量响应:
[
{"jsonrpc": "2.0", "result": 7, "id": "1"},
{"jsonrpc": "2.0", "result": 19, "id": "2"}
]
注意:通知不会在批量响应中出现。
MCP的数据层协议 #
MCP使用 JSON-RPC 2.0 作为底层协议,支持请求/响应和单向通知两种消息模式,定义客户端和服务器之间交换消息的具体格式,确保双方能听懂对方。
生命周期管理 #
有状态协议,连接建立时需进行能力协商,确定双方支持的功能。
原语(Primitives) #
服务端原语(Server → Client):
| 原语 | 说明 |
|---|---|
| Tools | 可执行函数,如文件操作、API 调用 |
| Resources | 上下文数据源,如文件内容、数据库记录 |
| Prompts | 可复用的交互模板 |
每种原语均支持
*/list发现、*/get获取,Tools 额外支持tools/call执行。
客户端原语(Client → Server):
| 原语 | 说明 |
|---|---|
| Sampling | 服务器请求客户端 LLM 生成内容 |
| Elicitation | 服务器向用户请求额外输入或确认 |
| Logging | 服务器向客户端发送调试日志 |
跨切面原语:
- Tasks(实验性):支持长时间运行任务的状态追踪与延迟结果获取
通知机制 #
服务器状态变化时(如工具列表更新),主动推送 JSON-RPC 通知消息,无需客户端轮询,实现实时同步。
数据层交互示例 #
本节通过 JSON-RPC 2.0 消息,逐步演示 MCP 客户端与服务端的交互过程,涵盖生命周期管理、工具操作和通知机制。
1. 初始化(生命周期管理) #
MCP 连接建立时,客户端通过发送 initialize 请求进行能力协商握手,以协商双方支持的功能。
如下是一次请求和响应的消息报文:
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-06-18",
"capabilities": {
"elicitation": {}
},
"clientInfo": {
"name": "example-client",
"version": "1.0.0"
}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-06-18",
"capabilities": {
"tools": {
"listChanged": true
},
"resources": {}
},
"serverInfo": {
"name": "example-server",
"version": "1.0.0"
}
}
}
完成三件事:
- 版本协商:通过
protocolVersion确保双方协议版本兼容,不兼容则断开连接 - 能力发现:通过
capabilities声明各自支持的原语和功能,避免调用不支持的操作。- 客户端声明支持
elicitation,即可接收服务器发起的用户交互请求 - 服务端声明支持
tools(含listChanged: true,可推送工具列表变更通知)和resources(可处理资源列表与读取请求)
- 客户端声明支持
- 身份交换:通过
clientInfo/serverInfo传递身份信息,用于调试和兼容性判断
初始化成功后,客户端发送 notifications/initialized 通知表示就绪:
{
"jsonrpc": "2.0",
"method": "notifications/initialized"
}
在 AI 应用中的工作方式:
初始化时,AI 应用的 MCP 客户端管理器连接所有配置的 Server,缓存其能力信息,后续据此判断哪个 Server 能提供所需功能(工具、资源、提示词)以及是否支持实时更新。
2. 工具发现(原语) #
连接建立后,客户端发送 tools/list 请求发现可用工具,在调用工具前先了解服务端有哪些工具。
如下是一次请求和响应的消息报文:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list"
}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"tools": [
{
"name": "calculator_arithmetic",
"title": "Calculator",
"description": "Perform mathematical calculations including basic arithmetic, trigonometric functions, and algebraic operations",
"inputSchema": {
"type": "object",
"properties": {
"expression": {
"type": "string",
"description": "Mathematical expression to evaluate (e.g., '2 + 3 * 4', 'sin(30)', 'sqrt(16)')"
}
},
"required": ["expression"]
}
},
{
"name": "weather_current",
"title": "Weather Information",
"description": "Get current weather information for any location worldwide",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, address, or coordinates (latitude,longitude)"
},
"units": {
"type": "string",
"enum": ["metric", "imperial", "kelvin"],
"description": "Temperature units to use in response",
"default": "metric"
}
},
"required": ["location"]
}
}
]
}
}
客户端发送 tools/list 请求,服务器响应所有可用工具的元数据数组。每个工具对象包含四个关键字段:
name:工具唯一标识符,用于调用title:面向用户的可读名称description:工具功能及使用场景说明inputSchema:JSON Schema 定义,描述输入参数的类型与约束
在 AI 应用中的工作方式:
AI 应用从所有已连接的 MCP Server 获取工具列表,合并为统一的工具注册表供 LLM 使用,使其了解可执行的操作并在对话中自动生成相应的工具调用。
3. 工具执行(原语) #
发现工具后,客户端通过 tools/call 方法携带参数请求执行具体工具。
如下是一次请求和响应的消息报文:
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "weather_current",
"arguments": {
"location": "San Francisco",
"units": "imperial"
}
}
}
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [
{
"type": "text",
"text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"
}
]
}
}
工具执行的关键要素:
name:必须与发现阶段返回的工具名完全一致,确保客户端与服务端之间类型安全、通信明确。arguments:按inputSchema传入参数,分必填和可选- JSON-RPC 2.0:使用唯一
id关联请求与响应
响应结构:
content数组支持多种类型(文本、图片等),通过type字段区分- 结构化输出可直接作为 LLM 的上下文使用
在 AI 应用中的工作方式:
AI 应用可动态调用服务端功能,并将结构化响应集成进 LLM 对话。LLM 决定调用工具时,AI 应用拦截请求 → 路由至对应 MCP Server → 执行 → 将结果返回 LLM,使其能访问实时数据并操作外部世界。
4. 实时通知 #
工具列表变化时,Server 主动推送 notifications/tools/list_changed(无需响应),客户端收到通知后,会重新请求tools/list 刷新工具列表,形成刷新循环,确保本地工具信息始终最新。
如下是通知的消息报文:
{
"jsonrpc": "2.0",
"method": "notifications/tools/list_changed"
}
关键特性:
- 无需响应:无
id字段,遵循 JSON-RPC 2.0 通知语义 - 能力驱动:仅限初始化时声明
listChanged: true的服务端发送 - 事件驱动:服务端根据内部状态变化主动推送,连接动态响应
通知机制的价值:
- 动态适应:工具可随服务端状态、权限等变化动态增减
- 高效:无需轮询,变更时主动推送
- 一致性:确保客户端始终掌握最新能力信息
- 实时同步:该机制不限于工具,覆盖所有 MCP 原语
在 AI 应用中的工作方式:
AI 应用收到工具变更通知后,立即刷新工具注册表并更新 LLM 的可用能力,确保对话中始终能使用最新工具。
MCP Server #
MCP Server是通过标准化协议向 AI 应用暴露特定能力的程序,可以运行在本地或者远程,通过 stdio 或者 http 与 Client 通讯,提供三大核心功能:
| 功能 | 说明 | 控制方 |
|---|---|---|
| 工具 Tools | LLM 主动调用的函数,可写数据库、调 API、修改文件 | 模型 |
| 资源 Resources | 只读数据源,提供上下文信息,如文件、数据库结构 | 应用 |
| 提示 Prompts | 预置指令模板,引导模型使用特定工具和资源 | 用户 |
Tools #
工具(Tools)让 AI 模型能够执行操作,每个工具定义明确的输入输出,模型根据上下文决定何时调用。基于 JSON Schema 定义的接口,每个工具执行单一操作,执行前可要求用户确认。
协议方法:
| 方法 | 用途 | 返回值 |
|---|---|---|
tools/list | 发现可用工具 | 包含 schema 的工具定义数组 |
tools/call | 执行指定工具 | 工具执行结果 |
工具(Tools)由模型自动发现和调用,但 MCP 通过多种机制确保人工监督。为保障安全,应用可通过以下机制实现用户管控:UI 展示可用工具、执行前弹窗确认、预授权安全操作、记录执行日志。
Resources #
资源(Resources)为 AI 应用提供结构化的信息访问,供应用检索后作为上下文传递给模型。本质是暴露文件、API、数据库等数据,每个资源有唯一 URI 和 MIME 类型,支持两种模式:
- 直接资源:固定 URI,如
calendar://events/2024 - 资源模板:动态 URI,如
travel://activities/{city}/{category}
协议方法:
| 方法 | 用途 | 返回值 |
|---|---|---|
resources/list | 列出可用资源 | 资源描述符数组 |
resources/templates/list | 发现资源模板 | 资源模板定义数组 |
resources/read | 获取资源内容 | 带元数据的资源数据 |
resources/subscribe | 监听资源变更 | 订阅确认 |
资源(Resources)由AI应用驱动,界面形式自由,常见模式有:树形/列表浏览、搜索过滤、智能推荐、手动批量选择。协议不强制规定 UI 形式,支持预览、上下文感知推荐及与现有文件浏览器集成。
Prompts #
提示(Prompts)是可复用的参数化模板,帮助用户更好地使用 MCP 服务器。需用户主动调用(非自动触发),可引用资源和工具构建完整工作流,并支持参数补全。
协议方法:
| 方法 | 用途 | 返回值 |
|---|---|---|
prompts/list | 发现可用提示 | 提示描述符数组 |
prompts/get | 获取提示详情 | 包含参数的完整提示定义 |
提示(Prompts)由用户主动调用,实现者可自由设计界面,核心原则:易于发现、描述清晰、参数验证、模板透明展示。常见 UI 形式:斜杠命令(/plan-vacation)、命令面板、快捷按钮、右键菜单。
开发 MCP Server #
准备环境 #
在WSL2的Ubuntu24中开发。需要如下工具
- python3:开发语言,系统默认版本
- uv:python 的包和项目管理器,需要安装,参考:https://docs.astral.sh/uv/getting-started/installation/
- npm:nodejs的包管理器,需要安装,参考:https://nodejs.org/zh-cn/download
新建 MCP Server #
新建一个项目:
uv init mcp-server
cd mcp-server
添加依赖的包:
uv add mcp
在 main.py 文件中添加如下源码:
from mcp.server.fastmcp import FastMCP
# Create an MCP server
mcp = FastMCP("Demo")
# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
"""Get a personalized greeting"""
return f"Hello, {name}!"
# Main execution block - this is required to run the server
if __name__ == "__main__":
mcp.run()
这是一个简单的MCP Server,默认的传输方式是 stdio,提供了两个功能:
- 一个工具
add,输入两个整数参数,返回两数之和。例如 - 一个资源模板
get_greeting,注册了一个带参数的资源地址模板greeting://{name},当访问某个名字时,会返回对应问候语。例如greeting://Alice会返回Hello, Alice!。
用 uv 启动这个 MCP Server,启动后会阻塞:
uv run main.py
使用 MCP Inspector 调试 #
MCP Inspector 是一个用于 测试和调试 MCP(Model Context Protocol)服务器 的交互式开发工具。基于NodeJS开发,具有如下特点:
- 可直接通过
npx启动 - 可以连接服务器,测试各项功能
- 查看服务器发送的通知和日志
- 适合本地开发、联调和排查问题
- 帮助开发者快速验证 MCP 服务器能力是否正常
启动 MCP Inspector:
npx @modelcontextprotocol/inspector
启动后会自动在浏览器中打开界面:

左侧是连接配置区域,选择传输方式,填写对应的参数,然后点击「Connect」按钮,就可以连接到 MCP Server。对应STDIO的服务器,Command和 Arguments按照服务进程的名称填写,这样它才能找到这个进程,然后通过STDIO与之通讯。连接成功后,在右侧会显示显示调试工具和通讯过程的报文。首先就是连接初始化时的报文:

进入Tools页面,可以点击「List Tools」列出可用的工具,选择相应的工具后,可以填写输入参数,运行工具,查看结果和通讯报文:

在Cursor中使用MCP Server #
以 markitdown 为例,这是微软开源的Python工具,用于将各种文件转换为 Markdown。同时提供markitdown-mcp ,一个本地运行的轻量级 MCP Server,支持三种传输协议:
- stdio:标准输入输出
- Streamable HTTP:流式 HTTP
- SSE:服务器推送事件
核心功能只有一个工具:convert_to_markdown(uri),可将 http:、https:、file:、data: 等 URI 指向的内容转换为 Markdown 格式。
推荐在Docker中运行这个MCP Server(https://hub.docker.com/r/mcp/markitdown),Docker 容器本身支持 stdio 透传。
先安装:
# 安装 docker image
> docker pull mcp/markitdown
# 安装后确认
> docker images
i Info → U In Use
IMAGE ID DISK USAGE CONTENT SIZE EXTRA
mcp/markitdown:latest 66579f88f7fe 1.53GB 405MB
在Cursor的MCP Server配置文件(~/.cursor/mcp.json)中添加如下内容:
{
"mcpServers": {
"markitdown": {
"command": "docker",
"args": [
"run",
"--rm",
"-i",
"-v",
"/home/lsc/workspace:/workdir",
"mcp/markitdown:latest"
]
}
}
}
说明:
-i(interactive):保持 stdin 开启,是 stdio 通信的关键参数mcp/markitdown:latest是安装的image的名称。/home/lsc/workspace:/workdir表示把本地的/home/lsc/workspace挂载到docker镜像的/workdir,这样才可以访问本地文件。
启动 Cursor时,会解析MCP配置文件,然后启动docker容器。以Cursor CLI为例,启动后执行/mcp list命令可以列出所有的MCP服务(根据提示,可能需要使能一些权限):
> agent
Cursor Agent
v2026.05.20-2b5dd59
Use /plan to plan execution and reach the right outcome faster.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
MCP Servers (1 servers)
User
→ markitdown - enabled (Enter to view details)
↑/↓ to navigate • Enter to select • Esc to close
选中以后,按Enter查看详情:
markitdown
Status: enabled
Command: docker
1 tools
View Tools Manage Server (tab to cycle)
→ convert_to_markdown (uri)
Tab to switch sections • ↑/↓ to navigate • Enter to act • Esc to go back
选中View Tools可以看到支持一个Tools:convert_to_markdown (uri),再按Enter可以查看 Tools的详情:
convert_to_markdown
markitdown
Params: uri
Input schema
{
"type": "object",
"properties": {
"uri": {
"title": "Uri",
"type": "string"
}
},
"required": [
"uri"
],
"title": "convert_to_markdownArguments"
}
↑/↓ to scroll schema • Esc to go back
在对话中输入提示词,会自动触发转换,例如“将 https://docs.kernel.org/i2c/summary.html 转换为markdown”:
Cursor Agent
v2026.05.20-2b5dd59
Use /plan to iterate on an implementation plan before code changes.
> convert to markdown: https://docs.kernel.org/i2c/summary.html , save ./i2c-summary.md
正在将内核文档页面转换为 Markdown 并保存到 i2c-summary.md。
markitdown convert_to_markdown
正在清理 Sphinx 侧边栏导航,生成适合独立阅读的 Markdown 文档并保存。