Spring Boot MCP服务器

一个生产就绪的Spring Boot MCP服务器,用于将业务服务暴露为AI/LLM集成的工具。

  • by MindCres
  • Java
  • 本地部署
  • 更新于
在 GitHub 查看 MindCres/mcpspring

使用说明

Spring Boot MCP服务器-完整指南

生产准备就绪 Spring Boot MCP(模型上下文协议)服务器 它将业务服务作为AI/LLM集成的工具。


目录

  1. 什么是MCP?
  2. 快速入门(5分钟)
  3. 项目概述
  4. 先决条件
  5. 安装和设置
  6. 运行服务器
  7. 测试您的服务器
  8. 理解代码
  9. 添加自己的服务(一步一步)
  10. 连接到真实API
  11. REST API(适用于非MPCP客户端)
  12. 连接到LLM
  13. 配置参考
  14. 故障排除
  15. 资源

什么是MCP?

模型上下文协议(MCP) 是Anthropic的一个开放标准,允许AI模型(如Claude、ChatGPT)将您的后端服务称为“工具”。

在MCP之前:

User: "What phones do you have?"
AI: "I don't have access to your inventory system."

MCP之后:

User: "What phones do you have?"
AI: [Calls your shop_get_all_phones tool]
AI: "We have iPhone 15 Pro Max ($799), Galaxy S24 Ultra ($798)..."

工作原理:

┌─────────────────┐     MCP Protocol      ┌─────────────────────┐
│   AI/LLM        │◄────────────────────► │  Your Spring Boot   │
│   (Claude)      │    (JSON-RPC)         │  MCP Server         │
└─────────────────┘                       └──────────┬──────────┘
                                                     │
                                          ┌──────────▼──────────┐
                                          │   Your Services     │
                                          │  - PhoneService     │
                                          │  - PlanService      │
                                          │  - External APIs    │
                                          └─────────────────────┘

快速入门(5分钟)

步骤1:克隆和构建

git clone <repository-url>
cd mcpspring
./gradlew build

步骤2:运行服务器

# SSE Mode (HTTP-based, recommended for testing)
./gradlew bootRun --args='--spring.profiles.active=sse'

第三步:测试

打开一个新终端:

# Check server is running
curl http://localhost:8080/

# Test SSE endpoint
curl http://localhost:8080/sse

# Test REST API
curl http://localhost:8080/api/tools/phones

步骤4:使用MCP检查器(目视测试)

npx @modelcontextprotocol/inspector --url http://localhost:8080/sse

打开http://localhost:6274在浏览器中查看所有工具并对其进行测试!


项目概述

该项目包括 3示例服务 和 17个MCP工具:

服务 类型 工具 描述
电话服务 模拟数据 5 手机库存(苹果、三星等)
PlanService 模拟数据 7 移动计划(5G、仅SIM卡等)
产品目录服务 真实API 5 从FakeStore API获取

项目结构

mcpspring/
├── build.gradle                         # Gradle dependencies
├── settings.gradle                      # Gradle settings
├── gradlew                              # Gradle wrapper (Unix)
├── gradlew.bat                          # Gradle wrapper (Windows)
├── gradle/wrapper/                      # Gradle wrapper files
├── README.md                            # This file
│
└── src/main/
    ├── java/com/example/mcpserver/
    │   ├── McpServerApplication.java    # Main entry point
    │   │
    │   ├── config/
    │   │   ├── McpToolConfig.java       # ⭐ IMPORTANT: Tool registration
    │   │   └── CacheConfig.java         # Cache settings
    │   │
    │   ├── service/                     # ⭐ YOUR TOOLS GO HERE
    │   │   ├── PhoneService.java        # Example: Mock data service
    │   │   ├── PlanService.java         # Example: Mock data service
    │   │   └── ProductCatalogService.java # Example: Real API service
    │   │
    │   ├── client/
    │   │   └── ProductApiClient.java    # REST client for external APIs
    │   │
    │   ├── controller/
    │   │   ├── InfoController.java      # Health check endpoints
    │   │   └── ToolRestController.java  # REST API wrapper
    │   │
    │   ├── model/                       # Data models
    │   │   ├── PhoneModel.java
    │   │   └── MobilePlan.java
    │   │
    │   ├── dto/                         # Data Transfer Objects
    │   │   ├── ProductDTO.java
    │   │   └── RatingDTO.java
    │   │
    │   └── exception/
    │       └── ApiException.java        # Custom exceptions
    │
    └── resources/
        ├── application.properties       # STDIO mode config
        └── application-sse.properties   # SSE mode config

先决条件

在开始之前,请确保您已经:

