@@ -71,26 +71,27 @@ Future<Map<String, Object?>?> handleRequestScopedMessage(
7171 MCPServerFactory serverFactory, {
7272 void Function (Map <String , Object ?> notification)? onNotification,
7373}) async {
74- final method = message[ Keys .method] ;
75- if (method is ! String ) {
74+ final object = JsonRpc2Object . fromMap (message) ;
75+ if (object.kind == JsonRpc2Kind .response ) {
7676 throw ArgumentError .value (
7777 message,
7878 'message' ,
79- 'A dispatched message must have a string method ' ,
79+ 'A request or notification must not carry a result or error ' ,
8080 );
8181 }
82- if (message.containsKey (Keys .id) && message[Keys .id] == null ) {
82+ final method = object.method;
83+ if (method is ! String ) {
8384 throw ArgumentError .value (
8485 message,
8586 'message' ,
86- 'A request id must not be null ' ,
87+ 'A dispatched message must have a string method ' ,
8788 );
8889 }
89- if (message. containsKey ( Keys .result) || message. containsKey ( Keys .error) ) {
90+ if (object.kind == JsonRpc2Kind .request && object.id == null ) {
9091 throw ArgumentError .value (
9192 message,
9293 'message' ,
93- 'A request or notification must not carry a result or error ' ,
94+ 'A request id must not be null ' ,
9495 );
9596 }
9697 if (method == InitializeRequest .methodName ||
@@ -112,14 +113,14 @@ Future<Map<String, Object?>?> handleRequestScopedMessage(
112113 StreamChannel .withCloseGuarantee (inbound.stream, outbound.sink),
113114 );
114115
115- final isRequest = message. containsKey ( Keys .id) ;
116+ final isRequest = object.kind == JsonRpc2Kind .request ;
116117 final response = Completer <Map <String , Object ?>?>();
117118 final subscription = outbound.stream.listen (
118119 (encoded) {
119120 try {
120121 final decoded = (jsonDecode (encoded) as Map ).cast <String , Object ?>();
121- if (decoded. containsKey ( Keys .method) ) {
122- if (decoded. containsKey ( Keys .id)) {
122+ switch ( JsonRpc2Object . fromMap (decoded).kind ) {
123+ case JsonRpc2Kind .request :
123124 // A request from the server to the client. Nothing can answer it
124125 // in a single-message exchange, so fail it back to the server
125126 // instead of leaving its handler waiting forever. Late requests
@@ -129,24 +130,27 @@ Future<Map<String, Object?>?> handleRequestScopedMessage(
129130 inbound.add (
130131 jsonEncode (
131132 _errorResponse (
132- decoded[ Keys .id] ,
133+ JsonRpc2Request . fromMap ( decoded) .id,
133134 'Server to client requests are not supported on a '
134135 'request-scoped transport' ,
135136 ),
136137 ),
137138 );
138139 }
139- } else {
140+ case JsonRpc2Kind .notification :
140141 try {
141142 onNotification? .call (decoded);
142143 } catch (error, stackTrace) {
143144 // A misbehaving callback must not fail the request being
144145 // handled, but it should still be visible.
145146 Zone .current.handleUncaughtError (error, stackTrace);
146147 }
147- }
148- } else if (! response.isCompleted) {
149- response.complete (_withServerInfo (decoded, server.implementation));
148+ case JsonRpc2Kind .response:
149+ if (! response.isCompleted) {
150+ response.complete (
151+ _withServerInfo (decoded, server.implementation),
152+ );
153+ }
150154 }
151155 } catch (error, stackTrace) {
152156 // The server sent a frame we could not process. Never let it wedge or
@@ -205,11 +209,11 @@ Map<String, Object?> _withServerInfo(
205209 Map <String , Object ?> response,
206210 Implementation implementation,
207211) {
208- final result = response[ Keys .result] ;
212+ final result = JsonRpc2Response . fromMap ( response) .result;
209213 if (result is ! Map ) return response;
210- final existingMeta = result[Keys .meta];
211- if (existingMeta is ! Map ? ) return response;
212214 final resultMap = result.cast <String , Object ?>();
215+ final existingMeta = resultMap[Keys .meta];
216+ if (existingMeta is ! Map ? ) return response;
213217 final meta = existingMeta? .cast <String , Object ?>() ?? < String , Object ? > {};
214218 // Copy so the returned response does not alias the shared server info map.
215219 meta.putIfAbsent (
0 commit comments