Skip to content

Commit b514bc4

Browse files
authored
fix: resolve compatibility issues with servers sending LSP notifications (#413)
- Gracefully ignore non-MCP notifications (like window/logMessage) for compatibility - Add proper MCP method validation based on 2025-06-18 specification - Fix connection failures with servers like 21Magic that send IDE integration messages Resolves connection closed errors during initialization with mixed-protocol servers.
1 parent f381c2b commit b514bc4

File tree

1 file changed

+55
-18
lines changed

1 file changed

+55
-18
lines changed

crates/rmcp/src/transport/async_rw.rs

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,31 @@ fn without_carriage_return(s: &[u8]) -> &[u8] {
179179
}
180180
}
181181

182-
/// Check if a notification method is a standard MCP notification
183-
/// should update this when MCP spec is updated about new notifications
182+
/// Check if a method is a standard MCP method (request, response, or notification).
183+
/// This includes both requests and notifications defined in the MCP specification.
184+
///
185+
/// Based on MCP specification 2025-06-18: https://modelcontextprotocol.io/specification/2025-06-18
186+
fn is_standard_method(method: &str) -> bool {
187+
matches!(
188+
method,
189+
"initialize"
190+
| "ping"
191+
| "prompts/get"
192+
| "prompts/list"
193+
| "resources/list"
194+
| "resources/read"
195+
| "resources/subscribe"
196+
| "resources/unsubscribe"
197+
| "resources/templates/list"
198+
| "tools/call"
199+
| "tools/list"
200+
| "completion/complete"
201+
| "logging/setLevel"
202+
| "roots/list"
203+
| "sampling/createMessage"
204+
) || is_standard_notification(method)
205+
}
206+
184207
fn is_standard_notification(method: &str) -> bool {
185208
matches!(
186209
method,
@@ -196,6 +219,29 @@ fn is_standard_notification(method: &str) -> bool {
196219
)
197220
}
198221

222+
/// Determines if a notification should be ignored for compatibility.
223+
fn should_ignore_notification(json_value: &serde_json::Value, method: &str) -> bool {
224+
let is_notification = json_value.get("id").is_none();
225+
226+
// Ignore non-MCP notifications (like LSP messages) for compatibility
227+
if is_notification && !is_standard_method(method) {
228+
tracing::trace!(
229+
"Ignoring non-MCP notification '{}' for compatibility",
230+
method
231+
);
232+
return true;
233+
}
234+
235+
// Ignore non-standard MCP notifications
236+
matches!(
237+
(
238+
method.starts_with("notifications/"),
239+
is_standard_notification(method)
240+
),
241+
(true, false)
242+
)
243+
}
244+
199245
/// Try to parse a message with compatibility handling for non-standard notifications
200246
fn try_parse_with_compatibility<T: serde::de::DeserializeOwned>(
201247
line: &[u8],
@@ -205,22 +251,13 @@ fn try_parse_with_compatibility<T: serde::de::DeserializeOwned>(
205251
match serde_json::from_slice(line) {
206252
Ok(item) => Ok(Some(item)),
207253
Err(e) => {
208-
// Check if this is a non-standard notification that should be ignored
209-
if line_str.contains("\"method\":\"notifications/") {
210-
// Extract the method name to check if it's standard
211-
if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(line_str) {
212-
if let Some(method) = json_value.get("method").and_then(|m| m.as_str()) {
213-
if method.starts_with("notifications/")
214-
&& !is_standard_notification(method)
215-
{
216-
tracing::debug!(
217-
"Ignoring non-standard notification {} {}: {}",
218-
method,
219-
context,
220-
line_str
221-
);
222-
return Ok(None); // Skip this message
223-
}
254+
// Check if this is a notification that should be ignored for compatibility
255+
if let Ok(json_value) = serde_json::from_str::<serde_json::Value>(line_str) {
256+
if let Some(method) =
257+
json_value.get("method").and_then(serde_json::Value::as_str)
258+
{
259+
if should_ignore_notification(&json_value, method) {
260+
return Ok(None);
224261
}
225262
}
226263
}

0 commit comments

Comments
 (0)