要求 版本 检查命令
Java JDK 17+ java -version
Node.js 18+(用于MCP检查器) node -version

注: Gradle通过Gradle包装器包含在内(gradlew),因此您不需要单独安装。

安装先决条件

macOS:

# Install Java 17
brew install openjdk@17

# Install Node.js
brew install node

窗户:

Linux(Ubuntu/Debian):

sudo apt update
sudo apt install openjdk-17-jdk nodejs npm

安装和设置

步骤1:克隆存储库

git clone <repository-url>
cd mcpspring

步骤2:了解依赖关系(build.gradle)

关键依赖关系是 Spring AI MCP服务器启动器:

dependencies {
    // This enables MCP protocol support
    implementation 'org.springframework.ai:spring-ai-starter-mcp-server-webmvc'
}

所有依赖项均由Spring AI BOM(物料清单)管理:

dependencyManagement {
    imports {
        mavenBom "org.springframework.ai:spring-ai-bom:1.0.0"
    }
}

步骤3:构建项目

# Full build with tests
./gradlew build

# Quick build (skip tests)
./gradlew build -x test

# Clean and build
./gradlew clean build

预期产量:

BUILD SUCCESSFUL in Xs
5 actionable tasks: 5 executed

JAR文件将位于: build/libs/mcp-server-poc-0.0.1-SNAPSHOT.jar


运行服务器

选项1:SSE模式(建议用于测试)

SSE(服务器发送事件)模式作为HTTP服务器运行。在以下情况下使用此功能:

  • 您没有克劳德桌面
  • 您想通过浏览器/curl进行测试
  • 您正在与基于HTTP的客户端集成
# Using Gradle
./gradlew bootRun --args='--spring.profiles.active=sse'

# Using JAR
java -jar build/libs/mcp-server-poc-0.0.1-SNAPSHOT.jar --spring.profiles.active=sse

服务器启动时间: http://localhost:8080

选项2:STDIO模式(适用于克劳德桌面)

STDIO模式通过标准输入/输出进行通信。在以下情况下使用此功能:

  • 连接到克劳德桌面
  • 使用期望STDIO传输的MCP客户端
java -jar build/libs/mcp-server-poc-0.0.1-SNAPSHOT.jar

测试您的服务器

1.基本健康检查

curl http://localhost:8080/
# Returns: {"name":"shop-mcp-server","status":"running",...}

curl http://localhost:8080/health
# Returns: {"status":"UP"}

2.测试SSE端点

curl -N http://localhost:8080/sse
# Returns:
# id:abc123-def456...
# event:endpoint
# data:/mcp/message?sessionId=abc123-def456...

3.测试REST API

# Get all phones
curl http://localhost:8080/api/tools/phones

# Get Apple phones
curl http://localhost:8080/api/tools/phones/brand/Apple

# Get 5G plans
curl http://localhost:8080/api/tools/plans/5g

# Get products from external API
curl http://localhost:8080/api/tools/products

4.MCP检查员(最适合目视测试)

npx @modelcontextprotocol/inspector --url http://localhost:8080/sse
  1. 打开http://localhost:6274在浏览器中
  2. 点击“连接”
  3. 转到“工具”选项卡-您将看到所有17个工具
  4. 点击任何工具进行测试!

理解代码

如何创建MCP工具

MCP工具只是一个Java方法 @Tool 注释:

@Service
public class PhoneService {

    @Tool(name = "shop_get_phones_by_brand",
          description = "Get phone models filtered by brand")
    public List<PhoneModel> getPhonesByBrand(
            @ToolParam(description = "Brand name: Apple, Samsung, Google, Xiaomi")
            String brand) {

        // Your business logic here
        return phones.stream()
                .filter(phone -> phone.brand().equalsIgnoreCase(brand))
                .collect(Collectors.toList());
    }
}

关键注释:

  • @Tool(name, description) -将方法标记为MCP工具
  • @ToolParam(description) -描述AI的每个参数

注册工具(重要提示!)

在Spring AI 1.0.0中,您必须在 McpToolConfig.java:

@Configuration
public class McpToolConfig {

    @Bean
    public ToolCallbackProvider phoneToolCallbackProvider(PhoneService phoneService) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(phoneService)
                .build();
    }

    // Add similar beans for each service...
}

为什么? Spring AI 1.0.0不会自动发现 @Tool 方法。您必须明确注册每个服务。


添加自己的服务(一步一步)

让我们添加一个新 订单服务 例如:

步骤1:创建数据模型

创建 src/main/java/com/example/mcpserver/model/Order.java:

package com.example.mcpserver.model;

import java.time.LocalDateTime;

