前言
在当今快速发展的AI应用生态中,我们从优化提示词到使用Tool Calling突破大模型语言生成的界限,实现调用外部系统完成实际任务。但随着工具数量的增长和应用场景的复杂化,传统的Tool Calling实现方式暴露出一系列挑战:工具接口格式不统一、模型需硬编码工具定义、跨平台兼容性差等问题日益凸显。
为了解决这些痛点,一个全新的概念——MCP应运而生。
什么是MCP
MCP全称为Model Context Protocol,即模型上下文协议。需要明确的是,MCP并不是Tool Calling的替代品,而是为其提供一个统一、可扩展、跨平台的连接基础设施。
简单来说,MCP就是Tool Calling的管理者:
- Tool Calling:负责决策——模型决定要不要调用工具、调用哪个工具
- MCP:负责规范——规定如何描述工具、如何发起调用、如何传递结果
有了MCP之后,AI模型只需要学习一种标准格式,所有的协议转换工作都由MCP Server负责完成,极大降低了多工具集成的复杂度。
MCP Java SDK 架构
MCP Java SDK提供了MCP协议的Java语言实现,支持通过同步和异步两种通信模式,与AI模型及各类工具进行标准化交互。
其核心架构可以用餐饮服务类比来理解:
- Client/Server:分别代表请求的发起者和请求的接收者,如同顾客和后厨的关系
- Session:负责管理会话的整个生命周期,相当于订单管理系统
- Transport:定义消息传递的具体方式,就像手机订餐加上骑手送餐的完整配送链路
Transport传输协议
MCP Java SDK提供了多种"通信方式",让AI应用(客户端)能够灵活地与各种工具服务(服务器)进行对话,目前主要支持三种传输方式:
-
基于Stdio的进程间通信传输协议 通过标准输入/输出(stdin和stdout)在两个程序之间传递消息,高效直接,适合本地进程间通信
-
基于Java HttpClient的SSE客户端传输协议 基于Java HttpClient发起HTTP请求,并接收服务端持续发送的事件流,适合远程服务调用
-
WebFlux SSE客户端传输协议 基于WebFlux的非阻塞、响应式编程模型处理SSE流,适合高并发场景
MCP Server与MCP Client
MCP Server
MCP Server是MCP协议的具体服务端实现,是对外提供特定功能的服务程序。开发者可以直接到MCP Server社区查找并调用所需的功能,目前活跃的社区资源包括:
- GitHub MCP Registry:https://github.com/mcp/registry
- MCP Flow:https://mcpflow.io/home
- 火山引擎MCP广场:www.volcengine.com/mcp-marketplace
MCP Client
有了MCP服务端后,如何在代码中调用这些服务?这就需要借助MCP客户端。MCP客户端是连接本地开发环境或应用与远程MCP服务器之间的桥梁,不同客户端对MCP协议的支持程度各不相同,用户可以根据自己的需求选择合适的客户端。
MCP使用实战
在使用MCP Client之前,通常需要先运行一个或多个MCP Server实例。许多MCP Server是通过npx或uv命令启动的,在开始使用前,必须正确配置相应的运行环境。
第一步:准备MCP Server配置
可以到各大MCP社区获取相应的服务配置,以百度地图服务为例:
{
"mcpServers": {
"baidu-map": {
"command": "npx",
"args": [
"-y",
"@baidumap/mcp-server-baidu-map"
],
"env": {
"BAIDU_MAP_API_KEY": "xxx"
}
}
}
}
第二步:Spring AI项目接入
除了通过Cursor等客户端使用外,我们也可以通过Spring AI代码来接入这些MCP资源。首先引入相关依赖:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring-ai-project</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mcp-client-demo</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-bom</artifactId>
<version>1.0.0.2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
第三步:配置文件设置
配置application.yml文件:
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY}
mcp:
client:
request-timeout: 60000
stdio:
servers-configuration: classpath:/mcp/mcp-servers-config.json
同时创建MCP服务配置文件mcp/mcp-servers-config.json:
{
"mcpServers": {
"baidu-map": {
"command": "npx.cmd",
"args": ["-y", "@baidumap/mcp-server-baidu-map"],
"env": {
"BAIDU_MAP_API_KEY": "nLpm876DutMXGl6gEwzJksuya0gbfk0B"
}
}
}
}
第四步:编写Controller
在Controller中集成MCP工具调用:
@RestController
@RequestMapping("/chat")
public class ChatController {
private ChatClient chatClient;
public ChatController(DashScopeChatModel chatModel, ToolCallbackProvider toolCallbackProvider) {
this.chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(toolCallbackProvider)
.build();
}
@RequestMapping("/generate")
public String generate(String message){
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
ToolCallbackProvider是Spring AI中用于向AI模型注册和提供可用工具的核心接口。只要有MCP配置进来,ToolCallbackProvider就可以自动发现并调用相应工具,完美解决了Tool Calling中各个工具接口不同的问题,实现了动态工具组合。
自定义MCP Server开发
MCP主要支持两种通信方式:Stdio和Streamable HTTP。在2025年3月26日的协议更新后,官方已用更强大的Streamable HTTP取代SSE,解决了SSE连接容易断开的痛点。
方式一:使用Stdio自定义MCP Server
首先创建天气查询服务类:
package com.zc.mcp.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Service
@Slf4j
public class WeatherService {
private final Map<String, WeatherInfo> weatherCache = new ConcurrentHashMap<>();
public WeatherService() {
weatherCache.put("北京", new WeatherInfo("晴转多云", "22~28", "南风2级", "78"));
weatherCache.put("上海", new WeatherInfo("小雨", "18~24", "东风3级", "52"));
weatherCache.put("广州", new WeatherInfo("晴朗", "25~33", "微风", "45"));
weatherCache.put("深圳", new WeatherInfo("多云", "24~30", "东北风2级", "60"));
}
@Tool(description = "查询指定城市的天气信息,返回天气状况、温度范围、风力、空气质量")
public String queryWeather(
@ToolParam(description = "城市名称,如:北京、上海、广州、深圳") String city) {
log.info("[HTTP MCP] queryWeather 调用,城市: {}", city);
if (!weatherCache.containsKey(city)) {
return String.format("未找到「%s」的天气信息,支持的城市:%s",
city, weatherCache.keySet());
}
WeatherInfo info = weatherCache.get(city);
return String.format("""
🌍 %s天气报告
─────────────────
☁️ 天气:%s
🌡️ 温度:%s°C
💨 风力:%s
🏭 AQI:%s
─────────────────
🕐 更新时间:%s
""",
city, info.weather, info.temp, info.wind, info.aqi,
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
);
}
record WeatherInfo(String weather, String temp, String wind, String aqi) {}
}
然后创建工具配置类:
package com.zc.mcp.config;
import com.zc.mcp.service.WeatherService;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ToolConfig {
@Bean
public ToolCallbackProvider getWeather(WeatherService weatherService){
return MethodToolCallbackProvider.builder()
.toolObjects(weatherService)
.build();
}
}
配置application.yml:
spring:
ai:
mcp:
server:
name: stdio-server
version: 0.0.1
main:
web-application-type: none
banner-mode: off
最后打包生成jar包即可使用。
方式二:使用SSE自定义MCP Server
使用SSE传输策略时,依赖选择取决于角色定位:
| Starter | 角色 | 被谁调用 |
|---|---|---|
| spring-ai-starter-mcp-server | MCP Server | 本地MCP Client(通过Stdio) |
| spring-ai-starter-mcp-server-webmvc | MCP Server | 远程MCP Client(通过HTTP/SSE) |
| spring-ai-starter-mcp-server-webflux | MCP Server | 远程MCP Client(通过HTTP/SSE/WebFlux) |
| spring-ai-starter-mcp-client | MCP Client | Stdio/SSE客户端 |
| spring-ai-starter-mcp-client-webflux | MCP Client | WebFlux客户端 |
注意:在Web项目中同时存在Servlet和Reactive依赖时,Spring Boot会默认优先使用Servlet堆栈,导致WebFlux的/sse端点失效。可以通过以下配置解决:
server:
port: 8081
spring:
ai:
mcp:
server:
name: sse-server
version: 0.0.1
main:
web-application-type: reactive
SSE服务的pom.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mcp</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mcp-sse</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Service实现工具业务逻辑,Config将工具暴露给MCP Server(代码与Stdio方式类似)。Config中的MethodToolCallbackProvider就像一个"扫描器",把所有@Tool注解的方法收集起来"交给"MCP Server。
SSE服务启动后,在Cursor中配置即可使用:
{
"mcpServers": {
"sse-server":{
"url":"http://127.0.0.1:8081/sse"
}
}
}
在Spring AI中作为MCP Client调用该服务的Controller示例:
@RestController
@RequestMapping("/chat")
public class ChatController {
private final ChatClient chatClient;
@Autowired
public ChatController(DashScopeChatModel chatModel,
SyncMcpToolCallbackProvider mcpToolProvider) {
this.chatClient = ChatClient.builder(chatModel)
.defaultToolCallbacks(mcpToolProvider.getToolCallbacks())
.build();
}
@RequestMapping("/generate")
public String generate(String message) {
return chatClient.prompt()
.user(message)
.call()
.content();
}
}
配合TreeRouter提升开发效率
在MCP标准化工具调用的基础上,搭配TreeRouter API中转站能够进一步提升AI应用开发效率。TreeRouter作为专业的API聚合中转平台,提供了统一的大模型API接入方案,支持GPT、Gemini、Claude、DeepSeek、Qwen等主流AI模型的统一调用。
开发者无需对接多家厂商的不同接口,只需通过TreeRouter一套标准API即可接入所有主流模型,配合MCP的工具管理能力,能够快速构建功能强大、扩展性强的AI应用系统,真正实现"一次开发,多模型兼容"的高效开发体验。




