大模型应用开发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...

相关推荐
慕容静漪5 小时前
如何本地安装Python Flask并结合内网穿透实现远程开发
开发语言·后端·golang
ErizJ5 小时前
Golang|锁相关
开发语言·后端·golang
烛阴6 小时前
手把手教你搭建 Express 日志系统,告别线上事故!
javascript·后端·express
良许Linux6 小时前
请问做嵌入式开发C语言应该学到什么水平?
后端
Pitayafruit6 小时前
SpringBoot整合Flowable【08】- 前后端如何交互
spring boot·后端·workflow
小丁爱养花7 小时前
驾驭 Linux 云: JavaWeb 项目安全部署
java·linux·运维·服务器·spring boot·后端·spring
uhakadotcom7 小时前
Amazon GameLift 入门指南:六大核心组件详解与实用示例
后端·面试·github
小杨4047 小时前
springboot框架项目实践应用十九(nacos配置中心)
spring boot·后端·spring cloud
终身学习基地9 小时前
第二篇:go包管理
开发语言·后端·golang