public record Order(
    String orderId,
    String customerName,
    String phoneId,
    String planId,
    double totalPrice,
    String status,
    LocalDateTime createdAt
) {}

步骤2:使用@Tool方法创建服务

创建 src/main/java/com/example/mcpserver/service/OrderService.java:

package com.example.mcpserver.service;

import com.example.mcpserver.model.Order;
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.util.*;

@Service
public class OrderService {

    private final Map<String, Order> orders = new HashMap<>();

    @Tool(name = "order_create",
          description = "Create a new order for a phone and plan combination")
    public Order createOrder(
            @ToolParam(description = "Customer's full name") String customerName,
            @ToolParam(description = "Phone ID (e.g., iphone-15-pro)") String phoneId,
            @ToolParam(description = "Plan ID (e.g., combo-plus-98)") String planId,
            @ToolParam(description = "Total price in SGD") double totalPrice) {

        String orderId = "ORD-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
        Order order = new Order(orderId, customerName, phoneId, planId,
                               totalPrice, "PENDING", LocalDateTime.now());
        orders.put(orderId, order);
        return order;
    }

    @Tool(name = "order_get_by_id",
          description = "Get order details by order ID")
    public Order getOrderById(
            @ToolParam(description = "Order ID (e.g., ORD-ABC12345)") String orderId) {
        return orders.get(orderId);
    }

    @Tool(name = "order_list_all",
          description = "Get all orders")
    public List<Order> getAllOrders() {
        return new ArrayList<>(orders.values());
    }

    @Tool(name = "order_update_status",
          description = "Update order status")
    public Order updateOrderStatus(
            @ToolParam(description = "Order ID") String orderId,
            @ToolParam(description = "New status: PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED") String status) {

        Order existing = orders.get(orderId);
        if (existing == null) return null;

        Order updated = new Order(existing.orderId(), existing.customerName(),
                                  existing.phoneId(), existing.planId(),
                                  existing.totalPrice(), status, existing.createdAt());
        orders.put(orderId, updated);
        return updated;
    }
}

步骤3:在McpToolConfig中注册服务

编辑 src/main/java/com/example/mcpserver/config/McpToolConfig.java:

@Configuration
public class McpToolConfig {

    // ... existing beans ...

    @Bean
    public ToolCallbackProvider orderToolCallbackProvider(OrderService orderService) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(orderService)
                .build();
    }
}

步骤4:(可选)添加REST端点

编辑 src/main/java/com/example/mcpserver/controller/ToolRestController.java:

// Add to existing controller

@Autowired
private OrderService orderService;

@PostMapping("/orders")
public Order createOrder(@RequestBody Map<String, Object> request) {
    return orderService.createOrder(
        (String) request.get("customerName"),
        (String) request.get("phoneId"),
        (String) request.get("planId"),
        ((Number) request.get("totalPrice")).doubleValue()
    );
}

@GetMapping("/orders")
public List<Order> getAllOrders() {
    return orderService.getAllOrders();
}

@GetMapping("/orders/{id}")
public Order getOrderById(@PathVariable String id) {
    return orderService.getOrderById(id);
}

步骤5:重建和测试

# Rebuild
./gradlew clean build -x test

# Run
./gradlew bootRun --args='--spring.profiles.active=sse'

# Test with MCP Inspector
npx @modelcontextprotocol/inspector --url http://localhost:8080/sse

您的新工具将出现: order_create, order_get_by_id, order_list_all, order_update_status


连接到真实API

这 ProductCatalogService 显示了如何连接到外部API:

1.创建API客户端

@Component
public class ProductApiClient {

    private final WebClient webClient;

    public ProductApiClient(@Value("${api.product.base-url}") String baseUrl) {
        this.webClient = WebClient.builder()
                .baseUrl(baseUrl)
                .build();
    }

    @Cacheable(value = "products", key = "'all'")
    public List<ProductDTO> getAllProducts() {
        return webClient.get()
                .uri("/products")
                .retrieve()
                .bodyToFlux(ProductDTO.class)
                .collectList()
                .timeout(Duration.ofSeconds(10))
                .block();
    }
}

2.在application.properties中配置

api.product.base-url=https://fakestoreapi.com
api.product.timeout-seconds=10

3.在您的服务中使用

@Service
public class ProductCatalogService {

    private final ProductApiClient apiClient;

    @Tool(name = "catalog_get_all_products",
          description = "Get all products from catalog")
    public List<ProductDTO> getAllProducts() {
        return apiClient.getAllProducts();
    }
}

REST API(适用于非MPCP客户端)

所有工具也可通过REST API访问 /api/tools/:

API指数

GET http://localhost:8080/api/tools

