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.
This commit is contained in:
parent
f381c2b899
commit
b514bc4358
1 changed files with 55 additions and 18 deletions
|
|
@ -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,
|
||||
|
|
@ -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],
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue