diff --git a/lib/src/types/initialization.dart b/lib/src/types/initialization.dart index 03d1007a..8ba21bf3 100644 --- a/lib/src/types/initialization.dart +++ b/lib/src/types/initialization.dart @@ -1083,6 +1083,16 @@ class DiscoverResult implements BaseResultData { }); factory DiscoverResult.fromJson(Map json) { + final resultType = readOptionalString( + json['resultType'], + 'DiscoverResult.resultType', + ); + if (resultType != resultTypeComplete) { + throw const FormatException( + 'DiscoverResult.resultType must be complete', + ); + } + final supportedVersions = json['supportedVersions']; if (supportedVersions is! List) { throw const FormatException( @@ -1091,7 +1101,6 @@ class DiscoverResult implements BaseResultData { } return DiscoverResult( - resultType: json['resultType'] as String? ?? 'complete', supportedVersions: supportedVersions.cast(), capabilities: ServerCapabilities.fromJson( json['capabilities'] as Map, @@ -1105,14 +1114,24 @@ class DiscoverResult implements BaseResultData { } @override - Map toJson() => { - 'resultType': resultType, - 'supportedVersions': supportedVersions, - 'capabilities': capabilities.toJson(), - 'serverInfo': serverInfo.toJson(), - if (instructions != null) 'instructions': instructions, - if (meta != null) '_meta': readJsonObject(meta, 'DiscoverResult._meta'), - }; + Map toJson() { + if (resultType != resultTypeComplete) { + throw ArgumentError.value( + resultType, + 'DiscoverResult.resultType', + 'must be complete', + ); + } + + return { + 'resultType': resultType, + 'supportedVersions': supportedVersions, + 'capabilities': capabilities.toJson(), + 'serverInfo': serverInfo.toJson(), + if (instructions != null) 'instructions': instructions, + if (meta != null) '_meta': readJsonObject(meta, 'DiscoverResult._meta'), + }; + } } /// Notification sent from the client to the server after initialization is finished. diff --git a/test/mcp_2026_07_28_test.dart b/test/mcp_2026_07_28_test.dart index a5b58d26..5d86b5ac 100644 --- a/test/mcp_2026_07_28_test.dart +++ b/test/mcp_2026_07_28_test.dart @@ -573,6 +573,43 @@ void main() { ); }); + test('requires complete resultType on server/discover results', () { + final validResult = const DiscoverResult( + supportedVersions: [draftProtocolVersion2026_07_28], + capabilities: ServerCapabilities(), + serverInfo: Implementation(name: 'server', version: '1.0.0'), + ).toJson(); + + for (final json in [ + { + ...validResult, + }..remove('resultType'), + { + ...validResult, + 'resultType': resultTypeInputRequired, + }, + { + ...validResult, + 'resultType': 1, + }, + ]) { + expect( + () => DiscoverResult.fromJson(json), + throwsFormatException, + ); + } + + expect( + () => const DiscoverResult( + resultType: resultTypeInputRequired, + supportedVersions: [draftProtocolVersion2026_07_28], + capabilities: ServerCapabilities(), + serverInfo: Implementation(name: 'server', version: '1.0.0'), + ).toJson(), + throwsArgumentError, + ); + }); + test('requires server/discover request metadata in params', () { expect( () => JsonRpcServerDiscoverRequest(id: 'discover-1').toJson(),