connectWithRetry method

Future<void> connectWithRetry(
  1. ClientTransport transport, {
  2. int maxRetries = 3,
  3. Duration delay = const Duration(seconds: 2),
})

Connect with retry mechanism

Implementation

Future<void> connectWithRetry(
  ClientTransport transport, {
  int maxRetries = 3,
  Duration delay = const Duration(seconds: 2),
}) async {
  if (_transport != null) {
    throw McpError('Client is already connected to a transport');
  }

  if (_connecting) {
    throw McpError('Client is already connecting to a transport');
  }

  _connecting = true;
  int attempts = 0;

  while (attempts < maxRetries) {
    try {
      _transport = transport;
      _transport!.onMessage.listen(_handleMessage);
      _transport!.onClose
          .then((_) {
            // Only send disconnect event if we're still connected
            if (_transport != null) {
              _disconnectStreamController.add(
                DisconnectReason.transportClosed,
              );
              _onDisconnect();
            }
          })
          .catchError((error) {
            // Only handle error if we're still connected
            if (_transport != null) {
              _errorStreamController.add(McpError('Transport error: $error'));
              _disconnectStreamController.add(
                DisconnectReason.transportError,
              );
              _onDisconnect();
            }
          });

      // Message handling setup
      _messageController.stream.listen((message) async {
        try {
          await _processMessage(message);
        } catch (e) {
          _logger.debug('Error processing message: $e');
          _errorStreamController.add(
            McpError('Error processing message: $e'),
          );
        }
      });

      // Initialize connection
      await initialize();
      _connecting = false;

      // Emit connection event after successful initialization
      if (_initialized &&
          _serverInfo != null &&
          _serverCapabilities != null) {
        _connectStreamController.add(
          ServerInfo(
            name: _serverInfo!['name'] as String? ?? 'Unknown',
            version: _serverInfo!['version'] as String? ?? 'Unknown',
            capabilities: _serverCapabilities!.toJson(),
            protocolVersion: protocolVersion,
          ),
        );
      }

      return; // Successfully connected
    } catch (e) {
      // Clean up resources on failure
      if (_transport != null) {
        try {
          _transport!.close();
        } catch (_) {}
        _transport = null;
      }

      attempts++;
      if (attempts >= maxRetries) {
        _connecting = false;
        _errorStreamController.add(
          McpError('Failed to connect after $maxRetries attempts: $e'),
        );
        throw McpError('Failed to connect after $maxRetries attempts: $e');
      }

      _logger.debug(
        'Connection attempt $attempts failed: $e. Retrying in ${delay.inSeconds} seconds...',
      );
      await Future.delayed(delay);
    }
  }
}