rust_mcp_sdk/mcp_runtimes/client_runtime/
mcp_client_runtime.rs1use std::sync::Arc;
2
3use crate::schema::{
4 schema_utils::{
5 MessageFromClient, NotificationFromServer, RequestFromServer, ResultFromClient,
6 ServerMessage,
7 },
8 InitializeRequestParams, RpcError, ServerNotification, ServerRequest,
9};
10use async_trait::async_trait;
11use rust_mcp_transport::Transport;
12
13use crate::{
14 error::SdkResult, mcp_client::ClientHandler, mcp_traits::mcp_handler::McpClientHandler,
15 McpClient,
16};
17
18use super::ClientRuntime;
19
20pub fn create_client(
42 client_details: InitializeRequestParams,
43 transport: impl Transport<ServerMessage, MessageFromClient>,
44 handler: impl ClientHandler,
45) -> Arc<ClientRuntime> {
46 Arc::new(ClientRuntime::new(
47 client_details,
48 transport,
49 Box::new(ClientInternalHandler::new(Box::new(handler))),
50 ))
51}
52
53struct ClientInternalHandler<H> {
56 handler: H,
57}
58impl ClientInternalHandler<Box<dyn ClientHandler>> {
59 pub fn new(handler: Box<dyn ClientHandler>) -> Self {
60 Self { handler }
61 }
62}
63
64#[async_trait]
67impl McpClientHandler for ClientInternalHandler<Box<dyn ClientHandler>> {
68 async fn handle_request(
70 &self,
71 server_jsonrpc_request: RequestFromServer,
72 runtime: &dyn McpClient,
73 ) -> std::result::Result<ResultFromClient, RpcError> {
74 match server_jsonrpc_request {
75 RequestFromServer::ServerRequest(request) => match request {
76 ServerRequest::PingRequest(ping_request) => self
77 .handler
78 .handle_ping_request(ping_request, runtime)
79 .await
80 .map(|value| value.into()),
81 ServerRequest::CreateMessageRequest(create_message_request) => self
82 .handler
83 .handle_create_message_request(create_message_request, runtime)
84 .await
85 .map(|value| value.into()),
86 ServerRequest::ListRootsRequest(list_roots_request) => self
87 .handler
88 .handle_list_roots_request(list_roots_request, runtime)
89 .await
90 .map(|value| value.into()),
91 #[cfg(feature = "2025_06_18")]
92 ServerRequest::ElicitRequest(elicit_request) => self
93 .handler
94 .handle_elicit_request(elicit_request, runtime)
95 .await
96 .map(|value| value.into()),
97 },
98 RequestFromServer::CustomRequest(custom_request) => self
100 .handler
101 .handle_custom_request(custom_request, runtime)
102 .await
103 .map(|value| value.into()),
104 }
105 }
106
107 async fn handle_error(
109 &self,
110 jsonrpc_error: RpcError,
111 runtime: &dyn McpClient,
112 ) -> SdkResult<()> {
113 self.handler.handle_error(jsonrpc_error, runtime).await?;
114 Ok(())
115 }
116
117 async fn handle_notification(
119 &self,
120 server_jsonrpc_notification: NotificationFromServer,
121 runtime: &dyn McpClient,
122 ) -> SdkResult<()> {
123 match server_jsonrpc_notification {
124 NotificationFromServer::ServerNotification(server_notification) => {
125 match server_notification {
126 ServerNotification::CancelledNotification(cancelled_notification) => {
127 self.handler
128 .handle_cancelled_notification(cancelled_notification, runtime)
129 .await?;
130 }
131 ServerNotification::ProgressNotification(progress_notification) => {
132 self.handler
133 .handle_progress_notification(progress_notification, runtime)
134 .await?;
135 }
136 ServerNotification::ResourceListChangedNotification(
137 resource_list_changed_notification,
138 ) => {
139 self.handler
140 .handle_resource_list_changed_notification(
141 resource_list_changed_notification,
142 runtime,
143 )
144 .await?;
145 }
146 ServerNotification::ResourceUpdatedNotification(
147 resource_updated_notification,
148 ) => {
149 self.handler
150 .handle_resource_updated_notification(
151 resource_updated_notification,
152 runtime,
153 )
154 .await?;
155 }
156 ServerNotification::PromptListChangedNotification(
157 prompt_list_changed_notification,
158 ) => {
159 self.handler
160 .handle_prompt_list_changed_notification(
161 prompt_list_changed_notification,
162 runtime,
163 )
164 .await?;
165 }
166 ServerNotification::ToolListChangedNotification(
167 tool_list_changed_notification,
168 ) => {
169 self.handler
170 .handle_tool_list_changed_notification(
171 tool_list_changed_notification,
172 runtime,
173 )
174 .await?;
175 }
176 ServerNotification::LoggingMessageNotification(
177 logging_message_notification,
178 ) => {
179 self.handler
180 .handle_logging_message_notification(
181 logging_message_notification,
182 runtime,
183 )
184 .await?;
185 }
186 }
187 }
188 NotificationFromServer::CustomNotification(custom_notification) => {
190 self.handler
191 .handle_custom_notification(custom_notification, runtime)
192 .await?;
193 }
194 }
195 Ok(())
196 }
197
198 async fn handle_process_error(
200 &self,
201 error_message: String,
202 runtime: &dyn McpClient,
203 ) -> SdkResult<()> {
204 self.handler
205 .handle_process_error(error_message, runtime)
206 .await
207 .map_err(|err| err.into())
208 }
209}