Skip to content

Commit 2863526

Browse files
committed
feat: implement SEP-2164 resource not found errors
1 parent f1ef2ec commit 2863526

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

crates/rmcp/src/model.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ impl std::fmt::Display for ProtocolVersion {
152152
}
153153

154154
impl ProtocolVersion {
155+
pub const V_2026_07_28: Self = Self(Cow::Borrowed("2026-07-28"));
155156
pub const V_2025_11_25: Self = Self(Cow::Borrowed("2025-11-25"));
156157
pub const V_2025_06_18: Self = Self(Cow::Borrowed("2025-06-18"));
157158
pub const V_2025_03_26: Self = Self(Cow::Borrowed("2025-03-26"));
@@ -164,6 +165,7 @@ impl ProtocolVersion {
164165
Self::V_2025_03_26,
165166
Self::V_2025_06_18,
166167
Self::V_2025_11_25,
168+
Self::V_2026_07_28,
167169
];
168170

169171
/// Returns the string representation of this protocol version.
@@ -193,6 +195,7 @@ impl<'de> Deserialize<'de> for ProtocolVersion {
193195
"2025-03-26" => return Ok(ProtocolVersion::V_2025_03_26),
194196
"2025-06-18" => return Ok(ProtocolVersion::V_2025_06_18),
195197
"2025-11-25" => return Ok(ProtocolVersion::V_2025_11_25),
198+
"2026-07-28" => return Ok(ProtocolVersion::V_2026_07_28),
196199
_ => {}
197200
}
198201
Ok(ProtocolVersion(Cow::Owned(s)))
@@ -544,6 +547,25 @@ impl ErrorData {
544547
pub fn resource_not_found(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
545548
Self::new(ErrorCode::RESOURCE_NOT_FOUND, message, data)
546549
}
550+
551+
/// Create a resource-not-found error using the code required by the negotiated protocol version.
552+
///
553+
/// SEP-2164 standardizes resource-not-found as JSON-RPC `INVALID_PARAMS` (`-32602`)
554+
/// starting with protocol version `2026-07-28`. Older protocol versions continue to use
555+
/// the legacy MCP-specific `RESOURCE_NOT_FOUND` code (`-32002`).
556+
pub fn resource_not_found_for(
557+
protocol_version: &ProtocolVersion,
558+
message: impl Into<Cow<'static, str>>,
559+
data: Option<Value>,
560+
) -> Self {
561+
let code = if protocol_version.as_str() >= ProtocolVersion::V_2026_07_28.as_str() {
562+
ErrorCode::INVALID_PARAMS
563+
} else {
564+
ErrorCode::RESOURCE_NOT_FOUND
565+
};
566+
Self::new(code, message, data)
567+
}
568+
547569
pub fn parse_error(message: impl Into<Cow<'static, str>>, data: Option<Value>) -> Self {
548570
Self::new(ErrorCode::PARSE_ERROR, message, data)
549571
}
@@ -4021,6 +4043,26 @@ mod tests {
40214043
assert_eq!(json_url, expected_url_json);
40224044
}
40234045

4046+
#[test]
4047+
fn resource_not_found_for_uses_legacy_code_for_older_protocol_versions() {
4048+
let error = ErrorData::resource_not_found_for(
4049+
&ProtocolVersion::V_2025_11_25,
4050+
"resource not found",
4051+
None,
4052+
);
4053+
assert_eq!(error.code, ErrorCode::RESOURCE_NOT_FOUND);
4054+
}
4055+
4056+
#[test]
4057+
fn resource_not_found_for_uses_invalid_params_for_sep_2164_protocol_versions() {
4058+
let error = ErrorData::resource_not_found_for(
4059+
&ProtocolVersion::V_2026_07_28,
4060+
"resource not found",
4061+
None,
4062+
);
4063+
assert_eq!(error.code, ErrorCode::INVALID_PARAMS);
4064+
}
4065+
40244066
#[test]
40254067
fn notification_without_params_should_deserialize_as_bare_jsonrpc_message() {
40264068
let payload = b"{\"method\":\"notifications/initialized\",\"jsonrpc\":\"2.0\"}";

0 commit comments

Comments
 (0)