电话端点

GET /api/tools/phones                    # All phones
GET /api/tools/phones/brand/{brand}      # By brand
GET /api/tools/phones/{id}               # By ID
GET /api/tools/phones/search?minPrice=0&maxPrice=500
GET /api/tools/phones/in-stock

规划端点

GET /api/tools/plans                     # All plans
GET /api/tools/plans/category/{category} # By category
GET /api/tools/plans/5g                  # 5G only
GET /api/tools/plans/recommend?dataUsageGB=50&budget=100&needs5G=true

产品端点

GET /api/tools/products                  # All products
GET /api/tools/products/{id}             # By ID
GET /api/tools/products/categories       # List categories
GET /api/tools/products/search?keyword=jacket
GET /api/tools/products/stats            # Statistics

连接到LLM

克劳德桌面版

  1. 构建JAR:

    ./gradlew clean build -x test
    
  2. 编辑Claude配置文件:

    macOS: ~/Library/Application Support/Claude/claude_desktop_config.json 窗户: %APPDATA%\Claude\claude_desktop_config.json

    {
      "mcpServers": {
        "shop-service": {
          "command": "java",
          "args": [
            "-jar",
            "/full/path/to/mcpspring/build/libs/mcp-server-poc-0.0.1-SNAPSHOT.jar"
          ]
        }
      }
    }
    
  3. 重新启动克劳德桌面

  4. 测试:问克劳德“有什么手机?”

ChatGPT/OpenAI(通过函数调用)

将REST API与OpenAI函数调用一起使用:

import openai
import requests

# Define tools as OpenAI functions
tools = [{
    "type": "function",
    "function": {
        "name": "get_phones_by_brand",
        "description": "Get phones filtered by brand",
        "parameters": {
            "type": "object",
            "properties": {
                "brand": {"type": "string", "enum": ["Apple", "Samsung", "Google"]}
            },
            "required": ["brand"]
        }
    }
}]

# When GPT calls the function, forward to your REST API
def call_tool(name, args):
    if name == "get_phones_by_brand":
        response = requests.get(f"http://localhost:8080/api/tools/phones/brand/{args['brand']}")
        return response.json()

# Use with OpenAI
response = openai.chat.completions.create(
    model="gpt-4",
    messages=[{"role": "user", "content": "Show me Apple phones"}],
    tools=tools
)

配置参考

application.properties(STDIO模式)

spring.main.web-application-type=none
spring.ai.mcp.server.name=shop-mcp-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.stdio=true

application-se.properties(sse模式)

spring.main.web-application-type=servlet
spring.ai.mcp.server.name=shop-mcp-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.stdio=false
spring.ai.mcp.server.type=SYNC
server.port=8080

# External API
api.product.base-url=https://fakestoreapi.com
api.product.timeout-seconds=10

# Caching
spring.cache.type=caffeine
spring.cache.caffeine.spec=maximumSize=100,expireAfterWrite=5m

# Logging (set to DEBUG for troubleshooting)
logging.level.com.example.mcpserver=DEBUG
logging.level.org.springframework.ai.mcp=DEBUG

故障排除

构建失败

问题: Gradle构建失败

# Check Java version
java -version  # Should be 17+

# Clear Gradle cache and rebuild
./gradlew clean build --refresh-dependencies

服务器无法启动

问题: 端口8080已在使用中

# Find and kill process on port 8080
lsof -ti:8080 | xargs kill -9

# Or use a different port
./gradlew bootRun --args='--spring.profiles.active=sse --server.port=9090'

SSE端点返回404

问题: 工具未注册

解决方案: 确保您的服务已在中注册 McpToolConfig.java:

@Bean
public ToolCallbackProvider myServiceToolCallbackProvider(MyService myService) {
    return MethodToolCallbackProvider.builder()
            .toolObjects(myService)
            .build();
}

MCP检查器无法连接

问题: 连接被拒绝

解决方案:

  1. 确保服务器正在运行: curl http://localhost:8080/health
  2. 检查SSE端点: curl http://localhost:8080/sse
  3. 尝试使用显式URL: npx @modelcontextprotocol/inspector --url http://127.0.0.1:8080/sse

工具未出现

问题: 已定义但不可见的工具

检查表:

  • []方法有 @Tool 注释
  • []班级有 @Service 注释
  • []服务已在中注册 McpToolConfig.java
  • []服务器在更改后重新启动

资源

官方文件

工具

例子


许可证

麻省理工学院许可证-您可以自由使用和修改您的项目。


问题?

如果您有任何疑问或问题:

  1. 检查 故障排除 章节
  2. 查看 MCP文件
  3. 在此存储库中打开问题