Get ahead
VMware offers training and certification to turbo-charge your progress.
Learn moreThe Model Context Protocol (MCP) is a powerful feature in Spring AI that enables AI models to access external tools and resources through a standardized interface. One interesting capabilities of MCP is its ability to dynamically update available tools at runtime.
This blog post explores how Spring AI implements dynamic tool updates in MCP, providing flexibility and extensibility to AI-powered applications.
The related example code is available here: Dynamic Tool Update Example
Before diving into dynamic tool updates, let's understand what MCP is and why it matters:
The Model Context Protocol (MCP) is a standardized interface that allows AI applicaitons and Agents to: Access external tools , Retrieve resources , Use prompt templates .
MCP follows a client-server architecture: MCP Servers - expose tools, resources, and prompts; MCP Clients - connect to servers and use their capabilities; AI Models - interact with the world through these clients
Spring AI provides a comprehensive implementation of MCP with both client and server components, making it easy to integrate AI capabilities into Spring applications.
One powerful aspects of the MCP is the ability to dynamically update the available tools at runtime. This means:
The dynamic tool update process involves several components working together:
Spring AI's @Tool
annotation makes it easy to expose methods as MCP tools:
public class MathTools {
@Tool(description = "Adds two numbers")
public int sumNumbers(int number1, int number2) {
return number1 + number2;
}
// ...
}
The framework automatically:
On the server side, Spring AI's MCP implementation provides a straightforward way to add MCP tools at start time and dynamically at runtime:
@SpringBootApplication
public class ServerApplication {
//1. Tools added at start time by the Spring AI MCP Server Boot starter
@Bean
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
}
//2. Runtime tool addition
@Bean
public CommandLineRunner commandRunner(McpSyncServer mcpSyncServer) {
return args -> {
// Wait for some tool update signal
// Add math tools dynamically
List<SyncToolSpecification> newTools = McpToolUtils
.toSyncToolSpecifications(ToolCallbacks.from(new MathTools()));
for (SyncToolSpecification newTool : newTools) {
mcpSyncServer.addTool(newTool);
}
};
}
}
In this example:
McpSyncServer.addTool()
method is used to dynamically register new toolsThe McpSyncServer
class provides methods for tool management:
addTool(SyncToolSpecification)
- Adds a new toolremoveTool(String)
- Removes a tool by namenotifyToolsListChanged()
- Notifies clients about tool changesNOTE: you can add and/or remove Tools only after the Clinet/Server connection has been initialized.
The MCP protocol includes a notification system that allows servers to inform clients about changes to available tools. This notification system ensures that clients always have an up-to-date view of the server's capabilities.
On the client side, Spring AI provides mechanisms to detect and react to tool changes:
@Bean
McpSyncClientCustomizer customizeMcpClient() {
return (name, mcpClientSpec) -> {
mcpClientSpec.toolsChangeConsumer(tv -> {
logger.info("\nMCP TOOLS CHANGE: " + tv);
latch.countDown();
});
};
}
The client registers a listener that is invoked whenever the server's available tools change. This allows the client to:
Currently Spring AI doesn't maintain internal state about the updated tools, but you can use the customization listener to implement smart tool caching or similar.
The client can discover available tools at any time:
List<ToolDescription> toolDescriptions = chatClientBuilder.build()
.prompt("What tools are available?")
.toolCallbacks(tools)
.call()
.entity(new ParameterizedTypeReference<List<ToolDescription>>() {});
A key insight from the Spring AI MCP implementation is:
TIP: The client implementation relies on the fact that the ToolCallbackProvider#getToolCallbacks implementation for MCP will always retrieves the current list of MCP tools from the server.
This means that whenever a client requests the available tools, it will always get the most up-to-date list from the server, without needing to restart or reinitialize the client.
Dynamic tool updates in MCP enable several powerful use cases:
You can implement feature flags that control which AI capabilities are available:
if (featureFlags.isEnabled("advanced-math")) {
mcpSyncServer.addTool(advancedMathTools);
}
Load tools based on the current context or user permissions:
if (userHasPermission(currentUser, "admin-tools")) {
mcpSyncServer.addTool(adminTools);
}
Start with basic tools and add more advanced capabilities as needed:
// Start with basic tools
mcpSyncServer.addTool(basicTools);
// Add advanced tools when the user reaches a certain level
userService.onUserLevelUp(user -> {
if (user.getLevel() >= 5) {
mcpSyncServer.addTool(advancedTools);
}
});
Implement a plugin system where new capabilities can be added at runtime:
pluginRegistry.onPluginLoaded(plugin -> {
if (plugin.hasMcpTools()) {
mcpSyncServer.addTool(plugin.getMcpTools());
}
});
Spring AI's handling of dynamic tool updates in the Model Context Protocol provides a mechanism for extending AI capabilities at runtime. This feature enables more flexible, extensible, and resource-efficient AI applications.
Key takeaways:
Standardized Interface: MCP provides a consistent way for AI models to interact with external tools and resources.
Dynamic Updates: Tools can be added or removed at runtime without requiring application restarts.
Automatic Discovery: Clients can detect changes to available tools and make them immediately available to AI models.
Simple API: Spring AI provides a clean, annotation-based API for defining and managing MCP tools.
By leveraging dynamic tool updates in Spring AI's MCP implementation, developers can create more adaptable AI applications that can evolve their capabilities based on runtime conditions, user needs, and system requirements.