Spring AI Alibaba MCP协议实战:模型上下文协议集成与工具调用
导读:MCP(Model Context Protocol,模型上下文协议)是 Anthropic 于 2024 年末发布的开放标准,旨在解决 AI 工具调用的碎片化问题。Spring AI Alibaba 1.1 版对 MCP 提供了完整支持。本文深入讲解 MCP 的三层架构、服务端开发、客户端接入,以及与 Python MCP Server 的跨语言互通。
一、MCP 的诞生背景
在 MCP 出现之前,每个 AI 应用都需要为自己的工具调用写一套独立的集成代码。你用的是通义千问,我用的是 GPT,他用的是 Claude,各自的工具接口不通,无法复用------这就是 AI 工具生态碎片化的现状。
MCP 的价值在于定义了一套统一的工具调用协议,类似于 REST API 之于 Web 服务的地位:
没有 MCP(碎片化):
Application A ←→ 自定义集成 ←→ Tool 1
Application B ←→ 自定义集成 ←→ Tool 2
Application C ←→ 自定义集成 ←→ Tool 3
有了 MCP(标准化):
Application A ──┐
Application B ──┤←→ MCP Protocol ←→ MCP Server(Tool 1 + Tool 2 + Tool 3)
Application C ──┘
二、MCP 三层架构
+-------------------+ MCP Protocol +------------------+
| Host(宿主层) | ←←←←←←←←←←←←←←←←←← | Server(服务层) |
| | →→→→→→→→→→→→→→→→→→ | |
| - AI 应用 | | - 工具实现 |
| - 管理 Client | +---------------+ | - 资源暴露 |
+-------------------+ | Client(客户层)| | - Prompt 模板 |
| | - 工具发现 | +------------------+
+--→ 创建 Client → | - 工具调用 |
| - 资源访问 |
+---------------+
传输协议:
Stdio(标准输入输出):本地进程通信,适合本地工具
SSE(Server-Sent Events):HTTP 长连接,适合远程服务
WebSocket:双向通信,适合高频实时交互
三种能力类型(MCP Server 可以暴露):
- Tool:可调用的函数(最常用);
- Resource:可读取的资源(如文件、数据库);
- Prompt:预定义的提示模板(如角色扮演模板)。
三、依赖配置
3.1 Server 端依赖
xml
<!-- Spring AI MCP Server(提供工具服务)-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-server-spring-boot-starter</artifactId>
</dependency>
<!-- SSE 传输模式需要 Web 支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
3.2 Client 端依赖
xml
<!-- Spring AI MCP Client(消费工具服务)-->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-mcp-client-spring-boot-starter</artifactId>
</dependency>
<!-- DashScope 模型 -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
四、MCP Server 开发
4.1 基于 SSE 传输的 MCP Server
java
package com.example.mcp.server;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import lombok.extern.slf4j.Slf4j;
/**
* 天气查询 MCP 工具
* 通过 MCP 协议暴露给任何兼容的 AI 应用
*/
@Slf4j
@Component
public class WeatherMcpTool {
/**
* 获取城市天气
* @Tool 注解的方法会自动通过 MCP 协议暴露为工具
*/
@Tool(description = "获取指定城市的实时天气信息,包括温度、天气状况、湿度、风力等")
public WeatherInfo getWeather(
@ToolParam(description = "城市名称,支持中文,如:北京、上海") String city) {
log.info("[MCP Tool] 天气查询:{}", city);
// 实际项目:调用真实天气 API(和风天气、高德天气等)
return new WeatherInfo(city, "晴转多云", 22.5, 68, "东南风 3级");
}
/**
* 获取天气预报(未来 N 天)
*/
@Tool(description = "获取城市未来几天的天气预报,最多7天")
public String getWeatherForecast(
@ToolParam(description = "城市名称") String city,
@ToolParam(description = "预报天数,1-7之间") int days) {
log.info("[MCP Tool] 天气预报查询:{} 未来{}天", city, days);
StringBuilder sb = new StringBuilder(city).append(" 未来").append(days).append("天预报:\n");
String[] conditions = {"晴", "多云", "阴", "小雨", "晴", "多云", "晴"};
int[] temps = {22, 20, 18, 16, 19, 21, 23};
for (int i = 0; i < Math.min(days, 7); i++) {
sb.append(String.format("第%d天:%s,气温约%d°C\n", i + 1, conditions[i], temps[i]));
}
return sb.toString();
}
public record WeatherInfo(
String city,
String condition,
double temperature,
int humidity,
String wind
) {}
}
java
/**
* 数据库查询 MCP 工具
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class DatabaseMcpTool {
private final UserRepository userRepository;
private final OrderRepository orderRepository;
@Tool(description = "根据用户ID查询用户基本信息")
public String getUserInfo(@ToolParam(description = "用户ID") String userId) {
return userRepository.findById(userId)
.map(u -> String.format("用户:%s, 邮箱:%s, 注册时间:%s",
u.getName(), u.getEmail(), u.getCreatedAt()))
.orElse("用户 " + userId + " 不存在");
}
@Tool(description = "查询用户最近的订单记录")
public String getRecentOrders(
@ToolParam(description = "用户ID") String userId,
@ToolParam(description = "查询条数,1-20之间") int limit) {
List<Order> orders = orderRepository.findByUserIdOrderByCreatedAtDesc(
userId, PageRequest.of(0, Math.min(limit, 20)));
if (orders.isEmpty()) return "暂无订单记录";
return orders.stream()
.map(o -> String.format("订单%s:%s ¥%.2f [%s]",
o.getId(), o.getProductName(), o.getAmount(), o.getStatus()))
.collect(Collectors.joining("\n"));
}
}
4.2 Server 配置
yaml
# application.yml(MCP Server 端)
spring:
application:
name: mcp-weather-server
ai:
mcp:
server:
# 服务名称(客户端用于标识此 Server)
name: weather-and-database-tools
# 版本
version: 1.0.0
# 传输模式:SSE(HTTP) 或 STDIO(标准输入输出)
transport: SSE
# 服务描述
description: "提供天气查询和数据库查询能力的 MCP Server"
server:
port: 8090
启动后,MCP Server 会自动在以下端点暴露工具信息:
GET /mcp/tools- 查询可用工具列表POST /mcp/call- 调用工具
五、MCP Client 接入
5.1 配置 MCP Client
yaml
# application.yml(MCP Client 端)
spring:
ai:
mcp:
client:
# 配置多个 MCP Server
servers:
# 本地天气服务(SSE 模式)
weather-server:
transport: SSE
url: http://localhost:8090
# 超时配置
connection-timeout: 5s
request-timeout: 30s
# 远程数据分析服务(SSE 模式)
analytics-server:
transport: SSE
url: https://analytics.internal.company.com/mcp
# 本地 Python MCP Server(Stdio 模式)
python-tools:
transport: STDIO
command: python
args: ["-m", "my_mcp_server"]
5.2 在 ChatClient 中使用 MCP 工具
java
@Service
@RequiredArgsConstructor
@Slf4j
public class McpChatService {
private final ChatClient chatClient;
// Spring AI 自动注入所有已配置的 MCP 工具
private final List<McpSyncClient> mcpClients;
/**
* 使用 MCP 工具的智能对话
* Spring AI 自动处理 MCP 工具的发现和调用
*/
public String chatWithMcpTools(String message) {
log.info("使用 MCP 工具处理消息:{}", message);
// 获取所有 MCP 工具的 ToolCallbackProvider
List<ToolCallback> mcpToolCallbacks = mcpClients.stream()
.flatMap(client -> {
// 工具发现:获取 Server 暴露的所有工具
var toolsResult = client.listTools();
return toolsResult.tools().stream()
.map(tool -> McpFunctionCallback.builder()
.mcpClient(client)
.tool(tool)
.build());
})
.collect(Collectors.toList());
return chatClient.prompt()
.user(message)
.tools(mcpToolCallbacks.toArray(new ToolCallback[0]))
.call()
.content();
}
/**
* 动态工具发现:运行时查询 MCP Server 可用工具
*/
public List<String> discoverTools() {
return mcpClients.stream()
.flatMap(client -> {
String serverName = client.getServerInfo().name();
return client.listTools().tools().stream()
.map(tool -> serverName + "/" + tool.name() +
":" + tool.description());
})
.collect(Collectors.toList());
}
}
六、与 Python MCP Server 跨语言互通
MCP 的一大优势是语言无关性。Python 社区有大量优秀的 MCP Server 实现(如代码执行、数据分析等),可以直接从 Java 侧接入:
yaml
# 接入 Python MCP Server(Stdio 模式)
spring:
ai:
mcp:
client:
servers:
python-analyzer:
transport: STDIO
# 启动 Python MCP Server 进程
command: /usr/bin/python3
args: ["/opt/mcp-servers/data-analyzer/main.py"]
# 环境变量(传入数据库连接等配置)
environment:
DB_HOST: "localhost"
DB_PORT: "5432"
Python 侧 MCP Server 示例(仅供理解协议,不做重点展开):
python
# main.py - Python MCP Server 示例结构
from mcp.server import Server
from mcp.server.stdio import stdio_server
app = Server("data-analyzer")
@app.call_tool()
async def analyze_data(name: str, arguments: dict) -> list:
if name == "run_sql":
query = arguments["query"]
# 执行 SQL 并返回结果
return [{"type": "text", "text": f"查询结果: {execute_sql(query)}"}]
async def main():
async with stdio_server() as streams:
await app.run(*streams, app.create_initialization_options())
Java 侧通过 Stdio 模式调用 Python Server,完全透明。
七、安全机制
7.1 Server 端安全隔离
yaml
spring:
ai:
mcp:
server:
# 启用工具白名单(只允许调用指定工具)
tool-whitelist:
- getWeather
- getWeatherForecast
- getUserInfo
# 不在列表中的工具不对外暴露
# 启用请求鉴权
security:
enabled: true
api-key: ${MCP_SERVER_API_KEY}
7.2 Client 端权限控制
java
@Configuration
public class McpSecurityConfig {
/**
* MCP Client 请求拦截器:添加认证头
*/
@Bean
public McpClientCustomizer mcpClientCustomizer() {
return (clientBuilder) -> clientBuilder
// 为每个 MCP 请求添加认证 Header
.requestInterceptor(request -> {
request.headers().add("X-MCP-API-Key",
System.getenv("MCP_SERVER_API_KEY"));
return request;
})
// 请求超时
.requestTimeout(Duration.ofSeconds(30));
}
}
八、企业内部 MCP Registry
大型企业可以构建内部的 MCP 工具注册中心,统一管理所有 MCP Server:
java
/**
* MCP Registry:企业内部工具注册中心
*/
@RestController
@RequestMapping("/api/mcp/registry")
@RequiredArgsConstructor
public class McpRegistryController {
private final McpRegistryService registryService;
/**
* 注册新的 MCP Server
*/
@PostMapping("/register")
public ResponseEntity<McpServerInfo> register(
@RequestBody McpServerRegistration registration) {
McpServerInfo info = registryService.register(registration);
return ResponseEntity.ok(info);
}
/**
* 查询所有可用的 MCP Server 和工具
*/
@GetMapping("/discover")
public ResponseEntity<List<McpServerInfo>> discover(
@RequestParam(required = false) String category,
@RequestParam(required = false) String keyword) {
return ResponseEntity.ok(registryService.discover(category, keyword));
}
/**
* 健康检查:验证所有注册的 MCP Server 是否在线
*/
@GetMapping("/health")
public ResponseEntity<Map<String, String>> healthCheck() {
return ResponseEntity.ok(registryService.checkAllHealth());
}
}
九、总结
MCP 正在成为 AI 工具生态的"通用插座",本文的核心收获:
- MCP 三层架构:Host(宿主)→ Client(客户端)→ Server(工具服务);
- 传输协议:Stdio 适合本地进程,SSE 适合远程 HTTP 服务;
- 三种能力:Tool(可调用函数)、Resource(可读资源)、Prompt(模板);
- Server 开发 :
@Tool注解 + Spring Boot,几行代码构建 MCP Server; - 跨语言互通:通过 Stdio 模式接入 Python、Node.js 等语言的 MCP Server;
- 安全机制:工具白名单 + API Key 认证,防止未授权访问。
下一篇将进入 Deep Research 自动化调研领域,探讨如何利用 Spring AI Alibaba 1.1 的推理模式实现多步骤深度研究报告自动生成。
参考资料