序
本文主要研究下如何使用spring-ai-starter-mcp-client
步骤
pom.xml
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client</artifactId></dependency><dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-ollama-spring-boot-starter</artifactId></dependency>
application.yml
spring:application:name: mcp-client-examplemain:web-application-type: noneai:ollama:base-url: http://localhost:11434chat:model: qwen2.5:latestmcp:client:enabled: truename: my-mcp-clientversion: 1.0.0request-timeout: 30stype: SYNC # or ASYNC for reactive applicationssse:connections:server1:url: http://localhost:8080
# server2:
# url: http://otherserver:8081toolcallback:enabled: 'true'
logging:level:io:modelcontextprotocol:client: WARNspec: WARN
示例
@Beanpublic CommandLineRunner predefinedQuestions(ChatClient.Builder chatClientBuilder,ConfigurableApplicationContext context, SyncMcpToolCallbackProvider toolCallbackProvider) {return args -> {var chatClient = chatClientBuilder.defaultTools(toolCallbackProvider).defaultAdvisors(new MessageChatMemoryAdvisor(new InMemoryChatMemory())).build();System.out.println("\n>>> ASSISTANT: " + chatClient.prompt("帮我调用tool查一下xxx").call().content());System.out.println("\n>>> ASSISTANT: " + chatClient.prompt("取出create_time的最大值").call().content());context.close();};}
源码
McpClientAutoConfiguration
org/springframework/ai/mcp/client/autoconfigure/McpClientAutoConfiguration.java
@AutoConfiguration(after = { StdioTransportAutoConfiguration.class, SseHttpClientTransportAutoConfiguration.class,SseWebFluxTransportAutoConfiguration.class })
@ConditionalOnClass({ McpSchema.class })
@EnableConfigurationProperties(McpClientCommonProperties.class)
@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",matchIfMissing = true)
public class McpClientAutoConfiguration {/*** Create a dynamic client name based on the client name and the name of the server* connection.* @param clientName the client name as defined by the configuration* @param serverConnectionName the name of the server connection being used by the* client* @return the connected client name*/private String connectedClientName(String clientName, String serverConnectionName) {return clientName + " - " + serverConnectionName;}/*** Creates a list of {@link McpSyncClient} instances based on the available* transports.** <p>* Each client is configured with:* <ul>* <li>Client information (name and version) from common properties* <li>Request timeout settings* <li>Custom configurations through {@link McpSyncClientConfigurer}* </ul>** <p>* If initialization is enabled in properties, the clients are automatically* initialized.* @param mcpSyncClientConfigurer the configurer for customizing client creation* @param commonProperties common MCP client properties* @param transportsProvider provider of named MCP transports* @return list of configured MCP sync clients*/@Bean@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "type", havingValue = "SYNC",matchIfMissing = true)public List<McpSyncClient> mcpSyncClients(McpSyncClientConfigurer mcpSyncClientConfigurer,McpClientCommonProperties commonProperties,ObjectProvider<List<NamedClientMcpTransport>> transportsProvider) {List<McpSyncClient> mcpSyncClients = new ArrayList<>();List<NamedClientMcpTransport> namedTransports = transportsProvider.stream().flatMap(List::stream).toList();if (!CollectionUtils.isEmpty(namedTransports)) {for (NamedClientMcpTransport namedTransport : namedTransports) {McpSchema.Implementation clientInfo = new McpSchema.Implementation(this.connectedClientName(commonProperties.getName(), namedTransport.name()),commonProperties.getVersion());McpClient.SyncSpec syncSpec = McpClient.sync(namedTransport.transport()).clientInfo(clientInfo).requestTimeout(commonProperties.getRequestTimeout());syncSpec = mcpSyncClientConfigurer.configure(namedTransport.name(), syncSpec);var syncClient = syncSpec.build();if (commonProperties.isInitialized()) {syncClient.initialize();}mcpSyncClients.add(syncClient);}}return mcpSyncClients;}//......
}
McpClientAutoConfiguration依赖McpClientCommonProperties,它根据McpClientCommonProperties和
List<NamedClientMcpTransport>
构建List<McpSyncClient>
及List<McpAsyncClient>
McpToolCallbackAutoConfiguration
org/springframework/ai/mcp/client/autoconfigure/McpToolCallbackAutoConfiguration.java
@AutoConfiguration(after = { McpClientAutoConfiguration.class })
@EnableConfigurationProperties(McpClientCommonProperties.class)
@Conditional(McpToolCallbackAutoConfiguration.McpToolCallbackAutoconfigurationCondition.class)
public class McpToolCallbackAutoConfiguration {public static class McpToolCallbackAutoconfigurationCondition extends AllNestedConditions {public McpToolCallbackAutoconfigurationCondition() {super(ConfigurationPhase.PARSE_CONFIGURATION);}@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",matchIfMissing = true)static class McpAutoConfigEnabled {}@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX + ".toolcallback", name = "enabled",havingValue = "true", matchIfMissing = false)static class ToolCallbackProviderEnabled {}}/*** Creates tool callbacks for all configured MCP clients.** <p>* These callbacks enable integration with Spring AI's tool execution framework,* allowing MCP tools to be used as part of AI interactions.* @param syncMcpClients provider of MCP sync clients* @return list of tool callbacks for MCP integration*/@Bean@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "type", havingValue = "SYNC",matchIfMissing = true)public ToolCallbackProvider mcpToolCallbacks(ObjectProvider<List<McpSyncClient>> syncMcpClients) {List<McpSyncClient> mcpClients = syncMcpClients.stream().flatMap(List::stream).toList();return new SyncMcpToolCallbackProvider(mcpClients);}@Bean@ConditionalOnProperty(prefix = McpClientCommonProperties.CONFIG_PREFIX, name = "type", havingValue = "ASYNC")public ToolCallbackProvider mcpAsyncToolCallbacks(ObjectProvider<List<McpAsyncClient>> mcpClientsProvider) {List<McpAsyncClient> mcpClients = mcpClientsProvider.stream().flatMap(List::stream).toList();return new AsyncMcpToolCallbackProvider(mcpClients);}}
McpToolCallbackAutoConfiguration在
spring.ai.mcp.client.enabled
及spring.ai.mcp.client.toolcallback.enabled
都为true时才生效,它会根据List<McpSyncClient>
去创建SyncMcpToolCallbackProvider或AsyncMcpToolCallbackProvider
小结
spring ai提供了spring-ai-starter-mcp-client用于快速集成mcpClient到chatClient中;McpClientAutoConfiguration依赖McpClientCommonProperties,它根据McpClientCommonProperties和List<NamedClientMcpTransport>
构建List<McpSyncClient>
及List<McpAsyncClient>
;McpToolCallbackAutoConfiguration在spring.ai.mcp.client.enabled
及spring.ai.mcp.client.toolcallback.enabled
都为true时才生效,它会根据List<McpSyncClient>
去创建SyncMcpToolCallbackProvider或AsyncMcpToolCallbackProvider
doc
- MCP Client Boot Starter