agenterra_rmcp/handler/
client.rs

1use crate::{
2    error::Error as McpError,
3    model::*,
4    service::{NotificationContext, RequestContext, RoleClient, Service, ServiceRole},
5};
6
7impl<H: ClientHandler> Service<RoleClient> for H {
8    async fn handle_request(
9        &self,
10        request: <RoleClient as ServiceRole>::PeerReq,
11        context: RequestContext<RoleClient>,
12    ) -> Result<<RoleClient as ServiceRole>::Resp, McpError> {
13        match request {
14            ServerRequest::PingRequest(_) => self.ping(context).await.map(ClientResult::empty),
15            ServerRequest::CreateMessageRequest(request) => self
16                .create_message(request.params, context)
17                .await
18                .map(ClientResult::CreateMessageResult),
19            ServerRequest::ListRootsRequest(_) => self
20                .list_roots(context)
21                .await
22                .map(ClientResult::ListRootsResult),
23        }
24    }
25
26    async fn handle_notification(
27        &self,
28        notification: <RoleClient as ServiceRole>::PeerNot,
29        context: NotificationContext<RoleClient>,
30    ) -> Result<(), McpError> {
31        match notification {
32            ServerNotification::CancelledNotification(notification) => {
33                self.on_cancelled(notification.params, context).await
34            }
35            ServerNotification::ProgressNotification(notification) => {
36                self.on_progress(notification.params, context).await
37            }
38            ServerNotification::LoggingMessageNotification(notification) => {
39                self.on_logging_message(notification.params, context).await
40            }
41            ServerNotification::ResourceUpdatedNotification(notification) => {
42                self.on_resource_updated(notification.params, context).await
43            }
44            ServerNotification::ResourceListChangedNotification(_notification_no_param) => {
45                self.on_resource_list_changed(context).await
46            }
47            ServerNotification::ToolListChangedNotification(_notification_no_param) => {
48                self.on_tool_list_changed(context).await
49            }
50            ServerNotification::PromptListChangedNotification(_notification_no_param) => {
51                self.on_prompt_list_changed(context).await
52            }
53        };
54        Ok(())
55    }
56
57    fn get_info(&self) -> <RoleClient as ServiceRole>::Info {
58        self.get_info()
59    }
60}
61
62#[allow(unused_variables)]
63pub trait ClientHandler: Sized + Send + Sync + 'static {
64    fn ping(
65        &self,
66        context: RequestContext<RoleClient>,
67    ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
68        std::future::ready(Ok(()))
69    }
70
71    fn create_message(
72        &self,
73        params: CreateMessageRequestParam,
74        context: RequestContext<RoleClient>,
75    ) -> impl Future<Output = Result<CreateMessageResult, McpError>> + Send + '_ {
76        std::future::ready(Err(
77            McpError::method_not_found::<CreateMessageRequestMethod>(),
78        ))
79    }
80
81    fn list_roots(
82        &self,
83        context: RequestContext<RoleClient>,
84    ) -> impl Future<Output = Result<ListRootsResult, McpError>> + Send + '_ {
85        std::future::ready(Ok(ListRootsResult::default()))
86    }
87
88    fn on_cancelled(
89        &self,
90        params: CancelledNotificationParam,
91        context: NotificationContext<RoleClient>,
92    ) -> impl Future<Output = ()> + Send + '_ {
93        std::future::ready(())
94    }
95    fn on_progress(
96        &self,
97        params: ProgressNotificationParam,
98        context: NotificationContext<RoleClient>,
99    ) -> impl Future<Output = ()> + Send + '_ {
100        std::future::ready(())
101    }
102    fn on_logging_message(
103        &self,
104        params: LoggingMessageNotificationParam,
105        context: NotificationContext<RoleClient>,
106    ) -> impl Future<Output = ()> + Send + '_ {
107        std::future::ready(())
108    }
109    fn on_resource_updated(
110        &self,
111        params: ResourceUpdatedNotificationParam,
112        context: NotificationContext<RoleClient>,
113    ) -> impl Future<Output = ()> + Send + '_ {
114        std::future::ready(())
115    }
116    fn on_resource_list_changed(
117        &self,
118        context: NotificationContext<RoleClient>,
119    ) -> impl Future<Output = ()> + Send + '_ {
120        std::future::ready(())
121    }
122    fn on_tool_list_changed(
123        &self,
124        context: NotificationContext<RoleClient>,
125    ) -> impl Future<Output = ()> + Send + '_ {
126        std::future::ready(())
127    }
128    fn on_prompt_list_changed(
129        &self,
130        context: NotificationContext<RoleClient>,
131    ) -> impl Future<Output = ()> + Send + '_ {
132        std::future::ready(())
133    }
134
135    fn get_info(&self) -> ClientInfo {
136        ClientInfo::default()
137    }
138}
139
140/// Do nothing, with default client info.
141impl ClientHandler for () {}
142
143/// Do nothing, with a specific client info.
144impl ClientHandler for ClientInfo {
145    fn get_info(&self) -> ClientInfo {
146        self.clone()
147    }
148}