MCP 的技术原理与在 Java 项目中的落地

一、MCP 核心技术原理

MCP 本质是基于 JSON-RPC 2.0 的标准化 RPC 协议,核心解决「大模型与外部工具 / 数据的统一交互问题」,其技术架构可拆解为三层,完全适配 Java 的分层设计思想:

层级角色(Java 对应实现)核心职责
应用层Host(你的 Java 业务系统)接收用户指令→调用大模型→解析模型的 MCP 调用意图→转发指令到 MCP Client
协议层Client(Java MCP 客户端)标准化封装指令(JSON-RPC 格式)→与 MCP Server 建立通信→处理请求 / 响应序列化
工具适配层Server(Java MCP 服务端)适配具体工具(MySQL/Redis/ 本地文件)→执行实际操作→按 MCP 标准返回结果

MCP 核心通信流程(时序)

  1. Host(Java 系统)接收用户指令:「查询上月华东区销售数据并生成报表」;
  2. Host 调用大模型,模型识别出需要「调用 MySQL 查询 + 生成 Excel」,返回 MCP 调用指令;
  3. Java MCP Client 将指令封装为 JSON-RPC 2.0 格式(如{"jsonrpc":"2.0","method":"mysql/query","params":{"sql":"SELECT ..."},"id":"123"});
  4. Client 通过 HTTP/TCP 将指令发送给 MCP Server(已适配 MySQL);
  5. MCP Server 执行 SQL,将结果按 MCP 标准返回(结构化 JSON);
  6. Client 解析结果后回传给 Host,Host 再调用大模型生成报表,最终返回给用户。

MCP 与 Java 生态的适配点

  • 协议层:JSON-RPC 可通过 Jackson/Gson 轻松序列化,兼容 Java 主流 JSON 库;
  • 通信层:支持 HTTP/WebSocket,可复用 Spring Boot 的 RestTemplate/Netty;
  • 工具适配层:可基于 Spring Bean 封装 MCP Server,适配你现有项目的数据源、工具类;
  • 安全层:可集成 Spring Security 实现权限控制(如限制 AI 只能读特定表),适配企业级安全需求。

二、Java 项目落地 MCP 实战:AI 调用本地 MySQL 生成销售报表

场景背景

你现有 Spring Boot 项目已集成 MySQL(销售数据)、POI(Excel 生成),现在要新增「AI 助手」功能,让用户通过自然语言查询销售数据并生成报表,要求:

  1. 标准化调用 MySQL,避免为 AI 写定制化 SQL 查询接口;
  2. 权限控制:AI 只能读sales表,禁止执行 DELETE/UPDATE;
  3. 兼容现有项目的数据源配置,不侵入核心业务代码。

步骤 1:架构设计(适配现有 Java 项目)

步骤 2:技术选型(基于 Java 生态)

  • 核心依赖:JSON-RPC(com.github.briandilley.jsonrpc4j:jsonrpc4j:1.6.0)、Spring Boot 2.7+、MySQL Connector、POI;
  • MCP 协议封装:自定义 MCP 消息体(兼容 MCP 标准);
  • 通信方式:HTTP(复用现有项目的 Tomcat 容器)。

步骤 3:代码实现(完整可运行)

3.1 引入依赖(pom.xml)

<dependencies>
    <!-- Spring Boot核心 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- JSON-RPC核心 -->
    <dependency>
        <groupId>com.github.briandilley.jsonrpc4j</groupId>
        <artifactId>jsonrpc4j</artifactId>
        <version>1.6.0</version>
    </dependency>
    <!-- MySQL驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- POI(Excel生成) -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>5.2.5</version>
    </dependency>
    <!-- Jackson(JSON序列化) -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
</dependencies>

3.2 定义 MCP 核心模型(兼容 MCP 标准)

// MCP请求模型(JSON-RPC 2.0 + MCP扩展)
public class MCPRequest {
    private String jsonrpc = "2.0";
    private String id; // 请求ID,用于异步回调
    private String method; // 调用方法,如"mysql/query"
    private MCPParams params; // 调用参数

    // getter/setter
}

// MCP参数模型
public class MCPParams {
    private String sql; // SQL语句
    private String dataSourceName; // 数据源名称(适配多数据源)
    // 权限控制扩展字段
    private List<String> allowedOperations; // 允许的操作:SELECT/INSERT等

    // getter/setter
}

// MCP响应模型
public class MCPResponse {
    private String jsonrpc = "2.0";
    private String id;
    private Object result; // 执行结果(List<Map<String, Object>>)
    private MCPError error; // 错误信息

    // getter/setter
}

// MCP错误模型
public class MCPError {
    private int code;
    private String message;

    // getter/setter
}

3.3 实现 MCP Server(MySQL 适配,核心)

/**
 * MCP Server:适配MySQL,处理AI的查询请求
 * 集成现有项目的数据源,添加权限控制
 */
