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