在企业IT架构中,大量运行数年的Spring Boot系统承载着核心业务逻辑、数据与流程,是数字化体系里不可替代的资产。但随着大模型与AI应用的普及,一个普遍难题逐渐凸显:这些成熟的Java业务系统拥有完整接口与数据,却无法被AI直接识别和调用,形成了数据与智能之间的壁垒。传统解决方案往往需要人工导出数据、复制内容至AI对话框,不仅效率低下,还存在数据泄露、操作繁琐等问题。而MCP(模型上下文协议)的出现,搭配Spring AI生态,为存量Spring Boot服务接入AI提供了轻量化、无侵入的解决方案。本文将结合企业人力资源管理系统实战,完整讲解如何基于SSE传输模式搭建MCP服务端与客户端,无需重构原有业务代码,就能让老旧Java系统无缝对接各类AI工具,实现自然语言驱动业务查询、数据统计、流程操作等能力。
一、业务困境:存量Java系统与AI的对接鸿沟
本文实战载体是一套稳定运行五年的企业员工绩效与薪酬管理平台,技术栈采用Java 17搭配Spring Boot 3.x,持久层依托MyBatis实现数据交互,包含员工信息管理、薪资统计、绩效考评三大核心模块,接口文档完善、业务逻辑成熟。当企业希望借助AI能力提升办公效率,例如通过自然语言分析部门薪资结构、筛选优秀晋升候选人、批量生成绩效报告时,原有系统的短板彻底暴露。阿里云部署AI Agent:OpenClaw/Hermes Agent全网最简单,只需两步,详情👉访问阿里云OpenClaw/Hermes一键部署专题页面 了解。








👉访问订阅阿里云百炼Token Plan AI大模型服务 。支持多模型切换,用于多模态模型灵活调用,实现多模型、多工具、多场景下的额度共享与统一管理,兼顾灵活性、稳定性与安全性,大幅降低企业使用大模型的门槛与成本。




