一、什么是 MCP?为什么需要它?
在 AI 应用开发中,大语言模型(LLM)虽然知识丰富,但它本身只是一个"文本生成器"------它无法访问实时数据库、不能查询天气、也不能帮你操作系统里的业务数据。
为了解决这个问题,MCP(Model Context Protocol,模型上下文协议) 应运而生。
1.1 MCP 的定位
官方定义很形象:
Think of MCP like a USB-C port for AI applications.
就像 USB-C 为电子设备提供了统一的接口标准,MCP 为 AI 应用连接数据源和工具提供了标准化方式。
MCP 并不是替代 Tool Calling(工具调用),而是为其提供一个统一、可扩展、跨平台的连接基础设施。可以理解为:
- Tool Calling 是"能力":AI 可以调用外部工具
- MCP 是"通信协议":规定如何描述工具、如何发起调用、如何传递结果、如何管理会话状态
1.2 MCP 的架构
Java MCP SDK 采用三层架构:
| 架构层 | 功能说明 | 比喻 |
|---|---|---|
| Client/Server 层 | McpClient 处理客户端操作,McpServer 管理服务端协议 | 顾客 vs 厨房 |
| Session 层 | DefaultMcpSession 管理通信模式和状态 | 订单管理系统 |
| Transport 层 | McpTransport 处理 JSON-RPC 消息的序列化与反序列化 | 外卖骑手 |
支持的传输方式包括:
- Stdio:通过标准输入/输出通信,适合本地进程调用
- SSE(Server-Sent Events):基于 HTTP 的单向推送,适合远程服务
- Streamable HTTP:更灵活的 HTTP 流式通信
二、项目整体架构
本文将构建三个模块,组成完整的 MCP 应用体系:
┌─────────────────────────────────────────────────┐
│ mcp-client-demo │
│ (AI 客户端 + DashScope 模型 + MCP Client) │
│ ↓ 通过 Stdio 或 SSE 连接 │
├──────────────────┬───────────────────────────────┤
│ mcp-stdio-server-demo │ mcp-sse-server-demo │
│ (Stdio 传输方式) │ (SSE 传输方式) │
│ 暴露 getUserInfo 工具 │ 暴露 getUserInfo 工具 │
└──────────────────┴───────────────────────────────┘
- mcp-stdio-server-demo:以 Stdio 方式暴露工具,通过 jar 包进程调用
- mcp-sse-server-demo:以 SSE 方式暴露工具,通过 HTTP 端点通信
- mcp-client-demo:AI 客户端,接入通义千问(DashScope)和 MCP 服务
三、搭建 MCP Server(Stdio 方式)
3.1 创建项目与依赖
使用 Spring Boot 3.x + JDK 17,在 pom.xml 中引入核心依赖:
xml
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI MCP Server (Stdio) -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
注意 :
spring-boot-maven-plugin的repackage目标是必须的,因为 Stdio 模式需要将 Server 打包成可执行的 jar 文件,由客户端进程启动。
3.2 配置文件
application.yml:
yaml
spring:
ai:
mcp:
server:
name: user-info
version: 0.0.1
main:
web-application-type: none # Stdio 模式不需要 Web 容器
banner-mode: off
关键点:Stdio 模式不需要 Web 应用类型,关闭 banner 可以减少标准输出的干扰。
3.3 定义实体与服务
UserInfo.java:
java
@Data
@AllArgsConstructor
public class UserInfo {
private String name;
private Integer age;
private String sex;
private String address;
}
UserService.java:
java
@Service
public class UserService {
static Map<String, UserInfo> userInfoMap = new HashMap<>();
static {
userInfoMap.put("zhangsan", new UserInfo("zhangsan", 15, "男", "北京"));
userInfoMap.put("lisi", new UserInfo("lisi", 16, "男", "上海"));
userInfoMap.put("wangwu", new UserInfo("wangwu", 17, "男", "广州"));
userInfoMap.put("zhaoliu", new UserInfo("zhaoliu", 18, "女", "深圳"));
userInfoMap.put("sunqi", new UserInfo("sunqi", 19, "女", "香港"));
userInfoMap.put("zhaoba", new UserInfo("zhaoba", 20, "女", "澳门"));
}
@Tool(description = "根据用户的姓名, 返回用户信息")
public String getUserInfo(@ToolParam(description = "用户的姓名") String name) {
if (userInfoMap.containsKey(name)) {
return userInfoMap.get(name).toString();
}
return "未查询到用户信息";
}
}
这里的核心注解:
@Tool:标记一个方法为 MCP 工具,description会告诉 AI 这个工具是做什么的@ToolParam:描述参数的含义,帮助 AI 理解何时以及如何调用
3.4 注册工具
ToolConfig.java:
java
@Configuration
public class ToolConfig {
@Bean
public ToolCallbackProvider getUserInfo(UserService userService) {
return MethodToolCallbackProvider.builder()
.toolObjects(userService)
.build();
}
}
通过 MethodToolCallbackProvider 将带有 @Tool 注解的服务注册为 MCP 工具回调提供者。
3.5 启动类
java
@SpringBootApplication
public class McpServerDemo {
public static void main(String[] args) {
SpringApplication.run(McpServerDemo.class, args);
}
}
打包后,这个 jar 就是 MCP Server 的可执行文件。
四、搭建 MCP Server(SSE 方式)
SSE 方式与 Stdio 的核心差异在于传输层 和依赖选择。
4.1 依赖调整
xml
<dependencies>
<!-- 注意:SSE 模式需要使用 webmvc 或 webflux 启动器 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
说明:Spring AI 为 MCP Server 提供了三个启动器:
spring-ai-starter-mcp-server:Stdio 模式spring-ai-starter-mcp-server-webmvc:基于 Servlet/MVC 的 SSE 模式spring-ai-starter-mcp-server-webflux:响应式 SSE 模式选错启动器会导致 MCP 端点(如
/sse)无法正常工作。
4.2 配置文件
yaml
server:
port: 8088
spring:
ai:
mcp:
server:
name: user-info
version: 0.0.1
SSE 模式需要指定端口,因为客户端将通过 HTTP 连接到这个服务。
4.3 其他代码
实体类(UserInfo)、服务类(UserService)、配置类(ToolConfig)和启动类与 Stdio 模式完全一致,无需修改。
五、搭建 MCP Client
客户端是整个系统的"大脑",负责接收用户请求、调用 AI 模型、并通过 MCP 协议调用工具。
5.1 依赖配置
xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Spring AI Alibaba DashScope(通义千问) -->
<dependency>
<groupId>com.alibaba.cloud.ai</groupId>
<artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
</dependency>
<!-- Spring WebFlux(MCP Client 需要) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
</dependency>
<!-- Spring AI MCP Client -->
<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>
5.2 配置文件
application.yml:
yaml
spring:
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY:your-api-key-here}
mcp:
client:
request-timeout: 60000
sse:
connections:
user-info:
url: http://127.0.0.1:8088/sse
logging:
level:
io:
modelcontextprotocol:
client: DEBUG
spec: DEBUG
这里使用 SSE 方式连接 MCP Server。如果要用 Stdio 方式,改为:
yaml
spring:
ai:
mcp:
client:
request-timeout: 60000
stdio:
servers-configuration: classpath:/mcp/mcp-servers-config.json
对应的 mcp-servers-config.json:
json
{
"mcpServers": {
"baidu-map": {
"command": "npx.cmd",
"args": ["-y", "@baidumap/mcp-server-baidu-map"],
"env": {
"BAIDU_MAP_API_KEY": "your-api-key"
}
},
"user-info": {
"command": "java",
"args": [
"-Dspring.ai.mcp.server.stdio=true",
"-Dlogging.pattern.console=",
"-jar",
"D:\\code\\javacode\\spring-ai\\spring-ai-project\\mcp-stdio-server-demo\\target\\mcp-stdio-server-demo-1.0-SNAPSHOT.jar"
]
}
}
}
Windows 用户注意 :在 IDEA 中配置 MCP 服务时,需要将
npx改为npx.cmd,避免因扩展名缺失导致启动失败。
5.3 Chat Controller
java
@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();
}
}
关键点在于 .defaultToolCallbacks(toolCallbackProvider) ------ 这行代码将 MCP 工具注册到 ChatClient,让 AI 在需要时可以自动发现并调用。
5.4 启动类
java
@SpringBootApplication
public class MCPClientDemo {
public static void main(String[] args) {
SpringApplication.run(MCPClientDemo.class, args);
}
}
六、测试与效果
6.1 启动服务
- 先启动 MCP Server (SSE 方式):运行
mcp-sse-server-demo,监听 8088 端口 - 再启动 MCP Client :运行
mcp-client-demo
6.2 发送请求
bash
curl "http://localhost:8080/chat/generate?message=帮我查一下zhangsan的信息"
6.3 工作流程
当你发送请求后,整个调用链路如下:
用户请求 → ChatClient → DashScope AI 模型
↓
AI 判断需要调用工具
↓
通过 MCP 协议 → MCP Server
↓
UserService.getUserInfo("zhangsan")
↓
返回: UserInfo{name=zhangsan, age=15, sex=男, address=北京}
↓
AI 整合结果 → 返回给用户
客户端日志中可以看到 MCP 通信的完整 DEBUG 信息:
io.modelcontextprotocol.spec.McpSchema : Received JSON message: {"result": {...}}
6.4 无工具 vs 有工具对比
- 没有接入 MCP 工具时:问"zhangsan 的信息",AI 只能基于训练数据回答或表示不知道
- 接入 MCP 工具后 :AI 自动发现
getUserInfo工具,提取参数zhangsan,调用后返回准确的业务数据
这就是 MCP 的价值------让 AI 从"聊天机器人"变成能操作真实业务的智能助手。
七、两种传输方式的对比
| 特性 | Stdio | SSE |
|---|---|---|
| 通信方式 | 标准输入/输出(进程间) | HTTP Server-Sent Events |
| 部署方式 | 打包为 jar,客户端进程启动 | 独立部署为 HTTP 服务 |
| 适用场景 | 本地嵌入式、IDE 插件 | 远程服务、微服务架构 |
| 依赖启动器 | spring-ai-starter-mcp-server |
spring-ai-starter-mcp-server-webmvc |
| 是否需要端口 | 否 | 是 |
| 多服务管理 | 通过 JSON 配置文件 | 通过 URL 配置 |
开发建议:
- 本地开发和插件化场景优先使用 Stdio
- 需要远程部署或集成到微服务体系时使用 SSE
- 生产环境推荐将 MCP Server 注册为微服务(Nacos/Consul/Eureka),方便服务治