Please do a quick search on GitHub issues first, the feature you are about to request might have already been requested.
Expected Behavior
After the MCP SSE server restarts, the client can automatically connect without restarting
Current Behavior
After the MCP SSE server restarts, the client will not automatically connect
Context
In MCP SSE mode, the client must rely on the MCP server to start, otherwise it cannot start. I don't think it's reasonable. The server has been restarted, so all clients need to be restarted? Why not use heartbeat detection. The MCP native SDK may not have a heartbeat mechanism, but I think Spring AI can have it.
Comment From: 1435646097
Yes, I think so too
Comment From: andresssantos
I'm facing the same situation, where I have to restart my client every time something changes in the mcp server. I wonder if there's something to avoid that.
Comment From: Ltyro
I tried to rewrite the client auto configuration the day before tomorrow, but I haven't finished writing it yet. The idea is to connect by heartbeat monitoring. If client.ping() goes through, then execute initialization method. If the server is disconnected, create a loop to ping, and create a client until the ping is connected. However, I haven't continued to write because I've been on vacation recently. If you are interested, you can try it.
Comment From: tinomthomas
I think this is a much needed feature especially in auto adjusting environments like Kubernetes where an auto scale down happens based on the load.
Comment From: arsereg
Is there anything on the roadmap for this? Is August and this is still happening
Comment From: dvag-joerg-winter
Same goes for streamable-http connections of course
Comment From: dimroussis
We managed to overcome the issue by utilizing the following code. Not the best approach but it seems to work in a dynamic environment
@Service
@EnableScheduling
public class McpClientManager {
private final Map<String, McpSyncClient> mcpSyncClientMap = new ConcurrentHashMap<>();
public McpClientManager(McpClientProperties mcpClientProperties) {
mcpClientProperties.getServers()
.forEach(serverUrl -> {
var mcpClient = createAndInitializeMcpSyncClient(serverUrl);
mcpSyncClientMap.put(serverUrl, mcpClient);
});
}
public List<McpSyncClient> getMcpClients() {
return List.copyOf(mcpSyncClientMap.values());
}
@Scheduled(fixedDelay = 30000)
public void refreshClients() {
mcpSyncClientMap.forEach((serverUrl, mcpSyncClient) -> {
try {
mcpSyncClient.ping();
} catch (Exception e) {
mcpSyncClient.close();
mcpSyncClientMap.put(serverUrl, createAndInitializeMcpSyncClient(serverUrl));
}
});
}
private static McpSyncClient createAndInitializeMcpSyncClient(String serverUrl) {
var mcpClient = McpClient.sync(HttpClientSseClientTransport.builder(serverUrl).build()).build();
mcpClient.initialize();
return mcpClient;
}
}
Comment From: tinomthomas
We have ended up using the stateless streamable http where each call to the server creates a new session and closes the connection once the response is complete. This is ideal for use cases that doesn't require a server side push or session that spans over multiple calls.