create static method
Future<SseAuthClientTransport>
create({
- required String serverUrl,
- Map<
String, String> ? headers, - OAuthToken? oauthToken,
- OAuthClient? oauthClient,
- 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');
}
}