diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dcaae5c..751ace65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,6 +88,8 @@ stable and MCP 2026 schemas. - Rejected form elicitation schemas that provide legacy `enumNames` without the required string `enum`. +- Rejected `ElicitResult.content` when the result action is `decline` or + `cancel`. ## 2.2.0 diff --git a/lib/src/types/elicitation.dart b/lib/src/types/elicitation.dart index 653295bc..7543311c 100644 --- a/lib/src/types/elicitation.dart +++ b/lib/src/types/elicitation.dart @@ -267,9 +267,16 @@ class ElicitResult implements BaseResultData { throw FormatException('Invalid elicitation action: $action'); } + final content = _parseElicitResultContent(json['content']); + _validateElicitResultContentForAction( + action, + content, + formatException: true, + ); + return ElicitResult( action: action, - content: _parseElicitResultContent(json['content']), + content: content, url: json['url'] as String?, elicitationId: json['elicitationId'] as String?, meta: (json['_meta'] as Map?)?.cast(), @@ -278,9 +285,11 @@ class ElicitResult implements BaseResultData { @override Map toJson() { + final resultAction = action; + _validateElicitResultContentForAction(resultAction, content); _validateElicitResultContent(content); return { - 'action': action, + 'action': resultAction, if (content != null) 'content': content, if (meta != null) '_meta': meta, }; @@ -638,6 +647,26 @@ void _validateElicitResultContent( } } +void _validateElicitResultContentForAction( + String action, + Map? content, { + bool formatException = false, +}) { + if (content == null || action == 'accept') { + return; + } + if (formatException) { + throw const FormatException( + 'ElicitResult.content is only allowed when action is accept.', + ); + } + throw ArgumentError.value( + content, + 'content', + 'ElicitResult.content is only allowed when action is accept.', + ); +} + void _validateUrlElicitations( List elicitations, { bool formatException = false, diff --git a/test/elicitation_test.dart b/test/elicitation_test.dart index a417cbcd..08580a46 100644 --- a/test/elicitation_test.dart +++ b/test/elicitation_test.dart @@ -1051,6 +1051,15 @@ void main() { }), throwsA(isA()), ); + expect( + () => ElicitResult.fromJson({ + 'action': 'decline', + 'content': { + 'name': 'Alice', + }, + }), + throwsA(isA()), + ); expect( () => const ElicitResult( action: 'accept', @@ -1069,6 +1078,15 @@ void main() { ).toJson(), throwsA(isA()), ); + expect( + () => const ElicitResult( + action: 'cancel', + content: { + 'name': 'Alice', + }, + ).toJson(), + throwsA(isA()), + ); }); test('URLElicitationRequiredErrorData validates URL-only entries', () {