什么是Model Context Protocol (MCP)?
MCP(模型上下文协议)是一种为 AI 助手(如聊天机器人或自动化代理)提供访问外部数据和工具的 通用规则(协议)。
传统上,若想让 AI 使用数据库、Web 服务或本地文件,开发者需要为每种连接方式单独编写代码。这意味着每次扩展 AI 功能时,都需为新工具开发专属代码。
MCP 通过 标准化“AI ⇔ 数据或工具”的连接方式,允许 AI 使用统一的机制与各种数据源或外部服务交互。这为 AI 开发者和数据管理者带来了显著的效率提升和更高的代码复用性。
MCP 的通用规则是什么?
MCP 通过初始化时确认双方的“角色与功能”,随后使用统一格式的请求/响应进行自由交互。其核心机制可概括为以下三点:
-
通用语言:JSON-RPC 如同国际会议指定英语为通用语言,MCP 使用 JSON-RPC 2.0 作为通信格式。
-
首次“名片交换”:initialize
客户端首次向服务器发送 initialize 方法,类似于“自我介绍”:
- 客户端:我具备这些功能。
- 服务器:我能提供这些功能。
这建立了双方的信任和功能清单。
- 通道建立后的交互
初始化完成后,客户端和服务器可通过统一规则进行以下交互:
- tools:调用注册的函数。
- resources:获取文件或数据。
- prompts:获取对话模板。
- logging/completion/ping:日志、完成状态或心跳检测。
通信方式自由:JSON-RPC 仅定义格式,实际传输可- 使用标准输入输出(stdio)、Streamable HTTP、WebSocket 等。目前,stdio 和 Streamable HTTP 是标准选项。
MCP 架构
MCP 架构以 主机(Host)、客户端(Client) 和 服务器(Server) 三个角色为核心,构建了一个灵活的 AI 功能扩展框架。
- 一个主机可生成多个客户端。
- 每个客户端与一个服务器进行一对一通信。
- 通过这种结构,AI 功能得以动态扩展。
三个角色的职责
- 主机(Host) 主机是 MCP 系统的核心,负责:
- 管理客户端:生成并管理多个客户端(会话),控制安全性和权限。
- 协调 AI:决定 AI(LLM)使用哪些数据或功能,并向服务器发送请求。
- 整合信息:汇总各客户端从服务器获取的数据,供 AI 优化使用。
- 客户端 (Client)
客户端负责与特定服务器进行 一对一通信,其功能包括:
- 专用通信:一个客户端只与一个服务器交互,例如“数据库客户端”或“翻译客户端”。
- JSON-RPC 交互:使用 initialize、call_tool、read_resource 等方法与服务器通信。
- 事件处理:接收服务器的日志通知等,并反馈给主机。
- 实现要点:
(1)客户端实现较简单,主要包括
ClientSession
(协议层)和传输模块(如stdio_client、sse_client
、websocket_client
)。 (2)ClientSession
负责生成和发送JSON-RPC
消息,处理核心操作(如initialize、tools/call
)。 (3)传输层使用 stdio 或 SSE 交换 JSON 消息。
- 服务器 (Server)
服务器为 AI 提供可用的功能或数据,职责包括:
- 提供工具和资源:公开功能(如翻译、数据库查询、文件读写)供客户端调用。
- 隔离操作:为安全起见,仅处理自身权限内的资源,不直接访问主机或其他服务器数据。
- 可选 AI 交互:通过客户端向主机的 LLM 请求额外处理(例如,翻译服务器请求其他语言处理)。
- 实现要点:
(1)提供低级 Server 类和高级 FastMCP 框架。
(2)Server 使用装饰器(如
@server.call_tool
、@server.list_tools
)定义请求处理逻辑,管理“哪个方法调用哪个函数”。 (3)ServerSession
为每个客户端连接生成会话,处理JSON-RPC
消息并调用注册的处理函数。 (4)FastMCP
自动配置 SSE 路由和工具管理,简化开发。 (5)传输层与客户端类似,使用 stdio 或 SSE。
设计原则
MCP 的设计遵循以下原则:
- 服务器简洁:服务器专注单一功能,复杂协调由主机负责。
- 高组合性:通过通用协议,服务器如积木般可自由组合,扩展 AI 功能。
- 权限隔离:服务器仅操作自身权限内的资源,主机负责全局管理。
- 渐进扩展:核心功能保持最小化,通过“功能协商”(capability negotiation)逐步添加扩展,兼顾后向兼容性。
客户端与服务器的通信机制
MCP 的通信分为 协议层、传输层 和 消息类型 三个层面:
- 协议层(会话)
- 作用:定义消息框架(JSON-RPC 结构),关联请求与响应。
- 实现:
(1)客户端使用
ClientSession
管理“生成请求-发送-接收响应”的流程。 (2)服务器使用ServerSession
管理“接收请求-调用处理函数-返回结果”的流程。 (3)消息以“请求/结果/错误/通知”形式处理,由会话解析和匹配。
- 传输层
- 作用:负责实际的字节流传输。
- 标准方式: (1)stdio:通过标准输入输出交换 JSON 消息,适合本地进程间通信。 (2)Streamable HTTP:服务器通过 SSE(Server-Sent Events)发送消息,客户端通过 HTTP POST 发送请求。
- 机制:会话生成 JSON-RPC 消息,传输层负责实际发送和接收。
- 消息类型
MCP 基于 JSON-RPC 定义了四种消息:
- 请求 (Requests):需要响应的调用,包含 method、params 和 id。
- 结果 (Results):请求的成功响应,包含 result 字段。
- 错误 (Errors):请求失败时的信息,包含 code、message 和 data。
- 通知 (Notifications):无需响应的单向消息,用于日志或进度通知。
连接生命周期
MCP 的客户端与服务器通信遵循明确的生命周期,违反规则将导致错误:
- 初始化 (Initialization)
- 客户端发送
initialize
请求,包含版本和功能信息。 - 服务器返回支持的版本和功能。
- 客户端发送
initialized
通知,确认连接建立。 - 完成初始化后,进入可交互状态。
- 消息交换 (Message Exchange)
- 请求-响应:双方可互发请求并接收响应。
- 通知:双方可发送单向通知。
- 终止 (Termination)
- 正常关闭:通过
close()
等方法。 - 异常终止:网络断开或错误状态。
MCP 的核心组件通过协议层管理交互,传输层处理输入输出,客户端与服务器在统一规则下交换工具、资源等功能。
实现简单的MCP服务器:Python入门实践
准备工作
在开始之前,确保你的系统已安装 Python(推荐 3.8+)和 uv(一个快速的 Python 包管理和虚拟环境工具)。关于 uv 的安装,请参考 uv 官方文档(https://docs.astral.sh/uv/)。
步骤 1:创建虚拟环境
为隔离项目依赖,推荐使用虚拟环境。uv 提供了一种轻量高效的解决方案。以下是创建虚拟环境的命令:
uv init mcp-server-demo
cd mcp-server-demo
uv add "mcp[cli]"
这些命令将初始化一个名为 mcp-server-demo 的项目。然后进入项目目录,安装 MCP Python SDK 及其 CLI 工具。
步骤 2:编写 MCP 服务器代码
在 mcp-server-demo 目录下,创建 server.py
文件,并添加以下代码,这个服务器实现了一个简单的加法工具:
//server.py
from mcp.server.fastmcp import FastMCP
# 创建一个启用调试模式的 MCP 服务器
mcp = FastMCP("Demo", debug=True)
# 定义加法工具
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers"""
return a + b
# 运行服务器
if __name__ == "__main__":
print("Starting MCP server in stdio mode")
mcp.run(transport="stdio")
代码解析:
- FastMCP("Demo", debug=True):初始化一个名为“Demo”的 MCP 服务器,启用调试模式以便查看详细日志。
- @mcp.tool():将 add 函数注册为 MCP 工具,接受两个整数参数并返回其和。
- mcp.run(transport="stdio"):以 stdio 传输模式启动服务器,适合本地测试。
步骤 3:配置 Cline 或 Cursor
要让 Cline 或 Cursor 识别 MCP 服务器,需配置相应的 JSON 文件:
- Cline:编辑
cline_mcp_settings.json
。 - Cursor:编辑
mcp.json
(通常位于项目根目录下的.cursor
文件夹或用户目录下的~/.cursor
)。
配置文件内容如下:
{
"mcpServers": {
"mcp-demo-server": {
"command": "uv",
"args": [
"--directory",
"<mcp server directory>",
"run",
"server.py"
],
"alwaysAllow": [
"add"
],
"disabled": false
}
}
}
配置说明:
<mcp server directory>
:替换为mcp-server-demo
目录的绝对路径,例如/Users/karaage/mcp-server-demo
。"command": "uv"
:使用uv
运行服务器。"alwaysAllow": ["add"]
:允许客户端调用add
工具。"disabled": false
:启用服务器。
保存配置后,Cline 或 Cursor 会自动执行指定命令以启动服务器。
步骤 4:验证服务器运行
在 Cline 或 Cursor 的 MCP 服务器管理界面中,检查服务器状态:
- 如果显示服务器名称(如 mcp-demo-server)且无错误提示,说明服务器已成功启动。
- 若需重启服务器(例如代码更改后),点击界面右上角的“重启”按钮(旋转箭头图标)。
步骤 5:测试 MCP 服务器
在 Cline 或 Cursor 的聊天窗口中输入以下指令:
简单计算
使用 MCP 服务器 mcp-demo-server 进行加法计算,例如 3 + 5。
如果配置正确,LLM 会自动调用 add
工具并返回结果(如 8
)。
测试用例 1:错误计算
假设我们故意将加法改为减法(a - b
),例如计算 5 - 3
:
LLM 可能会注意到计算逻辑与指令不符,并提示错误。
测试用例 2:复杂计算
再试一个复杂场景,例如计算 (a + b - 1
),如 3 + 5 - 1
:
在这里,LLM 可能直接接受服务器的结果(如 7
),而未察觉逻辑错误。这表明 LLM 通常信任 MCP 服务器的输出。
最后
希望本文能为 MCP 初学者提供参考!
参考资料:
评论(0)