构建一个简单智能客户服务系统的案例

场景案例:智能客户服务系统

构建一个智能客户服务系统,包含客户信息服务和订单服务两个MCP服务器,以及一个AI客户端应用。

第一步:理解架构设计

MCP架构允许多个Spring Boot应用作为MCP服务器,它们连接到数据库并使用Spring AI MCP服务器支持来向MCP客户端应用暴露@Tool方法。

我们的系统架构:

  • 客户信息MCP服务器 (customer-mcp-service): 管理客户数据
  • 订单MCP服务器 (order-mcp-service): 管理订单数据
  • AI客户端应用 (ai-client-service): 整合工具并提供智能服务

第二步:创建客户信息MCP服务器

2.1 Maven依赖配置

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-mcp-server-webflux-spring-boot-starter</artifactId>
    </dependency>
    <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>
</dependencies>

2.2 客户实体类

java 复制代码
@Entity
@Table(name = "customers")
public class Customer {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;
    private String phone;
    private String address;
    private String membershipLevel; // BRONZE, SILVER, GOLD
    
    @Column(name = "created_date")
    private LocalDateTime createdDate;
    
    // 构造函数、getter和setter
    public Customer() {}
    
    public Customer(String name, String email, String phone, String address, String membershipLevel) {
        this.name = name;
        this.email = email;
        this.phone = phone;
        this.address = address;
        this.membershipLevel = membershipLevel;
        this.createdDate = LocalDateTime.now();
    }
    
    // getters and setters...
}

2.3 数据访问层

java 复制代码
@Repository
public interface CustomerRepository extends CrudRepository<Customer, Long> {
    List<Customer> findByMembershipLevel(String membershipLevel);
    Optional<Customer> findByEmail(String email);
    List<Customer> findByNameContainingIgnoreCase(String name);
}

2.4 工具服务类

java 复制代码
@Service
public class CustomerTools {
    
    private final CustomerRepository customerRepository;
    
    public CustomerTools(CustomerRepository customerRepository) {
        this.customerRepository = customerRepository;
    }
    
    @Tool(description = "根据客户ID查找客户信息")
    public Customer getCustomerById(
            @ToolParam(description = "客户ID") Long customerId) {
        return customerRepository.findById(customerId).orElse(null);
    }
    
    @Tool(description = "根据邮箱查找客户")
    public Customer getCustomerByEmail(
            @ToolParam(description = "客户邮箱") String email) {
        return customerRepository.findByEmail(email).orElse(null);
    }
    
    @Tool(description = "根据会员等级查找客户列表")
    public List<Customer> getCustomersByMembershipLevel(
            @ToolParam(description = "会员等级:BRONZE, SILVER, GOLD") String membershipLevel) {
        return customerRepository.findByMembershipLevel(membershipLevel);
    }
    
    @Tool(description = "根据姓名搜索客户")
    public List<Customer> searchCustomersByName(
            @ToolParam(description = "客户姓名关键词") String name) {
        return customerRepository.findByNameContainingIgnoreCase(name);
    }
}

2.5 主应用类

java 复制代码
@SpringBootApplication
public class CustomerMcpServerApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(CustomerMcpServerApplication.class, args);
    }
    
    @Bean
    public ToolCallbackProvider customerTools(CustomerTools customerTools) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(customerTools)
                .build();
    }
}

2.6 配置文件 (application.yml)

yaml 复制代码
spring:
  ai:
    mcp:
      server:
        name: customer-mcp-server
        version: 1.0.0
  jpa:
    database-platform: H2
    generate-ddl: true
    hibernate:
      ddl-auto: create-drop
  h2:
    console:
      enabled: true

server:
  port: 8061

logging:
  level:
    org.springframework.ai: DEBUG

2.7 测试数据 (import.sql)

sql 复制代码
INSERT INTO customers (name, email, phone, address, membership_level, created_date) VALUES 
('张三', 'zhangsan@example.com', '13812345678', '北京市朝阳区', 'GOLD', '2024-01-15T10:30:00'),
('李四', 'lisi@example.com', '13987654321', '上海市浦东新区', 'SILVER', '2024-02-20T14:20:00'),
('王五', 'wangwu@example.com', '13555666777', '广州市天河区', 'BRONZE', '2024-03-10T09:15:00'),
('赵六', 'zhaoliu@example.com', '13666777888', '深圳市南山区', 'GOLD', '2024-01-25T16:45:00');

