大模型应用开发Spring AI实战-开发自己的MCP应用

今天这篇文章我来分享大模型应用开发Spring AI实战-开发自己的MCP服务。通过实际代码案例,逐步掌握Java生态下的AI大模型应用产品开发。

AI专栏软件环境

  • IntelliJ IDEA2024.3.5
  • JDK 17.0.13
  • Spring AI 1.0.0-SNAPSHOT
  • Spring Boot 3.4.4
  • Spring 6.2.5
  • 智谱大模型

我们先看本篇文章对应的项目结构,请看下图

text 复制代码
    spring-ai-lab07
    ├─spring-ai-mcp-client
    │  └─src
    │      ├─main
    │      │  ├─java
    │      │  │  └─cn
    │      │  │      └─itbeien
    │      │  │          └─lab07
    │      │  │              └─client
    │      │  │                  ├─config
    │      │  │                  └─controller
    │      │  └─resources
    │      └─test
    │          └─java
    └─spring-ai-mcp-server
        └─src
            ├─main
            │  ├─java
            │  │  └─cn
            │  │      └─itbeien
            │  │          └─lab07
            │  │              └─server
            │  │                  ├─config
            │  │                  └─service
            │  └─resources
            └─test
                └─java

完整代码在文章最后,如果觉得本篇文章对你有用,记得点赞、关注、收藏哦。你的支持是我持续更新的动力!

1 什么是MCP

​ MCP (Model Context Protocol)是一种开放协议,它标准化了应用程序向 LLM 提供上下文的方式。可以将 MCP 视为 AI 应用程序的 USB-C 端口。正如 USB-C 提供了一种将设备连接到各种外围设备和配件的标准化方式一样,MCP 提供了一种将 AI 模型连接到不同数据源和工具的标准化方式。MCP 是 Claude (Anthropic) 主导发布的一个开放的、通用的、有共识的协议标准。

​ MCP 可帮助用户在 LLM 之上构建代理和复杂的工作流程。LLM 经常需要与数据和工具集成,每一个环节的交互响应都需要花费时间,特别是在复杂的工作流程下,耗时更长,而 MCP 提供:

  • 越来越多的预构建集成(比如通用工具或通用的企业级业务服务),LLM 可以直接插入
  • LLM对接业务服务和工具就像使用USB集成一样简单
  • 可以使用MCP共享你的业务数据

2 MCP核心概念及架构

2.1 核心概念

  • MCP主机:像Claude Desktop、ide或AI工具这样想要通过MCP访问数据的程序
  • MCP客户端:与服务器保持1:1连接的协议客户端,比如本篇文章3.3为自定义的客户端实现
  • MCP服务器:轻量级程序,每个程序都通过标准化的模型上下文协议公开特定的功能,比如本篇文章3.2为自定义的服务端实现
  • 本地数据源:MCP服务器可以安全访问的计算机文件、数据库和服务
  • 远程服务:MCP服务器可以连接到的可通过internet(例如,通过api)访问的外部系统

2.2 MCP基础架构

2.3 MCP 与 API 快速比较

特征 MCP apI
集成工作 单一标准化集成 每个API单独集成,有各自的接入标准
实时通信 √支持 × 不支持
动态发现 √支持 × 不支持
可扩展性 简单(即插即用) 需要额外集成
安全与控制 跨工具/程序保持一致 因API而异

MCP 与传统 API 之间的主要区别在于:

  • 单一协议:MCP 充当标准化的"连接器",因此集成一个 MCP 意味着可能访问多个工具和服务,而不仅仅是一个。
  • 动态发现:MCP 允许 AI 模型动态发现可用工具并与之交互,而无需对每个集成进行硬编码。
  • 双向通信:MCP 支持持久的实时双向通信 - 类似于 WebSockets。AI 模型既可以检索信息,也可以动态触发操作。

MCP 提供实时的双向通信:

  • 拉取数据:LLM查询服务器以获取上下文→例如获取订单信息
  • 触发:LLM指示服务器采取行动→例如发起下单,退订

