Skip to content

Commit 95d3e3f

Browse files
authored
fix: use the json rpc error from the initialize response and bubble it up to the client (#569)
1 parent 81f8588 commit 95d3e3f

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

crates/rmcp/src/service/client.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
ArgumentInfo, CallToolRequest, CallToolRequestParam, CallToolResult, CancelledNotification,
99
CancelledNotificationParam, ClientInfo, ClientJsonRpcMessage, ClientNotification,
1010
ClientRequest, ClientResult, CompleteRequest, CompleteRequestParam, CompleteResult,
11-
CompletionContext, CompletionInfo, GetPromptRequest, GetPromptRequestParam,
11+
CompletionContext, CompletionInfo, ErrorData, GetPromptRequest, GetPromptRequestParam,
1212
GetPromptResult, InitializeRequest, InitializedNotification, JsonRpcResponse,
1313
ListPromptsRequest, ListPromptsResult, ListResourceTemplatesRequest,
1414
ListResourceTemplatesResult, ListResourcesRequest, ListResourcesResult, ListToolsRequest,
@@ -44,6 +44,9 @@ pub enum ClientInitializeError {
4444
context: Cow<'static, str>,
4545
},
4646

47+
#[error("JSON-RPC error: {0}")]
48+
JsonRpcError(ErrorData),
49+
4750
#[error("Cancelled")]
4851
Cancelled,
4952
}
@@ -92,6 +95,10 @@ where
9295
ServerJsonRpcMessage::Response(JsonRpcResponse { id, result, .. }) => {
9396
break Ok((result, id));
9497
}
98+
// Handle JSON-RPC error responses
99+
ServerJsonRpcMessage::Error(error) => {
100+
break Err(ClientInitializeError::JsonRpcError(error.error));
101+
}
95102
// Server could send logging messages before handshake
96103
ServerJsonRpcMessage::Notification(mut notification) => {
97104
let ServerNotification::LoggingMessageNotification(logging) =
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// cargo test --features "server client" --package rmcp test_client_initialization
2+
mod common;
3+
4+
use std::borrow::Cow;
5+
6+
use common::handlers::TestClientHandler;
7+
use rmcp::{
8+
ServiceExt,
9+
model::{
10+
ErrorCode, ErrorData, JsonRpcError, JsonRpcVersion2_0, RequestId, ServerJsonRpcMessage,
11+
},
12+
transport::{IntoTransport, Transport},
13+
};
14+
15+
#[tokio::test]
16+
async fn test_client_init_handles_jsonrpc_error() {
17+
let (server_transport, client_transport) = tokio::io::duplex(1024);
18+
let mut server = IntoTransport::<rmcp::RoleServer, _, _>::into_transport(server_transport);
19+
20+
let client_handle = tokio::spawn(async move {
21+
TestClientHandler::new(true, true)
22+
.serve(client_transport)
23+
.await
24+
});
25+
26+
tokio::spawn(async move {
27+
let _init_request = server.receive().await;
28+
29+
let error_msg = ServerJsonRpcMessage::Error(JsonRpcError {
30+
jsonrpc: JsonRpcVersion2_0,
31+
id: RequestId::Number(1),
32+
error: ErrorData {
33+
code: ErrorCode(-32600),
34+
message: Cow::Borrowed("Invalid Request"),
35+
data: None,
36+
},
37+
});
38+
let _: Result<(), _> = server.send(error_msg).await;
39+
});
40+
41+
let result = client_handle.await.unwrap();
42+
43+
assert!(result.is_err());
44+
match result {
45+
Err(rmcp::service::ClientInitializeError::JsonRpcError(error_data)) => {
46+
assert_eq!(error_data.code, ErrorCode(-32600));
47+
assert_eq!(error_data.message, "Invalid Request");
48+
}
49+
_ => panic!("Expected ClientInitializeError::JsonRpcError"),
50+
}
51+
}

0 commit comments

Comments
 (0)