create static method

Future<SseAuthClientTransport> create({
  1. required String serverUrl,
  2. Map<String, String>? headers,
  3. OAuthToken? oauthToken,
  4. OAuthClient? oauthClient,
  5. String? bearerToken,
})

Create SSE transport with Bearer Token authentication

Implementation

static Future<SseAuthClientTransport> create({
  required String serverUrl,
  Map<String, String>? headers,
  OAuthToken? oauthToken,
  OAuthClient? oauthClient,
  String? bearerToken,
}) async {
  final transport = SseAuthClientTransport._internal(
    serverUrl: serverUrl,
    headers: headers,
    oauthToken: oauthToken,
    oauthClient: oauthClient,
  );

  try {
    // Set up authentication headers
    final authHeaders = Map<String, String>.from(transport._baseHeaders);

    if (bearerToken != null) {
      authHeaders['Authorization'] = 'Bearer $bearerToken';
    } else if (oauthToken != null) {
      authHeaders['Authorization'] = 'Bearer ${oauthToken.accessToken}';

      // Set up automatic token refresh if needed
      transport._scheduleTokenRefresh();
    }

    // Add standard SSE headers
    authHeaders['Accept'] = 'text/event-stream';
    authHeaders['Cache-Control'] = 'no-cache';
    authHeaders['Connection'] = 'keep-alive';

    _logger.debug(
      'Connecting with authentication headers: ${authHeaders.keys.toList()}',
    );

    // Set up event handlers
    final endpointCompleter = Completer<String>();

    await transport._eventSource.connect(
      serverUrl,
      headers: authHeaders,
      onOpen: (endpoint) {
        if (!endpointCompleter.isCompleted && endpoint != null) {
          endpointCompleter.complete(endpoint);
        }
      },
      onMessage: (data) {
        if (!transport._messageController.isClosed) {
          transport._messageController.add(data);
        }
      },
      onError: (e) {
        _logger.debug('SSE authentication error: $e');
        if (!endpointCompleter.isCompleted) {
          endpointCompleter.completeError(e);
        }
        transport._handleError(e);
      },
      onAuthFailure: (statusCode, body) {
        transport._handleAuthFailure(statusCode, body);
      },
    );

    // Wait for endpoint
    final endpointPath = await endpointCompleter.future.timeout(
      Duration(seconds: 15),
      onTimeout:
          () =>
              throw McpError('Timed out waiting for authenticated endpoint'),
    );

    transport._messageEndpoint =
        endpointPath.startsWith('http')
            ? endpointPath
            : transport._constructEndpointUrl(
              Uri.parse(serverUrl),
              endpointPath,
            );

    _logger.debug(
      'Authenticated SSE transport ready: ${transport._messageEndpoint}',
    );

    return transport;
  } catch (e) {
    transport.close();
    if (e.toString().contains('401') || e.toString().contains('403')) {
      throw McpError('Authentication failed: Invalid or expired token');
    }
    throw McpError('Failed to establish authenticated SSE connection: $e');
  }
}