MCP Client Boot Starter :: Spring AI Reference (original) (raw)

Sync/Async Client Types

The starter supports two types of clients:

NOTE: The SYNC client will register only synchronous MCP annotated methods. Asynchronous methods will be ignored.

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:

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.

@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:

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:

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:

For example: * First occurrence of tool searchsearch* Second occurrence of tool search from a different connection → alt_1_search* Tool with special characters my-special-toolmy_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:

Built-in Prefix Generators

The framework provides several built-in prefix generators:

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:

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:

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.