手把手教你用 Spring Boot 搭建一个 MCP Server
随着 AI Agent 技术的发展,MCP(Model Context Protocol) 正在成为连接大模型与外部工具的标准协议之一。使用 Spring Boot 搭建一个 MCP Server,可以帮助你将自己的业务能力(如数据库查询、文件处理、内部系统调用等)安全地暴露给 LLM Agents 使用。
🚀 使用 Spring Boot 搭建自己的 MCP Server
✅ 本文将带你从零开始构建一个符合 MCP 规范 的轻量级 MCP Server,支持:工具注册动态上下文交互JSON-RPC over HTTPOpenAPI 文档集成
🔧 技术栈:Spring Boot 3 + Java 17 + Maven + Spring Web + Jackson
一、什么是 MCP?
MCP(Model Context Protocol) 是由 Anthropic 提出的一种标准化协议,用于让语言模型(LLM)以结构化方式访问外部工具和数据源。
核心功能:
- List Tools:列出可用的工具
- Call Tool:调用指定工具并返回结果
- Streaming Support(可选):支持流式响应
类似于 OpenAI 的 Function Calling 或 Google 的 Vertex AI Gateway,但更开放、轻量。
二、项目结构设计
src/ ├── main/ │ ├── java/ │ │ └── com.example.mcpserver/ │ │ ├── McpApplication.java # 主启动类 │ │ │ │ │ ├── controller/ │ │ │ └── McpController.java # 处理 /mcp 路由 │ │ │ │ │ ├── model/ │ │ │ ├── Tool.java # 工具元信息 │ │ │ ├── ToolCallRequest.java # 调用请求 │ │ │ └── ToolResult.java # 返回结果 │ │ │ │ │ └── service/ │ │ ├── ToolRegistry.java # 工具注册中心 │ │ └── impl/ │ │ ├── TimeTool.java # 示例工具:获取当前时间 │ │ └── WeatherTool.java # 示例工具:查天气 │ │ │ └── resources/ │ ├── application.yml │ └── openapi/mcp-api.yaml # OpenAPI 描述文件(可选)三、添加依赖(pom.xml)
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Lombok 简化 POJO --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><scope>provided</scope></dependency><!-- JSON 处理 --><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId></endependency></dependencies>四、定义核心数据模型
Tool.java —— 工具元信息
packagecom.example.mcpserver.model;importlombok.Data;importjava.util.Map;@DatapublicclassTool{privateString name;privateString description;privateMap<String,Object> inputSchema;// JSON Schema 格式}ToolCallRequest.java
packagecom.example.mcpserver.model;importlombok.Data;importjava.util.List;importjava.util.Map;@DatapublicclassToolCallRequest{privateList<Map<String,Object>> toolCalls;}ToolResult.java
packagecom.example.mcpserver.model;importlombok.Data;@DatapublicclassToolResult{privateString toolName;privateObject result;privateboolean isError;}五、实现工具接口与注册中心
定义工具接口
// service/Tool.javapublicinterfaceTool{StringgetName();StringgetDescription();ObjectgetInputSchema();// 返回 JSON SchemaObjectinvoke(Map<String,Object> input);}实现示例工具:获取当前时间
// service/impl/TimeTool.java@ComponentpublicclassTimeToolimplementsTool{@OverridepublicStringgetName(){return"get_current_time";}@OverridepublicStringgetDescription(){return"Returns the current time in ISO8601 format.";}@OverridepublicObjectgetInputSchema(){returnMap.of("type","object","properties",Map.of());}@OverridepublicObjectinvoke(Map<String,Object> input){returnMap.of("time",Instant.now().toString(),"timezone",ZoneId.systemDefault());}}工具注册中心(自动收集所有工具)
// service/ToolRegistry.java@ServicepublicclassToolRegistry{privatefinalMap<String,Tool> tools =newConcurrentHashMap<>();publicToolRegistry(List<Tool> toolList){for(Tool tool : toolList){ tools.put(tool.getName(), tool);}System.out.println("✅ 注册了 "+ tools.size()+" 个 MCP 工具");}publicCollection<Tool>getTools(){return tools.values();}publicToolgetTool(String name){return tools.get(name);}}Spring 会自动注入所有实现了 Tool 接口的 Bean。六、编写 MCP Controller(核心端点)
// controller/McpController.java@RestController@RequestMapping("/mcp")@RequiredArgsConstructorpublicclassMcpController{privatefinalToolRegistry toolRegistry;/** * GET /mcp/tools - 列出所有可用工具 */@GetMapping("/tools")publicResponseEntity<List<Tool>>listTools(){returnResponseEntity.ok(toolRegistry.getTools().stream().toList());}/** * POST /mcp/call-tool - 调用工具 */@PostMapping("/call-tool")publicResponseEntity<List<ToolResult>>callTools(@RequestBodyToolCallRequest request){returnResponseEntity.ok(request.getToolCalls().stream().map(call ->{String toolName =(String) call.get("name");Map<String,Object> input =(Map<String,Object>) call.get("input");Tool tool = toolRegistry.getTool(toolName);if(tool ==null){returnnewToolResult(toolName,"Tool not found",true);}try{Object result = tool.invoke(input);returnnewToolResult(toolName, result,false);}catch(Exception e){returnnewToolResult(toolName, e.getMessage(),true);}}).collect(Collectors.toList()));}}七、配置路由(application.yml)
server:port:8080logging:level:com.example: DEBUG 八、测试你的 MCP Server
启动应用
mvn spring-boot:run 1. 查看可用工具
curl http://localhost:8080/mcp/tools 输出示例:
[{"name":"get_current_time","description":"Returns the current time in ISO8601 format.","inputSchema":{...}}]2. 调用工具
curl -X POST http://localhost:8080/mcp/call-tool \ -H "Content-Type: application/json"\ -d '{ "toolCalls": [ { "name": "get_current_time", "input": {} } ] }'返回:
[{"toolName":"get_current_time","result":{"time":"2025-11-04T15:40:00Z","timezone":"Asia/Shanghai"},"isError":false}]九、进阶优化建议
| 功能 | 实现思路 |
|---|---|
| ✅ 认证鉴权 | 添加 JWT 或 API Key 验证(如 @RequestHeader("X-API-Key")) |
| ✅ 请求校验 | 使用 @Valid 和 JSON Schema 校验输入参数 |
| ✅ 异步执行 | 对耗时工具使用 @Async 支持非阻塞调用 |
| ✅ 日志追踪 | 加入 MDC、Trace ID,便于调试 |
| ✅ OpenAPI 文档 | 使用 SpringDoc(Swagger)生成 /docs 页面 |
| ✅ 流式响应 | 改用 SseEmitter 或 WebSocket 支持 streaming |
| ✅ 自动发现 | 扫描注解(如 @McPTool)自动注册 |
十、部署与集成
部署方式
- 构建成 JAR 包运行
- 打包为 Docker 镜像
- 部署到 Kubernetes 并通过 Ingress 暴露
与 AI Agent 集成
你可以将这个 MCP Server 地址注册到支持 MCP 的客户端中,例如:
{"mcpServers":{"my-company-tools":{"url":"https://mcp.yourcompany.com/mcp","apiKey":"xxx"}}}目前主流平台如 Anthropic Claude,以及开源框架如 LangChain、LlamaIndex 正在逐步支持 MCP。
✅ 总结:搭建 MCP Server 的关键步骤
- ✅ 定义工具接口
Tool - ✅ 实现具体业务逻辑(如时间、天气、订单查询)
- ✅ 使用
ToolRegistry自动注册 - ✅ 提供
/mcp/tools和/mcp/call-tool两个标准接口 - ✅ 安全加固 + 监控日志
- ✅ 部署上线并接入 AI Agent
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