2
2
// for details. All rights reserved. Use of this source code is governed by a
3
3
// BSD-style license that can be found in the LICENSE file.
4
4
5
- /// Interfaces are based on https://github.com/modelcontextprotocol/specification/blob/main/schema/2024-11-05/schema.json
5
+ /// Interfaces are based on
6
+ /// https://github.com/modelcontextprotocol/specification/blob/main/schema/2025-06-18/schema.ts
6
7
library ;
7
8
8
9
import 'dart:collection' ;
@@ -11,6 +12,7 @@ import 'package:collection/collection.dart';
11
12
import 'package:json_rpc_2/json_rpc_2.dart' ;
12
13
13
14
part 'completions.dart' ;
15
+ part 'elicitation.dart' ;
14
16
part 'initialization.dart' ;
15
17
part 'logging.dart' ;
16
18
part 'prompts.dart' ;
@@ -22,7 +24,8 @@ part 'tools.dart';
22
24
/// Enum of the known protocol versions.
23
25
enum ProtocolVersion {
24
26
v2024_11_05 ('2024-11-05' ),
25
- v2025_03_26 ('2025-03-26' );
27
+ v2025_03_26 ('2025-03-26' ),
28
+ v2025_06_18 ('2025-06-18' );
26
29
27
30
const ProtocolVersion (this .versionString);
28
31
@@ -35,7 +38,7 @@ enum ProtocolVersion {
35
38
static const oldestSupported = ProtocolVersion .v2024_11_05;
36
39
37
40
/// The most recent version supported by the current API.
38
- static const latestSupported = ProtocolVersion .v2025_03_26 ;
41
+ static const latestSupported = ProtocolVersion .v2025_06_18 ;
39
42
40
43
/// The version string used over the wire to identify this version.
41
44
final String versionString;
@@ -58,9 +61,65 @@ extension type ProgressToken( /*String|int*/ Object _) {}
58
61
/// An opaque token used to represent a cursor for pagination.
59
62
extension type Cursor (String _) {}
60
63
61
- /// Generic metadata passed with most requests, can be anything.
64
+ /// Generic metadata passed with most requests.
65
+ ///
66
+ /// Metadata reserved by MCP to allow clients and servers to attach additional
67
+ /// metadata to their interactions.
68
+ ///
69
+ /// Certain key names are reserved by MCP for protocol-level metadata, as
70
+ /// specified below; implementations MUST NOT make assumptions about values at
71
+ /// these keys.
72
+ ///
73
+ /// Additionally, definitions in the schema may reserve particular names for
74
+ /// purpose-specific metadata, as declared in those definitions.
75
+ ///
76
+ /// Key name format: valid `_meta` key names have two segments: an optional
77
+ /// prefix, and a name.
78
+ ///
79
+ /// - Prefix: If specified, MUST be a series of labels separated by dots
80
+ /// (`.` ), followed by a slash (`/` ). Labels MUST start with a letter and
81
+ /// end with a letter or digit; interior characters can be letters, digits,
82
+ /// or hyphens (`-` ). Any prefix beginning with zero or more valid labels,
83
+ /// followed by `modelcontextprotocol` or `mcp` , followed by any valid
84
+ /// label, is reserved for MCP use. For example: `modelcontextprotocol.io/` ,
85
+ /// `mcp.dev/` , `api.modelcontextprotocol.org/` , and `tools.mcp.com/` are
86
+ /// all reserved.
87
+ /// - Name: Unless empty, MUST begin and end with an alphanumeric character
88
+ /// (`[a-z0-9A-Z]` ). MAY contain hyphens (`-` ), underscores (`_` ), dots
89
+ /// (`.` ), and alphanumerics in between.
62
90
extension type Meta .fromMap (Map <String , Object ?> _value) {}
63
91
92
+ /// Basic metadata required by multiple types.
93
+ ///
94
+ /// Not to be confused with the `_meta` property in the spec, which has a
95
+ /// different purpose.
96
+ extension type BaseMetadata .fromMap (Map <String , Object ?> _value)
97
+ implements Meta {
98
+ factory BaseMetadata ({required String name, String ? title}) =>
99
+ BaseMetadata .fromMap ({'name' : name, 'title' : title});
100
+
101
+ /// Intended for programmatic or logical use, but used as a display name in
102
+ /// past specs for fallback (if title isn't present).
103
+ String get name {
104
+ final name = _value['name' ] as String ? ;
105
+ if (name == null ) {
106
+ throw ArgumentError ('Missing name field in $runtimeType ' );
107
+ }
108
+ return name;
109
+ }
110
+
111
+ /// A short title for this object.
112
+ ///
113
+ /// Intended for UI and end-user contexts — optimized to be human-readable and
114
+ /// easily understood, even by those unfamiliar with domain-specific
115
+ /// terminology.
116
+ ///
117
+ /// If not provided, the name should be used for display (except for Tool,
118
+ /// where `annotations.title` should be given precedence over using `name` , if
119
+ /// present).
120
+ String ? get title => _value['title' ] as String ? ;
121
+ }
122
+
64
123
/// A "mixin"-like extension type for any extension type that might contain a
65
124
/// [ProgressToken] at the key "progressToken".
66
125
///
@@ -78,10 +137,22 @@ extension type MetaWithProgressToken.fromMap(Map<String, Object?> _value)
78
137
MetaWithProgressToken .fromMap ({'progressToken' : progressToken});
79
138
}
80
139
140
+ /// Base interface for all types that can have arbitrary metadata attached.
141
+ ///
142
+ /// Should not be constructed directly, and has no public constructor.
143
+ extension type WithMetadata ._fromMap (Map <String , Object ?> _value) {
144
+ /// The `_meta` property/parameter is reserved by MCP to allow clients and
145
+ /// servers to attach additional metadata to their interactions.
146
+ ///
147
+ /// See [Meta] for more information about the format of these values.
148
+ Meta ? get meta => _value['_meta' ] as Meta ? ;
149
+ }
150
+
81
151
/// Base interface for all request types.
82
152
///
83
153
/// Should not be constructed directly, and has no public constructor.
84
- extension type Request ._fromMap (Map <String , Object ?> _value) {
154
+ extension type Request ._fromMap (Map <String , Object ?> _value)
155
+ implements WithMetadata {
85
156
/// If specified, the caller is requesting out-of-band progress notifications
86
157
/// for this request (as represented by notifications/progress).
87
158
///
@@ -273,15 +344,19 @@ extension type Content._(Map<String, Object?> _value) {
273
344
274
345
/// Text provided to or from an LLM.
275
346
extension type TextContent .fromMap (Map <String , Object ?> _value)
276
- implements Content , Annotated {
347
+ implements Content , Annotated , WithMetadata {
277
348
static const expectedType = 'text' ;
278
349
279
- factory TextContent ({required String text, Annotations ? annotations}) =>
280
- TextContent .fromMap ({
281
- 'text' : text,
282
- 'type' : expectedType,
283
- if (annotations != null ) 'annotations' : annotations,
284
- });
350
+ factory TextContent ({
351
+ required String text,
352
+ Annotations ? annotations,
353
+ Meta ? meta,
354
+ }) => TextContent .fromMap ({
355
+ 'text' : text,
356
+ 'type' : expectedType,
357
+ if (annotations != null ) 'annotations' : annotations,
358
+ if (meta != null ) '_meta' : meta,
359
+ });
285
360
286
361
String get type {
287
362
final type = _value['type' ] as String ;
@@ -295,18 +370,20 @@ extension type TextContent.fromMap(Map<String, Object?> _value)
295
370
296
371
/// An image provided to or from an LLM.
297
372
extension type ImageContent .fromMap (Map <String , Object ?> _value)
298
- implements Content , Annotated {
373
+ implements Content , Annotated , WithMetadata {
299
374
static const expectedType = 'image' ;
300
375
301
376
factory ImageContent ({
302
377
required String data,
303
378
required String mimeType,
304
379
Annotations ? annotations,
380
+ Meta ? meta,
305
381
}) => ImageContent .fromMap ({
306
382
'data' : data,
307
383
'mimeType' : mimeType,
308
384
'type' : expectedType,
309
385
if (annotations != null ) 'annotations' : annotations,
386
+ if (meta != null ) '_meta' : meta,
310
387
});
311
388
312
389
String get type {
@@ -328,18 +405,20 @@ extension type ImageContent.fromMap(Map<String, Object?> _value)
328
405
///
329
406
/// Only supported since version [ProtocolVersion.v2025_03_26] .
330
407
extension type AudioContent .fromMap (Map <String , Object ?> _value)
331
- implements Content , Annotated {
408
+ implements Content , Annotated , WithMetadata {
332
409
static const expectedType = 'audio' ;
333
410
334
411
factory AudioContent ({
335
412
required String data,
336
413
required String mimeType,
337
414
Annotations ? annotations,
415
+ Meta ? meta,
338
416
}) => AudioContent .fromMap ({
339
417
'data' : data,
340
418
'mimeType' : mimeType,
341
419
'type' : expectedType,
342
420
if (annotations != null ) 'annotations' : annotations,
421
+ if (meta != null ) '_meta' : meta,
343
422
});
344
423
345
424
String get type {
@@ -362,16 +441,18 @@ extension type AudioContent.fromMap(Map<String, Object?> _value)
362
441
/// It is up to the client how best to render embedded resources for the benefit
363
442
/// of the LLM and/or the user.
364
443
extension type EmbeddedResource .fromMap (Map <String , Object ?> _value)
365
- implements Content , Annotated {
444
+ implements Content , Annotated , WithMetadata {
366
445
static const expectedType = 'resource' ;
367
446
368
447
factory EmbeddedResource ({
369
448
required Content resource,
370
449
Annotations ? annotations,
450
+ Meta ? meta,
371
451
}) => EmbeddedResource .fromMap ({
372
452
'resource' : resource,
373
453
'type' : expectedType,
374
454
if (annotations != null ) 'annotations' : annotations,
455
+ if (meta != null ) '_meta' : meta,
375
456
});
376
457
377
458
String get type {
@@ -386,6 +467,76 @@ extension type EmbeddedResource.fromMap(Map<String, Object?> _value)
386
467
String ? get mimeType => _value['mimeType' ] as String ? ;
387
468
}
388
469
470
+ /// A resource link returned from a tool.
471
+ ///
472
+ /// Resource links returned by tools are not guaranteed to appear in the results
473
+ /// of a `resources/list` request.
474
+ extension type ResourceLink .fromMap (Map <String , Object ?> _value)
475
+ implements Content , Annotated , WithMetadata , BaseMetadata {
476
+ static const expectedType = 'resource_link' ;
477
+
478
+ factory ResourceLink ({
479
+ required String name,
480
+ String ? title,
481
+ required String description,
482
+ required String uri,
483
+ required String mimeType,
484
+ Annotations ? annotations,
485
+ Meta ? meta,
486
+ }) => ResourceLink .fromMap ({
487
+ 'name' : name,
488
+ if (title != null ) 'title' : title,
489
+ 'description' : description,
490
+ 'uri' : uri,
491
+ 'mimeType' : mimeType,
492
+ 'type' : expectedType,
493
+ if (annotations != null ) 'annotations' : annotations,
494
+ if (meta != null ) '_meta' : meta,
495
+ });
496
+
497
+ String get type {
498
+ final type = _value['type' ] as String ;
499
+ assert (type == expectedType);
500
+ return type;
501
+ }
502
+
503
+ /// The name of the resource.
504
+ String get name {
505
+ final name = _value['name' ] as String ? ;
506
+ if (name == null ) {
507
+ throw ArgumentError ('Missing name field in $ResourceLink .' );
508
+ }
509
+ return name;
510
+ }
511
+
512
+ /// The description of the resource.
513
+ String get description {
514
+ final description = _value['description' ] as String ? ;
515
+ if (description == null ) {
516
+ throw ArgumentError ('Missing description field in $ResourceLink .' );
517
+ }
518
+ return description;
519
+ }
520
+
521
+ /// The URI of the resource.
522
+ String get uri {
523
+ final uri = _value['uri' ] as String ? ;
524
+ if (uri == null ) {
525
+ throw ArgumentError ('Missing uri field in $ResourceLink .' );
526
+ }
527
+ return uri;
528
+ }
529
+
530
+ /// The MIME type of the resource.
531
+ String get mimeType {
532
+ final mimeType = _value['mimeType' ] as String ? ;
533
+ if (mimeType == null ) {
534
+ throw ArgumentError ('Missing mimeType field in $ResourceLink .' );
535
+ }
536
+ return mimeType;
537
+ }
538
+ }
539
+
389
540
/// Base type for objects that include optional annotations for the client.
390
541
///
391
542
/// The client can use annotations to inform how objects are used or displayed.
@@ -396,10 +547,15 @@ extension type Annotated._fromMap(Map<String, Object?> _value) {
396
547
397
548
/// The annotations for an [Annotated] object.
398
549
extension type Annotations .fromMap (Map <String , Object ?> _value) {
399
- factory Annotations ({List <Role >? audience, double ? priority}) {
550
+ factory Annotations ({
551
+ List <Role >? audience,
552
+ DateTime ? lastModified,
553
+ double ? priority,
554
+ }) {
400
555
assert (priority == null || (priority >= 0 && priority <= 1 ));
401
556
return Annotations .fromMap ({
402
557
if (audience != null ) 'audience' : [for (var role in audience) role.name],
558
+ if (lastModified != null ) 'lastModified' : lastModified.toIso8601String (),
403
559
if (priority != null ) 'priority' : priority,
404
560
});
405
561
}
@@ -416,6 +572,18 @@ extension type Annotations.fromMap(Map<String, Object?> _value) {
416
572
];
417
573
}
418
574
575
+ /// Describes when this data was last modified.
576
+ ///
577
+ /// The moment the resource was last modified.
578
+ ///
579
+ /// Examples: last activity timestamp in an open file, timestamp when the
580
+ /// resource was attached, etc.
581
+ DateTime ? get lastModified {
582
+ final lastModified = _value['lastModified' ] as String ? ;
583
+ if (lastModified == null ) return null ;
584
+ return DateTime .parse (lastModified);
585
+ }
586
+
419
587
/// Describes how important this data is for operating the server.
420
588
///
421
589
/// A value of 1 means "most important," and indicates that the data is
0 commit comments