1pub mod progress;
2use std::sync::Arc;
3
4use crate::{
5 error::ErrorData as McpError,
6 model::*,
7 service::{
8 MaybeSendFuture, NotificationContext, RequestContext, RoleClient, Service, ServiceRole,
9 },
10};
11
12impl<H: ClientHandler> Service<RoleClient> for H {
13 async fn handle_request(
14 &self,
15 request: <RoleClient as ServiceRole>::PeerReq,
16 context: RequestContext<RoleClient>,
17 ) -> Result<<RoleClient as ServiceRole>::Resp, McpError> {
18 match request {
19 ServerRequest::PingRequest(_) => self.ping(context).await.map(ClientResult::empty),
20 ServerRequest::CreateMessageRequest(request) => self
21 .create_message(request.params, context)
22 .await
23 .map(Box::new)
24 .map(ClientResult::CreateMessageResult),
25 ServerRequest::ListRootsRequest(_) => self
26 .list_roots(context)
27 .await
28 .map(ClientResult::ListRootsResult),
29 ServerRequest::CreateElicitationRequest(request) => self
30 .create_elicitation(request.params, context)
31 .await
32 .map(ClientResult::CreateElicitationResult),
33 ServerRequest::CustomRequest(request) => self
34 .on_custom_request(request, context)
35 .await
36 .map(ClientResult::CustomResult),
37 }
38 }
39
40 async fn handle_notification(
41 &self,
42 notification: <RoleClient as ServiceRole>::PeerNot,
43 context: NotificationContext<RoleClient>,
44 ) -> Result<(), McpError> {
45 match notification {
46 ServerNotification::CancelledNotification(notification) => {
47 self.on_cancelled(notification.params, context).await
48 }
49 ServerNotification::ProgressNotification(notification) => {
50 self.on_progress(notification.params, context).await
51 }
52 ServerNotification::LoggingMessageNotification(notification) => {
53 self.on_logging_message(notification.params, context).await
54 }
55 ServerNotification::ResourceUpdatedNotification(notification) => {
56 self.on_resource_updated(notification.params, context).await
57 }
58 ServerNotification::ResourceListChangedNotification(_notification_no_param) => {
59 self.on_resource_list_changed(context).await
60 }
61 ServerNotification::ToolListChangedNotification(_notification_no_param) => {
62 self.on_tool_list_changed(context).await
63 }
64 ServerNotification::PromptListChangedNotification(_notification_no_param) => {
65 self.on_prompt_list_changed(context).await
66 }
67 ServerNotification::ElicitationCompletionNotification(notification) => {
68 self.on_url_elicitation_notification_complete(notification.params, context)
69 .await
70 }
71 ServerNotification::CustomNotification(notification) => {
72 self.on_custom_notification(notification, context).await
73 }
74 };
75 Ok(())
76 }
77
78 fn get_info(&self) -> <RoleClient as ServiceRole>::Info {
79 self.get_info()
80 }
81}
82
83#[allow(unused_variables)]
84pub trait ClientHandler: Sized + Send + Sync + 'static {
85 fn ping(
86 &self,
87 context: RequestContext<RoleClient>,
88 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
89 std::future::ready(Ok(()))
90 }
91
92 fn create_message(
93 &self,
94 params: CreateMessageRequestParams,
95 context: RequestContext<RoleClient>,
96 ) -> impl Future<Output = Result<CreateMessageResult, McpError>> + MaybeSendFuture + '_ {
97 std::future::ready(Err(
98 McpError::method_not_found::<CreateMessageRequestMethod>(),
99 ))
100 }
101
102 fn list_roots(
103 &self,
104 context: RequestContext<RoleClient>,
105 ) -> impl Future<Output = Result<ListRootsResult, McpError>> + MaybeSendFuture + '_ {
106 std::future::ready(Ok(ListRootsResult::default()))
107 }
108
109 fn create_elicitation(
166 &self,
167 request: CreateElicitationRequestParams,
168 context: RequestContext<RoleClient>,
169 ) -> impl Future<Output = Result<CreateElicitationResult, McpError>> + MaybeSendFuture + '_
170 {
171 let _ = (request, context);
173 std::future::ready(Ok(CreateElicitationResult {
174 action: ElicitationAction::Decline,
175 content: None,
176 meta: None,
177 }))
178 }
179
180 fn on_custom_request(
181 &self,
182 request: CustomRequest,
183 context: RequestContext<RoleClient>,
184 ) -> impl Future<Output = Result<CustomResult, McpError>> + MaybeSendFuture + '_ {
185 let CustomRequest { method, .. } = request;
186 let _ = context;
187 std::future::ready(Err(McpError::new(
188 ErrorCode::METHOD_NOT_FOUND,
189 method,
190 None,
191 )))
192 }
193
194 fn on_cancelled(
195 &self,
196 params: CancelledNotificationParam,
197 context: NotificationContext<RoleClient>,
198 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
199 std::future::ready(())
200 }
201 fn on_progress(
202 &self,
203 params: ProgressNotificationParam,
204 context: NotificationContext<RoleClient>,
205 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
206 std::future::ready(())
207 }
208 fn on_logging_message(
209 &self,
210 params: LoggingMessageNotificationParam,
211 context: NotificationContext<RoleClient>,
212 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
213 std::future::ready(())
214 }
215 fn on_resource_updated(
216 &self,
217 params: ResourceUpdatedNotificationParam,
218 context: NotificationContext<RoleClient>,
219 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
220 std::future::ready(())
221 }
222 fn on_resource_list_changed(
223 &self,
224 context: NotificationContext<RoleClient>,
225 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
226 std::future::ready(())
227 }
228 fn on_tool_list_changed(
229 &self,
230 context: NotificationContext<RoleClient>,
231 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
232 std::future::ready(())
233 }
234 fn on_prompt_list_changed(
235 &self,
236 context: NotificationContext<RoleClient>,
237 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
238 std::future::ready(())
239 }
240
241 fn on_url_elicitation_notification_complete(
242 &self,
243 params: ElicitationResponseNotificationParam,
244 context: NotificationContext<RoleClient>,
245 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
246 std::future::ready(())
247 }
248 fn on_custom_notification(
249 &self,
250 notification: CustomNotification,
251 context: NotificationContext<RoleClient>,
252 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
253 let _ = (notification, context);
254 std::future::ready(())
255 }
256
257 fn get_info(&self) -> ClientInfo {
258 ClientInfo::default()
259 }
260}
261
262impl ClientHandler for () {}
264
265impl ClientHandler for ClientInfo {
267 fn get_info(&self) -> ClientInfo {
268 self.clone()
269 }
270}
271
272macro_rules! impl_client_handler_for_wrapper {
273 ($wrapper:ident) => {
274 impl<T: ClientHandler> ClientHandler for $wrapper<T> {
275 fn ping(
276 &self,
277 context: RequestContext<RoleClient>,
278 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
279 (**self).ping(context)
280 }
281
282 fn create_message(
283 &self,
284 params: CreateMessageRequestParams,
285 context: RequestContext<RoleClient>,
286 ) -> impl Future<Output = Result<CreateMessageResult, McpError>> + MaybeSendFuture + '_ {
287 (**self).create_message(params, context)
288 }
289
290 fn list_roots(
291 &self,
292 context: RequestContext<RoleClient>,
293 ) -> impl Future<Output = Result<ListRootsResult, McpError>> + MaybeSendFuture + '_ {
294 (**self).list_roots(context)
295 }
296
297 fn create_elicitation(
298 &self,
299 request: CreateElicitationRequestParams,
300 context: RequestContext<RoleClient>,
301 ) -> impl Future<Output = Result<CreateElicitationResult, McpError>> + MaybeSendFuture + '_ {
302 (**self).create_elicitation(request, context)
303 }
304
305 fn on_custom_request(
306 &self,
307 request: CustomRequest,
308 context: RequestContext<RoleClient>,
309 ) -> impl Future<Output = Result<CustomResult, McpError>> + MaybeSendFuture + '_ {
310 (**self).on_custom_request(request, context)
311 }
312
313 fn on_cancelled(
314 &self,
315 params: CancelledNotificationParam,
316 context: NotificationContext<RoleClient>,
317 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
318 (**self).on_cancelled(params, context)
319 }
320
321 fn on_progress(
322 &self,
323 params: ProgressNotificationParam,
324 context: NotificationContext<RoleClient>,
325 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
326 (**self).on_progress(params, context)
327 }
328
329 fn on_logging_message(
330 &self,
331 params: LoggingMessageNotificationParam,
332 context: NotificationContext<RoleClient>,
333 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
334 (**self).on_logging_message(params, context)
335 }
336
337 fn on_resource_updated(
338 &self,
339 params: ResourceUpdatedNotificationParam,
340 context: NotificationContext<RoleClient>,
341 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
342 (**self).on_resource_updated(params, context)
343 }
344
345 fn on_resource_list_changed(
346 &self,
347 context: NotificationContext<RoleClient>,
348 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
349 (**self).on_resource_list_changed(context)
350 }
351
352 fn on_tool_list_changed(
353 &self,
354 context: NotificationContext<RoleClient>,
355 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
356 (**self).on_tool_list_changed(context)
357 }
358
359 fn on_prompt_list_changed(
360 &self,
361 context: NotificationContext<RoleClient>,
362 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
363 (**self).on_prompt_list_changed(context)
364 }
365
366 fn on_custom_notification(
367 &self,
368 notification: CustomNotification,
369 context: NotificationContext<RoleClient>,
370 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
371 (**self).on_custom_notification(notification, context)
372 }
373
374 fn get_info(&self) -> ClientInfo {
375 (**self).get_info()
376 }
377 }
378 };
379}
380
381impl_client_handler_for_wrapper!(Box);
382impl_client_handler_for_wrapper!(Arc);