rust_mcp_sdk/mcp_runtimes/client_runtime/
mcp_client_runtime.rs1use std::sync::Arc;
2
3use async_trait::async_trait;
4use rust_mcp_schema::{
5 schema_utils::{
6 MessageFromClient, NotificationFromServer, RequestFromServer, ResultFromClient,
7 ServerMessage,
8 },
9 InitializeRequestParams, RpcError,
10};
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 rust_mcp_schema::ServerRequest::PingRequest(ping_request) => self
77 .handler
78 .handle_ping_request(ping_request, runtime)
79 .await
80 .map(|value| value.into()),
81 rust_mcp_schema::ServerRequest::CreateMessageRequest(create_message_request) => {
82 self.handler
83 .handle_create_message_request(create_message_request, runtime)
84 .await
85 .map(|value| value.into())
86 }
87 rust_mcp_schema::ServerRequest::ListRootsRequest(list_roots_request) => self
88 .handler
89 .handle_list_roots_request(list_roots_request, runtime)
90 .await
91 .map(|value| value.into()),
92 },
93 RequestFromServer::CustomRequest(custom_request) => self
95 .handler
96 .handle_custom_request(custom_request, runtime)
97 .await
98 .map(|value| value.into()),
99 }
100 }
101
102 async fn handle_error(
104 &self,
105 jsonrpc_error: RpcError,
106 runtime: &dyn McpClient,
107 ) -> SdkResult<()> {
108 self.handler.handle_error(jsonrpc_error, runtime).await?;
109 Ok(())
110 }
111
112 async fn handle_notification(
114 &self,
115 server_jsonrpc_notification: NotificationFromServer,
116 runtime: &dyn McpClient,
117 ) -> SdkResult<()> {
118 match server_jsonrpc_notification {
119 NotificationFromServer::ServerNotification(server_notification) => {
120 match server_notification {
121 rust_mcp_schema::ServerNotification::CancelledNotification(
122 cancelled_notification,
123 ) => {
124 self.handler
125 .handle_cancelled_notification(cancelled_notification, runtime)
126 .await?;
127 }
128 rust_mcp_schema::ServerNotification::ProgressNotification(
129 progress_notification,
130 ) => {
131 self.handler
132 .handle_progress_notification(progress_notification, runtime)
133 .await?;
134 }
135 rust_mcp_schema::ServerNotification::ResourceListChangedNotification(
136 resource_list_changed_notification,
137 ) => {
138 self.handler
139 .handle_resource_list_changed_notification(
140 resource_list_changed_notification,
141 runtime,
142 )
143 .await?;
144 }
145 rust_mcp_schema::ServerNotification::ResourceUpdatedNotification(
146 resource_updated_notification,
147 ) => {
148 self.handler
149 .handle_resource_updated_notification(
150 resource_updated_notification,
151 runtime,
152 )
153 .await?;
154 }
155 rust_mcp_schema::ServerNotification::PromptListChangedNotification(
156 prompt_list_changed_notification,
157 ) => {
158 self.handler
159 .handle_prompt_list_changed_notification(
160 prompt_list_changed_notification,
161 runtime,
162 )
163 .await?;
164 }
165 rust_mcp_schema::ServerNotification::ToolListChangedNotification(
166 tool_list_changed_notification,
167 ) => {
168 self.handler
169 .handle_tool_list_changed_notification(
170 tool_list_changed_notification,
171 runtime,
172 )
173 .await?;
174 }
175 rust_mcp_schema::ServerNotification::LoggingMessageNotification(
176 logging_message_notification,
177 ) => {
178 self.handler
179 .handle_logging_message_notification(
180 logging_message_notification,
181 runtime,
182 )
183 .await?;
184 }
185 }
186 }
187 NotificationFromServer::CustomNotification(custom_notification) => {
189 self.handler
190 .handle_custom_notification(custom_notification, runtime)
191 .await?;
192 }
193 }
194 Ok(())
195 }
196
197 async fn handle_process_error(
199 &self,
200 error_message: String,
201 runtime: &dyn McpClient,
202 ) -> SdkResult<()> {
203 self.handler
204 .handle_process_error(error_message, runtime)
205 .await
206 .map_err(|err| err.into())
207 }
208}