Spring Boot MCP服务器-完整指南
生产准备就绪 Spring Boot MCP(模型上下文协议)服务器 它将业务服务作为AI/LLM集成的工具。
______________________________________________________________________
目录
- 什么是MCP?
- 快速入门(5分钟)
- 项目概述
- 先决条件
- 安装和设置
- 运行服务器
- 测试您的服务器
- 理解代码
- 添加自己的服务(一步一步)
- 连接到真实API
- REST API(适用于非MPCP客户端)
- 连接到LLM
- 配置参考
- 故障排除
- 资源
______________________________________________________________________
什么是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
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窗户:
- 下载JDK 17 艾多普蒂姆
- 从下载Node.js
Linux(Ubuntu/Debian):
sudo apt update
sudo apt install openjdk-17-jdk nodejs npm______________________________________________________________________
安装和设置
步骤1:克隆存储库
git clone
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 executedJAR文件将位于: 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/products4.MCP检查员(最适合目视测试)
npx @modelcontextprotocol/inspector --url http://localhost:8080/sse- 打开http://localhost:6274在浏览器中
- 点击“连接”
- 转到“工具”选项卡-您将看到所有17个工具
- 点击任何工具进行测试!
______________________________________________________________________
理解代码
如何创建MCP工具
MCP工具只是一个Java方法 @Tool 注释:
@Service
public class PhoneService {
@Tool(name = "shop_get_phones_by_brand",
description = "Get phone models filtered by brand")
public List
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 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 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 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 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
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=103.在您的服务中使用
@Service
public class ProductCatalogService {
private final ProductApiClient apiClient;
@Tool(name = "catalog_get_all_products",
description = "Get all products from catalog")
public List
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
克劳德桌面版
- 构建JAR:
./gradlew clean build -x test- 编辑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"
]
}
}
}- 重新启动克劳德桌面
- 测试:问克劳德“有什么手机?”
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=trueapplication-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检查器无法连接
问题: 连接被拒绝
解决方案:
- 确保服务器正在运行:
curl http://localhost:8080/health - 检查SSE端点:
curl http://localhost:8080/sse - 尝试使用显式URL:
npx @modelcontextprotocol/inspector --url http://127.0.0.1:8080/sse
工具未出现
问题: 已定义但不可见的工具
检查表:
- \[\]方法有
@Tool注释 - \[\]班级有
@Service注释 - \[\]服务已在中注册
McpToolConfig.java - \[\]服务器在更改后重新启动
______________________________________________________________________
资源
官方文件
- 模型上下文协议 -MCP规范
- 春季AI MCP -Spring AI文档
- MCP Java SDK -Java SDK
工具
- MCP检查员 -视觉测试工具
- -npm包
例子
- Spring AI示例 -官方样品
- FakeStore API -免费API测试
______________________________________________________________________
许可证
麻省理工学院许可证-您可以自由使用和修改您的项目。
______________________________________________________________________
问题?
如果您有任何疑问或问题:
