Description
Is your feature request related to a problem? Please describe.
Currently, the DefaultMcpClient is passive regarding connection health. It only detects a disconnection when an operation is actively performed and fails, or when the underlying transport layer explicitly reports a failure.
Describe the solution you'd like
I propose implementing an optional, proactive health-checking mechanism within the DefaultMcpClient. This feature would provide a self-healing capability for more resilient long-lived connections.
The key aspects of the solution are:
Background Health Checks: Introduce a ScheduledExecutorService that runs checkHealth() periodically in the background.
Automatic Reconnection: If the health check (ping) fails, it automatically triggers the client's internal reconnection logic to re-establish the session.
Configurability: This feature should be fully configurable via the Builder, allowing users to:
Enable or disable the automatic health check (defaulting to disabled for backward compatibility).
Configure the interval of the health checks (e.g., every 30 seconds).
Additional context
Below are the primary proposed code changes to implement this feature.
1.Add new fields and logic to DefaultMcpClient:
autoHealthCheckEnabled = getOrDefault(builder.autoHealthCheckEnabled, Boolean.TRUE);
autoHealthCheckInterval = getOrDefault(builder.autoHealthCheckInterval, Duration.ofSeconds(30));
healthCheckScheduler = Boolean.TRUE.equals(autoHealthCheckEnabled)
? Executors.newSingleThreadScheduledExecutor()
: null;
....
transport.onFailure(() -> {
try {
TimeUnit.MILLISECONDS.sleep(reconnectInterval.toMillis());
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
log.info("Trying to reconnect...");
triggerReconnection();
});
initialize();
startAutoHealthCheck();
- Implement the new private helper methods in DefaultMcpClient
private void startAutoHealthCheck() {
if (Boolean.FALSE.equals(autoHealthCheckEnabled)) {
return;
}
Runnable healthCheckTask = () -> {
try {
checkHealth();
} catch (Exception e) {
log.warn("mcp server health check failed. Attempting to reconnect...", e);
triggerReconnection();
}
};
healthCheckScheduler.scheduleAtFixedRate(
healthCheckTask,
autoHealthCheckInterval.toMillis(),
autoHealthCheckInterval.toMillis(),
TimeUnit.MILLISECONDS
);
}
private void triggerReconnection() {
if (initializationLock.tryLock()) {
try {
initialize();
} finally {
initializationLock.unlock();
}
}
}