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 },
92 RequestFromServer::CustomRequest(custom_request) => self
94 .handler
95 .handle_custom_request(custom_request, runtime)
96 .await
97 .map(|value| value.into()),
98 }
99 }
100
101 async fn handle_error(
103 &self,
104 jsonrpc_error: RpcError,
105 runtime: &dyn McpClient,
106 ) -> SdkResult<()> {
107 self.handler.handle_error(jsonrpc_error, runtime).await?;
108 Ok(())
109 }
110
111 async fn handle_notification(
113 &self,
114 server_jsonrpc_notification: NotificationFromServer,
115 runtime: &dyn McpClient,
116 ) -> SdkResult<()> {
117 match server_jsonrpc_notification {
118 NotificationFromServer::ServerNotification(server_notification) => {
119 match server_notification {
120 ServerNotification::CancelledNotification(cancelled_notification) => {
121 self.handler
122 .handle_cancelled_notification(cancelled_notification, runtime)
123 .await?;
124 }
125 ServerNotification::ProgressNotification(progress_notification) => {
126 self.handler
127 .handle_progress_notification(progress_notification, runtime)
128 .await?;
129 }
130 ServerNotification::ResourceListChangedNotification(
131 resource_list_changed_notification,
132 ) => {
133 self.handler
134 .handle_resource_list_changed_notification(
135 resource_list_changed_notification,
136 runtime,
137 )
138 .await?;
139 }
140 ServerNotification::ResourceUpdatedNotification(
141 resource_updated_notification,
142 ) => {
143 self.handler
144 .handle_resource_updated_notification(
145 resource_updated_notification,
146 runtime,
147 )
148 .await?;
149 }
150 ServerNotification::PromptListChangedNotification(
151 prompt_list_changed_notification,
152 ) => {
153 self.handler
154 .handle_prompt_list_changed_notification(
155 prompt_list_changed_notification,
156 runtime,
157 )
158 .await?;
159 }
160 ServerNotification::ToolListChangedNotification(
161 tool_list_changed_notification,
162 ) => {
163 self.handler
164 .handle_tool_list_changed_notification(
165 tool_list_changed_notification,
166 runtime,
167 )
168 .await?;
169 }
170 ServerNotification::LoggingMessageNotification(
171 logging_message_notification,
172 ) => {
173 self.handler
174 .handle_logging_message_notification(
175 logging_message_notification,
176 runtime,
177 )
178 .await?;
179 }
180 }
181 }
182 NotificationFromServer::CustomNotification(custom_notification) => {
184 self.handler
185 .handle_custom_notification(custom_notification, runtime)
186 .await?;
187 }
188 }
189 Ok(())
190 }
191
192 async fn handle_process_error(
194 &self,
195 error_message: String,
196 runtime: &dyn McpClient,
197 ) -> SdkResult<()> {
198 self.handler
199 .handle_process_error(error_message, runtime)
200 .await
201 .map_err(|err| err.into())
202 }
203}