diff --git a/internal/mcp/manager_connect.go b/internal/mcp/manager_connect.go index 590cdeb2..18937feb 100644 --- a/internal/mcp/manager_connect.go +++ b/internal/mcp/manager_connect.go @@ -241,21 +241,30 @@ func (m *Manager) healthLoop(ctx context.Context, ss *serverState) { ss.connected.Store(true) ss.mu.Lock() ss.reconnAttempts = 0 + ss.healthFailures = 0 ss.lastErr = "" ss.mu.Unlock() continue } - ss.connected.Store(false) ss.mu.Lock() + ss.healthFailures++ + failures := ss.healthFailures ss.lastErr = err.Error() ss.mu.Unlock() - slog.Warn("mcp.server.health_failed", "server", ss.name, "error", err) - m.tryReconnect(ctx, ss) + slog.Warn("mcp.server.health_failed", "server", ss.name, "error", err, "consecutive", failures) + + // Only mark disconnected and attempt reconnect after consecutive failures + // to tolerate transient errors (e.g. 504 from upstream proxy). + if failures >= healthFailThreshold { + ss.connected.Store(false) + m.tryReconnect(ctx, ss) + } } else { ss.connected.Store(true) ss.mu.Lock() ss.reconnAttempts = 0 + ss.healthFailures = 0 ss.lastErr = "" ss.mu.Unlock() } diff --git a/internal/mcp/pool.go b/internal/mcp/pool.go index f20bf0c5..2d19a332 100644 --- a/internal/mcp/pool.go +++ b/internal/mcp/pool.go @@ -610,17 +610,27 @@ func poolHealthLoop(ctx context.Context, ss *serverState) { if err := ss.client.Ping(ctx); err != nil { if isMethodNotFound(err) { ss.connected.Store(true) + ss.mu.Lock() + ss.healthFailures = 0 + ss.mu.Unlock() continue } - ss.connected.Store(false) ss.mu.Lock() + ss.healthFailures++ + failures := ss.healthFailures ss.lastErr = err.Error() ss.mu.Unlock() - slog.Warn("mcp.pool.health_failed", "server", ss.name, "error", err) + + slog.Warn("mcp.pool.health_failed", "server", ss.name, "error", err, "consecutive", failures) + + if failures >= healthFailThreshold { + ss.connected.Store(false) + } } else { ss.connected.Store(true) ss.mu.Lock() ss.reconnAttempts = 0 + ss.healthFailures = 0 ss.lastErr = "" ss.mu.Unlock() }