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

工作流程

  1. 客户端发送 JSON-RPC 请求到 /mcp
  2. Spring Boot Controller 解析 method 字段
  3. 根据方法名分发到对应处理逻辑
  4. 返回符合 JSON-RPC 规范的响应
  5. 客户端解析结果并展示给用户

✅ 关键点:你不需要实现完整 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 助手!

posted @ 2026-01-16 17:22  蓝迷梦  阅读(35)  评论(0)    收藏  举报