Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 55 additions & 18 deletions crates/rmcp/src/transport/async_rw.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,31 @@ fn without_carriage_return(s: &[u8]) -> &[u8] {
}
}

/// Check if a notification method is a standard MCP notification
/// should update this when MCP spec is updated about new notifications
/// Check if a method is a standard MCP method (request, response, or notification).
/// This includes both requests and notifications defined in the MCP specification.
///
/// Based on MCP specification 2025-06-18: https://modelcontextprotocol.io/specification/2025-06-18
fn is_standard_method(method: &str) -> bool {
matches!(
method,
"initialize"
| "ping"
| "prompts/get"
| "prompts/list"
| "resources/list"
| "resources/read"
| "resources/subscribe"
| "resources/unsubscribe"
| "resources/templates/list"
| "tools/call"
| "tools/list"
| "completion/complete"
| "logging/setLevel"
| "roots/list"
| "sampling/createMessage"
) || is_standard_notification(method)
}

fn is_standard_notification(method: &str) -> bool {
matches!(
method,
Expand All @@ -196,6 +219,29 @@ fn is_standard_notification(method: &str) -> bool {
)
}

/// Determines if a notification should be ignored for compatibility.
fn should_ignore_notification(json_value: &serde_json::Value, method: &str) -> bool {
let is_notification = json_value.get("id").is_none();

// Ignore non-MCP notifications (like LSP messages) for compatibility
if is_notification && !is_standard_method(method) {
tracing::trace!(
"Ignoring non-MCP notification '{}' for compatibility",
method
);
return true;
}

// Ignore non-standard MCP notifications
matches!(
(
method.starts_with("notifications/"),
is_standard_notification(method)
),
(true, false)
)
}

/// Try to parse a message with compatibility handling for non-standard notifications
fn try_parse_with_compatibility<T: serde::de::DeserializeOwned>(
line: &[u8],
Expand All @@ -205,22 +251,13 @@ fn try_parse_with_compatibility<T: serde::de::DeserializeOwned>(
match serde_json::from_slice(line) {
Ok(item) => Ok(Some(item)),
Err(e) => {
// Check if this is a non-standard notification that should be ignored
if line_str.contains("\"method\":\"notifications/") {
// Extract the method name to check if it's standard
if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(line_str) {
if let Some(method) = json_value.get("method").and_then(|m| m.as_str()) {
if method.starts_with("notifications/")
&& !is_standard_notification(method)
{
tracing::debug!(
"Ignoring non-standard notification {} {}: {}",
method,
context,
line_str
);
return Ok(None); // Skip this message
}
// Check if this is a notification that should be ignored for compatibility
if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(line_str) {
if let Some(method) =
json_value.get("method").and_then(serde_json::Value::as_str)
{
if should_ignore_notification(&json_value, method) {
return Ok(None);
}
}
}
Expand Down