MCP 是什么? Link to heading
MCP 是一个开放协议,它规范了应用程序向大型语言模型提供上下文的方式。你可以把 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为你的设备连接各种外设和配件提供了一种标准化的方式一样,MCP 也为 AI 模型连接不同的数据源和工具提供了一种标准化的方式。
MCP 帮助我们在 LLM 之上构建代理和复杂的业务流程。LLM 经常需要与数据和工具集成,MCP 提供了:
- 让 LLM 可以直接接入一个不断增长的预构建集成服务列表的能力
- 能够在大型语言模型服务提供商和供应商之间灵活切换
- 保护基础设施中数据的安全最佳实践
通用架构 Link to heading
MCP 核心采用客户端-服务器(CS)架构,主机应用可以连接多个服务器:
(Claude, IDEs, Tools)"] S1["MCP Server A"] S2["MCP Server B"] S3["MCP Server C"] Host <-->|"MCP Protocol"| S1 Host <-->|"MCP Protocol"| S2 Host <-->|"MCP Protocol"| S3 S1 <--> D1[("Local
Data Source A")] S2 <--> D2[("Local
Data Source B")] end subgraph "Internet" S3 <-->|"Web APIs"| D3[("Remote
Service C")] end
- MCP主机:如 Claude 桌面版、集成开发环境(IDE)或 AI 工具等,需要通过 MCP 访问数据的程序
- MCP客户端:与服务器保持 1:1 连接的协议客户端
- MCP服务器:轻量级程序,通过标准化的模型上下文协议(Model Context Protocol)暴露特定功能
- 本地数据源:MCP 服务器可安全访问的计算机文件、数据库和服务
- 远程服务:可通过互联网(如 API)连接的外部系统,MCP 服务器可与之交互
核心架构 Link to heading
模型上下文协议(MCP)基于灵活且可扩展的架构,能够实现大型语言模型应用与集成之间的无缝通信。接下来介绍 MCP 核心的架构组件与概念,帮助我们理解 MCP 如何连接客户端、服务器和 LLM。
核心组件 Link to heading
协议层 Link to heading
协议层负责消息封装、请求/响应关联以及高级通信模式。
以 Typescript 为例,MCP 协议层可以采用以下方式实现:
class Protocol<Request, Notification, Result> {
// Handle incoming requests
setRequestHandler<T>(schema: T, handler: (request: T, extra: RequestHandlerExtra) => Promise<Result>): void
// Handle incoming notifications
setNotificationHandler<T>(schema: T, handler: (notification: T) => Promise<void>): void
// Send requests and await responses
request<T>(request: Request, schema: T, options?: RequestOptions): Promise<T>
// Send one-way notifications
notification(notification: Notification): Promise<void>
}
关键类包括:
Protocol
Client
Server
传输层 Link to heading
传输层负责客户端与服务器之间的实际通信。MCP 支持多种传输机制:
-
Stdio 传输
- 使用标准输入/输出进行通信
- 非常适合本地进程
-
HTTP with SSE 传输
- 使用 Server-Sent Events 实现服务器向客户端的消息传递
- 使用 HTTP POST 实现客户端向服务器的消息传递
所有传输方式均使用 JSON-RPC 2.0 交换消息。有关 Model Context Protocol 消息格式的详细信息,请参阅 MCP 规范文档。
消息 Link to heading
MCP 主要包含以下几种类型的消息:
-
Requests 向对方发送请求,等待对方的回应:
interface Request { method: string; params?: { ... }; }
-
Results 针对请求的回应:
interface Result { [key: string]: unknown; }
-
Errors 表示请求失败:
interface Error { code: number; message: string; data?: unknown; }
-
Notifications 一种单向信息,无需回复:
interface Notification { method: string; params?: { ... }; }
连接生命周期 Link to heading
1. 初始化 Link to heading
- 客户端发送
initialize
请求,包含协议版本和功能特性 - 服务器响应其协议版本和功能特性
- 客户端发送
initialized
通知,表示确认 - 正常消息交互开始
2. 消息交换 Link to heading
初始化完成后,支持以下模式:
- Request-Response:客户端或服务器一方发送请求,另一方进行响应
- Notifications:任何一方单向发送消息
3. 终止 Link to heading
任何一方都可以终止连接:
- 通过
close()
进行正常关闭 - 传输层断开连接
- 出现错误情况
错误处理 Link to heading
MCP 定义了以下标准错误代码:
enum ErrorCode {
// Standard JSON-RPC error codes
ParseError = -32700,
InvalidRequest = -32600,
MethodNotFound = -32601,
InvalidParams = -32602,
InternalError = -32603
}
SDK 和应用程序可以定义自己的错误码,范围在 -32000
以上。
错误通过以下方式传播:
- 请求的错误响应
- 传输层的错误事件
- 协议层的错误处理器
实现示例 Link to heading
这里有一个实现MCP服务器的简单 Typescript 示例:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({
name: "example-server",
version: "1.0.0"
}, {
capabilities: {
resources: {}
}
});
// Handle requests
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "example://resource",
name: "Example Resource"
}
]
};
});
// Connect transport
const transport = new StdioServerTransport();
await server.connect(transport);
对最佳实践的一些建议 Link to heading
对协议实现的一些建议 Link to heading
传输层模式选择 Link to heading
-
本地通信
- 使用 stdio 传输进行本地进程通信
- 同机通信效率高
- 进程管理简单
-
远程通信
- 需要 HTTP 兼容的场景使用 SSE
- 考虑安全影响,包括认证和授权
消息处理 Link to heading
-
请求处理
- 彻底验证输入
- 使用类型安全的模式
- 优雅处理错误
- 实现超时机制
-
进度报告
- 长操作使用进度令牌
- 分步报告进度
- 知道总进度时包含在内
-
错误管理
- 使用合适的错误码
- 提供有价值的错误信息
- 错误时清理资源
对安全的一些建议 Link to heading
-
传输安全
- 远程连接使用 TLS
- 验证连接来源
- 需要时实施认证
-
消息验证
- 验证所有传入消息
- 消毒输入
- 检查消息大小限制
- 验证 JSON-RPC 格式
-
资源保护
- 实施访问控制
- 验证资源路径
- 监控资源使用情况
- 限制请求频率
-
错误处理
- 不泄露敏感信息
- 记录安全相关的错误
- 实施正确清理
- 处理拒绝服务攻击场景
对调试与监控的一些建议 Link to heading
-
日志记录
- 记录协议事件
- 追踪消息流向
- 监控性能
- 记录错误
-
诊断
- 实施健康检查
- 监控连接状态
- 追踪资源使用情况
- 性能分析
-
测试
- 测试不同传输方式
- 验证错误处理
- 检查边界情况
- 对服务器进行压力测试