MCP Client Boot Starter :: Spring AI Reference (original) (raw)
Sync/Async Client Types
The starter supports two types of clients:
- Synchronous - default client type (
spring.ai.mcp.client.type=SYNC), suitable for traditional request-response patterns with blocking operations
NOTE: The SYNC client will register only synchronous MCP annotated methods. Asynchronous methods will be ignored.
- Asynchronous - suitable for reactive applications with non-blocking operations, configured using
spring.ai.mcp.client.type=ASYNC
NOTE: The ASYNC client will register only asynchronous MCP annotated methods. Synchronous methods will be ignored.
Client Customization
The auto-configuration provides extensive client spec customization capabilities through callback interfaces. These customizers allow you to configure various aspects of the MCP client behavior, from request timeouts to event handling and message processing.
Customization Types
The following customization options are available:
- Request Configuration - Set custom request timeouts
- Custom Sampling Handlers - standardized way for servers to request LLM sampling (
completionsorgenerations) from LLMs via clients. This flow allows clients to maintain control over model access, selection, and permissions while enabling servers to leverage AI capabilities — with no server API keys necessary. - File system (Roots) Access - standardized way for clients to expose filesystem
rootsto servers. Roots define the boundaries of where servers can operate within the filesystem, allowing them to understand which directories and files they have access to. Servers can request the list of roots from supporting clients and receive notifications when that list changes. - Elicitation Handlers - standardized way for servers to request additional information from users through the client during interactions.
- Event Handlers - client’s handler to be notified when a certain server event occurs:
- Tools change notifications - when the list of available server tools changes
- Resources change notifications - when the list of available server resources changes.
- Prompts change notifications - when the list of available server prompts changes.
- Logging Handlers - standardized way for servers to send structured log messages to clients.
- Progress Handlers - standardized way for servers to send structured progress messages to clients.
Clients can control logging verbosity by setting minimum log levels
Client Customization Example
You can implement either McpSyncClientCustomizer for synchronous clients or McpAsyncClientCustomizer for asynchronous clients, depending on your application’s needs.
- Sync
- Async
@Component
public class CustomMcpSyncClientCustomizer implements McpSyncClientCustomizer {
@Override
public void customize(String serverConfigurationName, McpClient.SyncSpec spec) {
// Customize the request timeout configuration
spec.requestTimeout(Duration.ofSeconds(30));
// Sets the root URIs that this client can access.
spec.roots(roots);
// Sets a custom sampling handler for processing message creation requests.
spec.sampling((CreateMessageRequest messageRequest) -> {
// Handle sampling
CreateMessageResult result = ...
return result;
});
// Sets a custom elicitation handler for processing elicitation requests.
spec.elicitation((ElicitRequest request) -> {
// handle elicitation
return new ElicitResult(ElicitResult.Action.ACCEPT, Map.of("message", request.message()));
});
// Adds a consumer to be notified when progress notifications are received.
spec.progressConsumer((ProgressNotification progress) -> {
// Handle progress notifications
});
// Adds a consumer to be notified when the available tools change, such as tools
// being added or removed.
spec.toolsChangeConsumer((List<McpSchema.Tool> tools) -> {
// Handle tools change
});
// Adds a consumer to be notified when the available resources change, such as resources
// being added or removed.
spec.resourcesChangeConsumer((List<McpSchema.Resource> resources) -> {
// Handle resources change
});
// Adds a consumer to be notified when the available prompts change, such as prompts
// being added or removed.
spec.promptsChangeConsumer((List<McpSchema.Prompt> prompts) -> {
// Handle prompts change
});
// Adds a consumer to be notified when logging messages are received from the server.
spec.loggingConsumer((McpSchema.LoggingMessageNotification log) -> {
// Handle log messages
});
}
}@Component
public class CustomMcpAsyncClientCustomizer implements McpAsyncClientCustomizer {
@Override
public void customize(String serverConfigurationName, McpClient.AsyncSpec spec) {
// Customize the async client configuration
spec.requestTimeout(Duration.ofSeconds(30));
}
}The serverConfigurationName parameter is the name of the server configuration that the customizer is being applied to and the MCP Client is created for.
The MCP client auto-configuration automatically detects and applies any customizers found in the application context.
Transport Support
The auto-configuration supports multiple transport types:
- Standard I/O (Stdio) (activated by the
spring-ai-starter-mcp-clientandspring-ai-starter-mcp-client-webflux) - (HttpClient) HTTP/SSE and Streamable-HTTP (activated by the
spring-ai-starter-mcp-client) - (WebFlux) HTTP/SSE and Streamable-HTTP (activated by the
spring-ai-starter-mcp-client-webflux)
Tool Filtering
The MCP Client Boot Starter supports filtering of discovered tools through the McpToolFilter interface. This allows you to selectively include or exclude tools based on custom criteria such as the MCP connection information or tool properties.
To implement tool filtering, create a bean that implements the McpToolFilter interface:
@Component
public class CustomMcpToolFilter implements McpToolFilter {
@Override
public boolean test(McpConnectionInfo connectionInfo, McpSchema.Tool tool) {
// Filter logic based on connection information and tool properties
// Return true to include the tool, false to exclude it
// Example: Exclude tools from a specific client
if (connectionInfo.clientInfo().name().equals("restricted-client")) {
return false;
}
// Example: Only include tools with specific names
if (tool.name().startsWith("allowed_")) {
return true;
}
// Example: Filter based on tool description or other properties
if (tool.description() != null &&
tool.description().contains("experimental")) {
return false;
}
return true; // Include all other tools by default
}
}The McpConnectionInfo record provides access to:
clientCapabilities- The capabilities of the MCP clientclientInfo- Information about the MCP client (name and version)initializeResult- The initialization result from the MCP server
The filter is automatically detected and applied to both synchronous and asynchronous MCP tool callback providers. If no custom filter is provided, all discovered tools are included by default.
Note: Only one McpToolFilter bean should be defined in the application context. If multiple filters are needed, combine them into a single composite filter implementation.
Tool Name Prefix Generation
The MCP Client Boot Starter supports customizable tool name prefix generation through the McpToolNamePrefixGenerator interface. This feature helps avoid naming conflicts when integrating tools from multiple MCP servers by adding unique prefixes to tool names.
By default, if no custom McpToolNamePrefixGenerator bean is provided, the starter uses DefaultMcpToolNamePrefixGenerator which ensures unique tool names across all MCP client connections. The default generator:
- Tracks all existing connections and tool names to ensure uniqueness
- Formats tool names by replacing non-alphanumeric characters with underscores (e.g.,
my-toolbecomesmy_tool) - When duplicate tool names are detected across different connections, adds a counter prefix (e.g.,
alt_1_toolName,alt_2_toolName) - Is thread-safe and maintains idempotency - the same combination of (client, server, tool) always gets the same unique name
- Ensures the final name doesn’t exceed 64 characters (truncating from the beginning if necessary)
For example: * First occurrence of tool search → search* Second occurrence of tool search from a different connection → alt_1_search* Tool with special characters my-special-tool → my_special_tool
You can customize this behavior by providing your own implementation:
@Component
public class CustomToolNamePrefixGenerator implements McpToolNamePrefixGenerator {
@Override
public String prefixedToolName(McpConnectionInfo connectionInfo, Tool tool) {
// Custom logic to generate prefixed tool names
// Example: Use server name and version as prefix
String serverName = connectionInfo.initializeResult().serverInfo().name();
String serverVersion = connectionInfo.initializeResult().serverInfo().version();
return serverName + "_v" + serverVersion.replace(".", "_") + "_" + tool.name();
}
}The McpConnectionInfo record provides comprehensive information about the MCP connection:
clientCapabilities- The capabilities of the MCP clientclientInfo- Information about the MCP client (name, title, and version)initializeResult- The initialization result from the MCP server, including server information
Built-in Prefix Generators
The framework provides several built-in prefix generators:
DefaultMcpToolNamePrefixGenerator- Ensures unique tool names by tracking duplicates and adding counter prefixes when needed (used by default if no custom bean is provided)McpToolNamePrefixGenerator.noPrefix()- Returns tool names without any prefix (may cause conflicts if multiple servers provide tools with the same name)
To disable prefixing entirely and use raw tool names (not recommended if using multiple MCP servers), register the no-prefix generator as a bean:
@Configuration
public class McpConfiguration {
@Bean
public McpToolNamePrefixGenerator mcpToolNamePrefixGenerator() {
return McpToolNamePrefixGenerator.noPrefix();
}
}The prefix generator is automatically detected and applied to both synchronous and asynchronous MCP tool callback providers through Spring’s ObjectProvider mechanism. If no custom generator bean is provided, the DefaultMcpToolNamePrefixGenerator is used automatically.
| | When using McpToolNamePrefixGenerator.noPrefix() with multiple MCP servers, duplicate tool names will cause an IllegalStateException. The default DefaultMcpToolNamePrefixGenerator prevents this by automatically adding unique prefixes to duplicate tool names. | | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
Tool Context to MCP Meta Converter
The MCP Client Boot Starter supports customizable conversion of Spring AI’s ToolContext to MCP tool-call metadata through the ToolContextToMcpMetaConverter interface. This feature allows you to pass additional contextual information (e.g. user id, secrets token) as metadata along with the LLM’s generated call arguments.
For example you can pass the MCP progressToken to your MCP Progress Flow in the tool context to track the progress of long-running operations:
ChatModel chatModel = ...
String response = ChatClient.create(chatModel)
.prompt("Tell me more about the customer with ID 42")
.toolContext(Map.of("progressToken", "my-progress-token"))
.call()
.content();By default, if no custom converter bean is provided, the starter uses ToolContextToMcpMetaConverter.defaultConverter() which:
- Filters out the MCP exchange key (
McpToolUtils.TOOL_CONTEXT_MCP_EXCHANGE_KEY) - Filters out entries with null values
- Passes through all other context entries as metadata
You can customize this behavior by providing your own implementation:
@Component
public class CustomToolContextToMcpMetaConverter implements ToolContextToMcpMetaConverter {
@Override
public Map<String, Object> convert(ToolContext toolContext) {
if (toolContext == null || toolContext.getContext() == null) {
return Map.of();
}
// Custom logic to convert tool context to MCP metadata
Map<String, Object> metadata = new HashMap<>();
// Example: Add custom prefix to all keys
for (Map.Entry<String, Object> entry : toolContext.getContext().entrySet()) {
if (entry.getValue() != null) {
metadata.put("app_" + entry.getKey(), entry.getValue());
}
}
// Example: Add additional metadata
metadata.put("timestamp", System.currentTimeMillis());
metadata.put("source", "spring-ai");
return metadata;
}
}Built-in Converters
The framework provides built-in converters:
ToolContextToMcpMetaConverter.defaultConverter()- Filters out MCP exchange key and null values (used by default if no custom bean is provided)ToolContextToMcpMetaConverter.noOp()- Returns an empty map, effectively disabling context-to-metadata conversion
To disable context-to-metadata conversion entirely:
@Configuration
public class McpConfiguration {
@Bean
public ToolContextToMcpMetaConverter toolContextToMcpMetaConverter() {
return ToolContextToMcpMetaConverter.noOp();
}
}The converter is automatically detected and applied to both synchronous and asynchronous MCP tool callbacks through Spring’s ObjectProvider mechanism. If no custom converter bean is provided, the default converter is used automatically.
Disable the MCP ToolCallback Auto-Configuration
The MCP ToolCallback auto-configuration is enabled by default, but can be disabled with the spring.ai.mcp.client.toolcallback.enabled=false property.
When disabled, no ToolCallbackProvider bean is created from the available MCP tools.