文章最后可以加入免费的Java&AI技术和支付系统沟通社群,一起探讨Java/你的产品如何与AI结合,请按照要求加入。在群中可以聊开发、系统设计、架构、行业趋势、AI等等话题

3 Spring AI MCP实战

3.1 MCP Java SDK 架构

3.1.1 Java MCP实现遵循三层架构

SSE协议调用为跨进程API调用,通过http进行MCP 服务端网络资源调用,Stdio为进程间调用用于访问本地数据源,Jar或网络资源。

  • Client/Server 层: McpClient处理客户端操作,而McpServer管理服务器端协议操作。两者都使用McpSession进行通信管理.
  • Session层(McpSession): 通过DefaultMcpSession实现管理通信模式和状态.
  • Transport层(McpTransport): 处理JSON-RPC消息序列化和反序列化,支持多种传输实现.

3.1.2 MCP Client

​ MCP客户端是模型上下文协议(MCP)体系结构中的关键组件,负责建立和管理与MCP服务器的连接。它实现了协议的客户端处理

3.1.3 MCP Server

​ MCP服务器是模型上下文协议(MCP)体系结构中的基础组件,为客户端提供工具、资源和功能。它实现了协议的服务器端处理

3.2 MCP Server代码实现

以下代码基于SSE实现MCP Server和MCP Client

3.2.1 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.itbeien.ai</groupId>
        <artifactId>spring-ai-lab07</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>spring-ai-mcp-server</artifactId>

   <dependencies>
       <dependency>
           <groupId>org.projectlombok</groupId>
           <artifactId>lombok</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.boot</groupId>
           <artifactId>spring-boot-starter-web</artifactId>
       </dependency>
       <dependency>
           <groupId>org.springframework.ai</groupId>
           <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
       </dependency>
      <!-- <dependency>
           <groupId>org.springframework.ai</groupId>
           <artifactId>spring-ai-starter-mcp-server</artifactId>
       </dependency>-->
   </dependencies>

</project>

3.2.2 MCP服务

java 复制代码
package cn.itbeien.lab07.server.service;

import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

/**
 * @author itbeien
 * 项目网站:https://www.itbeien.cn
 * 公众号:贝恩聊架构
 * 全网同名,欢迎小伙伴们关注
 * Java/AI/支付系统/SAAS多租户基础技术平台学习社群
 * Copyright© 2025 itbeien
 */
@Service
@Slf4j
public class McpService {

    @Tool(description = "获取城市的天气信息")
    public String getWeatherByCity(@ToolParam(required=true,description = "城市名称") String city) {
        log.info("获取城市天气信息:{}",city);
        return city +"天气信息:晴空万里,气温25°C";
    }
}

3.2.3 创建ToolCallbackProvider

java 复制代码
package cn.itbeien.lab07.server.config;

import cn.itbeien.lab07.server.service.McpService;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.ai.tool.method.MethodToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author itbeien
 * 项目网站:https://www.itbeien.cn
 * 公众号:贝恩聊架构
 * 全网同名,欢迎小伙伴们关注
 * Java/AI/支付系统/SAAS多租户基础技术平台学习社群
 * Copyright© 2025 itbeien
 */
@Configuration
public class AppConfig {
    @Bean
    public ToolCallbackProvider weatherTools(McpService mcpService) {
        return  MethodToolCallbackProvider.builder().toolObjects(mcpService).build();
    }

}

3.3 MCP Client代码实现

