1pub mod progress;
2use std::sync::Arc;
3
4use crate::{
5 error::ErrorData as McpError,
6 model::*,
7 service::{NotificationContext, RequestContext, RoleClient, Service, ServiceRole},
8};
9
10impl<H: ClientHandler> Service<RoleClient> for H {
11 async fn handle_request(
12 &self,
13 request: <RoleClient as ServiceRole>::PeerReq,
14 context: RequestContext<RoleClient>,
15 ) -> Result<<RoleClient as ServiceRole>::Resp, McpError> {
16 match request {
17 ServerRequest::PingRequest(_) => self.ping(context).await.map(ClientResult::empty),
18 ServerRequest::CreateMessageRequest(request) => self
19 .create_message(request.params, context)
20 .await
21 .map(Box::new)
22 .map(ClientResult::CreateMessageResult),
23 ServerRequest::ListRootsRequest(_) => self
24 .list_roots(context)
25 .await
26 .map(ClientResult::ListRootsResult),
27 ServerRequest::CreateElicitationRequest(request) => self
28 .create_elicitation(request.params, context)
29 .await
30 .map(ClientResult::CreateElicitationResult),
31 ServerRequest::CustomRequest(request) => self
32 .on_custom_request(request, context)
33 .await
34 .map(ClientResult::CustomResult),
35 }
36 }
37
38 async fn handle_notification(
39 &self,
40 notification: <RoleClient as ServiceRole>::PeerNot,
41 context: NotificationContext<RoleClient>,
42 ) -> Result<(), McpError> {
43 match notification {
44 ServerNotification::CancelledNotification(notification) => {
45 self.on_cancelled(notification.params, context).await
46 }
47 ServerNotification::ProgressNotification(notification) => {
48 self.on_progress(notification.params, context).await
49 }
50 ServerNotification::LoggingMessageNotification(notification) => {
51 self.on_logging_message(notification.params, context).await
52 }
53 ServerNotification::ResourceUpdatedNotification(notification) => {
54 self.on_resource_updated(notification.params, context).await
55 }
56 ServerNotification::ResourceListChangedNotification(_notification_no_param) => {
57 self.on_resource_list_changed(context).await
58 }
59 ServerNotification::ToolListChangedNotification(_notification_no_param) => {
60 self.on_tool_list_changed(context).await
61 }
62 ServerNotification::PromptListChangedNotification(_notification_no_param) => {
63 self.on_prompt_list_changed(context).await
64 }
65 ServerNotification::CustomNotification(notification) => {
66 self.on_custom_notification(notification, context).await
67 }
68 };
69 Ok(())
70 }
71
72 fn get_info(&self) -> <RoleClient as ServiceRole>::Info {
73 self.get_info()
74 }
75}
76
77#[allow(unused_variables)]
78pub trait ClientHandler: Sized + Send + Sync + 'static {
79 fn ping(
80 &self,
81 context: RequestContext<RoleClient>,
82 ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
83 std::future::ready(Ok(()))
84 }
85
86 fn create_message(
87 &self,
88 params: CreateMessageRequestParams,
89 context: RequestContext<RoleClient>,
90 ) -> impl Future<Output = Result<CreateMessageResult, McpError>> + Send + '_ {
91 std::future::ready(Err(
92 McpError::method_not_found::<CreateMessageRequestMethod>(),
93 ))
94 }
95
96 fn list_roots(
97 &self,
98 context: RequestContext<RoleClient>,
99 ) -> impl Future<Output = Result<ListRootsResult, McpError>> + Send + '_ {
100 std::future::ready(Ok(ListRootsResult::default()))
101 }
102
103 fn create_elicitation(
120 &self,
121 request: CreateElicitationRequestParams,
122 context: RequestContext<RoleClient>,
123 ) -> impl Future<Output = Result<CreateElicitationResult, McpError>> + Send + '_ {
124 let _ = (request, context);
126 std::future::ready(Ok(CreateElicitationResult {
127 action: ElicitationAction::Decline,
128 content: None,
129 }))
130 }
131
132 fn on_custom_request(
133 &self,
134 request: CustomRequest,
135 context: RequestContext<RoleClient>,
136 ) -> impl Future<Output = Result<CustomResult, McpError>> + Send + '_ {
137 let CustomRequest { method, .. } = request;
138 let _ = context;
139 std::future::ready(Err(McpError::new(
140 ErrorCode::METHOD_NOT_FOUND,
141 method,
142 None,
143 )))
144 }
145
146 fn on_cancelled(
147 &self,
148 params: CancelledNotificationParam,
149 context: NotificationContext<RoleClient>,
150 ) -> impl Future<Output = ()> + Send + '_ {
151 std::future::ready(())
152 }
153 fn on_progress(
154 &self,
155 params: ProgressNotificationParam,
156 context: NotificationContext<RoleClient>,
157 ) -> impl Future<Output = ()> + Send + '_ {
158 std::future::ready(())
159 }
160 fn on_logging_message(
161 &self,
162 params: LoggingMessageNotificationParam,
163 context: NotificationContext<RoleClient>,
164 ) -> impl Future<Output = ()> + Send + '_ {
165 std::future::ready(())
166 }
167 fn on_resource_updated(
168 &self,
169 params: ResourceUpdatedNotificationParam,
170 context: NotificationContext<RoleClient>,
171 ) -> impl Future<Output = ()> + Send + '_ {
172 std::future::ready(())
173 }
174 fn on_resource_list_changed(
175 &self,
176 context: NotificationContext<RoleClient>,
177 ) -> impl Future<Output = ()> + Send + '_ {
178 std::future::ready(())
179 }
180 fn on_tool_list_changed(
181 &self,
182 context: NotificationContext<RoleClient>,
183 ) -> impl Future<Output = ()> + Send + '_ {
184 std::future::ready(())
185 }
186 fn on_prompt_list_changed(
187 &self,
188 context: NotificationContext<RoleClient>,
189 ) -> impl Future<Output = ()> + Send + '_ {
190 std::future::ready(())
191 }
192 fn on_custom_notification(
193 &self,
194 notification: CustomNotification,
195 context: NotificationContext<RoleClient>,
196 ) -> impl Future<Output = ()> + Send + '_ {
197 let _ = (notification, context);
198 std::future::ready(())
199 }
200
201 fn get_info(&self) -> ClientInfo {
202 ClientInfo::default()
203 }
204}
205
206impl ClientHandler for () {}
208
209impl ClientHandler for ClientInfo {
211 fn get_info(&self) -> ClientInfo {
212 self.clone()
213 }
214}
215
216macro_rules! impl_client_handler_for_wrapper {
217 ($wrapper:ident) => {
218 impl<T: ClientHandler> ClientHandler for $wrapper<T> {
219 fn ping(
220 &self,
221 context: RequestContext<RoleClient>,
222 ) -> impl Future<Output = Result<(), McpError>> + Send + '_ {
223 (**self).ping(context)
224 }
225
226 fn create_message(
227 &self,
228 params: CreateMessageRequestParams,
229 context: RequestContext<RoleClient>,
230 ) -> impl Future<Output = Result<CreateMessageResult, McpError>> + Send + '_ {
231 (**self).create_message(params, context)
232 }
233
234 fn list_roots(
235 &self,
236 context: RequestContext<RoleClient>,
237 ) -> impl Future<Output = Result<ListRootsResult, McpError>> + Send + '_ {
238 (**self).list_roots(context)
239 }
240
241 fn create_elicitation(
242 &self,
243 request: CreateElicitationRequestParams,
244 context: RequestContext<RoleClient>,
245 ) -> impl Future<Output = Result<CreateElicitationResult, McpError>> + Send + '_ {
246 (**self).create_elicitation(request, context)
247 }
248
249 fn on_custom_request(
250 &self,
251 request: CustomRequest,
252 context: RequestContext<RoleClient>,
253 ) -> impl Future<Output = Result<CustomResult, McpError>> + Send + '_ {
254 (**self).on_custom_request(request, context)
255 }
256
257 fn on_cancelled(
258 &self,
259 params: CancelledNotificationParam,
260 context: NotificationContext<RoleClient>,
261 ) -> impl Future<Output = ()> + Send + '_ {
262 (**self).on_cancelled(params, context)
263 }
264
265 fn on_progress(
266 &self,
267 params: ProgressNotificationParam,
268 context: NotificationContext<RoleClient>,
269 ) -> impl Future<Output = ()> + Send + '_ {
270 (**self).on_progress(params, context)
271 }
272
273 fn on_logging_message(
274 &self,
275 params: LoggingMessageNotificationParam,
276 context: NotificationContext<RoleClient>,
277 ) -> impl Future<Output = ()> + Send + '_ {
278 (**self).on_logging_message(params, context)
279 }
280
281 fn on_resource_updated(
282 &self,
283 params: ResourceUpdatedNotificationParam,
284 context: NotificationContext<RoleClient>,
285 ) -> impl Future<Output = ()> + Send + '_ {
286 (**self).on_resource_updated(params, context)
287 }
288
289 fn on_resource_list_changed(
290 &self,
291 context: NotificationContext<RoleClient>,
292 ) -> impl Future<Output = ()> + Send + '_ {
293 (**self).on_resource_list_changed(context)
294 }
295
296 fn on_tool_list_changed(
297 &self,
298 context: NotificationContext<RoleClient>,
299 ) -> impl Future<Output = ()> + Send + '_ {
300 (**self).on_tool_list_changed(context)
301 }
302
303 fn on_prompt_list_changed(
304 &self,
305 context: NotificationContext<RoleClient>,
306 ) -> impl Future<Output = ()> + Send + '_ {
307 (**self).on_prompt_list_changed(context)
308 }
309
310 fn on_custom_notification(
311 &self,
312 notification: CustomNotification,
313 context: NotificationContext<RoleClient>,
314 ) -> impl Future<Output = ()> + Send + '_ {
315 (**self).on_custom_notification(notification, context)
316 }
317
318 fn get_info(&self) -> ClientInfo {
319 (**self).get_info()
320 }
321 }
322 };
323}
324
325impl_client_handler_for_wrapper!(Box);
326impl_client_handler_for_wrapper!(Arc);