序
本文主要研究下如何使用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-example
main:
web-application-type: none
ai:
ollama:
base-url: http://localhost:11434
chat:
model: qwen2.5:latest
mcp:
client:
enabled: true
name: my-mcp-client
version: 1.0.0
request-timeout: 30s
type: SYNC # or ASYNC for reactive applications
sse:
connections:
server1:
url: http://localhost:8080
# server2:
# url: http://otherserver:8081
toolcallback:
enabled: 'true'
logging:
level:
io:
modelcontextprotocol:
client: WARN
spec: WARN
示例
@Bean
public 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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。