关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言
前两天,有个粉丝朋友咨询MCP
服务如何动态调用,动态加载MCP
服务的链接?我们都知道MCP
客户端可以配置多个MCP
服务的地址:
properties
spring.ai.mcp.client.sse.connections.server1.url=http://localhost:xxxx
spring.ai.mcp.client.sse.connections.server2.url=http://localhost:xxxx
spring.ai.mcp.client.sse.connections.server3.url=http://localhost:xxxx
这样的MCP
服务会自动加载到项目中,类似合成一个服务。一个请求进来,MCP
客户端会在所有的服务中寻找合适的方法。
但是,业务中总会有各种不同的场景。例如,粉丝朋友的需求。SpringBoot
一直坚持约定大于配置的方式,Spring AI
也不例外,既然提供配置文件的配置,那么JavaBean
的配置一样可行。指定调用只要需要找到调用的时机,自然可以控制。
本篇就带大家一起解决这份粉丝朋友的问题。
02 MCP
动态调用
2.1 代码追踪
在研究动态调用之前,我们需要知道配置用在了哪里?
我们直接在.properties
或.yml
配置文件中,

按住Ctrl
,然后用鼠标点击url
,就会跳转到下面的文件:

从方法中可以看到:
最终的配置会保存在SseParameters
中,最后放到Map
集合中。使用或者获取服务链接的时候,肯定也会通过getConnections()
来获取,这个也是突破问题的关键。
2.2 探寻使用位置
上面找到了配置文件对用的Java
类:
org.springframework.ai.mcp.client.autoconfigure.properties.McpSseClientProperties
我们可以采用上面相同的方法,看看哪里调用了getConnections()
,由于我们的源码没有全部下载下来,所以很大程度上可能找不到。所以,断点提示就变成了我们唯一的出路。
断点启动之后,我们看到连接数为0,也就是还没有加载MCP
服务的链接呢。如下图:

我们断点继续向下执行(快捷键:F8
),中间会经历漫长的Bean
的创建过程。我们的目标就是看看是哪一个Bean
实例化的时候会获取连接。
我们就需要注意几个注解:@Bean
、@Component
等,终于实例化出来了,找到了关键类:
org.springframework.ai.mcp.client.autoconfigure.McpClientAutoConfiguration
具体如图:

我们可以看到namedTransports
里面就包含了我们MCP
服务,最终放到mcpSyncClients
集合中,如下图:

至此,Spring 启动随后完成。
2.3 修改点
我们可以看到mcpSyncClients
集合上有@Bean
标签,所以会被Spring
管理,所以可以直接从Spring
容器中,通过注入的方式获取到。
但是修改点有在哪里呢?我们先看看MCP
调用的案例:

从构建ChatClient
到发送请求参数,就只有ChatModel
和ToolCallbackProvider
两个参数。而ChatMode
表示采用的大模型的类型,显然和MCP
服务没有关系,就只有ToolCallbackProvider
这个类了。
org.springframework.ai.tool.ToolCallbackProvider
的实现有四个:

通过注入的ToolCallbackProvider
,我们断点可以看到它的实现是:
org.springframework.ai.mcp.SyncMcpToolCallbackProvider
从代码的构造启可以看到,参数就是我们上面注入的mcpSyncClients
。

2.4 动态调用
我们只要根据MCP
服务的名称区分不同的McpSyncClient
即可。

我们从截图可以看到:
小编提供了两个MCP
服务,分别是csdn-mcp-server
(CSDN
文章浏览服务)和gzh-mcp-server
(种种好推荐服务)。小编没有传递参数,默认会调用gzh-mcp-server
。
我们看看返回的结果:

请求是一个与csdn-mcp-server
匹配度比较高的请求,最终只调用了gzh-mcp-server
。所以我们就可以控制调用的MCP
服务了。
03 动态加载
动态调用的问题,我们已经解决了。如果这些服务链接想从数据库读取,又该如何处理呢?
最直接的想法,就是直接将配置文件对应的Bean
自己new
出来交给Spring
管理。
3.1 配置McpSseClientProperties
Bean配置
java
@Bean
public McpSseClientProperties mcpSseClientProperties() {
McpSseClientProperties mcpSseClientProperties = new McpSseClientProperties();
Map<String, SseParameters> connections = mcpSseClientProperties.getConnections();
connections.put("server1", new SseParameters("http://localhost:8080", null));
connections.put("server2", new SseParameters("http://localhost:8082", null));
return mcpSseClientProperties;
}
启动结果

McpSseClientProperties
发现了2个,实际只需要一个。也就是说,框架自动实例化McpSseClientProperties
和我们的冲突了。
这种方式行不通!!!
既然已经存在,那就直接添加连接呢?因为Spring
默认是单例。
3.2 动态加载链接
容器启动后加载链接

测试

已经加载成功了。
04 小结
到这里粉丝朋友的问题就全部解决了。同时,也分享给大家,希望对大家有帮助!