@@ -35,7 +35,7 @@ use crate::jsonrpc::task_actor::{Task, TaskTx};
3535use crate :: mcp_server:: McpServer ;
3636use crate :: role:: HasPeer ;
3737use crate :: role:: Role ;
38- use crate :: util:: json_cast ;
38+ use crate :: util:: json_cast_params ;
3939use crate :: { Agent , Client , ConnectTo , RoleId } ;
4040
4141/// Handlers process incoming JSON-RPC messages on a connection.
@@ -2198,8 +2198,16 @@ pub trait JsonRpcMessage: 'static + Debug + Sized + Send + Clone {
21982198
21992199 /// Parse this type from a method name and parameters.
22002200 ///
2201- /// Returns an error if the method doesn't match or deserialization fails.
2202- /// Callers should use `matches_method` first to check if this type handles the method.
2201+ /// Return `crate::Error::method_not_found()` only when `method` is not handled by this
2202+ /// type. When the method matches, any other error is treated as terminal for that dispatch:
2203+ /// the message will be rejected rather than falling through to later handlers for the same
2204+ /// method.
2205+ ///
2206+ /// For incoming request/notification params, prefer `crate::util::json_cast_params()` so
2207+ /// malformed payloads become `crate::Error::invalid_params()`.
2208+ ///
2209+ /// For backward compatibility, the incoming dispatch matchers still normalize legacy
2210+ /// `crate::ErrorCode::ParseError` values from older custom parsers into `Invalid params`.
22032211 fn parse_message ( method : & str , params : & impl Serialize ) -> Result < Self , crate :: Error > ;
22042212}
22052213
@@ -2460,8 +2468,14 @@ impl<Req: JsonRpcRequest, Notif: JsonRpcMessage> Dispatch<Req, Notif> {
24602468 }
24612469}
24622470
2471+ /// Normalize legacy parse errors from matched incoming request/notification params.
2472+ ///
2473+ /// `MethodNotFound` still means "this type does not handle the method" and therefore falls
2474+ /// through to later handlers. The SDK's own request/notification parsers now return
2475+ /// `InvalidParams` directly; this rewrite remains only as a compatibility backstop for older
2476+ /// custom parsers that still emit `ParseError`.
24632477fn normalize_incoming_message_parse_error ( err : crate :: Error ) -> Option < crate :: Error > {
2464- match err. code {
2478+ match & err. code {
24652479 crate :: ErrorCode :: MethodNotFound => None ,
24662480 crate :: ErrorCode :: ParseError => {
24672481 let mut invalid_params = crate :: Error :: invalid_params ( ) ;
@@ -2522,6 +2536,9 @@ pub enum TypedDispatchMatch<Req: JsonRpcRequest, Notif: JsonRpcNotification> {
25222536
25232537impl Dispatch {
25242538 /// Match this dispatch against a request type without using `Err` for parse failures.
2539+ ///
2540+ /// Once `Req::matches_method` is true, any parse error is terminal for that method.
2541+ /// The request is rejected rather than offered to later handlers for the same method.
25252542 #[ must_use]
25262543 pub fn match_request < Req : JsonRpcRequest > ( self ) -> RequestMatch < Req > {
25272544 match self {
@@ -2548,6 +2565,9 @@ impl Dispatch {
25482565 }
25492566
25502567 /// Match this dispatch against a notification type without using `Err` for parse failures.
2568+ ///
2569+ /// Once `Notif::matches_method` is true, any parse error is terminal for that method.
2570+ /// The notification is rejected rather than offered to later handlers for the same method.
25512571 #[ must_use]
25522572 pub fn match_notification < Notif : JsonRpcNotification > ( self ) -> NotificationMatch < Notif > {
25532573 match self {
@@ -2575,6 +2595,10 @@ impl Dispatch {
25752595
25762596 /// Match this dispatch against typed request and notification types without using `Err`
25772597 /// for parse failures.
2598+ ///
2599+ /// Once the request/notification side matches by method, any parse error is terminal for
2600+ /// that method and yields [`TypedDispatchMatch::Rejected`]. Likewise, a matched response
2601+ /// whose result cannot be decoded is rejected instead of bubbling up as a fatal `Err`.
25782602 pub fn match_typed_dispatch < Req : JsonRpcRequest , Notif : JsonRpcNotification > (
25792603 self ,
25802604 ) -> TypedDispatchMatch < Req , Notif > {
@@ -2659,7 +2683,7 @@ impl Dispatch {
26592683 let Some ( value) = message. params ( ) . get ( "sessionId" ) else {
26602684 return Ok ( None ) ;
26612685 } ;
2662- let session_id = serde_json :: from_value ( value. clone ( ) ) ?;
2686+ let session_id = json_cast_params ( value) ?;
26632687 Ok ( Some ( session_id) )
26642688 }
26652689}
@@ -2735,7 +2759,11 @@ impl UntypedMessage {
27352759 id : Option < jsonrpcmsg:: Id > ,
27362760 ) -> Result < jsonrpcmsg:: Request , crate :: Error > {
27372761 let Self { method, params } = self ;
2738- Ok ( jsonrpcmsg:: Request :: new_v2 ( method, json_cast ( params) ?, id) )
2762+ Ok ( jsonrpcmsg:: Request :: new_v2 (
2763+ method,
2764+ crate :: util:: json_cast_params ( params) ?,
2765+ id,
2766+ ) )
27392767 }
27402768}
27412769
0 commit comments