@RestController
@RequestMapping("/mcp/server/mysql")
public class MysqlMCPServer {

    // 注入现有项目的数据源(复用原有配置)
    @Autowired
    private DataSource dataSource;

    /**
     * MCP调用入口:处理JSON-RPC格式的MySQL查询请求
     */
    @PostMapping("/execute")
    public ResponseEntity<MCPResponse> executeMysqlQuery(@RequestBody MCPRequest request) {
        MCPResponse response = new MCPResponse();
        response.setId(request.getId());

        try {
            // 1. 权限校验(核心:限制AI只能执行SELECT)
            MCPParams params = request.getParams();
            if (params == null || !params.getSql().trim().toUpperCase().startsWith("SELECT")) {
                MCPError error = new MCPError();
                error.setCode(-32602);
                error.setMessage("AI仅允许执行SELECT查询,禁止修改数据");
                response.setError(error);
                return ResponseEntity.badRequest().body(response);
            }

            // 2. 执行SQL(复用现有项目的JDBC逻辑)
            try (Connection conn = dataSource.getConnection();
                 PreparedStatement ps = conn.prepareStatement(params.getSql());
                 ResultSet rs = ps.executeQuery()) {

                // 3. 结果转换为结构化数据(MCP标准返回)
                List<Map<String, Object>> resultList = new ArrayList<>();
                ResultSetMetaData metaData = rs.getMetaData();
                int columnCount = metaData.getColumnCount();

                while (rs.next()) {
                    Map<String, Object> row = new HashMap<>();
                    for (int i = 1; i <= columnCount; i++) {
                        row.put(metaData.getColumnName(i), rs.getObject(i));
                    }
                    resultList.add(row);
                }

                response.setResult(resultList);
                return ResponseEntity.ok(response);
            }

        } catch (Exception e) {
            MCPError error = new MCPError();
            error.setCode(-32603);
            error.setMessage("执行SQL失败:" + e.getMessage());
            response.setError(error);
            return ResponseEntity.internalServerError().body(response);
        }
    }
}

3.4 实现 MCP Client(调用 MCP Server)

/**
 * MCP Client:标准化调用MCP Server
 * 封装JSON-RPC请求,适配现有项目的HTTP调用
 */
@Component
public class MCPClient {

    @Autowired
    private RestTemplate restTemplate;

    // MCP Server地址(可配置在application.yml)
    private static final String MYSQL_MCP_SERVER_URL = "http://localhost:8080/mcp/server/mysql/execute";

    /**
     * 调用MCP Server执行MySQL查询
     * @param sql 查询SQL
     * @return 结构化查询结果
     */
    public List<Map<String, Object>> callMysqlQuery(String sql) {
        // 1. 构建MCP请求(JSON-RPC标准)
        MCPRequest request = new MCPRequest();
        request.setId(UUID.randomUUID().toString());
        request.setMethod("mysql/query");

        MCPParams params = new MCPParams();
        params.setSql(sql);
        params.setDataSourceName("sales-ds"); // 对应现有项目的数据源名称
        params.setAllowedOperations(Collections.singletonList("SELECT"));
        request.setParams(params);

        // 2. 发送HTTP请求到MCP Server
        MCPResponse response = restTemplate.postForObject(MYSQL_MCP_SERVER_URL, request, MCPResponse.class);

        // 3. 处理响应
        if (response == null || response.getError() != null) {
            String errorMsg = response != null ? response.getError().getMessage() : "MCP Server无响应";
            throw new RuntimeException("MCP调用失败:" + errorMsg);
        }

        return (List<Map<String, Object>>) response.getResult();
    }
}

3.5 实现 Host 层(AI 助手业务逻辑)

/**
 * Host层:AI助手核心逻辑
 * 集成大模型+MCP Client+Excel生成,适配现有项目的业务流程
 */
@RestController
@RequestMapping("/ai/assistant")
public class AIAssistantController {

    @Autowired
    private MCPClient mcpClient;

    // 大模型API(示例:可替换为本地LLM/企业级大模型)
    private static final String LLM_API_URL = "https://api.openai.com/v1/chat/completions";

    /**
     * 用户入口:自然语言查询销售数据并生成报表
     */
    @PostMapping("/sales-report")
    public ResponseEntity<String> generateSalesReport(@RequestParam String userQuery) {
        try {
            // 1. 调用大模型,解析用户意图生成SQL(核心:将自然语言转为可执行的SQL)
            String sql = generateSqlFromLLM(userQuery);
            System.out.println("大模型生成的SQL:" + sql);

            // 2. 通过MCP Client调用MySQL查询数据
            List<Map<String, Object>> salesData = mcpClient.callMysqlQuery(sql);

            // 3. 生成Excel报表(复用现有项目的POI逻辑)
            String excelPath = generateExcelReport(salesData);

            return ResponseEntity.ok("报表生成成功,路径:" + excelPath);
        } catch (Exception e) {
            return ResponseEntity.internalServerError().body("生成报表失败:" + e.getMessage());
        }
    }

