Skip to content

Commit 2c9fa4d

Browse files
committed
Add dynamic tool update example for Model Context Protocol
Implement a new example demonstrating how MCP servers can dynamically update available tools at runtime and how clients can detect these changes. - Add Server implementation that starts with weather forecast tools and dynamically adds math operation tools - Add Client implementation that detects tool changes via MCP notifications - Complete client/server architecture with proper tool registration and discovery - Add detailed README explaining the dynamic tool update process and implementation Signed-off-by: Christian Tzolov <[email protected]>
1 parent f79eef4 commit 2c9fa4d

File tree

22 files changed

+1653
-241
lines changed

22 files changed

+1653
-241
lines changed

mcp.weather.log

Lines changed: 0 additions & 4 deletions
This file was deleted.

mcp.webmvc.log

Lines changed: 0 additions & 237 deletions
This file was deleted.
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# Dynamic Tool Update Example
2+
3+
This example demonstrates how a Model Context Protocol (MCP) server can dynamically update its available tools at runtime, and how a client can detect and use these updated tools.
4+
5+
## Overview
6+
7+
The MCP protocol allows AI models to access external tools and resources through a standardized interface. This example showcases a key feature of MCP: the ability to dynamically update the available tools on the server side, with the client detecting and utilizing these changes.
8+
9+
## Key Components
10+
11+
### Server
12+
13+
The server application consists of:
14+
15+
1. **WeatherService**: Initially provides a weather forecast tool that retrieves temperature data for a specific location.
16+
2. **MathTools**: Contains mathematical operations (sum, multiply, divide) that are added dynamically to the server.
17+
3. **ServerApplication**: Manages the server lifecycle and handles the dynamic tool update process.
18+
19+
### Client
20+
21+
The client application:
22+
23+
1. Connects to the MCP server
24+
2. Retrieves the initial list of available tools
25+
3. Triggers the server to update its tools
26+
4. Detects the tool changes
27+
5. Retrieves the updated list of tools
28+
29+
## How It Works
30+
31+
1. **Initial Setup**: When the server starts, it only exposes the weather forecast tool.
32+
33+
2. **Dynamic Update Process**:
34+
- The client sends a request to the server's `/updateTools` endpoint
35+
- The server receives this signal and adds the math tools to its available tools
36+
- The server notifies connected clients about the tool changes
37+
- The client receives the notification and can now use the new tools
38+
39+
3. **Tool Discovery**: The client can query the available tools at any time, demonstrating that the tool list has been updated.
40+
41+
## Implementation Details
42+
43+
### Server-Side Implementation
44+
45+
The server uses Spring AI's MCP server implementation:
46+
47+
```java
48+
@Bean
49+
public ToolCallbackProvider weatherTools(WeatherService weatherService) {
50+
return MethodToolCallbackProvider.builder().toolObjects(weatherService).build();
51+
}
52+
53+
@Bean
54+
public CommandLineRunner predefinedQuestions(McpSyncServer mcpSyncServer) {
55+
return args -> {
56+
logger.info("Server: " + mcpSyncServer.getServerInfo());
57+
58+
latch.await(); // Wait for update signal
59+
60+
// Add math tools dynamically
61+
List<SyncToolSpecification> newTools = McpToolUtils
62+
.toSyncToolSpecifications(ToolCallbacks.from(new MathTools()));
63+
64+
mcpSyncServer.addTool(newTools.iterator().next());
65+
66+
logger.info("Tools updated: ");
67+
};
68+
}
69+
```
70+
71+
### Client-Side Implementation
72+
73+
The client connects to the server and registers a callback to be notified when tools change:
74+
75+
```java
76+
@Bean
77+
McpSyncClientCustomizer customizeMcpClient() {
78+
return (name, mcpClientSpec) -> {
79+
mcpClientSpec.toolsChangeConsumer(tv -> {
80+
logger.info("\nMCP TOOLS CHANGE: " + tv);
81+
latch.countDown();
82+
});
83+
};
84+
}
85+
```
86+
87+
The client retrieves the available tools before and after the update:
88+
89+
```java
90+
// Get initial tools
91+
List<ToolDescription> toolDescriptions = chatClientBuilder.build()
92+
.prompt("What tools are available?")
93+
.toolCallbacks(tools)
94+
.call()
95+
.entity(new ParameterizedTypeReference<List<ToolDescription>>() {});
96+
97+
// Signal the server to update tools
98+
String signal = RestClient.builder().build().get()
99+
.uri("http://localhost:8080/updateTools").retrieve().body(String.class);
100+
101+
// Wait for tool change notification
102+
latch.await();
103+
104+
// Get updated tools
105+
toolDescriptions = chatClientBuilder.build()
106+
.prompt("What tools are available?")
107+
.toolCallbacks(tools)
108+
.call()
109+
.entity(new ParameterizedTypeReference<List<ToolDescription>>() {});
110+
```
111+
112+
## Key Insight
113+
114+
The example demonstrates a crucial aspect of the MCP implementation in Spring AI:
115+
116+
> The client implementation relies on the fact that the `ToolCallbackProvider#getToolCallbacks` implementation for MCP will always get the current list of MCP tools from the server.
117+
118+
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.
119+
120+
## Running the Example
121+
122+
1. Start the server application:
123+
```
124+
cd server
125+
./mvnw spring-boot:run
126+
```
127+
128+
2. In a separate terminal, start the client application:
129+
```
130+
cd client
131+
./mvnw spring-boot:run
132+
```
133+
134+
3. Observe the console output to see:
135+
- The initial list of tools (only weather forecast)
136+
- The tool update notification
137+
- The updated list of tools (weather forecast + math operations)
138+
139+
## MCP Protocol Specification
140+
141+
For more information about the MCP protocol, refer to the official specification:
142+
[https://modelcontextprotocol.io/specification/2024-11-05/server/tools](https://modelcontextprotocol.io/specification/2024-11-05/server/tools)
Binary file not shown.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
2+
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar

0 commit comments

Comments
 (0)