泡沫机械
96.43M · 2026-03-24
在上一篇文章 《Spring AI MCP 实战:手把手构建 Todo Manager 应用》 中,我们通过一个完整案例了解了如何使用 Spring AI MCP 开发应用。
本文作为系列的第二篇,将深入讲解 MCP 协议本身,帮助你从原理层面理解这一新兴标准。Java SDK 代码仅作为示例使用。
**Model Context Protocol(MCP)**是一个开放的协议标准,用于定义 AI 模型与外部工具、资源之间的交互方式。
简单来说,MCP 想让 AI 模型能够像人类一样"使用工具"—— 只不过人类用鼠标点击,AI 通过协议调用。
在 AI 应用开发中,我们面临以下挑战:
| 挑战 | 描述 |
|---|---|
| 工具集成碎片化 | 每个工具都有自己的 API 格式 |
| 缺乏统一标准 | 不同 AI 框架使用不同的集成方式 |
| 互操作性差 | 跨语言、跨平台调用复杂 |
MCP 的目标就是解决这些问题。
┌─────────────────────────────────────────────┐
│ MCP 设计目标 │
├─────────────┬─────────────┬─────────────────┤
│ 标准化 │ 互操作性 │ 可扩展 │
│ 统一接口 │ 跨语言平台 │ 按需添加能力 │
│ 规范 │ 无缝通信 │ 灵活扩展 │
└─────────────┴─────────────┴─────────────────┘
| 场景 | 说明 | 示例 |
|---|---|---|
| AI 工具集成 | 让 AI 调用外部 API | 天气查询、数据库操作 |
| 资源访问 | AI 读取外部数据源 | 文件、文档、知识库 |
| 提示模板 | 预定义的 Prompt 模板 | 代码审查、文档生成 |
| 技术 | 定位 | 与 MCP 的关系 |
|---|---|---|
| REST API | 通用 HTTP API | MCP 可基于 HTTP 传输 |
| gRPC | RPC 框架 | 不同的抽象层次 |
| OpenAPI | API 文档规范 | MCP 包含类似的能力描述 |
MCP 采用经典的客户端 - 服务器架构:
┌─────────────────┐ ┌─────────────────┐
│ MCP Client │ │ MCP Server │
│ (请求发起方) │◄───────►│ (能力提供方) │
└─────────────────┘ JSON-RPC └─────────────────┘
角色说明:
| 角色 | 职责 | 典型实现 |
|---|---|---|
| Client | 发起请求、消费能力 | AI 应用、Agent 框架 |
| Server | 暴露能力、响应请求 | 工具服务、数据源 |
MCP 支持多种传输方式:
┌──────────┐ ┌──────────┐
│ Client │ ──stdin─►│ Server │
│ │ ◄─stdout─│ │
└──────────┘ └──────────┘
┌──────────┐ ┌──────────┐
│ Client │ ──HTTP─►│ Server │
│ │ ◄──SSE──│ │
└──────────┘ └──────────┘
┌──────────┐ ┌──────────┐
│ Client │ ◄──────►│ Server │
│ │ 双向流 │ │
└──────────┘ └──────────┘
MCP 基于 JSON-RPC 2.0 规范定义消息格式。
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [...]
}
}
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32600,
"message": "无效请求"
}
}
MCP 服务器可以暴露以下几种能力:
Tools 是服务器暴露给客户端的可调用功能。
客户端请求工具列表:
// 请求
{
"method": "tools/list",
"params": {}
}
// 响应
{
"tools": [
{
"name": "create_todo",
"description": "创建一个新的待办事项",
"inputSchema": {
"type": "object",
"properties": {
"title": {"type": "string", "description": "待办标题"},
"description": {"type": "string", "description": "待办描述"}
},
"required": ["title"]
}
}
]
}
// 请求
{
"method": "tools/call",
"params": {
"name": "create_todo",
"arguments": {
"title": "学习 MCP",
"description": "阅读协议文档"
}
}
}
// 响应
{
"content": [
{
"type": "text",
"text": " 待办已创建n ID: 550e8400-e29b-41d4-a716-446655440000"
}
]
}
// Server 端注册工具
@Bean
public McpServerFeatures.SyncToolSpecification createTodoTool() {
return SyncToolSpecification.builder()
.tool(McpSchema.Tool.builder()
.name("create_todo")
.description("创建待办事项")
.inputSchema(...) // JSON Schema 定义
.build())
.callHandler((exchange, request) -> {
// 处理工具调用
return McpSchema.CallToolResult.builder()...;
})
.build();
}
Resources 是服务器暴露的数据源,通过 URI 访问。
// 请求
{"method": "resources/list"}
// 响应
{
"resources": [
{
"uri": "todo://all",
"name": "所有待办",
"mimeType": "application/json"
}
]
}
// 请求
{
"method": "resources/read",
"params": {"uri": "todo://all"}
}
// 响应
{
"contents": [
{
"uri": "todo://all",
"text": "[{"id":"1","title":"学习 MCP"}]"
}
]
}
// 订阅
{
"method": "resources/subscribe",
"params": {"uri": "todo://all"}
}
// 变更通知(服务器主动推送)
{
"method": "notifications/resources/updated",
"params": {"uri": "todo://all"}
}
Prompts 是预定义的提示词模板。
// 获取 Prompt
{
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {"language": "java"}
}
}
// 响应
{
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "请审查以下 Java 代码..."
}
}
]
}
| 能力 | 说明 |
|---|---|
| Completions | 自动补全,类似 IDE 的智能提示 |
| Logging | 结构化日志,便于调试和监控 |
MCP 客户端也可以向服务器提供能力:
Roots 定义服务器可访问的文件系统边界。
// 获取 Roots
{"method": "roots/list"}
// 响应
{
"roots": [
{"uri": "file:///project/src", "name": "源代码"}
]
}
客户端提供 LLM 生成能力给服务器使用:
{
"method": "sampling/createMessage",
"params": {
"messages": [...],
"maxTokens": 100,
"modelPreferences": {"hints": ["claude-sonnet"]}
}
}
服务器通过客户端请求用户输入:
{
"method": "elicitation/create",
"params": {
"message": "请选择操作类型",
"requestedSchema": {
"type": "object",
"properties": {
"action": {"type": "string", "enum": ["create", "update", "delete"]}
}
}
}
}
MCP 连接建立需要完成握手流程:
Client Server
│ │
│──── initialize ────────────►│
│ │
│◄───── initialize ───────────│
│ │
│──── initialized ───────────►│
│ │
│ 连接建立完成 │
initialize 请求示例:
{
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {
"roots": {"listChanged": true}
},
"clientInfo": {
"name": "mcp-client",
"version": "1.0.0"
}
}
}
客户端和服务器在初始化时交换各自支持的能力:
// 服务器能力
{
"capabilities": {
"tools": {"listChanged": true},
"resources": {"subscribe": true, "listChanged": true},
"prompts": {}
}
}
标准 JSON-RPC 错误码:
| 错误码 | 含义 |
|---|---|
| -32700 | 解析错误 |
| -32600 | 无效请求 |
| -32601 | 方法不存在 |
| -32602 | 参数无效 |
| -32603 | 内部错误 |
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
<version>1.0.0</version>
</dependency>
// 创建传输层
McpAsyncTransport transport = new WebFluxSseClientTransport(
"http://localhost:8080"
);
// 创建客户端
McpSyncClient client = McpClient.sync(transport).build();
// 初始化握手
client.initialize();
// 列出工具
var tools = client.listTools();
// 调用工具
var result = client.callTool(
new CallToolRequest("create_todo",
Map.of("title", "学习 MCP"))
);
// 创建传输层
WebFluxSseServerTransportProvider transport =
new WebFluxSseServerTransportProvider();
// 创建服务端
McpSyncServer server = McpServer.sync(transport).build();
// 注册工具
server.addTool(toolSpec);
本文系统讲解了 MCP 协议的核心内容:
MCP 作为 AI 应用集成的新标准,其设计思想值得深入学习。掌握 MCP 协议,有助于我们更好地理解 AI Agent 生态的发展趋势。