requestClientElicitation method
Server-initiated request: ask the connected client to elicit input
from the user (spec 2025-06-18 elicitation/create).
params follows the spec ElicitRequest.params shape:
message (string) + requestedSchema (restricted JSON Schema —
flat object, primitive properties only).
Returns the spec ElicitResult map: action (accept /
decline / cancel) plus content when accepted.
Client must advertise the elicitation capability.
Implementation
Future<Map<String, dynamic>> requestClientElicitation(
String sessionId,
Map<String, dynamic> params, {
Duration timeout = const Duration(seconds: 120),
}) async {
final session = _sessions[sessionId];
if (session == null) {
throw StateError('Unknown sessionId: $sessionId');
}
final elicitation = session.capabilities?['elicitation'];
if (elicitation == null) {
throw McpError(
'Client does not advertise the `elicitation` capability',
code: ErrorCode.methodNotFound,
);
}
// Only modes the client declared (an elicitation object naming no mode
// means form); every request carries what its mode requires.
final mode = params['mode'] ?? 'form';
final modes = elicitation is Map ? elicitation : const {};
final supportsUrl = modes['url'] is Map;
final supportsForm = modes['form'] is Map || !supportsUrl;
if ((mode == 'url' && !supportsUrl) || (mode == 'form' && !supportsForm)) {
throw McpError(
'Client does not support $mode mode elicitation',
code: ErrorCode.invalidParams,
);
}
final problem = elicitationRequestProblem(params);
if (problem != null) throw ArgumentError.value(params, 'params', problem);
final result = await _sendRequestToClient(
sessionId,
'elicitation/create',
params,
timeout: timeout,
);
final map =
result is Map<String, dynamic>
? result
: Map<String, dynamic>.from(result as Map);
if (mode == 'url') {
_urlElicitations
.putIfAbsent(sessionId, () => {})
.add(params['elicitationId'] as String);
} else if (map['action'] == 'accept') {
// Servers should validate the data they receive.
final check = JsonSchemaValidator(
params['requestedSchema'],
).validate(map['content'] ?? const {});
if (!check.valid) {
throw McpError(
'Elicitation response does not match requestedSchema: ${check.errors.join('; ')}',
code: ErrorCode.invalidParams,
);
}
}
return map;
}