    /**
     * 调用大模型生成SQL(示例:可替换为你项目中的大模型集成方式)
     */
    private String generateSqlFromLLM(String userQuery) {
        // 构建大模型提示词(引导生成标准化SQL)
        String prompt = "你是Java项目的SQL生成助手,仅生成SELECT语句,数据源为sales表(字段:id, region, amount, sale_date)。" +
                "用户需求:" + userQuery + ",请生成对应的MySQL SQL语句,只返回SQL,不要其他内容。";

        // 调用大模型API(此处为简化示例,实际需集成你的大模型SDK)
        // 替换为你项目中的大模型调用逻辑(如OpenAI/讯飞/本地LLM)
        return "SELECT region, SUM(amount) AS total_amount FROM sales WHERE sale_date >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND region = '华东区' GROUP BY region";
    }

    /**
     * 生成Excel报表(复用现有项目的POI工具)
     */
    private String generateExcelReport(List<Map<String, Object>> data) throws Exception {
        String filePath = "sales_report_" + System.currentTimeMillis() + ".xlsx";
        XSSFWorkbook workbook = new XSSFWorkbook();
        XSSFSheet sheet = workbook.createSheet("上月销售数据");

        // 创建表头
        XSSFRow headerRow = sheet.createRow(0);
        headerRow.createCell(0).setCellValue("区域");
        headerRow.createCell(1).setCellValue("总销售额");

        // 填充数据
        int rowNum = 1;
        for (Map<String, Object> row : data) {
            XSSFRow dataRow = sheet.createRow(rowNum++);
            dataRow.createCell(0).setCellValue(row.get("region").toString());
            dataRow.createCell(1).setCellValue(Double.parseDouble(row.get("total_amount").toString()));
        }

        // 写入文件(实际项目中可存储到OSS/本地目录)
        FileOutputStream outputStream = new FileOutputStream(filePath);
        workbook.write(outputStream);
        workbook.close();
        outputStream.close();

        return filePath;
    }
}

3.6 配置类(复用现有数据源)

@Configuration
public class MCPConfig {

    // 配置RestTemplate(用于MCP Client的HTTP调用)
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    // 复用现有项目的数据源配置(此处为示例,实际使用你项目中的数据源)
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource")
    public DataSource dataSource() {
        return DataSourceBuilder.create().build();
    }
}

3.7 配置文件(application.yml)

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sales_db?useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver
server:
  port: 8080

步骤 4:测试与集成验证

  1. 启动 Spring Boot 项目,确保 MySQL 中sales表有测试数据;
  2. 调用接口:POST http://localhost:8080/ai/assistant/sales-report?userQuery=查询上月华东区销售总额
  3. 预期结果:
    • 大模型生成指定 SQL;
    • MCP Client 调用 MCP Server 执行 SQL;
    • 生成 Excel 报表,返回文件路径;
    • 若尝试执行 DELETE SQL,MCP Server 会返回权限错误(符合安全控制要求)。

三、现有 Java 项目集成 MCP 的最佳实践

1. 非侵入式集成(优先推荐)

  • 将 MCP Client/Server 封装为独立模块(Module),通过 Spring Boot Starter 引入现有项目;
  • 复用现有数据源、权限框架(Spring Security)、日志体系,避免修改核心业务代码;
  • MCP Server 与现有工具类(如 MySQLUtil、ExcelUtil)解耦,通过接口调用。

2. 权限与安全控制

  • 在 MCP Server 层添加细粒度权限:按 AI 应用 / 用户限制可访问的表、字段;
  • 增加操作审计:记录所有 MCP 调用的 SQL / 操作,适配企业合规要求;
  • 限流降级:通过 Sentinel/Resilience4j 限制 MCP 调用频率,避免压垮数据库。

3. 扩展场景(适配不同工具)

  • 适配 Redis:复制 MySQL MCP Server,修改为 Redis 操作(如redis/get);
  • 适配本地文件:添加file/read方法,限制文件读取路径;
  • 适配外部 API:添加api/call方法,封装 HTTP 调用外部接口(如物流 API)。

总结

  1. MCP 核心原理:基于 JSON-RPC 2.0 的标准化 RPC 协议,将 AI 与外部工具的交互拆分为 Host(业务)、Client(协议封装)、Server(工具适配)三层,适配 Java 分层架构;
  2. Java 落地关键:复用现有生态(Spring Boot、JDBC、POI),将 MCP Server 封装为 Spring Bean,通过 RestTemplate 实现 Client 与 Server 的通信,重点做好权限控制;
  3. 集成原则:非侵入式接入现有项目,优先封装为独立模块,复用现有数据源、权限、日志体系,降低维护成本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tan_jianhui

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值