SpringAI——整合MCP案例

前言

有了之前的基础,我们现在已经知道了如何 通过调用自己定义的 工具 对AI 的功能进行拓展,但是面对一些我们不能自己编写解决方案的场景时,这个工具调用 貌似就有点鸡肋了,作用有限。
所以,我们这篇文章讲讲,MCP 服务的调用。(第三方 提供的 特殊的工具集)

什么是MCP

MCP,实际上是一种协议,它定义了 AI 和 第三方工具集之间进行交互的 统一标准。
实际上,就是为了避免第三方工具集 千奇百怪 的返回值与要求的参数 对AI造成困扰 而制定的统一标准,可以参考 统一度量衡全国推行普通话 ,只不过对象变成了 各种第三方 和 AI。

MCP 服务,就是指第三方 为AI开放的专属服务,只有AI进去了才能获得 正确的结果。

搭建

首先,我们要明白,MCP服务的搭建 分为两部分,Server(服务端) 和 Client(客户端) 。

Server 通过向 Client 暴露工具集 来让 Client 注册
Client 注册完工具集后 将这些 列入自己回答的参考

Server 和 Client 的连接方式 有 stdio sse 两种.

stdio 是本地的方式,在启动的时候 需要添加 Server服务的 jar 包
sse 是Web连接的方式,在启动的时候 需要同时启动 Server 和Client ,Server需要持续监听

Other: 其实我们自己写的 包含工具的服务 也可以理解为 是暴露了工具集的 Server 和 Client 的结合体

这篇文章中 采用 SSE 。(为了具备 后续远程 MCP 的知识基础)
所以开始我们的搭建: (最好分成两个模块,这样好管理 )

大致项目图:

Server (服务端)

新增 Server 模块

引入依赖

引入依赖:

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-mcp</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
  <groupId>org.springframework.ai</groupId>
  <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
  <version>1.0.0</version>
</dependency>

如果出现了 依赖加载不了的情况,可以考虑在 父模块中 添加 以下内容:

xml 复制代码
<dependencyManagement>
  <dependencies>
      <dependency>
          <groupId>org.springframework.ai</groupId>
          <artifactId>spring-ai-bom</artifactId>
          <version>1.0.0</version>
          <type>pom</type>
          <scope>import</scope>
      </dependency>
  </dependencies>
</dependencyManagement>

这段内容是 导入 SpringAI 相关的依赖进行管理,当子模块需要的时候 直接分配。scope 一定得是 import

依赖导入完成后,就可以修改相关配置了

修改配置

修改 application.yaml,参考我的配置:

yaml 复制代码
server:
  port: 8085
spring:
  application:
    name: mcp-server
  ai:
    mcp:
      server:
        type: ASYNC
        name: mcp-server
#        stdio: true
        version: "1.0.0"
#        base-url: http://localhost:8085
        enabled: true

其中:

type 是表示 Server 支持 异步(async),还有同步(sync)
name 是方便记忆的 server 名字

version 是表示server 的版本

enabled: 是表示 开启 Server 模式(暴露工具集)

添加工具和配置类 ,将工具注册进 Spring容器,这里直接给出代码,不多做解释.
工具类:

less 复制代码
@Component
@Description("租借图书的 MCP 工具")
public class BookTools {

    @Tool(description = "获取书籍的详细信息")
    public String getBookInfo(@ToolParam(description = "需要获取信息的书的名字") String bookName) {

        String resFormat = """
                书名:%s
                作者:%s
                出版社:%s
                出版日期:%s
             """;
        return String.format(resFormat, bookName, "Alonet", "KiKo 出版社", "2023-01-01");
    }

    @Tool(description = "获取包含特定书籍的书店信息")
    public List<String> getBookStoreInfo(@ToolParam(description = "需要获取信息的书的名字") String bookName) {
        List<String> result = new ArrayList<>();
        String resFormat = """
                店铺名字: %s
                店铺地址: %s
                店铺电话: %s
            """;

        result.add(String.format(resFormat, "StavyTaff Shop", "1234 Street, LoShanJi,America", "18337067077771"));
        result.add(String.format(resFormat,"KiKoRepub Shop", "1234 Street,XiNi,Australia", "1921219054307765"));


        return result;
    }

