1
- import 'dart:convert' ;
2
-
3
- import 'package:test/test.dart' ;
4
1
import 'package:mcp_dart/mcp_dart.dart' ;
2
+ import 'package:test/test.dart' ;
5
3
6
4
void main () {
7
5
group ('JsonRpcMessage Tests' , () {
@@ -29,6 +27,20 @@ void main() {
29
27
equals (latestProtocolVersion));
30
28
});
31
29
30
+ test ('JsonRpcResponse serialization' , () {
31
+ final response = JsonRpcResponse (
32
+ id: 1 ,
33
+ result: {'key' : 'value' },
34
+ meta: {'metaKey' : 'metaValue' },
35
+ );
36
+
37
+ final json = response.toJson ();
38
+ expect (json['jsonrpc' ], equals (jsonRpcVersion));
39
+ expect (json['id' ], equals (1 ));
40
+ expect (json['result' ]['key' ], equals ('value' ));
41
+ expect (json['result' ]['_meta' ]['metaKey' ], equals ('metaValue' ));
42
+ });
43
+
32
44
test ('JsonRpcError serialization and deserialization' , () {
33
45
final error = JsonRpcError (
34
46
id: 1 ,
@@ -43,10 +55,15 @@ void main() {
43
55
expect (json['jsonrpc' ], equals (jsonRpcVersion));
44
56
expect (json['error' ]['code' ], equals (ErrorCode .invalidRequest.value));
45
57
expect (json['error' ]['message' ], equals ('Invalid request' ));
58
+ expect (
59
+ json['error' ]['data' ]['details' ], equals ('Missing required field' ));
46
60
47
61
final deserialized = JsonRpcError .fromJson (json);
48
62
expect (deserialized.id, equals (error.id));
49
63
expect (deserialized.error.code, equals (ErrorCode .invalidRequest.value));
64
+ expect (deserialized.error.message, equals ('Invalid request' ));
65
+ expect (
66
+ deserialized.error.data['details' ], equals ('Missing required field' ));
50
67
});
51
68
});
52
69
@@ -112,6 +129,19 @@ void main() {
112
129
expect (deserialized.data, equals ('base64data' ));
113
130
expect (deserialized.mimeType, equals ('image/png' ));
114
131
});
132
+
133
+ test ('UnknownContent serialization and deserialization' , () {
134
+ final content = UnknownContent (
135
+ type: 'unknown' , additionalProperties: {'key' : 'value' });
136
+ final json = content.toJson ();
137
+ expect (json['type' ], equals ('unknown' ));
138
+ expect (json['key' ], equals ('value' ));
139
+
140
+ final deserialized =
141
+ UnknownContent (type: 'unknown' , additionalProperties: json);
142
+ expect (deserialized.type, equals ('unknown' ));
143
+ expect (deserialized.additionalProperties['key' ], equals ('value' ));
144
+ });
115
145
});
116
146
117
147
group ('Resource Tests' , () {
@@ -151,6 +181,24 @@ void main() {
151
181
expect (deserialized.uri, equals ('file://example.txt' ));
152
182
expect (deserialized.text, equals ('Sample text content' ));
153
183
});
184
+
185
+ test ('BlobResourceContents serialization and deserialization' , () {
186
+ final contents = BlobResourceContents (
187
+ uri: 'file://example.bin' ,
188
+ blob: 'base64data' ,
189
+ mimeType: 'application/octet-stream' ,
190
+ );
191
+
192
+ final json = contents.toJson ();
193
+ expect (json['uri' ], equals ('file://example.bin' ));
194
+ expect (json['blob' ], equals ('base64data' ));
195
+ expect (json['mimeType' ], equals ('application/octet-stream' ));
196
+
197
+ final deserialized =
198
+ ResourceContents .fromJson (json) as BlobResourceContents ;
199
+ expect (deserialized.uri, equals ('file://example.bin' ));
200
+ expect (deserialized.blob, equals ('base64data' ));
201
+ });
154
202
});
155
203
156
204
group ('Prompt Tests' , () {
@@ -173,5 +221,169 @@ void main() {
173
221
expect (deserialized.name, equals ('example-prompt' ));
174
222
expect (deserialized.arguments? .first.name, equals ('arg1' ));
175
223
});
224
+
225
+ test ('PromptArgument serialization and deserialization' , () {
226
+ final argument = PromptArgument (
227
+ name: 'arg1' ,
228
+ description: 'Argument 1' ,
229
+ required : true ,
230
+ );
231
+
232
+ final json = argument.toJson ();
233
+ expect (json['name' ], equals ('arg1' ));
234
+ expect (json['description' ], equals ('Argument 1' ));
235
+ expect (json['required' ], equals (true ));
236
+
237
+ final deserialized = PromptArgument .fromJson (json);
238
+ expect (deserialized.name, equals ('arg1' ));
239
+ expect (deserialized.description, equals ('Argument 1' ));
240
+ expect (deserialized.required , equals (true ));
241
+ });
242
+ });
243
+ group ('CreateMessageResult Tests' , () {
244
+ test ('CreateMessageResult serialization and deserialization' , () {
245
+ final result = CreateMessageResult (
246
+ model: 'gpt-4' ,
247
+ stopReason: StopReason .maxTokens,
248
+ role: SamplingMessageRole .assistant,
249
+ content: SamplingTextContent (text: 'Hello, world!' ),
250
+ meta: {'key' : 'value' },
251
+ );
252
+
253
+ final json = result.toJson ();
254
+ expect (json['model' ], equals ('gpt-4' ));
255
+ expect (json['stopReason' ], equals (StopReason .maxTokens.toString ()));
256
+ expect (json['role' ], equals ('assistant' ));
257
+ expect (json['content' ]['type' ], equals ('text' ));
258
+ expect (json['content' ]['text' ], equals ('Hello, world!' ));
259
+ expect (json['_meta' ], isNull); // `_meta` is not included in `toJson`
260
+
261
+ final deserialized = CreateMessageResult .fromJson ({
262
+ 'model' : 'gpt-4' ,
263
+ 'stopReason' : 'maxTokens' ,
264
+ 'role' : 'assistant' ,
265
+ 'content' : {'type' : 'text' , 'text' : 'Hello, world!' },
266
+ '_meta' : {'key' : 'value' },
267
+ });
268
+
269
+ expect (deserialized.model, equals ('gpt-4' ));
270
+ expect (deserialized.stopReason, equals (StopReason .maxTokens));
271
+ expect (deserialized.role, equals (SamplingMessageRole .assistant));
272
+ expect (deserialized.content, isA <SamplingTextContent >());
273
+ expect ((deserialized.content as SamplingTextContent ).text,
274
+ equals ('Hello, world!' ));
275
+ expect (deserialized.meta, equals ({'key' : 'value' }));
276
+ });
277
+
278
+ test ('CreateMessageResult handles custom stopReason' , () {
279
+ final result = CreateMessageResult (
280
+ model: 'gpt-4' ,
281
+ stopReason: 'customReason' ,
282
+ role: SamplingMessageRole .assistant,
283
+ content: SamplingTextContent (text: 'Custom reason test' ),
284
+ );
285
+
286
+ final json = result.toJson ();
287
+ expect (json['stopReason' ], equals ('customReason' ));
288
+
289
+ final deserialized = CreateMessageResult .fromJson ({
290
+ 'model' : 'gpt-4' ,
291
+ 'stopReason' : 'customReason' ,
292
+ 'role' : 'assistant' ,
293
+ 'content' : {'type' : 'text' , 'text' : 'Custom reason test' },
294
+ });
295
+
296
+ expect (deserialized.stopReason, equals ('customReason' ));
297
+ });
298
+
299
+ test ('CreateMessageResult handles invalid stopReason gracefully' , () {
300
+ final deserialized = CreateMessageResult .fromJson ({
301
+ 'model' : 'gpt-4' ,
302
+ 'stopReason' : 'invalidReason' ,
303
+ 'role' : 'assistant' ,
304
+ 'content' : {'type' : 'text' , 'text' : 'Invalid reason test' },
305
+ });
306
+
307
+ expect (deserialized.stopReason, equals ('invalidReason' ));
308
+ });
309
+ });
310
+
311
+ group ('JsonRpcMessage.fromJson Tests' , () {
312
+ test ('Parses valid request with method and id' , () {
313
+ final json = {
314
+ 'jsonrpc' : '2.0' ,
315
+ 'id' : 1 ,
316
+ 'method' : 'ping' ,
317
+ };
318
+ final message = JsonRpcMessage .fromJson (json);
319
+ expect (message, isA <JsonRpcPingRequest >());
320
+ expect ((message as JsonRpcPingRequest ).id, equals (1 ));
321
+ });
322
+
323
+ test ('Parses valid notification without id' , () {
324
+ final json = {
325
+ 'jsonrpc' : '2.0' ,
326
+ 'method' : 'notifications/initialized' ,
327
+ };
328
+ final message = JsonRpcMessage .fromJson (json);
329
+ expect (message, isA <JsonRpcInitializedNotification >());
330
+ });
331
+
332
+ test ('Parses valid response with result and meta' , () {
333
+ final json = {
334
+ 'jsonrpc' : '2.0' ,
335
+ 'id' : 1 ,
336
+ 'result' : {
337
+ 'key' : 'value' ,
338
+ '_meta' : {'metaKey' : 'metaValue' }
339
+ },
340
+ };
341
+ final message = JsonRpcMessage .fromJson (json);
342
+ expect (message, isA <JsonRpcResponse >());
343
+ final response = message as JsonRpcResponse ;
344
+ expect (response.id, equals (1 ));
345
+ expect (response.result, equals ({'key' : 'value' }));
346
+ expect (response.meta, equals ({'metaKey' : 'metaValue' }));
347
+ });
348
+
349
+ test ('Parses valid error response' , () {
350
+ final json = {
351
+ 'jsonrpc' : '2.0' ,
352
+ 'id' : 1 ,
353
+ 'error' : {'code' : - 32601 , 'message' : 'Method not found' },
354
+ };
355
+ final message = JsonRpcMessage .fromJson (json);
356
+ expect (message, isA <JsonRpcError >());
357
+ final error = message as JsonRpcError ;
358
+ expect (error.id, equals (1 ));
359
+ expect (error.error.code, equals (- 32601 ));
360
+ expect (error.error.message, equals ('Method not found' ));
361
+ });
362
+
363
+ test ('Throws FormatException for invalid JSON-RPC version' , () {
364
+ final json = {
365
+ 'jsonrpc' : '1.0' ,
366
+ 'id' : 1 ,
367
+ 'method' : 'ping' ,
368
+ };
369
+ expect (() => JsonRpcMessage .fromJson (json), throwsFormatException);
370
+ });
371
+
372
+ test ('Throws UnimplementedError for unknown method' , () {
373
+ final json = {
374
+ 'jsonrpc' : '2.0' ,
375
+ 'id' : 1 ,
376
+ 'method' : 'unknownMethod' ,
377
+ };
378
+ expect (() => JsonRpcMessage .fromJson (json), throwsUnimplementedError);
379
+ });
380
+
381
+ test ('Throws FormatException for invalid message format' , () {
382
+ final json = {
383
+ 'jsonrpc' : '2.0' ,
384
+ 'id' : 1 ,
385
+ };
386
+ expect (() => JsonRpcMessage .fromJson (json), throwsFormatException);
387
+ });
176
388
});
177
389
}
0 commit comments