SpringAI——接入高德MCP服务

前言

在接入自己本地配置的 MCP Server 之后,我们已经具备了 整体流程 的知识基础,这篇文章中,由于是调用第三方的Server,代码的调整重心主要是在 Client 这边。

那么接下来就开始我们的接入吧

高德 MCP 服务获取

首先我们需要获取 高德的 MCP 服务,有了 高德的MCP服务调用的方法,我们才能针对性地对代码进行调整 相关链接:

快速接入-MCP Server|高德地图API

成为高德地图开发者

进入 高德开放平台 | 高德地图API,登录或者注册账户后,
前往创建应用和 Key-MCP Server|高德地图API查看大致的流程,如图:

得到 API-KEY

跟着上述链接里面的 内容执行完后,页面应该是这样子:

这个 Key 字段下的值,就是我们需要的 API_KEY, 记得保存 到自己的配置文件中。

查看使用方法

在上述文档中,找到 SpringAI 的使用方式:
友情链接:快速接入-MCP Server|高德地图API

注意到 它需要我们添加配置类,并且在使用的时候 只能根据特定的城市进行天气查询。可是我们创建应用的时候不是支持很多功能吗?

那现在就到了我们 修改代码的时候了。
(如果不想看中间过程,可以直接跳转到 最终版本 环节)

修改代码

在开始修改前,我们还是得 老老实实地 将文档里的代码 搬到项目中。这样我们才有了参考。

搬运提示

如果想 注入自己在配置文件中 写入的 API_KEY 或者 URL等,可以考虑使用 @Value 注入 :

typescript 复制代码
@Value("${amap.api-key}")
private String apiKey;
@Value("${amap.base-url}")
private String baseUrl;
@Bean
public List<NamedClientMcpTransport> aMapTransports() {
    McpClientTransport transport = HttpClientSseClientTransport.builder(baseUrl)
            .sseEndpoint("/sse?key=" + apiKey)
            .objectMapper(new ObjectMapper())
            .build();

    return Collections.singletonList(new NamedClientMcpTransport("amap", transport));
}

开始修改

修改的思路 大致上来讲,是将能使用的工具拓展到 所有支持的服务上,而如何让AI自己去选择,我们就需要将这些工具注册到 AI 的请求中了。
所以修改的步骤如下:

  1. 找出所有支持的工具

  2. 尝试将工具注册到 容器,之后进一步注册到AI的请求中

  3. 测试是否可行

获取所有工具

在那个接口的代码中,我们可以注意到 在Lambda表达式中 有这些内容:

java 复制代码
mcpClient.listTools() 
.flatMap(tools -> {
logger.info("tools: {}", tools); 
return mcpClient.callTool( 
new McpSchema.CallToolRequest( 
"maps_weather", Map.of("city", "北京")
) 
); 
});

可以看出 它们确实是获取到了 Tools,只是在获取了之后就开始了遍历,然后返回了天气查询的结果,
那我们是不是可以在获取到tools之后直接将逻辑截断呢,然后把tools 提取出来?

不浪费时间,我直接给出结果:

java 复制代码
List<McpSchema.Tool> tools = mcpClient.listTools().block().tools();

我们可以通过这个式子 获取所有的工具,那现在就差 如何把工具注册进去了。

注册 工具

在之前的MCP 服务调用中,我们知道 传入的参数 是一个 ToolCallBackProvider 类型的数据,所以我们能不能如法炮制一个 ToolCallBackProvider 出来,然后放进去呢?
上代码:

less 复制代码
@Component("aMapToolCallbackProvider")
public class AMapToolCallbackProvider implements ToolCallbackProvider { 
    @Autowired
    @Qualifier("aMapTools")
    private ToolCallback[] toolCallbacks;

    @NotNull
    @Override
    public ToolCallback[] getToolCallbacks() {
        return this.toolCallbacks;
    }
}

我们通过 重写 getToolCallback() 方法注入了我们自己的 工具,那现在问题又来了,我们如何将工具 封装进ToolCallback[] 中呢?

封装工具

既然自己想不出来, SpringAI 肯定有相关的实现对吧,那这样子的话,我们去挖一挖源码,就能知道方法了。
查看 AsyncMcpToolCallbackProvider 内部的实现,我们发现包含了这些内容:

里面是 直接将 client 和 tool 一起放入了一个构造函数 ,然后直接返回 ToolCallback[] 对象,我们也照着它的来干一干
代码如下:

java 复制代码
@Configuration
public class AMapMcpConfiguration {

    @Autowired
    private List<McpAsyncClient> mcpAsyncClients;
    @Bean
    public ToolCallback[] aMapTools(){
        McpAsyncClient mcpClient = mcpAsyncClients.get(0);

         ToolCallback[] toolCallbacks = mcpClient.listTools().map((response) -> {
            return response.tools().stream().map((tool) -> {
                return new AsyncMcpToolCallback(mcpClient, tool);
            }).toArray(ToolCallback[]::new);
        }).block();

        return toolCallbacks;

    }
}

