send method

  1. @override
void send(
  1. dynamic message
)
override

Send a message through the transport

Implementation

@override
void send(dynamic message) async {
  if (_isClosed) {
    _logger.debug('Attempted to send on closed heartbeat transport');
    return;
  }

  if (_messageEndpoint == null) {
    throw McpError(
      'Cannot send message: Heartbeat SSE connection not established',
    );
  }

  // Check connection health before sending
  if (_currentHealth == ConnectionHealth.disconnected) {
    throw McpError('Cannot send message: Connection is disconnected');
  }

  try {
    final jsonMessage = jsonEncode(message);
    _logger.debug(
      'Sending heartbeat message: ${jsonMessage.substring(0, 100)}...',
    );

    final url = Uri.parse(_messageEndpoint!);
    final client = HttpClient();
    final request = await client.postUrl(url);

    // Set content type
    request.headers.contentType = ContentType.json;

    // Add base headers
    _baseHeaders.forEach((name, value) {
      request.headers.add(name, value);
    });

    // Send the request
    request.write(jsonMessage);
    final response = await request.close();

    // Handle response
    if (response.statusCode == 200) {
      final responseBody = await response.transform(utf8.decoder).join();
      _logger.debug('Heartbeat message delivery confirmation: $responseBody');
    } else {
      final responseBody = await response.transform(utf8.decoder).join();
      _logger.debug('Error response: $responseBody');
      throw McpError(
        'Error sending heartbeat message: ${response.statusCode}',
      );
    }

    client.close();
    _logger.debug('Heartbeat message sent successfully');
  } catch (e) {
    _logger.debug('Error sending heartbeat message: $e');

    // Connection issue might affect health
    if (e.toString().contains('Connection') ||
        e.toString().contains('Network')) {
      _updateHealth(ConnectionHealth.degraded);
    }

    rethrow;
  }
}