springboot搭建MCP Server
使用 Spring Boot 搭建 MCP(Model Context Protocol)服务
原理 · 步骤 · 完整代码 · 部署指南
一、什么是 MCP?
MCP(Model Context Protocol) 是一种轻量级、标准化的协议,用于让 AI 客户端(如 Cursor、Continue、VS Code 插件)与后端工具/模型服务通信。
- 基于 JSON-RPC 2.0
- 支持三种传输方式:HTTP、WebSocket、stdio
- 核心能力:
list_tools:列出可用工具call_tool:调用指定工具list_resources/read_resource:访问上下文资源(可选)
📌 本文聚焦 HTTP 模式,这是最易部署且被主流 IDE 插件广泛支持的方式。
二、搭建原理
架构图
[Cursor / Continue 插件]
↓ (HTTP POST /mcp)
[Spring Boot MCP Server] ←→ [你的业务逻辑 / LLM / 数据库]
↑
JSON-RPC 2.0 over HTTP
工作流程
- 客户端发送 JSON-RPC 请求到
/mcp - Spring Boot Controller 解析
method字段 - 根据方法名分发到对应处理逻辑
- 返回符合 JSON-RPC 规范的响应
- 客户端解析结果并展示给用户
✅ 关键点:你不需要实现完整 JSON-RPC 框架,只需按规范处理几个固定方法即可。
三、详细步骤 + 完整代码实现
步骤 1:创建 Spring Boot 项目
使用 https://start.spring.io 创建项目:
- Project: Maven
- Language: Java
- Spring Boot: 3.x
- Dependencies:
- Spring Web
- Lombok(可选,简化日志和 getter/setter)
或直接使用以下 pom.xml:
<?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
https://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.2.0</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>mcp-server</artifactId>
<version>0.0.1</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</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>
步骤 2:定义数据结构(DTO)
1. JSON-RPC 基础类
// src/main/java/com/example/mcpserver/dto/JsonRpcRequest.java
package com.example.mcpserver.dto;
import lombok.Data;
@Data
public class JsonRpcRequest {
private String jsonrpc = "2.0";
private String method;
private Object params;
private Object id;
}
// src/main/java/com/example/mcpserver/dto/JsonRpcResponse.java
package com.example.mcpserver.dto;
import lombok.Data;
@Data
public class JsonRpcResponse {
private String jsonrpc = "2.0";
private Object result;
private JsonRpcError error;
private Object id;
}
// src/main/java/com/example/mcpserver/dto/JsonRpcError.java
package com.example.mcpserver.dto;
import lombok.Data;
@Data
public class JsonRpcError {
private int code;
private String message;
private Object data;
}
2. MCP 特定结构
// src/main/java/com/example/mcpserver/dto/Tool.java
package com.example.mcpserver.dto;
import lombok.Data;
import java.util.Map;
@Data
public class Tool {
private String name;
private String description;
private Map<String, Object> inputSchema; // JSON Schema
}
// src/main/java/com/example/mcpserver/dto/ListToolsResult.java
package com.example.mcpserver.dto;
import lombok.Data;
import java.util.List;
@Data
public class ListToolsResult {
private List<Tool> tools;
}
// src/main/java/com/example/mcpserver/dto/CallToolParams.java
package com.example.mcpserver.dto;
import lombok.Data;
import java.util.Map;
@Data
public class CallToolParams {
private String name;
private Map<String, Object> arguments;
}
步骤 3:实现 MCP 服务逻辑
// src/main/java/com/example/mcpserver/service/McpService.java
package com.example.mcpserver.service;
import com.example.mcpserver.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
@Slf4j
@Service
public class McpService {
public ListToolsResult listTools() {
Tool searchTool = new Tool();
searchTool.setName("search_documentation");
searchTool.setDescription("Search internal technical documentation");
searchTool.setInputSchema(Map.of(
"type", "object",
"properties", Map.of(
"query", Map.of("type", "string", "description", "Keywords to search")
),
"required", List.of("query")
));
Tool currentTimeTool = new Tool();
currentTimeTool.setName("get_current_time");
currentTimeTool.setDescription("Get current server time");
currentTimeTool.setInputSchema(Map.of("type", "object", "properties", Map.of()));
return new ListToolsResult(List.of(searchTool, currentTimeTool));
}
public Object callTool(CallToolParams params) {
String toolName = params.getName();
Map<String, Object> args = params.getArguments();
switch (toolName) {
case "search_documentation":
String query = (String) args.get("query");
if (query == null || query.trim().isEmpty()) {
throw new IllegalArgumentException("'query' is required");
}
// 模拟搜索(实际可接入 Elasticsearch、数据库等)
return Map.of("content", "Found 3 docs related to: " + query);
case "get_current_time":
return Map.of("time", new Date().toString());
default:
throw new IllegalArgumentException("Unknown tool: " + toolName);
}
}
}
步骤 4:创建 Controller(核心!)
// src/main/java/com/example/mcpserver/controller/McpController.java
package com.example.mcpserver.controller;
import com.example.mcpserver.dto.*;
import com.example.mcpserver.service.McpService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@Slf4j
@RequiredArgsConstructor
@RestController
public class McpController {
private final McpService mcpService;
private final ObjectMapper objectMapper; // Spring Boot 自动注入
@PostMapping("/mcp")
public ResponseEntity<JsonRpcResponse> handleMcpRequest(@RequestBody JsonRpcRequest request) {
log.info("MCP Request - ID: {}, Method: {}", request.getId(), request.getMethod());
try {
JsonRpcResponse response = new JsonRpcResponse();
response.setId(request.getId());
switch (request.getMethod()) {
case "list_tools":
response.setResult(mcpService.listTools());
break;
case "call_tool":
// 将 params 转为 CallToolParams 对象
CallToolParams params = objectMapper.convertValue(request.getParams(), CallToolParams.class);
Object result = mcpService.callTool(params);
response.setResult(result);
break;
default:
return createErrorResponse(-32601, "Method not found", request.getId());
}
return ResponseEntity.ok(response);
} catch (Exception e) {
log.error("Error processing MCP request", e);
return createErrorResponse(-32603, "Internal error: " + e.getMessage(), request.getId());
}
}
private ResponseEntity<JsonRpcResponse> createErrorResponse(int code, String message, Object id) {
JsonRpcError error = new JsonRpcError();
error.setCode(code);
error.setMessage(message);
JsonRpcResponse response = new JsonRpcResponse();
response.setError(error);
response.setId(id);
return ResponseEntity.badRequest().body(response);
}
}
步骤 5:启动类
// src/main/java/com/example/mcpserver/McpServerApplication.java
package com.example.mcpserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class McpServerApplication {
public static void main(String[] args) {
SpringApplication.run(McpServerApplication.class, args);
}
}
四、测试你的 MCP Server
启动应用
./mvnw spring-boot:run
# 或
java -jar target/mcp-server-0.0.1.jar
默认端口:8080
测试 1:list_tools
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "1",
"method": "list_tools"
}'
✅ 响应示例:
{
"jsonrpc": "2.0",
"id": "1",
"result": {
"tools": [
{
"name": "search_documentation",
"description": "Search internal technical documentation",
"inputSchema": { ... }
},
{
"name": "get_current_time",
"description": "Get current server time",
"inputSchema": { "type": "object", "properties": {} }
}
]
}
}
测试 2:call_tool
curl -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": "2",
"method": "call_tool",
"params": {
"name": "search_documentation",
"arguments": { "query": "MCP protocol" }
}
}'
✅ 响应:
{
"jsonrpc": "2.0",
"id": "2",
"result": {
"content": "Found 3 docs related to: MCP protocol"
}
}
五、部署到生产环境
1. 打包
./mvnw clean package
2. 运行(后台)
nohup java -jar target/mcp-server-0.0.1.jar --server.port=8080 > mcp.log 2>&1 &
3. 反向代理 + HTTPS(Nginx 示例)
server {
listen 443 ssl;
server_name mcp.yourcompany.com;
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
location /mcp {
proxy_pass http://127.0.0.1:8080/mcp;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
4. 在客户端配置(以 Cursor 为例)
- Settings → Language Models → Add Custom Model
- Protocol: MCP
- URL:
https://mcp.yourcompany.com/mcp
六、安全增强(生产必备)
添加 API Key 验证
@PostMapping("/mcp")
public ResponseEntity<JsonRpcResponse> handleMcpRequest(
@RequestHeader(value = "Authorization", required = false) String auth,
@RequestBody JsonRpcRequest request) {
if (!"Bearer YOUR_SECRET_TOKEN".equals(auth)) {
return ResponseEntity.status(401).build();
}
// ... rest of logic
}
然后客户端请求时加头:
Authorization: Bearer YOUR_SECRET_TOKEN
七、扩展建议
| 功能 | 实现方式 |
|---|---|
| 调用本地 LLM | 在 call_tool 中集成 Ollama/Qwen API |
| 访问数据库 | 工具逻辑中使用 Spring Data JPA |
| 流式响应 | 改用 WebSocket 或 Server-Sent Events(需修改协议) |
| 日志审计 | 在 Controller 中记录请求/响应 |
✅ 总结
你现在已经掌握了:
- ✅ MCP 协议的核心原理
- ✅ 用 Spring Boot 实现 HTTP 模式的 MCP Server
- ✅ 完整代码结构 + 测试方法
- ✅ 生产部署与安全加固方案
这个服务可以无缝集成到 Cursor、Continue、CodeLlama 等现代 AI 编程工具中,让你的私有工具或知识库被 AI 直接调用!
💡 下一步:将
search_documentation替换为真实的企业知识库搜索,打造专属 AI 助手!
本文来自博客园,作者:蓝迷梦,转载请注明原文链接:https://www.cnblogs.com/hewei-blogs/articles/19493216

浙公网安备 33010602011771号