1#![expect(deprecated)]
3use std::{borrow::Cow, sync::Arc};
4
5use crate::{
6 error::ErrorData as McpError,
7 model::{TaskSupport, *},
8 service::{
9 MaybeSendFuture, NotificationContext, RequestContext, RoleServer, Service, ServiceRole,
10 negotiate_protocol_version,
11 },
12};
13
14pub mod common;
15pub mod prompt;
16mod resource;
17pub mod router;
18pub mod tool;
19pub mod tool_name_validation;
20pub mod wrapper;
21
22impl<H: ServerHandler> Service<RoleServer> for H {
23 async fn handle_request(
24 &self,
25 request: <RoleServer as ServiceRole>::PeerReq,
26 context: RequestContext<RoleServer>,
27 ) -> Result<<RoleServer as ServiceRole>::Resp, McpError> {
28 let protocol_version = context.protocol_version();
30 let mrtr_supported = protocol_version
31 .as_ref()
32 .is_some_and(|v| v.as_str() >= ProtocolVersion::V_2026_07_28.as_str());
33 let requested_version = context.meta.protocol_version();
34 let uses_inline_negotiation = !matches!(&request, ClientRequest::InitializeRequest(_));
35 if uses_inline_negotiation && let Some(requested_version) = requested_version.as_ref() {
36 let supported_versions = self.supported_protocol_versions();
37 if !supported_versions.contains(requested_version) {
38 return Err(McpError::unsupported_protocol_version(
39 requested_version.clone(),
40 &supported_versions,
41 ));
42 }
43 }
44 let requires_request_metadata = uses_inline_negotiation
50 && (matches!(&request, ClientRequest::DiscoverRequest(_))
51 || context.peer.request_metadata_required()
52 || requested_version.as_ref().is_some_and(|version| {
53 version.as_str() >= ProtocolVersion::V_2026_07_28.as_str()
54 }));
55 if requires_request_metadata {
56 let missing = context
60 .meta
61 .missing_required_keys(&ProtocolVersion::V_2026_07_28);
62 if !missing.is_empty() {
63 return Err(McpError::invalid_params(
64 format!(
65 "request _meta is missing or has malformed required fields: {}",
66 missing.join(", ")
67 ),
68 None,
69 ));
70 }
71 }
72 let result = match request {
73 ClientRequest::InitializeRequest(request) => self
74 .initialize(request.params, context)
75 .await
76 .map(ServerResult::InitializeResult),
77 ClientRequest::DiscoverRequest(_request) => self
78 .discover(context)
79 .await
80 .map(ServerResult::DiscoverResult),
81 ClientRequest::PingRequest(_request) => {
82 self.ping(context).await.map(ServerResult::empty)
83 }
84 ClientRequest::CompleteRequest(request) => self
85 .complete(request.params, context)
86 .await
87 .map(ServerResult::CompleteResult),
88 ClientRequest::SetLevelRequest(request) => self
89 .set_level(request.params, context)
90 .await
91 .map(ServerResult::empty),
92 ClientRequest::GetPromptRequest(request) => self
93 .get_prompt(request.params, context)
94 .await
95 .map(ServerResult::from),
96 ClientRequest::ListPromptsRequest(request) => self
97 .list_prompts(request.params, context)
98 .await
99 .map(ServerResult::ListPromptsResult),
100 ClientRequest::ListResourcesRequest(request) => self
101 .list_resources(request.params, context)
102 .await
103 .map(ServerResult::ListResourcesResult),
104 ClientRequest::ListResourceTemplatesRequest(request) => self
105 .list_resource_templates(request.params, context)
106 .await
107 .map(ServerResult::ListResourceTemplatesResult),
108 ClientRequest::ReadResourceRequest(request) => self
109 .read_resource(request.params, context)
110 .await
111 .map(ServerResult::from),
112 ClientRequest::SubscribeRequest(request) => self
113 .subscribe(request.params, context)
114 .await
115 .map(ServerResult::empty),
116 ClientRequest::UnsubscribeRequest(request) => self
117 .unsubscribe(request.params, context)
118 .await
119 .map(ServerResult::empty),
120 ClientRequest::CallToolRequest(request) => {
121 let is_task = request.params.task.is_some();
122
123 if let Some(tool) = self.get_tool(&request.params.name) {
125 match (tool.task_support(), is_task) {
126 (TaskSupport::Required, false) => {
129 return Err(McpError::new(
130 ErrorCode::METHOD_NOT_FOUND,
131 "Tool requires task-based invocation",
132 None,
133 ));
134 }
135 (TaskSupport::Forbidden, true) => {
137 return Err(McpError::invalid_params(
138 "Tool does not support task-based invocation",
139 None,
140 ));
141 }
142 _ => {}
143 }
144 }
145
146 if is_task {
147 tracing::info!("Enqueueing task for tool call: {}", request.params.name);
148 self.enqueue_task(request.params, context.clone())
149 .await
150 .map(ServerResult::CreateTaskResult)
151 } else {
152 self.call_tool(request.params, context)
153 .await
154 .map(ServerResult::from)
155 }
156 }
157 ClientRequest::ListToolsRequest(request) => self
158 .list_tools(request.params, context)
159 .await
160 .map(ServerResult::ListToolsResult),
161 ClientRequest::CustomRequest(request) => self
162 .on_custom_request(request, context)
163 .await
164 .map(ServerResult::CustomResult),
165 ClientRequest::ListTasksRequest(request) => self
166 .list_tasks(request.params, context)
167 .await
168 .map(ServerResult::ListTasksResult),
169 ClientRequest::GetTaskRequest(request) => self
170 .get_task_info(request.params, context)
171 .await
172 .map(ServerResult::GetTaskResult),
173 ClientRequest::GetTaskPayloadRequest(request) => self
174 .get_task_result(request.params, context)
175 .await
176 .map(ServerResult::GetTaskPayloadResult),
177 ClientRequest::CancelTaskRequest(request) => self
178 .cancel_task(request.params, context)
179 .await
180 .map(ServerResult::CancelTaskResult),
181 };
182 let result = result.and_then(|result| {
183 if matches!(result, ServerResult::InputRequiredResult(_)) && !mrtr_supported {
184 Err(McpError::invalid_request(
185 "InputRequiredResult requires negotiated protocol version 2026-07-28 or newer",
186 None,
187 ))
188 } else {
189 Ok(result)
190 }
191 });
192
193 let use_invalid_params =
197 protocol_version.is_some_and(|v| v.as_str() >= ProtocolVersion::V_2026_07_28.as_str());
198 result.map_err(|mut error| {
199 if use_invalid_params && error.code == ErrorCode::RESOURCE_NOT_FOUND {
200 error.code = ErrorCode::INVALID_PARAMS;
201 }
202 error
203 })
204 }
205
206 async fn handle_notification(
207 &self,
208 notification: <RoleServer as ServiceRole>::PeerNot,
209 context: NotificationContext<RoleServer>,
210 ) -> Result<(), McpError> {
211 match notification {
212 ClientNotification::CancelledNotification(notification) => {
213 self.on_cancelled(notification.params, context).await
214 }
215 ClientNotification::ProgressNotification(notification) => {
216 self.on_progress(notification.params, context).await
217 }
218 ClientNotification::InitializedNotification(_notification) => {
219 self.on_initialized(context).await
220 }
221 ClientNotification::RootsListChangedNotification(_notification) => {
222 self.on_roots_list_changed(context).await
223 }
224 ClientNotification::TaskStatusNotification(notification) => {
225 self.on_task_status(notification.params, context).await
226 }
227 ClientNotification::CustomNotification(notification) => {
228 self.on_custom_notification(notification, context).await
229 }
230 };
231 Ok(())
232 }
233
234 fn get_info(&self) -> <RoleServer as ServiceRole>::Info {
235 self.get_info()
236 }
237}
238
239macro_rules! server_handler_methods {
240 () => {
241 fn enqueue_task(
242 &self,
243 _request: CallToolRequestParams,
244 _context: RequestContext<RoleServer>,
245 ) -> impl Future<Output = Result<CreateTaskResult, McpError>> + MaybeSendFuture + '_ {
246 std::future::ready(Err(McpError::internal_error(
247 "Task processing not implemented".to_string(),
248 None,
249 )))
250 }
251 fn ping(
252 &self,
253 context: RequestContext<RoleServer>,
254 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
255 std::future::ready(Ok(()))
256 }
257 fn initialize(
259 &self,
260 request: InitializeRequestParams,
261 context: RequestContext<RoleServer>,
262 ) -> impl Future<Output = Result<InitializeResult, McpError>> + MaybeSendFuture + '_ {
263 context.peer.set_peer_info(request.clone());
264 let mut info = self.get_info();
265 info.protocol_version = negotiate_protocol_version(
266 &request.protocol_version,
267 info.protocol_version,
268 );
269 std::future::ready(Ok(info))
270 }
271 fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]> {
273 Cow::Borrowed(ProtocolVersion::KNOWN_VERSIONS)
274 }
275 fn discover(
277 &self,
278 context: RequestContext<RoleServer>,
279 ) -> impl Future<Output = Result<DiscoverResult, McpError>> + MaybeSendFuture + '_ {
280 std::future::ready(Ok(DiscoverResult::from_server_info(
281 self.supported_protocol_versions().into_owned(),
282 self.get_info(),
283 )))
284 }
285 fn complete(
286 &self,
287 request: CompleteRequestParams,
288 context: RequestContext<RoleServer>,
289 ) -> impl Future<Output = Result<CompleteResult, McpError>> + MaybeSendFuture + '_ {
290 std::future::ready(Ok(CompleteResult::default()))
291 }
292 fn set_level(
293 &self,
294 request: SetLevelRequestParams,
295 context: RequestContext<RoleServer>,
296 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
297 std::future::ready(Err(McpError::method_not_found::<SetLevelRequestMethod>()))
298 }
299 fn get_prompt(
300 &self,
301 request: GetPromptRequestParams,
302 context: RequestContext<RoleServer>,
303 ) -> impl Future<Output = Result<GetPromptResponse, McpError>> + MaybeSendFuture + '_ {
304 std::future::ready(Err(McpError::method_not_found::<GetPromptRequestMethod>()))
305 }
306 fn list_prompts(
307 &self,
308 request: Option<PaginatedRequestParams>,
309 context: RequestContext<RoleServer>,
310 ) -> impl Future<Output = Result<ListPromptsResult, McpError>> + MaybeSendFuture + '_ {
311 std::future::ready(Ok(ListPromptsResult::default()))
312 }
313 fn list_resources(
314 &self,
315 request: Option<PaginatedRequestParams>,
316 context: RequestContext<RoleServer>,
317 ) -> impl Future<Output = Result<ListResourcesResult, McpError>> + MaybeSendFuture + '_ {
318 std::future::ready(Ok(ListResourcesResult::default()))
319 }
320 fn list_resource_templates(
321 &self,
322 request: Option<PaginatedRequestParams>,
323 context: RequestContext<RoleServer>,
324 ) -> impl Future<Output = Result<ListResourceTemplatesResult, McpError>>
325 + MaybeSendFuture
326 + '_ {
327 std::future::ready(Ok(ListResourceTemplatesResult::default()))
328 }
329 fn read_resource(
330 &self,
331 request: ReadResourceRequestParams,
332 context: RequestContext<RoleServer>,
333 ) -> impl Future<Output = Result<ReadResourceResponse, McpError>> + MaybeSendFuture + '_ {
334 std::future::ready(Err(
335 McpError::method_not_found::<ReadResourceRequestMethod>(),
336 ))
337 }
338 fn subscribe(
339 &self,
340 request: SubscribeRequestParams,
341 context: RequestContext<RoleServer>,
342 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
343 std::future::ready(Err(McpError::method_not_found::<SubscribeRequestMethod>()))
344 }
345 fn unsubscribe(
346 &self,
347 request: UnsubscribeRequestParams,
348 context: RequestContext<RoleServer>,
349 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
350 std::future::ready(Err(
351 McpError::method_not_found::<UnsubscribeRequestMethod>(),
352 ))
353 }
354 fn call_tool(
383 &self,
384 request: CallToolRequestParams,
385 context: RequestContext<RoleServer>,
386 ) -> impl Future<Output = Result<CallToolResponse, McpError>> + MaybeSendFuture + '_ {
387 std::future::ready(Err(McpError::method_not_found::<CallToolRequestMethod>()))
388 }
389 fn list_tools(
390 &self,
391 request: Option<PaginatedRequestParams>,
392 context: RequestContext<RoleServer>,
393 ) -> impl Future<Output = Result<ListToolsResult, McpError>> + MaybeSendFuture + '_ {
394 std::future::ready(Ok(ListToolsResult::default()))
395 }
396 fn get_tool(&self, _name: &str) -> Option<Tool> {
401 None
402 }
403 fn on_custom_request(
404 &self,
405 request: CustomRequest,
406 context: RequestContext<RoleServer>,
407 ) -> impl Future<Output = Result<CustomResult, McpError>> + MaybeSendFuture + '_ {
408 let CustomRequest { method, .. } = request;
409 let _ = context;
410 std::future::ready(Err(McpError::new(
411 ErrorCode::METHOD_NOT_FOUND,
412 method,
413 None,
414 )))
415 }
416
417 fn on_cancelled(
418 &self,
419 notification: CancelledNotificationParam,
420 context: NotificationContext<RoleServer>,
421 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
422 std::future::ready(())
423 }
424 fn on_progress(
425 &self,
426 notification: ProgressNotificationParam,
427 context: NotificationContext<RoleServer>,
428 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
429 std::future::ready(())
430 }
431 fn on_initialized(
432 &self,
433 context: NotificationContext<RoleServer>,
434 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
435 tracing::info!("client initialized");
436 std::future::ready(())
437 }
438 fn on_roots_list_changed(
439 &self,
440 context: NotificationContext<RoleServer>,
441 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
442 std::future::ready(())
443 }
444 fn on_task_status(
445 &self,
446 params: TaskStatusNotificationParam,
447 context: NotificationContext<RoleServer>,
448 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
449 std::future::ready(())
450 }
451 fn on_custom_notification(
452 &self,
453 notification: CustomNotification,
454 context: NotificationContext<RoleServer>,
455 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
456 let _ = (notification, context);
457 std::future::ready(())
458 }
459
460 fn get_info(&self) -> ServerInfo {
461 ServerInfo::default()
462 }
463
464 fn list_tasks(
465 &self,
466 request: Option<PaginatedRequestParams>,
467 context: RequestContext<RoleServer>,
468 ) -> impl Future<Output = Result<ListTasksResult, McpError>> + MaybeSendFuture + '_ {
469 std::future::ready(Err(McpError::method_not_found::<ListTasksMethod>()))
470 }
471
472 fn get_task_info(
473 &self,
474 request: GetTaskParams,
475 context: RequestContext<RoleServer>,
476 ) -> impl Future<Output = Result<GetTaskResult, McpError>> + MaybeSendFuture + '_ {
477 let _ = (request, context);
478 std::future::ready(Err(McpError::method_not_found::<GetTaskMethod>()))
479 }
480
481 fn get_task_result(
482 &self,
483 request: GetTaskPayloadParams,
484 context: RequestContext<RoleServer>,
485 ) -> impl Future<Output = Result<GetTaskPayloadResult, McpError>> + MaybeSendFuture + '_ {
486 let _ = (request, context);
487 std::future::ready(Err(McpError::method_not_found::<GetTaskPayloadMethod>()))
488 }
489
490 fn cancel_task(
491 &self,
492 request: CancelTaskParams,
493 context: RequestContext<RoleServer>,
494 ) -> impl Future<Output = Result<CancelTaskResult, McpError>> + MaybeSendFuture + '_ {
495 let _ = (request, context);
496 std::future::ready(Err(McpError::method_not_found::<CancelTaskMethod>()))
497 }
498 };
499}
500
501#[allow(unused_variables)]
502#[cfg(not(feature = "local"))]
503pub trait ServerHandler: Sized + Send + Sync + 'static {
504 server_handler_methods!();
505}
506
507#[allow(unused_variables)]
508#[cfg(feature = "local")]
509pub trait ServerHandler: Sized + 'static {
510 server_handler_methods!();
511}
512
513macro_rules! impl_server_handler_for_wrapper {
514 ($wrapper:ident) => {
515 impl<T: ServerHandler> ServerHandler for $wrapper<T> {
516 fn enqueue_task(
517 &self,
518 request: CallToolRequestParams,
519 context: RequestContext<RoleServer>,
520 ) -> impl Future<Output = Result<CreateTaskResult, McpError>> + MaybeSendFuture + '_ {
521 (**self).enqueue_task(request, context)
522 }
523
524 fn ping(
525 &self,
526 context: RequestContext<RoleServer>,
527 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
528 (**self).ping(context)
529 }
530
531 fn initialize(
532 &self,
533 request: InitializeRequestParams,
534 context: RequestContext<RoleServer>,
535 ) -> impl Future<Output = Result<InitializeResult, McpError>> + MaybeSendFuture + '_ {
536 (**self).initialize(request, context)
537 }
538
539 fn supported_protocol_versions(&self) -> Cow<'static, [ProtocolVersion]> {
540 (**self).supported_protocol_versions()
541 }
542
543 fn discover(
544 &self,
545 context: RequestContext<RoleServer>,
546 ) -> impl Future<Output = Result<DiscoverResult, McpError>> + MaybeSendFuture + '_ {
547 (**self).discover(context)
548 }
549
550 fn complete(
551 &self,
552 request: CompleteRequestParams,
553 context: RequestContext<RoleServer>,
554 ) -> impl Future<Output = Result<CompleteResult, McpError>> + MaybeSendFuture + '_ {
555 (**self).complete(request, context)
556 }
557
558 fn set_level(
559 &self,
560 request: SetLevelRequestParams,
561 context: RequestContext<RoleServer>,
562 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
563 (**self).set_level(request, context)
564 }
565
566 fn get_prompt(
567 &self,
568 request: GetPromptRequestParams,
569 context: RequestContext<RoleServer>,
570 ) -> impl Future<Output = Result<GetPromptResponse, McpError>> + MaybeSendFuture + '_ {
571 (**self).get_prompt(request, context)
572 }
573
574 fn list_prompts(
575 &self,
576 request: Option<PaginatedRequestParams>,
577 context: RequestContext<RoleServer>,
578 ) -> impl Future<Output = Result<ListPromptsResult, McpError>> + MaybeSendFuture + '_ {
579 (**self).list_prompts(request, context)
580 }
581
582 fn list_resources(
583 &self,
584 request: Option<PaginatedRequestParams>,
585 context: RequestContext<RoleServer>,
586 ) -> impl Future<Output = Result<ListResourcesResult, McpError>> + MaybeSendFuture + '_ {
587 (**self).list_resources(request, context)
588 }
589
590 fn list_resource_templates(
591 &self,
592 request: Option<PaginatedRequestParams>,
593 context: RequestContext<RoleServer>,
594 ) -> impl Future<Output = Result<ListResourceTemplatesResult, McpError>> + MaybeSendFuture + '_
595 {
596 (**self).list_resource_templates(request, context)
597 }
598
599 fn read_resource(
600 &self,
601 request: ReadResourceRequestParams,
602 context: RequestContext<RoleServer>,
603 ) -> impl Future<Output = Result<ReadResourceResponse, McpError>> + MaybeSendFuture + '_ {
604 (**self).read_resource(request, context)
605 }
606
607 fn subscribe(
608 &self,
609 request: SubscribeRequestParams,
610 context: RequestContext<RoleServer>,
611 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
612 (**self).subscribe(request, context)
613 }
614
615 fn unsubscribe(
616 &self,
617 request: UnsubscribeRequestParams,
618 context: RequestContext<RoleServer>,
619 ) -> impl Future<Output = Result<(), McpError>> + MaybeSendFuture + '_ {
620 (**self).unsubscribe(request, context)
621 }
622
623 fn call_tool(
624 &self,
625 request: CallToolRequestParams,
626 context: RequestContext<RoleServer>,
627 ) -> impl Future<Output = Result<CallToolResponse, McpError>> + MaybeSendFuture + '_ {
628 (**self).call_tool(request, context)
629 }
630
631 fn list_tools(
632 &self,
633 request: Option<PaginatedRequestParams>,
634 context: RequestContext<RoleServer>,
635 ) -> impl Future<Output = Result<ListToolsResult, McpError>> + MaybeSendFuture + '_ {
636 (**self).list_tools(request, context)
637 }
638
639 fn get_tool(&self, name: &str) -> Option<Tool> {
640 (**self).get_tool(name)
641 }
642
643 fn on_custom_request(
644 &self,
645 request: CustomRequest,
646 context: RequestContext<RoleServer>,
647 ) -> impl Future<Output = Result<CustomResult, McpError>> + MaybeSendFuture + '_ {
648 (**self).on_custom_request(request, context)
649 }
650
651 fn on_cancelled(
652 &self,
653 notification: CancelledNotificationParam,
654 context: NotificationContext<RoleServer>,
655 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
656 (**self).on_cancelled(notification, context)
657 }
658
659 fn on_progress(
660 &self,
661 notification: ProgressNotificationParam,
662 context: NotificationContext<RoleServer>,
663 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
664 (**self).on_progress(notification, context)
665 }
666
667 fn on_initialized(
668 &self,
669 context: NotificationContext<RoleServer>,
670 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
671 (**self).on_initialized(context)
672 }
673
674 fn on_roots_list_changed(
675 &self,
676 context: NotificationContext<RoleServer>,
677 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
678 (**self).on_roots_list_changed(context)
679 }
680
681 fn on_task_status(
682 &self,
683 params: TaskStatusNotificationParam,
684 context: NotificationContext<RoleServer>,
685 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
686 (**self).on_task_status(params, context)
687 }
688
689 fn on_custom_notification(
690 &self,
691 notification: CustomNotification,
692 context: NotificationContext<RoleServer>,
693 ) -> impl Future<Output = ()> + MaybeSendFuture + '_ {
694 (**self).on_custom_notification(notification, context)
695 }
696
697 fn get_info(&self) -> ServerInfo {
698 (**self).get_info()
699 }
700
701 fn list_tasks(
702 &self,
703 request: Option<PaginatedRequestParams>,
704 context: RequestContext<RoleServer>,
705 ) -> impl Future<Output = Result<ListTasksResult, McpError>> + MaybeSendFuture + '_ {
706 (**self).list_tasks(request, context)
707 }
708
709 fn get_task_info(
710 &self,
711 request: GetTaskParams,
712 context: RequestContext<RoleServer>,
713 ) -> impl Future<Output = Result<GetTaskResult, McpError>> + MaybeSendFuture + '_ {
714 (**self).get_task_info(request, context)
715 }
716
717 fn get_task_result(
718 &self,
719 request: GetTaskPayloadParams,
720 context: RequestContext<RoleServer>,
721 ) -> impl Future<Output = Result<GetTaskPayloadResult, McpError>> + MaybeSendFuture + '_ {
722 (**self).get_task_result(request, context)
723 }
724
725 fn cancel_task(
726 &self,
727 request: CancelTaskParams,
728 context: RequestContext<RoleServer>,
729 ) -> impl Future<Output = Result<CancelTaskResult, McpError>> + MaybeSendFuture + '_ {
730 (**self).cancel_task(request, context)
731 }
732 }
733 };
734}
735
736impl_server_handler_for_wrapper!(Box);
737impl_server_handler_for_wrapper!(Arc);