传统对接模式下,工作人员需要登录业务系统,手动查询数据并导出Excel文件,再将文件内容粘贴到AI对话窗口中完成分析。整个流程依赖人工中转,不仅耗时耗力,频繁的手动操作还容易出现数据错漏,薪资这类敏感数据在导出、传递过程中也存在安全风险。更关键的是,AI无法直接调用系统接口,业务接口对于大模型而言只是一串无意义的字符,两者之间缺少标准化的交互桥梁。
想要彻底解决这一问题,不能选择重构原有系统,这会带来极高的开发、测试与上线成本。最佳思路是在现有系统外层搭建适配层,基于MCP协议将业务方法封装为AI可识别的工具,让AI像调用内置能力一样,直接调用Spring Boot中的业务逻辑,实现“AI提问、系统执行、结果反馈”的全自动化链路。
二、技术选型解析:MCP协议与SSE传输模式优势
MCP是专门用于打通大模型与外部应用的标准化协议,它定义了统一的工具描述、参数传递、结果返回规范,让不同技术栈的系统都能快速对接各类AI客户端。Spring AI 1.0.0及以上版本原生提供了MCP相关启动器,支持两种主流传输模式:STDIO与SSE,结合企业多客户端、远程访问的场景,本次实战全程选用SSE(服务器推送事件) 模式。
STDIO模式将MCP服务作为AI客户端的子进程运行,依靠标准输入输出完成通信,仅适用于本地单场景调试。该模式存在三大硬伤:其一,Spring Boot启动日志、Banner等输出内容会破坏STDIO的JSON-RPC数据格式,需要额外屏蔽所有控制台输出;其二,每一个AI客户端都会独占一个独立JVM进程,无法实现服务共享;其三,仅支持本地访问,不能部署到服务器供团队多人使用。
而SSE模式则将MCP服务改造为标准的Spring Boot Web应用,通过专属HTTP端点提供服务,完美适配企业生产环境。它沿用Web应用的部署、运维逻辑,支持多客户端远程并发连接,无需改造日志输出规则,同时兼容内网服务器、云主机等各类部署环境,是企业级MCP服务的首选传输方案。
整套技术架构分为四层,逻辑清晰且低耦合:第一层为原有Spring Boot业务层,保留所有Service、数据访问逻辑,做到零修改;第二层为MCP工具封装层,通过注解将业务方法转化为MCP标准工具;第三层为MCP服务传输层,依托Spring AI Starter自动暴露SSE端点;第四层为消费端,包含Claude、Cursor等AI客户端,以及集成了MCP客户端的自有业务系统,两类角色均可通过SSE协议远程调用服务能力。
整体工作流程十分简洁:开发者或运维人员发起自然语言请求后,AI客户端会自动解析意图,通过SSE连接调用对应的MCP工具,MCP服务再转发请求至原有业务Service,执行完成后将结果逐层回传,最终由AI整合数据并生成分析结论,全程无需人工干预。
三、实战部署一:搭建MCP服务端(Spring Boot+MCP Server)
本次实战分为MCP服务端、MCP客户端两大模块,首先搭建承载原有HRM业务的MCP服务端,所有业务代码保持原有逻辑,仅新增MCP工具类与配置,实现无侵入改造。
3.1 项目整体结构
首先规范项目目录结构,区分领域实体、数据访问层、业务服务层、MCP工具层,目录如下:
hrm-mcp-server/
├── pom.xml
├── src/main/
│ ├── java/com/example/hrm/
│ │ ├── HrmMcpApplication.java # 项目启动类
│ │ ├── domain/ # 领域实体类
│ │ │ ├── Employee.java
│ │ │ ├── SalaryRecord.java
│ │ │ └── PerformanceReview.java
│ │ ├── repository/ # 数据访问层
│ │ │ ├── EmployeeRepository.java
│ │ │ ├── SalaryRepository.java
│ │ │ └── PerformanceRepository.java
│ │ ├── service/ # 原有业务服务层
│ │ │ ├── EmployeeService.java
│ │ │ ├── SalaryService.java
│ │ │ └── PerformanceService.java
│ │ └── mcp/ # 新增MCP工具封装层
│ │ ├── EmployeeTools.java
│ │ ├── SalaryTools.java
│ │ └── PerformanceTools.java
│ └── resources/
│ └── application.yml # 全局配置文件
3.2 引入MCP相关Maven依赖
修改根目录pom.xml,指定Spring Boot、Spring AI版本,引入MCP服务端核心启动器、Web、数据访问等依赖,完整配置如下:
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
</parent>
<groupId>com.example</groupId>
<artifactId>hrm-mcp-server</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>HRM MCP Server</name>
<properties>
<java.version>21</java.version>
<spring-ai.version>1.0.0</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- MCP Server SSE核心启动器 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
</dependency>
<!-- Spring Web 基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- JPA + H2内存数据库(演示使用,生产替换为MySQL) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 简化代码工具 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3.3 全局配置文件(application.yml)
配置服务端口、数据库、MCP SSE端点、日志级别,SSE端点是AI客户端连接的核心地址,配置如下:
server:
port: 8081 # MCP服务端端口
spring:
application:
name: hrm-mcp-server
# H2内存数据库配置
datasource:
url: jdbc:h2:mem:hrmdb;DB_CLOSE_DELAY=-1
driver-class-name: org.h2.Driver
username: sa
password:
jpa:
hibernate:
ddl-auto: create-drop
show-sql: false
h2:
console:
enabled: true
path: /h2-console
# MCP SSE端点配置
ai:
mcp:
server:
name: hrm-mcp-server
version: 1.0.0
sse-message-endpoint: /mcp/message
logging:
level:
root: WARN
com.example.hrm: INFO
3.4 领域实体、数据访问与业务服务层
这三层为原有业务代码,无需修改,仅做基础实现。首先是员工、薪资、绩效三大实体类,以员工实体为例:
// domain/Employee.java
package com.example.hrm.domain;
import jakarta.persistence.*;
import lombok.Data;
import lombok.Builder;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "employees")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String department;
private String role;
private String email;
private Integer yearsOfService;
private String status;
}
薪资、绩效实体参照此格式编写,随后编写JPA数据访问接口,无需额外逻辑:
// repository/EmployeeRepository.java
package com.example.hrm.repository;
import com.example.hrm.domain.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
业务服务层实现核心查询、统计、新增逻辑,以员工服务为例:
// service/EmployeeService.java
package com.example.hrm.service;
import com.example.hrm.domain.Employee;
import com.example.hrm.repository.EmployeeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
public class EmployeeService {
private final EmployeeRepository employeeRepository;
public List<Employee> queryEmployees(String department, String role, String status) {
List<Employee> all = employeeRepository.findAll();
return all.stream()
.filter(e -> department == null || e.getDepartment().contains(department))
.filter(e -> role == null || e.getRole().contains(role))
.filter(e -> status == null || e.getStatus().equalsIgnoreCase(status))
.collect(Collectors.toList());
}
public Map<String, Long> getDepartmentHeadcount() {
return employeeRepository.findAll().stream()
.filter(e -> "ACTIVE".equals(e.getStatus()))
.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
}
}
薪资服务、绩效服务按照业务需求实现统计、新增、排名逻辑,保证原有业务能力完整。
3.5 核心:MCP工具封装层
这是改造的核心环节,使用@Tool和@ToolParam注解将业务方法封装为MCP标准工具。注解描述是AI识别调用规则的关键,需要清晰说明使用场景、参数含义与返回内容。以员工工具类为例:
// mcp/EmployeeTools.java
package com.example.hrm.mcp;
import com.example.hrm.domain.Employee;
import com.example.hrm.service.EmployeeService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
@RequiredArgsConstructor
public class EmployeeTools {
private final EmployeeService employeeService;
@Tool(description = "查询员工列表,适用于询问部门人员、职级人员场景,返回员工基础信息,不含薪资")
public List<Map<String, Object>> queryEmployees(
@ToolParam(description = "部门名称,选填", required = false) String department,
@ToolParam(description = "职级名称,选填", required = false) String role,
@ToolParam(description = "员工状态,ACTIVE在职/RESIGNED离职,选填", required = false) String status) {
String effectiveStatus = (status == null) ? "ACTIVE" : status;
return employeeService.queryEmployees(department, role, effectiveStatus)
.stream()
.map(e -> {
Map<String, Object> item = new java.util.LinkedHashMap<>();
item.put("id", e.getId());
item.put("name", e.getName());
item.put("department", e.getDepartment());
item.put("role", e.getRole());
item.put("yearsOfService", e.getYearsOfService());
item.put("status", e.getStatus());
return item;
})
.collect(Collectors.toList());
}
@Tool(description = "统计各在职部门人数,适用于查询组织人员分布场景")
public Map<String, Long> getDepartmentHeadcount() {
return employeeService.getDepartmentHeadcount();
}
}
薪资工具、绩效工具采用相同方式封装,其中绩效提交属于写操作,需要在注解描述中提醒AI调用前向用户确认,避免误操作。
3.6 启动类与测试数据初始化
在启动类中通过CommandLineRunner初始化演示数据,方便后续测试:
// HrmMcpApplication.java
package com.example.hrm;
import com.example.hrm.domain.Employee;
import com.example.hrm.domain.SalaryRecord;
import com.example.hrm.domain.PerformanceReview;
import com.example.hrm.repository.EmployeeRepository;
import com.example.hrm.repository.SalaryRepository;
import com.example.hrm.repository.PerformanceRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
@SpringBootApplication
public class HrmMcpApplication {
public static void main(String[] args) {
SpringApplication.run(HrmMcpApplication.class, args);
}
@Bean
CommandLineRunner initData(EmployeeRepository empRepo,
SalaryRepository salaryRepo,
PerformanceRepository perfRepo) {
return args -> {
// 初始化员工数据
List<Employee> employees = empRepo.saveAll(List.of(
Employee.builder().name("张伟").department("研发部").role("高级工程师")
.yearsOfService(4).status("ACTIVE").build(),
Employee.builder().name("李娜").department("研发部").role("初级工程师")
.yearsOfService(1).status("ACTIVE").build()
));
// 初始化薪资、绩效数据(代码省略,参照完整示例补充)
};
}
}
3.7 服务端打包与启动
执行以下Maven命令完成打包与启动:
# 打包项目,跳过测试
mvn clean package -DskipTests
# 启动MCP服务端
java -jar target/hrm-mcp-server-1.0.0-SNAPSHOT.jar
启动成功后,服务会监听8081端口,SSE访问地址为http://localhost:8081/sse。
四、实战部署二:AI客户端与业务系统接入MCP服务
MCP服务端部署完成后,分为两类接入场景:第一类是Claude、Cursor等主流AI工具直接连接SSE端点;第二类是自有Spring Boot业务系统集成MCP客户端,实现系统内AI问答功能。
4.1 主流AI工具配置(Claude、Cursor)
两类工具配置方式一致,仅需修改本地配置文件,填入SSE远程地址即可。
Claude配置
Windows系统配置文件路径:%APPDATA%\Claude\claude_desktop_config.json
macOS系统配置文件路径:~/Library/Application Support/Claude/claude_desktop_config.json
写入配置:{ "mcpServers": { "hrm": { "url": "http://localhost:8081/sse" } } }Cursor配置
在Cursor的MCP设置面板中添加相同的JSON配置,重启工具后即可自动发现MCP服务暴露的所有工具。此时在对话框输入自然语言,例如“统计各部门在职人数”,AI会自动调用getDepartmentHeadcount工具获取数据并展示结果。
4.2 自有业务系统集成MCP客户端
当需要在企业内部系统嵌入AI问答功能时,需要搭建MCP客户端项目,对接远程MCP服务端。
4.2.1 客户端项目结构
hrm-ai-client/
├── pom.xml
├── src/main/
│ ├── java/com/example/hrm/client/
│ │ ├── HrmAiClientApplication.java
│ │ ├── config/McpClientConfig.java
│ │ ├── controller/AiAdvisorController.java
│ │ └── service/AiAdvisorService.java
│ └── resources/application.yml
4.2.2 客户端pom.xml依赖
引入MCP客户端、OpenAI模型、Web等依赖:
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.5</version>
</parent>
<groupId>com.example</groupId>
<artifactId>hrm-ai-client</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<java.version>21</java.version>
<spring-ai.version>1.0.0</spring-ai.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MCP客户端启动器 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
<!-- 大模型对接依赖 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
4.2.3 客户端application.yml配置
配置客户端端口、大模型密钥、MCP服务端SSE地址:
server:
port: 8082
spring:
application:
name: hrm-ai-client
openai:
api-key: sk-your-api-key
base-url: https://api.openai.com
chat:
options:
model: gpt-4o
temperature: 0.3
# 连接远程MCP服务端
ai:
mcp:
client:
sse:
connections:
hrm-server:
url: http://localhost:8081/sse
logging:
level:
root: WARN
com.example.hrm.client: INFO
org.springframework.ai.mcp: DEBUG
4.2.4 核心配置、服务与接口代码
- MCP客户端配置类,将MCP工具注册到对话客户端:
```java
// config/McpClientConfig.java
package com.example.hrm.client.config;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class McpClientConfig {
@Bean
ChatClient chatClient(ChatClient.Builder builder, ToolCallbackProvider toolCallbackProvider) {
return builder
.defaultSystem("你是HR智能顾问,可调用工具查询员工、薪资、绩效数据")
.defaultToolCallbacks(toolCallbackProvider)
.build();
}
}
2. AI对话服务层,处理用户自然语言请求:
```java
// service/AiAdvisorService.java
package com.example.hrm.client.service;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Slf4j
@Service
@RequiredArgsConstructor
public class AiAdvisorService {
private final ChatClient chatClient;
public String ask(String userQuestion) {
log.info("用户提问:{}", userQuestion);
String response = chatClient.prompt().user(userQuestion).call().content();
return response;
}
}
- REST接口,对外提供AI问答能力:
```java
// controller/AiAdvisorController.java
package com.example.hrm.client.controller;
import com.example.hrm.client.service.AiAdvisorService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/api/ai")
@RequiredArgsConstructor
public class AiAdvisorController {
private final AiAdvisorService aiAdvisorService;
@PostMapping("/ask")
public Map<String, String> ask(@RequestBody Map<String, String> request) {
String answer = aiAdvisorService.ask(request.get("question"));
return Map.of("question", request.get("question"), "answer", answer);
}
}
#### 4.2.5 客户端启动与接口测试
启动客户端项目后,使用`curl`命令测试接口:
```bash
curl -X POST http://localhost:8082/api/ask \
-H "Content-Type: application/json" \
-d '{"question": "分析研发部2026-Q2薪资,找出薪资偏低的员工并给出调薪建议"}'
请求发出后,客户端会自动通过SSE调用MCP服务端的薪资、员工、绩效工具,整合数据后由大模型生成分析报告,完整链路打通。
五、常见问题排查与企业级最佳实践
5.1 高频问题与解决方案
- 注解版本不匹配:Spring AI 1.0.x使用
@Tool和@ToolParam,早期版本使用@McpTool,需统一依赖版本,避免注解报错。 - 返回类型序列化失败:禁止直接返回实体类,优先使用
Map或自定义DTO,规避循环引用导致的JSON解析异常。 - 写操作误触发:在写类型工具的注解描述中,明确要求AI调用前向用户确认,同时增加接口日志与权限校验。
- SSE连接失败:检查服务端端口、防火墙规则,生产环境配置反向代理时,保证SSE长连接不被中断。
- 工具数量过多:单个MCP服务端工具数量建议控制在20个以内,按业务域拆分多个MCP服务,提升调用稳定性。
5.2 企业级优化策略
- 数据脱敏:在MCP工具层对手机号、邮箱、明文密码等敏感字段做脱敏处理,避免数据泄露。
- 分层权限:结合权限框架,限制不同角色可调用的MCP工具,例如HR仅可查看薪资,普通员工仅可查看个人信息。
- 日志审计:完整记录每一次MCP工具调用的用户、参数、结果,满足企业安全审计要求。
- 分批部署:先在非核心业务试点,验证稳定性后再全量推广,降低改造风险。
六、总结
借助Spring AI与MCP协议,存量Spring Boot系统无需重构代码,仅通过新增适配层就能快速接入AI生态,这是老旧Java系统智能化改造的低成本方案。SSE传输模式完美适配企业远程、多客户端的生产场景,兼顾部署便捷性与扩展性。
整套方案实现了“业务系统不变、AI能力新增”的目标,将传统接口转化为AI可调用的标准化工具,让自然语言交互落地到企业日常办公中。从AI工具直连,到自有业务系统集成MCP客户端,两种接入模式覆盖了绝大多数企业使用场景。在实际落地过程中,只需把控注解描述规范、数据安全、权限控制三大要点,就能搭建稳定、高效的AI+Java业务链路,充分释放存量系统的业务价值,让老旧技术架构跟上智能化发展趋势。