Skip to content

Commit 59694ed

Browse files
committed
feat(mcp): add 'ping' tool and better notification handling
Adds a 'ping' tool for clients to check server liveness. Improves JSON-RPC handling to distinguish between requests (expecting response) and notifications (no response), preventing protocol errors with strict clients. Signed-off-by: Roman Gushchin <[email protected]>
1 parent db95e9c commit 59694ed

File tree

1 file changed

+32
-13
lines changed

1 file changed

+32
-13
lines changed

src/bin/semcode-mcp.rs

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,7 @@ impl McpServer {
20902090
"initialize" => self.handle_initialize(params).await,
20912091
"tools/list" => self.handle_list_tools().await,
20922092
"tools/call" => self.handle_tool_call(params).await,
2093+
"ping" => json!({}),
20932094
_ => json!({
20942095
"error": {
20952096
"code": -32601,
@@ -5086,20 +5087,38 @@ async fn run_stdio_server(server: Arc<McpServer>) -> Result<()> {
50865087

50875088
match serde_json::from_str::<Value>(&line) {
50885089
Ok(request) => {
5089-
let response = server.handle_request(request).await;
5090-
if let Ok(response_str) = serde_json::to_string(&response) {
5091-
let mut stdout_guard = stdout.lock().await;
5092-
if let Err(e) = stdout_guard.write_all(response_str.as_bytes()).await {
5093-
eprintln!("Failed to write response: {e}");
5094-
break;
5095-
}
5096-
if let Err(e) = stdout_guard.write_all(b"\n").await {
5097-
eprintln!("Failed to write newline: {e}");
5098-
break;
5090+
// Check if this is a notification (no id) or a request (has id)
5091+
if request.get("id").is_some() {
5092+
// It's a request, send a response
5093+
let response = server.handle_request(request).await;
5094+
if let Ok(response_str) = serde_json::to_string(&response) {
5095+
let mut stdout_guard = stdout.lock().await;
5096+
if let Err(e) = stdout_guard.write_all(response_str.as_bytes()).await {
5097+
eprintln!("Failed to write response: {e}");
5098+
break;
5099+
}
5100+
if let Err(e) = stdout_guard.write_all(b"\n").await {
5101+
eprintln!("Failed to write newline: {e}");
5102+
break;
5103+
}
5104+
if let Err(e) = stdout_guard.flush().await {
5105+
eprintln!("Failed to flush stdout: {e}");
5106+
break;
5107+
}
50995108
}
5100-
if let Err(e) = stdout_guard.flush().await {
5101-
eprintln!("Failed to flush stdout: {e}");
5102-
break;
5109+
} else {
5110+
// It's a notification, handle without response
5111+
let method = request["method"].as_str().unwrap_or("");
5112+
match method {
5113+
"notifications/initialized" => {
5114+
eprintln!("Client initialized");
5115+
}
5116+
"notifications/cancelled" => {
5117+
eprintln!("Request cancelled (notification received)");
5118+
}
5119+
_ => {
5120+
eprintln!("Received notification: {}", method);
5121+
}
51035122
}
51045123
}
51055124
}

0 commit comments

Comments
 (0)