Spring AI + MCP最详细实践:从配置开始到服务搭建(踩坑无数版)

随着MCP的火爆,作者也是想要自己实践一下。但是看网上的资料,或是实践起来太过繁琐,或是因为Spring AI版本的快速更迭导致实现不了。于是自己记录一下实现过程。本篇会带大家从零开始手搓一个MCP服务端出来,并且验证。同时最后会给出一些常见报错的解决方案。

想必大家对于MCP都有一定的了解,这里就不多做赘述。直接开始上手

一、准备工作(都已经ok的大佬可以跳过看后面)

  • Java版本检查
  • Maven版本检查
  • Cherry Studio(用于前期验证MCP服务端,后面客户端搭建好了用自己的)

对于java版本需要17及以上,可以直接上21:点击下载jdk21 下载安装好后需要替换环境变量(也不多做赘述)。Maven版本最好是3.6.3及以上(没有为啥,我是这样),maven传送门。然后在命令行检查:java -version、javac -version、mvn -v(着重看它的输出),如下就是ok了

对于Cherry Studio,是我们在MCP服务端起来后,充当客户端调用来验证。下载链接

简单说一下怎么用,下载安装好后,点击设置

再配置大模型(这里选择DeepSeek,后续客户端也是,比起OpenAI就不用科学上网了),配置好了密钥后,再带点击检测。

检测通过后,别急,再返回它的对话框,选择模型(随便选一个)

然后再在这里测试一下能否正常对话,一般到这都是可以正常对话。

二、新建工程:开始了!

我们在IDEA里新建一个工程,然后选择的时候有几个小坑:

1.Server URL:选择start.spring.io   否则后续依赖不好操作

2.Spring Boot版本:最好大于等于3.4.X (我用3.5.3)   具体依赖可以后面再引入,这里可以都不选

三、POM文件依赖

导依赖是最麻烦的地方了,大家直接看我的依赖。比较重要的是要把spring的仓库给导入,maven中央仓库不知道什么时候才有这些依赖。(如果有的依赖导不进来的话继续往下看解决方案)

<properties>
        <java.version>21</java.version>
        <spring-ai.version>1.0.0-M5</spring-ai.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-core</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
            <version>1.0.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.ai</groupId>
                <artifactId>spring-ai-bom</artifactId>
                <version>${spring-ai.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

如果导入依赖没问题的话,就已经成功一大半了,接下来就是示例代码了。

四、代码与运行

4.1先看一下结构图,非常简单

4.2ToolCallbackProviderConfig代码如下:
import com.example.demo.service.impl.McpServiceImpl;
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;

@Configuration
public class ToolCallbackProviderConfig {
    @Bean
    public ToolCallbackProvider gzhRecommendTools(McpServiceImpl mcpServiceImpl) {
        return MethodToolCallbackProvider.builder().toolObjects(mcpServiceImpl).build();
    }
}
4.3McpServiceImpl代码如下:
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Service;

@Service
public class McpServiceImpl {

    @Tool(description = "Get weather information by city name")
    public String getWeather(String cityName) {
        return cityName + "天气很好";
    }

    @Tool(description = "用于回答关于小白和小鸡毛的相关问题")
    public String answerQuestionsAboutXiaoBaiAndXiaoJiMa(String question) {
        return "小鸡毛和小白是两个小可爱,小鸡毛是白毛,小鸡毛是白色";
    }

}
4.4application.properties配置属性如下:
# 端口
server.port=8080

# MCP 服务
spring.ai.mcp.server.name=mcp-server
spring.ai.mcp.server.sse-message-endpoint=/sse

然后就可以试着运行,如果控制台输出里有下面的信息,就说明是成功的

五、验证

因为我们现在还没搭建客户端,所以只能用现成的客户端来调用,我们一开始的CherryStudio就是用来验证的。

先打开CherryStudio,在接入我们的MCP服务之前,先确定CherryStudio是可以正常使用的(如上,可以正常对话自己选的大模型)。

然后在设置里,选择MCP服务器,添加服务器,快速创建

再然后,填写合适的参数即可

保存好了记得打开它(一般默认是打开),如果保存报错了,把spring工程重启一下试试

接下来让我们返回聊天框,把我们的MCP服务勾选

然后,就是见证奇迹的时刻,它会根据你的问题和代码里@Tool()的形容来决定是否调用,可以看见,我们自己定义的方法answerQuestionsAboutXiaoBaiAndXiaoJiMa被调用了

六、常见问题以及解决

在搭建MCP服务端的时候,最常见的问题就是POM文件里的依赖不好导入,各种版本不匹配,所以一开始就是要确认java、maven、SpringBoot等等这些前置工作要做好。但是因为springAI它现阶段更新太快了,有可能今天这个服务可以,明天这个服务就因为更新跑不了了。那么我们也需要有一些缝补的能力,在我们的POM文件里其实是有引入spring的仓库:JFrog  那么当我们引入依赖报错的时候,就可以去看看它的仓库里到底有没有这个,以及版本是否存在。比如,当我们遇到

        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-core</artifactId>
            <version>${spring-ai.version}</version>
        </dependency>

报错不存在的时候,我们就要去看看,仓库里面到底有没有我们指定的版本:

就一级一级点进去看看

可选的版本就在这里,如果哪天更新导致文章中出现的版本用不了,大家也能找到合适的版本来替换。同样的道理,maven中心仓库:Maven Repository: Search/Browse/Explore  也是可以去搜看看,就看大家用的是什么仓库了。

### Spring AIMCP 的集成概述 Spring AIMCP (Management Control Program 或其他可能含义) 可能涉及两种不同技术栈之间的协作。以下是关于如何实现两者之间潜在集成的一些分析: #### 技术背景 - **Spring AI**: 这是一个由 Spring 社区推出的框架,用于支持 Java 开发人员构建人工智能应用程序[^2]。它通过提供一系列工具和库来简化机器学习模型的训练、部署以及与其他系统的交互。 - **MCP Hosts**: 根据描述,MCP 主机可以指代运行特定程序(如 Claude Desktop、IDE 工具或其他 AI 工具)并允许这些程序访问数据的服务或平台[^1]。 #### 集成可能性 为了使 Spring AI 能够与 MCP 成功集成,通常需要考虑以下几个方面: ##### 数据交换模式 一种常见的做法是利用消息传递模式来进行通信。例如,在企业级架构设计中提到的消息队列模式可以帮助解决异构系统间的数据传输问题[^3]。具体来说,可以通过以下方式实现: - 使用 AMQP 协议或者 JMS 接口作为中间件连接 Spring AI 应用和服务端的 MCP 实体; - 设计标准化的消息格式以便于双方解析处理; ##### API 层面的支持 如果目标环境提供了 RESTful Web Service,则可以直接调用其公开接口完成所需操作。对于这种情况下的开发流程如下所示: ```java // 创建 RestTemplate 对象实例化 HTTP 请求客户端 RestTemplate restTemplate = new RestTemplate(); // 构建 URL 地址指向远程服务资源位置 String url = "http://example.com/mcp/resource"; // 发起 GET 方法请求获取响应实体对象 ResponseEntity<String> response = restTemplate.getForEntity(url, String.class); // 打印返回状态码及内容主体部分 System.out.println(response.getStatusCode()); System.out.println(response.getBody()); ``` ##### 插件扩展机制 当上述方案不适用时还可以探索插件形式加载额外功能模块的可能性。比如某些 IDE 平台就允许第三方开发者为其增添新特性从而增强整体用户体验效果。这种情况下就需要仔细阅读官方文档了解相关规范要求然后按照指引编写自定义组件提交审核上线发布供终用户选用安装激活启用等功能选项卡界面布局调整等等细节都需要遵循既定规则执行才能确保兼容性和稳定性达到预期水平。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值