3.3.1 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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.itbeien.ai</groupId>
        <artifactId>spring-ai-lab07</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>spring-ai-mcp-client</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-zhipuai-spring-boot-starter</artifactId>
            <version>${springai.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-mcp</artifactId>
        </dependency>
    </dependencies>

</project>

3.3.2 设置ToolCallbackProvider

java 复制代码
package cn.itbeien.lab07.client.config;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author itbeien
 * 项目网站:https://www.itbeien.cn
 * 公众号:贝恩聊架构
 * 全网同名,欢迎小伙伴们关注
 * Java/AI/支付系统/SAAS多租户基础技术平台学习社群
 * Copyright© 2025 itbeien
 */
@Configuration
public class AppConfig {

    @Bean
    public ChatClient chatClient(ChatClient.Builder builder,ToolCallbackProvider tools) {
        return builder.defaultTools(tools).build();
    }

}

3.3.3 大模型和MCP集成

java 复制代码
package cn.itbeien.lab07.client.controller;

import io.modelcontextprotocol.client.McpAsyncClient;
import io.modelcontextprotocol.client.McpSyncClient;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.mcp.SyncMcpToolCallbackProvider;
import org.springframework.ai.tool.ToolCallbackProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @author itbeien
 * 项目网站:https://www.itbeien.cn
 * 公众号:贝恩聊架构
 * 全网同名,欢迎小伙伴们关注
 * Java/AI学习社群
 * Copyright© 2025 itbeien
 */
@RestController
@RequestMapping("/ai")
@RequiredArgsConstructor
public class AiController {

    // 自定义人设,来与用户进行角色扮演 提示词
    private final static String systemPrompt = "你是智能天气助手,请回答与天气相关的问题,用户在询问天气情况时必须要求给出哪个城市和哪一天";

    // 历史消息列表
    static List<Message> historyMessage = new ArrayList<>(List.of(new SystemMessage(systemPrompt)));

    private final ChatModel chatModel;

    private final ChatClient chatClient;

    //private final ToolCallbackProvider tools;

    // 历史消息列表的最大长度
    static int maxLen = 10;
    @GetMapping("/chat")
    String generation(@RequestParam("prompt") String userInput) {
        return this.chatModel.call(userInput);
    }


    @GetMapping("/fcChat")
    String fcChat(@RequestParam("prompt") String userInput) {
        // 用户输入的文本是UserMessage
        historyMessage.add(new UserMessage(userInput));
        // 发给AI前对历史消息对列的长度进行检查
        if(historyMessage.size() > maxLen){
            historyMessage = historyMessage.subList(historyMessage.size()-maxLen-1,historyMessage.size());
            // 确保第一个是SystemMessage
            historyMessage.add(0,new SystemMessage(systemPrompt));
        }

        Prompt prompt = new Prompt(historyMessage);
        return chatClient.prompt(prompt).call().content();
       /* return ChatClient.create(chatModel)
                .prompt(prompt)
                .tools(tools)
                .call()
                .content();*/
    }
}

3.4 单元测试

通过向大模型提问"深圳今天的天气",大模型会通过设置的tools对mcp server服务进行调用

4 源码地址

贝恩聊架构-AI专栏,SpringBoot3专栏系列文章、资料和源代码会同步到以下地址,代码和资料每周都会同步更新

该仓库地址主要用于存放贝恩聊架构-SpringBoot3专栏、贝恩聊架构-AI专栏、基于企业级支付系统学习微服务整体技术栈所有资料和源码

Gitee:gitee.com/itbeien/pro...

Github:github.com/itbeien/pro...

相关推荐
Java水解27 分钟前
SpringBoot3全栈开发实战:从入门到精通的完整指南
spring boot·后端
Java水解31 分钟前
Java 中间件:Dubbo 服务降级(Mock 机制)
java·后端
千寻girling33 分钟前
一份不可多得的 《 Python 》语言教程
人工智能·后端·python
南风99934 分钟前
Claude code安装使用保姆级教程
后端
爱泡脚的鸡腿35 分钟前
Node.js 拓展
前端·后端
蚂蚁背大象2 小时前
Rust 所有权系统是为了解决什么问题
后端·rust
子玖3 小时前
go实现通过ip解析城市
后端·go
Java不加班3 小时前
Java 后端定时任务实现方案与工程化指南
后端
心在飞扬4 小时前
RAG 进阶检索学习笔记
后端