然后我们就获取到了所有需要的对象,现在可以尝试着将 获取到的 ToolCallBackProvider 对象注入到里面去了,通过 @Qualifier 解决了注入问题后,删掉之前搬运过来的接口,代码应该是这样:

less 复制代码
@RestController
@RequestMapping("/mcp")
public class MCPController extends AIController{
    @Autowired
    @Qualifier("aMapToolCallbackProvider")
    ToolCallbackProvider aMapToolProvider;
    @Autowired
    @Qualifier("mcpAsyncToolCallbacks")
    ToolCallbackProvider mcpToolProvider; 

    @Autowired
    ChatClient chatClient;

    @GetMapping("/push")
    public String push(@RequestParam("message") String message) {

        String infos = chatClient.prompt()
                .user(message)
                .toolCallbacks(mcpToolProvider,aMapToolProvider)
                .call()
                .content();

        System.out.println(infos);

        return infos;
    }
 }

尝试运行

运行后,一切正常
进行测试,发现报错了,说是有多个相同的工具被注册进去了:

其实这里就是 SpringAI 内部的机制导致的问题,还记得我们 获取 ToolCallback [] 的代码吗?

new AsyncMcpToolCallback(mcpClient, tool)

由于我们 获取的是 AsyncMapToolCallback 和 mcpToolProvider 中的 工具是一个类型,所以 mcpToolProvider 内部就包含了 我们注册上去的 工具。(相当于 SpringAI 提前帮我们注册上去了)
所以解决起来也很简单,删掉 aMapToolProvider 就可以了。

测试

调整了之后,进行测试,发现结果是对的,而且返回高德地图控制台,也能在流量详情 中 看到确实是发了请求:(会延迟几分钟)

流量详情 如下:

进一步思考

既然 SpringAI 会帮我们执行操作,那我们是不是只需要在配置文件中配置,然后它也可以全套操作都帮我们解决呢?
实践:

yaml 复制代码
sse:
          connections:
            server1:
              url: http://localhost:8085
            server2:
              url: https://mcp.amap.com
              sse-endpoint: /sse?key=${AMAP_API_KEY}

进行这一配置后,将其他配置都添加注释,再次运行,结果还是正确的。
说明真的可以这么干,但是 高德地图的文档中明确说明了:

注意不要在配置文件中填写高德sse 连接
所以 怎么弄 就 见仁见智 咯。(应该是担心 key 会泄露)

最终版本

application.yaml:

yaml 复制代码
        sse:
          connections:
            server1:
              url: http://localhost:8085
#              sse-endpoint: /mcp/book
            server2:
              url: https://mcp.amap.com
              sse-endpoint: /sse?key=${AMAP_API_KEY}
        enabled: true
        type: async
        request-timeout: 60000

MCPController:

java 复制代码
@RestController
@RequestMapping("/mcp")
public class MCPController extends AIController{
    @Autowired
    ToolCallbackProvider mcpToolProvider; 

    @Autowired
    ChatClient chatClient;

    @GetMapping("/push")
    public String push(@RequestParam("message") String message) {

        String infos = chatClient.prompt()
                .user(message)
                .toolCallbacks(mcpToolProvider)
                .call()
                .content();

        System.out.println(infos);

        return infos;
    }
 }

结束啦 !!!
最终版本 太简洁了 ヽ(ー_ー)ノ

总结

借助 整合 高德地图的 MCP,我们可以更深层次的了解到 SpringAI 是怎么注入工具类的。
也可以了解到如何进行配置,对后续的 MCP 导入会大有帮助。

相关推荐
Monkey-旭2 小时前
Android Handler 完全指南
android·java·handler
秃狼2 小时前
Execel文档批量替换标签实现方案
java
Brookty2 小时前
Java线程安全与中断机制详解
java·开发语言·后端·学习·java-ee
Sylvia-girl2 小时前
排序查找算法,Map集合,集合的嵌套,Collections工具类
java·算法·排序算法
TT哇2 小时前
【分治】归并排序——排序数组(medium)
java·算法·排序算法
给力学长2 小时前
自习室预约小程序的设计与实现
java·数据库·vue.js·elementui·小程序·uni-app·node.js
试着2 小时前
零基础学习性能测试第五章:JVM性能分析与调优-JVM概念,java程序运行原理
java·jvm·学习·零基础·性能测试
你的人类朋友3 小时前
❤️‍🔥BFF架构版的hello world
前端·后端·架构
孟婆来包棒棒糖~3 小时前
SpringCloude快速入门
分布式·后端·spring cloud·微服务·wpf
從南走到北3 小时前
JAVA东郊到家按摩服务同款同城家政服务按摩私教茶艺师服务系统小程序+公众号+APP+H5
android·java·开发语言·微信小程序·小程序