    @Tool(description = "获取特定店铺特定书籍的租借信息")
    public String getBookRentInfo(@ToolParam(description = "需要获取信息的书的名字") String bookName, @ToolParam(description = "需要获取信息的店铺名字") String storeName) {
        String resFormat = """
                书名:%s
                店铺:%s
                存量:%d
                租借价格:%s
                可租借时长:%s
             """;

        return String.format(resFormat,bookName,storeName,5,"free","3个月");
    }

}

配置类:

kotlin 复制代码
@Configuration
public class McpConfiguration {


    @Bean
    public ToolCallbackProvider weatherTools(BookTools bookTools) {
        return MethodToolCallbackProvider.builder()
                .toolObjects(bookTools)
                .build();
    }
}

启动服务

直接启动 Server 就可以,正常情况下 日志应该会有类似于下图中的输出出现:

包含 Registered tools: 3 。 表示 已经成功注册了 三个工具,然后在 8085端口 对请求进行监听

Client

由于我们采用的是 SSE 的连接方式,Client 这边有比较多的 概念,慢慢来
先创建 Client 模块 ,我这里直接使用 之前的项目作为 客户端了。

引入依赖

对比于之前的 依赖,这一次要加的有:

xml 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client-webflux</artifactId>
</dependency>

基于 WebFlux (流式传输) 的 MCP SSE 依赖。后续方便维护。
tips: 这里如果提示没有版本,可以前往 Server配置 中参考 父模块添加bom依赖 ,或者直接指定 1.0.0

修改配置

参考以下配置,在原有基础上新增

yaml 复制代码
spring:
    ai:
        mcp:
          client:
            toolcallback:
              enabled: true
            name: mcp-client
            sse:
              connections:
                server1:
                  url: http://localhost:8085
            enabled: true
            type: async

其中部分属性的作用:

toolcallback.enable = true : 允许接收 toolcallback 类型的工具集对象
name: Client 的名字

sse.connections : 内部的 server1 是用户自定义的属性名,表示 Client中 server的名字,内部的url 表示该服务的 监听地址 ,server 名字可以不一样,但是要有 url属性

enabled : 允许启用客户端

type :客户端的类型(异步 or 同步)

不需要添加配置类,因为 工具是 从Server 中传递过来的。

添加测试

添加 Controller 用来测试

less 复制代码
@RestController
@RequestMapping("/mcp")
public class MCPController extends AIController{

    @Autowired
    ToolCallbackProvider mcpToolProvider;

    @Autowired
    ChatClient chatClient;
    
    @GetMapping("/push")
    public String push(@RequestParam("message") String message) {
        ChatResponse response = chatClient.prompt()
                .user(message)
                .toolCallbacks(mcpToolProvider)
                .call()
                .chatResponse();
//
//
        String text = response.getResult().getOutput().getText();
        System.out.println("text = " + text);
        return text;
   }
   
}

这里直接注入就行,框架内部会自动帮我们聚合所有工具 ,包括 ClientServer

启动服务

服务正常启动后,Server 中应该有以下内容:

应该包含 Client 的注册信息 ,Client 中应该包含 Server 的响应信息

测试

朝 Client 发送 请求,可以获得:

请求成功,MCP 搭建完毕。

总结

没什么要总结的,就这样。后续就是关于 远程MCP服务 的连接知识库多模态了.

相关推荐
葫芦和十三1 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp2 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑2 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯3 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan5 小时前
多Agent之间的区别
后端
青石路7 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充8 小时前
1.面向对象设计思想
后端
IT_陈寒8 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro8 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端
要阿尔卑斯吗9 小时前
提示词优化启示:为什么“按顺序输出“比“关键度评分“更有效
后端