第三步:创建订单MCP服务器

3.1 订单实体类

java 复制代码
@Entity
@Table(name = "orders")
public class Order {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private Long customerId;
    private String orderNumber;
    private BigDecimal totalAmount;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    
    @Column(name = "order_date")
    private LocalDateTime orderDate;
    
    private String productName;
    private Integer quantity;
    
    // 构造函数、getter和setter
    public Order() {}
    
    public Order(Long customerId, String orderNumber, BigDecimal totalAmount, 
                 OrderStatus status, String productName, Integer quantity) {
        this.customerId = customerId;
        this.orderNumber = orderNumber;
        this.totalAmount = totalAmount;
        this.status = status;
        this.productName = productName;
        this.quantity = quantity;
        this.orderDate = LocalDateTime.now();
    }
    
    // getters and setters...
}

enum OrderStatus {
    PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED
}

3.2 订单工具服务

java 复制代码
@Service
public class OrderTools {
    
    private final OrderRepository orderRepository;
    
    public OrderTools(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
    
    @Tool(description = "根据客户ID查找订单列表")
    public List<Order> getOrdersByCustomerId(
            @ToolParam(description = "客户ID") Long customerId) {
        return orderRepository.findByCustomerId(customerId);
    }
    
    @Tool(description = "根据订单号查找订单")
    public Order getOrderByOrderNumber(
            @ToolParam(description = "订单号") String orderNumber) {
        return orderRepository.findByOrderNumber(orderNumber).orElse(null);
    }
    
    @Tool(description = "计算客户的总消费金额")
    public BigDecimal calculateCustomerTotalSpent(
            @ToolParam(description = "客户ID") Long customerId) {
        List<Order> orders = orderRepository.findByCustomerId(customerId);
        return orders.stream()
                .map(Order::getTotalAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    @Tool(description = "根据订单状态查找订单")
    public List<Order> getOrdersByStatus(
            @ToolParam(description = "订单状态") String status) {
        try {
            OrderStatus orderStatus = OrderStatus.valueOf(status.toUpperCase());
            return orderRepository.findByStatus(orderStatus);
        } catch (IllegalArgumentException e) {
            return Collections.emptyList();
        }
    }
}

第四步:创建AI客户端应用

4.1 Maven依赖

xml 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-mcp-client-webflux-spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.ai</groupId>
        <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
    </dependency>
</dependencies>

4.2 智能客服控制器

java 复制代码
@RestController
@RequestMapping("/api/customer-service")
public class CustomerServiceController {
    
    private final ChatClient chatClient;
    
    public CustomerServiceController(ChatClient.Builder chatClientBuilder,
                                   ToolCallbackProvider tools) {
        this.chatClient = chatClientBuilder
                .defaultTools(tools)
                .build();
    }
    
    @PostMapping("/query")
    public ResponseEntity<String> handleCustomerQuery(@RequestBody CustomerQuery query) {
        PromptTemplate promptTemplate = new PromptTemplate("""
            你是一个专业的客服助手。请根据客户的问题提供准确和友好的回答。
            
            客户问题: {question}
            
            请使用可用的工具来获取相关信息,并提供详细的回答。
            如果需要客户信息,请先通过邮箱或姓名搜索客户。
            如果涉及订单问题,请查询相关订单信息。
            
            回答要求:
            1. 语言友好、专业
            2. 信息准确、完整
            3. 如果无法找到信息,请说明并建议其他解决方案
            """);
        
        Prompt prompt = promptTemplate.create(Map.of("question", query.getQuestion()));
        
        String response = chatClient.prompt(prompt)
                .call()
                .content();
        
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/customer-summary/{email}")
    public ResponseEntity<String> getCustomerSummary(@PathVariable String email) {
        PromptTemplate promptTemplate = new PromptTemplate("""
            请为邮箱为 {email} 的客户生成一个详细的客户档案摘要。
            
            摘要应包含:
            1. 客户基本信息(姓名、联系方式、地址、会员等级)
            2. 订单历史(订单数量、总消费金额、最近订单状态)
            3. 客户价值评估
            
            请使用专业但友好的语言,格式清晰易读。
            """);
        
        Prompt prompt = promptTemplate.create(Map.of("email", email));
        
        String response = chatClient.prompt(prompt)
                .call()
                .content();
        
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/membership-analysis/{level}")
    public ResponseEntity<String> getMembershipAnalysis(@PathVariable String level) {
        PromptTemplate promptTemplate = new PromptTemplate("""
            请分析 {level} 级别的会员情况。
            
            分析内容包括:
            1. 该级别会员的数量
            2. 该级别会员的消费特点
            3. 业务建议和优化方案
            
            请基于实际数据提供分析结果。
            """);
        
        Prompt prompt = promptTemplate.create(Map.of("level", level));
        
        String response = chatClient.prompt(prompt)
                .call()
                .content();
        
        return ResponseEntity.ok(response);
    }
}

// 请求数据类
class CustomerQuery {
    private String question;
    
    public CustomerQuery() {}
    
    public String getQuestion() {
        return question;
    }
    
    public void setQuestion(String question) {
        this.question = question;
    }
}

4.3 配置文件

yaml 复制代码
spring:
  ai:
    mcp:
      client:
        sse:
          connections:
            customer-mcp-server:
              url: http://localhost:8061
            order-mcp-server:
              url: http://localhost:8062
    openai:
      api-key: ${SPRING_AI_OPENAI_API_KEY}

server:
  port: 8080

logging:
  level:
    org.springframework.ai: DEBUG

第五步:运行和测试

5.1 启动应用

bash 复制代码
# 启动客户信息MCP服务器
cd customer-mcp-service
mvn spring-boot:run

# 启动订单MCP服务器  
cd order-mcp-service
mvn spring-boot:run

# 设置OpenAI API密钥并启动客户端
export SPRING_AI_OPENAI_API_KEY=你的OpenAI密钥
cd ai-client-service
mvn spring-boot:run

5.2 测试API调用

bash 复制代码
# 测试客户咨询
curl -X POST http://localhost:8080/api/customer-service/query \
  -H "Content-Type: application/json" \
  -d '{"question": "我想查询张三的订单情况"}'

# 测试客户摘要
curl http://localhost:8080/api/customer-service/customer-summary/zhangsan@example.com

# 测试会员分析
curl http://localhost:8080/api/customer-service/membership-analysis/GOLD

核心优势和特点

这个案例展示了MCP的核心优势:

  1. 工具复用: MCP提供了一种标准化的协议,使AI模型能够以结构化的方式与外部工具和资源进行交互
  2. 松耦合架构: 每个服务都是独立的MCP服务器,可以独立部署和扩展
  3. 智能整合: AI客户端可以自动组合来自不同服务的工具来解决复杂问题
  4. 标准化接口: 所有工具都通过MCP协议暴露,便于集成和维护

这个场景案例展示了如何使用Spring AI和MCP构建一个智能的分布式系统,其中AI能够自动调用多个服务的功能来提供综合性的客户服务。

相关推荐
Chen-Edward2 小时前
有了Spring为什么还有要Spring Boot?
java·spring boot·spring
magic334165632 小时前
Springboot整合MinIO文件服务(windows版本)
windows·spring boot·后端·minio·文件对象存储
小学鸡!3 小时前
Spring Boot实现日志链路追踪
java·spring boot·后端
番茄Salad3 小时前
Spring Boot临时解决循环依赖注入问题
java·spring boot·spring cloud
摇滚侠6 小时前
Spring Boot 3零基础教程,WEB 开发 自定义静态资源目录 笔记31
spring boot·笔记·后端·spring
摇滚侠6 小时前
Spring Boot 3零基础教程,WEB 开发 Thymeleaf 遍历 笔记40
spring boot·笔记·thymeleaf
骑猪兜风2337 小时前
Claude 新功能 Skills 横空出世,比 MCP 更高效的 AI 增强方案!
ai编程·claude·mcp
橘子海全栈攻城狮7 小时前
【源码+文档+调试讲解】基于SpringBoot + Vue的知识产权管理系统 041
java·vue.js·人工智能·spring boot·后端·安全·spring
Json_8 小时前
学习springBoot框架-开发一个酒店管理系统,熟悉springboot框架语法~
java·spring boot·后端
kkkkk0211068 小时前
微服务学习笔记(黑马商城)
java·spring boot·spring·spring cloud·sentinel·mybatis·java-rabbitmq