1#![expect(deprecated)]
3use std::{borrow::Cow, sync::Arc, time::Duration};
4
5use thiserror::Error;
6
7use super::*;
8use crate::{
9 model::{
10 ArgumentInfo, CallToolRequest, CallToolRequestParams, CallToolResponse, CallToolResult,
11 CancelledNotification, CancelledNotificationParam, ClientInfo, ClientJsonRpcMessage,
12 ClientNotification, ClientRequest, ClientResult, CompleteRequest, CompleteRequestParams,
13 CompleteResult, CompletionContext, CompletionInfo, DEFAULT_MRTR_MAX_ROUNDS,
14 DiscoverRequest, DiscoverRequestParams, DiscoverResult, ErrorData, GetExtensions, GetMeta,
15 GetPromptRequest, GetPromptRequestParams, GetPromptResponse, GetPromptResult,
16 InitializeRequest, InitializedNotification, InputRequest, InputRequiredResult,
17 InputResponses, JsonRpcResponse, ListPromptsRequest, ListPromptsResult,
18 ListResourceTemplatesRequest, ListResourceTemplatesResult, ListResourcesRequest,
19 ListResourcesResult, ListToolsRequest, ListToolsResult, NumberOrString,
20 PaginatedRequestParams, ProgressNotification, ProgressNotificationParam, ProtocolVersion,
21 ReadResourceRequest, ReadResourceRequestParams, ReadResourceResponse, ReadResourceResult,
22 Reference, RequestId, RequestMetaObject, RootsListChangedNotification, ServerInfo,
23 ServerJsonRpcMessage, ServerNotification, ServerRequest, ServerResult, SetLevelRequest,
24 SetLevelRequestParams, SubscribeRequest, SubscribeRequestParams, UnsubscribeRequest,
25 UnsubscribeRequestParams,
26 },
27 transport::DynamicTransportError,
28};
29
30#[derive(Error, Debug)]
34#[non_exhaustive]
35pub enum ClientInitializeError {
36 #[error("expect initialized response, but received: {0:?}")]
37 ExpectedInitResponse(Option<ServerJsonRpcMessage>),
38
39 #[error("expect initialized result, but received: {0:?}")]
40 ExpectedInitResult(Option<ServerResult>),
41
42 #[error("conflict initialized response id: expected {0}, got {1}")]
43 ConflictInitResponseId(RequestId, RequestId),
44
45 #[error("connection closed: {0}")]
46 ConnectionClosed(String),
47
48 #[error("Send message error {error}, when {context}")]
49 TransportError {
50 error: DynamicTransportError,
51 context: Cow<'static, str>,
52 },
53
54 #[error("JSON-RPC error: {0}")]
55 JsonRpcError(ErrorData),
56
57 #[error(
58 "no compatible protocol version (client: {client_supported:?}, server: {server_supported:?})"
59 )]
60 NoCompatibleProtocolVersion {
61 client_supported: Vec<ProtocolVersion>,
62 server_supported: Vec<ProtocolVersion>,
63 },
64
65 #[error("discover startup requires at least one preferred protocol version")]
66 NoPreferredProtocolVersion,
67
68 #[error("Cancelled")]
69 Cancelled,
70}
71
72impl ClientInitializeError {
73 pub fn transport<T: Transport<RoleClient> + 'static>(
74 error: T::Error,
75 context: impl Into<Cow<'static, str>>,
76 ) -> Self {
77 Self::TransportError {
78 error: DynamicTransportError::new::<T, _>(error),
79 context: context.into(),
80 }
81 }
82}
83
84async fn expect_next_message<T>(
86 transport: &mut T,
87 context: &str,
88) -> Result<ServerJsonRpcMessage, ClientInitializeError>
89where
90 T: Transport<RoleClient>,
91{
92 transport
93 .receive()
94 .await
95 .ok_or_else(|| ClientInitializeError::ConnectionClosed(context.to_string()))
96}
97
98async fn expect_response<T, S>(
100 transport: &mut T,
101 context: &str,
102 service: &S,
103 peer: Peer<RoleClient>,
104) -> Result<(ServerResult, RequestId), ClientInitializeError>
105where
106 T: Transport<RoleClient>,
107 S: Service<RoleClient>,
108{
109 loop {
110 let message = expect_next_message(transport, context).await?;
111 match message {
112 ServerJsonRpcMessage::Response(JsonRpcResponse { id, result, .. }) => {
114 break Ok((result, id));
115 }
116 ServerJsonRpcMessage::Error(error) => {
118 break Err(ClientInitializeError::JsonRpcError(error.error));
119 }
120 ServerJsonRpcMessage::Notification(mut notification) => {
122 let ServerNotification::LoggingMessageNotification(logging) =
123 &mut notification.notification
124 else {
125 tracing::warn!(?notification, "Received unexpected message");
126 continue;
127 };
128
129 let mut context = NotificationContext {
130 peer: peer.clone(),
131 meta: NotificationMetaObject::default(),
132 extensions: Extensions::default(),
133 };
134
135 if let Some(meta) = logging.extensions.get_mut::<NotificationMetaObject>() {
136 std::mem::swap(&mut context.meta, meta);
137 }
138 std::mem::swap(&mut context.extensions, &mut logging.extensions);
139
140 if let Err(error) = service
141 .handle_notification(notification.notification, context)
142 .await
143 {
144 tracing::warn!(?error, "Handle logging before handshake failed.");
145 }
146 }
147 ServerJsonRpcMessage::Request(ref request)
149 if matches!(request.request, ServerRequest::PingRequest(_)) =>
150 {
151 tracing::trace!("Received ping request. Ignored.")
152 }
153 _ => tracing::warn!(?message, "Received unexpected message"),
155 }
156 }
157}
158
159#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
160#[expect(clippy::exhaustive_structs, reason = "intentionally exhaustive")]
161pub struct RoleClient;
162
163pub fn select_protocol_version(
167 client_preference: &[ProtocolVersion],
168 server_supported: &[ProtocolVersion],
169) -> Option<ProtocolVersion> {
170 client_preference
171 .iter()
172 .find(|version| server_supported.contains(version))
173 .cloned()
174}
175
176impl ServiceRole for RoleClient {
177 type Req = ClientRequest;
178 type Resp = ClientResult;
179 type Not = ClientNotification;
180 type PeerReq = ServerRequest;
181 type PeerResp = ServerResult;
182 type PeerNot = ServerNotification;
183 type Info = ClientInfo;
184 type PeerInfo = ServerInfo;
185 type InitializeError = ClientInitializeError;
186 const IS_CLIENT: bool = true;
187}
188
189pub type ServerSink = Peer<RoleClient>;
190
191#[derive(Debug, Clone, PartialEq, Eq)]
195#[non_exhaustive]
196pub enum ClientLifecycleMode {
197 Initialize,
199 Discover {
201 preferred_versions: Vec<ProtocolVersion>,
202 },
203 Auto {
205 preferred_versions: Vec<ProtocolVersion>,
206 legacy_version: Option<ProtocolVersion>,
207 },
208}
209
210pub trait ClientServiceExt: Service<RoleClient> + Sized {
212 fn serve_with_lifecycle<T, E, A>(
213 self,
214 transport: T,
215 lifecycle: ClientLifecycleMode,
216 ) -> impl Future<Output = Result<RunningService<RoleClient, Self>, ClientInitializeError>>
217 + MaybeSendFuture
218 where
219 T: IntoTransport<RoleClient, E, A>,
220 E: std::error::Error + Send + Sync + 'static,
221 {
222 serve_client_with_lifecycle(self, transport, lifecycle)
223 }
224}
225
226impl<S: Service<RoleClient>> ClientServiceExt for S {}
227
228impl<S: Service<RoleClient>> ServiceExt<RoleClient> for S {
229 fn serve_with_ct<T, E, A>(
230 self,
231 transport: T,
232 ct: CancellationToken,
233 ) -> impl Future<Output = Result<RunningService<RoleClient, Self>, ClientInitializeError>>
234 + MaybeSendFuture
235 where
236 T: IntoTransport<RoleClient, E, A>,
237 E: std::error::Error + Send + Sync + 'static,
238 Self: Sized,
239 {
240 serve_client_with_ct(self, transport, ct)
241 }
242}
243
244pub async fn serve_client<S, T, E, A>(
245 service: S,
246 transport: T,
247) -> Result<RunningService<RoleClient, S>, ClientInitializeError>
248where
249 S: Service<RoleClient>,
250 T: IntoTransport<RoleClient, E, A>,
251 E: std::error::Error + Send + Sync + 'static,
252{
253 serve_client_with_lifecycle_and_ct(
254 service,
255 transport,
256 ClientLifecycleMode::Initialize,
257 Default::default(),
258 )
259 .await
260}
261
262pub async fn serve_client_with_ct<S, T, E, A>(
263 service: S,
264 transport: T,
265 ct: CancellationToken,
266) -> Result<RunningService<RoleClient, S>, ClientInitializeError>
267where
268 S: Service<RoleClient>,
269 T: IntoTransport<RoleClient, E, A>,
270 E: std::error::Error + Send + Sync + 'static,
271{
272 serve_client_with_lifecycle_and_ct(service, transport, ClientLifecycleMode::Initialize, ct)
273 .await
274}
275
276pub async fn serve_client_with_lifecycle<S, T, E, A>(
277 service: S,
278 transport: T,
279 lifecycle: ClientLifecycleMode,
280) -> Result<RunningService<RoleClient, S>, ClientInitializeError>
281where
282 S: Service<RoleClient>,
283 T: IntoTransport<RoleClient, E, A>,
284 E: std::error::Error + Send + Sync + 'static,
285{
286 serve_client_with_lifecycle_and_ct(service, transport, lifecycle, Default::default()).await
287}
288
289pub async fn serve_client_with_lifecycle_and_ct<S, T, E, A>(
290 service: S,
291 transport: T,
292 lifecycle: ClientLifecycleMode,
293 ct: CancellationToken,
294) -> Result<RunningService<RoleClient, S>, ClientInitializeError>
295where
296 S: Service<RoleClient>,
297 T: IntoTransport<RoleClient, E, A>,
298 E: std::error::Error + Send + Sync + 'static,
299{
300 tokio::select! {
301 result = serve_client_with_ct_inner(service, transport.into_transport(), lifecycle, ct.clone()) => { result }
302 _ = ct.cancelled() => {
303 Err(ClientInitializeError::Cancelled)
304 }
305 }
306}
307
308async fn serve_client_with_ct_inner<S, T>(
309 service: S,
310 transport: T,
311 lifecycle: ClientLifecycleMode,
312 ct: CancellationToken,
313) -> Result<RunningService<RoleClient, S>, ClientInitializeError>
314where
315 S: Service<RoleClient>,
316 T: Transport<RoleClient> + 'static,
317{
318 let mut transport = transport.into_transport();
319 let id_provider = <Arc<AtomicU32RequestIdProvider>>::default();
320 let (peer, peer_rx) = Peer::new(id_provider.clone(), None);
321 let client_info = service.get_info();
322
323 match lifecycle {
324 ClientLifecycleMode::Initialize => {
325 legacy_startup(&service, &mut transport, &id_provider, &peer, client_info).await?;
326 }
327 ClientLifecycleMode::Discover { preferred_versions } => {
328 discover_startup(
329 &service,
330 &mut transport,
331 &id_provider,
332 &peer,
333 &client_info,
334 preferred_versions,
335 )
336 .await?;
337 }
338 ClientLifecycleMode::Auto {
339 preferred_versions,
340 legacy_version,
341 } => {
342 let discover_result = discover_startup(
343 &service,
344 &mut transport,
345 &id_provider,
346 &peer,
347 &client_info,
348 preferred_versions,
349 )
350 .await;
351 match discover_result {
352 Ok(()) => {}
353 Err(ClientInitializeError::JsonRpcError(error))
354 if error.code == crate::model::ErrorCode::METHOD_NOT_FOUND =>
355 {
356 let mut legacy_info = client_info;
357 if let Some(version) = legacy_version {
358 legacy_info.protocol_version = version;
359 }
360 legacy_startup(&service, &mut transport, &id_provider, &peer, legacy_info)
361 .await?;
362 }
363 Err(error) => return Err(error),
364 }
365 }
366 }
367 Ok(serve_inner(service, transport, peer, peer_rx, ct))
368}
369
370async fn legacy_startup<S, T>(
371 service: &S,
372 transport: &mut T,
373 id_provider: &Arc<AtomicU32RequestIdProvider>,
374 peer: &Peer<RoleClient>,
375 client_info: ClientInfo,
376) -> Result<(), ClientInitializeError>
377where
378 S: Service<RoleClient>,
379 T: Transport<RoleClient> + 'static,
380{
381 let id = id_provider.next_request_id();
382 let init_request = InitializeRequest {
383 method: Default::default(),
384 params: client_info,
385 extensions: Default::default(),
386 };
387 transport
388 .send(ClientJsonRpcMessage::request(
389 ClientRequest::InitializeRequest(init_request),
390 id.clone(),
391 ))
392 .await
393 .map_err(|error| ClientInitializeError::TransportError {
394 error: DynamicTransportError::new::<T, _>(error),
395 context: "send initialize request".into(),
396 })?;
397
398 let (response, response_id) =
399 expect_response(transport, "initialize response", service, peer.clone()).await?;
400
401 if id != response_id {
402 return Err(ClientInitializeError::ConflictInitResponseId(
403 id,
404 response_id,
405 ));
406 }
407
408 let ServerResult::InitializeResult(initialize_result) = response else {
409 return Err(ClientInitializeError::ExpectedInitResult(Some(response)));
410 };
411 peer.set_peer_info(initialize_result);
412
413 let notification = ClientJsonRpcMessage::notification(
415 ClientNotification::InitializedNotification(InitializedNotification {
416 method: Default::default(),
417 extensions: Default::default(),
418 }),
419 );
420 transport.send(notification).await.map_err(|error| {
421 ClientInitializeError::transport::<T>(error, "send initialized notification")
422 })?;
423 Ok(())
424}
425
426async fn discover_startup<S, T>(
427 service: &S,
428 transport: &mut T,
429 id_provider: &Arc<AtomicU32RequestIdProvider>,
430 peer: &Peer<RoleClient>,
431 client_info: &ClientInfo,
432 preferred_versions: Vec<ProtocolVersion>,
433) -> Result<(), ClientInitializeError>
434where
435 S: Service<RoleClient>,
436 T: Transport<RoleClient> + 'static,
437{
438 if preferred_versions.is_empty() {
439 return Err(ClientInitializeError::NoPreferredProtocolVersion);
440 }
441
442 let mut attempted = Vec::new();
443 let mut candidate = preferred_versions[0].clone();
444 loop {
445 attempted.push(candidate.clone());
446
447 let meta = RequestMetaObject::with_client_context(
448 candidate.clone(),
449 client_info.client_info.clone(),
450 client_info.capabilities.clone(),
451 );
452 let mut discover = DiscoverRequest::new(DiscoverRequestParams {});
453 discover.extensions.insert(meta);
454 let id = id_provider.next_request_id();
455 transport
456 .send(ClientJsonRpcMessage::request(
457 ClientRequest::DiscoverRequest(discover),
458 id.clone(),
459 ))
460 .await
461 .map_err(|error| {
462 ClientInitializeError::transport::<T>(error, "send discover request")
463 })?;
464
465 match expect_response(transport, "discover response", service, peer.clone()).await {
466 Ok((ServerResult::DiscoverResult(result), response_id)) => {
467 if response_id != id {
468 return Err(ClientInitializeError::ConflictInitResponseId(
469 id,
470 response_id,
471 ));
472 }
473 let Some(selected) =
474 select_protocol_version(&preferred_versions, &result.supported_versions)
475 else {
476 return Err(ClientInitializeError::NoCompatibleProtocolVersion {
477 client_supported: preferred_versions,
478 server_supported: result.supported_versions,
479 });
480 };
481 peer.set_peer_info(ServerInfo {
482 protocol_version: selected.clone(),
483 capabilities: result.capabilities,
484 server_info: result.server_info,
485 instructions: result.instructions,
486 meta: result.meta,
487 });
488 peer.set_client_request_metadata(ClientRequestMetadata {
489 protocol_version: selected,
490 client_info: client_info.client_info.clone(),
491 client_capabilities: client_info.capabilities.clone(),
492 });
493 return Ok(());
494 }
495 Ok((response, _)) => {
496 return Err(ClientInitializeError::ExpectedInitResult(Some(response)));
497 }
498 Err(ClientInitializeError::JsonRpcError(error))
499 if error.code == crate::model::ErrorCode::UNSUPPORTED_PROTOCOL_VERSION =>
500 {
501 let supported = error
502 .data
503 .as_ref()
504 .and_then(|data| data.get("supported"))
505 .cloned()
506 .and_then(|value| serde_json::from_value::<Vec<ProtocolVersion>>(value).ok())
507 .unwrap_or_default();
508 let may_retry_current = attempted
509 .iter()
510 .filter(|version| *version == &candidate)
511 .count()
512 == 1;
513 let next = preferred_versions
514 .iter()
515 .find(|version| {
516 supported.contains(version)
517 && (!attempted.contains(version)
518 || (may_retry_current && *version == &candidate))
519 })
520 .cloned();
521 let Some(next) = next else {
522 return Err(ClientInitializeError::NoCompatibleProtocolVersion {
523 client_supported: preferred_versions,
524 server_supported: supported,
525 });
526 };
527 candidate = next;
528 }
529 Err(error) => return Err(error),
530 }
531 }
532}
533
534macro_rules! method {
535 ($(#[$meta:meta])* peer_req $method:ident $Req:ident() => $Resp: ident ) => {
536 $(#[$meta])*
537 pub async fn $method(&self) -> Result<$Resp, ServiceError> {
538 let result = self
539 .send_request(ClientRequest::$Req($Req {
540 method: Default::default(),
541 }))
542 .await?;
543 match result {
544 ServerResult::$Resp(result) => Ok(result),
545 _ => Err(ServiceError::UnexpectedResponse),
546 }
547 }
548 };
549 ($(#[$meta:meta])* peer_req $method:ident $Req:ident($Param: ident) => $Resp: ident ) => {
550 $(#[$meta])*
551 pub async fn $method(&self, params: $Param) -> Result<$Resp, ServiceError> {
552 let result = self
553 .send_request(ClientRequest::$Req($Req {
554 method: Default::default(),
555 params,
556 extensions: Default::default(),
557 }))
558 .await?;
559 match result {
560 ServerResult::$Resp(result) => Ok(result),
561 _ => Err(ServiceError::UnexpectedResponse),
562 }
563 }
564 };
565 ($(#[$meta:meta])* peer_req $method:ident $Req:ident($Param: ident)? => $Resp: ident ) => {
566 $(#[$meta])*
567 pub async fn $method(&self, params: Option<$Param>) -> Result<$Resp, ServiceError> {
568 let result = self
569 .send_request(ClientRequest::$Req($Req {
570 method: Default::default(),
571 params,
572 extensions: Default::default(),
573 }))
574 .await?;
575 match result {
576 ServerResult::$Resp(result) => Ok(result),
577 _ => Err(ServiceError::UnexpectedResponse),
578 }
579 }
580 };
581 ($(#[$meta:meta])* peer_req $method:ident $Req:ident($Param: ident)) => {
582 $(#[$meta])*
583 pub async fn $method(&self, params: $Param) -> Result<(), ServiceError> {
584 let result = self
585 .send_request(ClientRequest::$Req($Req {
586 method: Default::default(),
587 params,
588 extensions: Default::default(),
589 }))
590 .await?;
591 match result {
592 ServerResult::EmptyResult(_) => Ok(()),
593 _ => Err(ServiceError::UnexpectedResponse),
594 }
595 }
596 };
597
598 ($(#[$meta:meta])* peer_not $method:ident $Not:ident($Param: ident)) => {
599 $(#[$meta])*
600 pub async fn $method(&self, params: $Param) -> Result<(), ServiceError> {
601 self.send_notification(ClientNotification::$Not($Not {
602 method: Default::default(),
603 params,
604 extensions: Default::default(),
605 }))
606 .await?;
607 Ok(())
608 }
609 };
610 ($(#[$meta:meta])* peer_not $method:ident $Not:ident) => {
611 $(#[$meta])*
612 pub async fn $method(&self) -> Result<(), ServiceError> {
613 self.send_notification(ClientNotification::$Not($Not {
614 method: Default::default(),
615 extensions: Default::default(),
616 }))
617 .await?;
618 Ok(())
619 }
620 };
621}
622
623impl Peer<RoleClient> {
624 pub async fn discover(&self, meta: RequestMetaObject) -> Result<DiscoverResult, ServiceError> {
629 let mut request = DiscoverRequest::new(DiscoverRequestParams {});
630 request.extensions.insert(meta);
631 let result = self
632 .send_request(ClientRequest::DiscoverRequest(request))
633 .await?;
634 match result {
635 ServerResult::DiscoverResult(result) => Ok(result),
636 _ => Err(ServiceError::UnexpectedResponse),
637 }
638 }
639
640 pub async fn call_tool_once(
643 &self,
644 params: CallToolRequestParams,
645 ) -> Result<CallToolResponse, ServiceError> {
646 let result = self
647 .send_request(ClientRequest::CallToolRequest(CallToolRequest {
648 method: Default::default(),
649 params,
650 extensions: Default::default(),
651 }))
652 .await?;
653 match result {
654 ServerResult::CallToolResult(result) => Ok(CallToolResponse::Complete(result)),
655 ServerResult::InputRequiredResult(result) => {
656 Ok(CallToolResponse::InputRequired(result))
657 }
658 _ => Err(ServiceError::UnexpectedResponse),
659 }
660 }
661
662 pub async fn get_prompt_once(
665 &self,
666 params: GetPromptRequestParams,
667 ) -> Result<GetPromptResponse, ServiceError> {
668 let result = self
669 .send_request(ClientRequest::GetPromptRequest(GetPromptRequest {
670 method: Default::default(),
671 params,
672 extensions: Default::default(),
673 }))
674 .await?;
675 match result {
676 ServerResult::GetPromptResult(result) => Ok(GetPromptResponse::Complete(result)),
677 ServerResult::InputRequiredResult(result) => {
678 Ok(GetPromptResponse::InputRequired(result))
679 }
680 _ => Err(ServiceError::UnexpectedResponse),
681 }
682 }
683
684 pub async fn read_resource_once(
687 &self,
688 params: ReadResourceRequestParams,
689 ) -> Result<ReadResourceResponse, ServiceError> {
690 let result = self
691 .send_request(ClientRequest::ReadResourceRequest(ReadResourceRequest {
692 method: Default::default(),
693 params,
694 extensions: Default::default(),
695 }))
696 .await?;
697 match result {
698 ServerResult::ReadResourceResult(result) => Ok(ReadResourceResponse::Complete(result)),
699 ServerResult::InputRequiredResult(result) => {
700 Ok(ReadResourceResponse::InputRequired(result))
701 }
702 _ => Err(ServiceError::UnexpectedResponse),
703 }
704 }
705
706 method!(peer_req complete CompleteRequest(CompleteRequestParams) => CompleteResult);
707 method!(
708 #[deprecated(
709 since = "1.8.0",
710 note = "Logging is deprecated by SEP-2577 and will be removed in a future release. See https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2577"
711 )]
712 peer_req set_level SetLevelRequest(SetLevelRequestParams)
713 );
714 method!(peer_req get_prompt GetPromptRequest(GetPromptRequestParams) => GetPromptResult);
715 method!(peer_req list_prompts ListPromptsRequest(PaginatedRequestParams)? => ListPromptsResult);
716 method!(peer_req list_resources ListResourcesRequest(PaginatedRequestParams)? => ListResourcesResult);
717 method!(peer_req list_resource_templates ListResourceTemplatesRequest(PaginatedRequestParams)? => ListResourceTemplatesResult);
718 method!(peer_req read_resource ReadResourceRequest(ReadResourceRequestParams) => ReadResourceResult);
719 method!(peer_req subscribe SubscribeRequest(SubscribeRequestParams) );
720 method!(peer_req unsubscribe UnsubscribeRequest(UnsubscribeRequestParams));
721 method!(peer_req call_tool CallToolRequest(CallToolRequestParams) => CallToolResult);
722 method!(peer_req list_tools ListToolsRequest(PaginatedRequestParams)? => ListToolsResult);
723
724 method!(peer_not notify_cancelled CancelledNotification(CancelledNotificationParam));
725 method!(peer_not notify_progress ProgressNotification(ProgressNotificationParam));
726 method!(peer_not notify_initialized InitializedNotification);
727 method!(peer_not notify_roots_list_changed RootsListChangedNotification);
728}
729
730impl Peer<RoleClient> {
731 pub async fn list_all_tools(&self) -> Result<Vec<crate::model::Tool>, ServiceError> {
735 let mut tools = Vec::new();
736 let mut cursor = None;
737 loop {
738 let result = self
739 .list_tools(Some(PaginatedRequestParams { meta: None, cursor }))
740 .await?;
741 tools.extend(result.tools);
742 cursor = result.next_cursor;
743 if cursor.is_none() {
744 break;
745 }
746 }
747 Ok(tools)
748 }
749
750 pub async fn list_all_prompts(&self) -> Result<Vec<crate::model::Prompt>, ServiceError> {
754 let mut prompts = Vec::new();
755 let mut cursor = None;
756 loop {
757 let result = self
758 .list_prompts(Some(PaginatedRequestParams { meta: None, cursor }))
759 .await?;
760 prompts.extend(result.prompts);
761 cursor = result.next_cursor;
762 if cursor.is_none() {
763 break;
764 }
765 }
766 Ok(prompts)
767 }
768
769 pub async fn list_all_resources(&self) -> Result<Vec<crate::model::Resource>, ServiceError> {
773 let mut resources = Vec::new();
774 let mut cursor = None;
775 loop {
776 let result = self
777 .list_resources(Some(PaginatedRequestParams { meta: None, cursor }))
778 .await?;
779 resources.extend(result.resources);
780 cursor = result.next_cursor;
781 if cursor.is_none() {
782 break;
783 }
784 }
785 Ok(resources)
786 }
787
788 pub async fn list_all_resource_templates(
792 &self,
793 ) -> Result<Vec<crate::model::ResourceTemplate>, ServiceError> {
794 let mut resource_templates = Vec::new();
795 let mut cursor = None;
796 loop {
797 let result = self
798 .list_resource_templates(Some(PaginatedRequestParams { meta: None, cursor }))
799 .await?;
800 resource_templates.extend(result.resource_templates);
801 cursor = result.next_cursor;
802 if cursor.is_none() {
803 break;
804 }
805 }
806 Ok(resource_templates)
807 }
808
809 pub async fn complete_prompt_argument(
820 &self,
821 prompt_name: impl Into<String>,
822 argument_name: impl Into<String>,
823 current_value: impl Into<String>,
824 context: Option<CompletionContext>,
825 ) -> Result<CompletionInfo, ServiceError> {
826 let request = CompleteRequestParams {
827 meta: None,
828 r#ref: Reference::for_prompt(prompt_name),
829 argument: ArgumentInfo {
830 name: argument_name.into(),
831 value: current_value.into(),
832 },
833 context,
834 };
835
836 let result = self.complete(request).await?;
837 Ok(result.completion)
838 }
839
840 pub async fn complete_resource_argument(
851 &self,
852 uri_template: impl Into<String>,
853 argument_name: impl Into<String>,
854 current_value: impl Into<String>,
855 context: Option<CompletionContext>,
856 ) -> Result<CompletionInfo, ServiceError> {
857 let request = CompleteRequestParams {
858 meta: None,
859 r#ref: Reference::for_resource(uri_template),
860 argument: ArgumentInfo {
861 name: argument_name.into(),
862 value: current_value.into(),
863 },
864 context,
865 };
866
867 let result = self.complete(request).await?;
868 Ok(result.completion)
869 }
870
871 pub async fn complete_prompt_simple(
876 &self,
877 prompt_name: impl Into<String>,
878 argument_name: impl Into<String>,
879 current_value: impl Into<String>,
880 ) -> Result<Vec<String>, ServiceError> {
881 let completion = self
882 .complete_prompt_argument(prompt_name, argument_name, current_value, None)
883 .await?;
884 Ok(completion.values)
885 }
886
887 pub async fn complete_resource_simple(
892 &self,
893 uri_template: impl Into<String>,
894 argument_name: impl Into<String>,
895 current_value: impl Into<String>,
896 ) -> Result<Vec<String>, ServiceError> {
897 let completion = self
898 .complete_resource_argument(uri_template, argument_name, current_value, None)
899 .await?;
900 Ok(completion.values)
901 }
902}
903
904impl<S> RunningService<RoleClient, S>
905where
906 S: Service<RoleClient>,
907{
908 pub async fn call_tool_once(
910 &self,
911 params: CallToolRequestParams,
912 ) -> Result<CallToolResponse, ServiceError> {
913 self.peer.call_tool_once(params).await
914 }
915
916 pub async fn get_prompt_once(
918 &self,
919 params: GetPromptRequestParams,
920 ) -> Result<GetPromptResponse, ServiceError> {
921 self.peer.get_prompt_once(params).await
922 }
923
924 pub async fn read_resource_once(
926 &self,
927 params: ReadResourceRequestParams,
928 ) -> Result<ReadResourceResponse, ServiceError> {
929 self.peer.read_resource_once(params).await
930 }
931
932 pub async fn call_tool(
941 &self,
942 params: CallToolRequestParams,
943 ) -> Result<CallToolResult, ServiceError> {
944 self.call_tool_with_mrtr_max_rounds(params, DEFAULT_MRTR_MAX_ROUNDS)
945 .await
946 }
947
948 pub async fn call_tool_with_mrtr_max_rounds(
957 &self,
958 mut params: CallToolRequestParams,
959 max_rounds: usize,
960 ) -> Result<CallToolResult, ServiceError> {
961 let mut state_only_rounds = 0usize;
962 for _round in 0..max_rounds {
963 match self.peer.call_tool_once(params.clone()).await? {
964 CallToolResponse::Complete(result) => return Ok(result),
965 CallToolResponse::InputRequired(result) => {
966 let (input_responses, request_state) = self
967 .prepare_input_required_retry(result, &mut state_only_rounds)
968 .await?;
969 params.input_responses = input_responses;
970 params.request_state = request_state;
971 }
972 }
973 }
974 Err(ServiceError::InputRequiredRoundsExceeded { max_rounds })
975 }
976
977 pub async fn get_prompt(
986 &self,
987 params: GetPromptRequestParams,
988 ) -> Result<GetPromptResult, ServiceError> {
989 self.get_prompt_with_mrtr_max_rounds(params, DEFAULT_MRTR_MAX_ROUNDS)
990 .await
991 }
992
993 pub async fn get_prompt_with_mrtr_max_rounds(
1002 &self,
1003 mut params: GetPromptRequestParams,
1004 max_rounds: usize,
1005 ) -> Result<GetPromptResult, ServiceError> {
1006 let mut state_only_rounds = 0usize;
1007 for _round in 0..max_rounds {
1008 match self.peer.get_prompt_once(params.clone()).await? {
1009 GetPromptResponse::Complete(result) => return Ok(result),
1010 GetPromptResponse::InputRequired(result) => {
1011 let (input_responses, request_state) = self
1012 .prepare_input_required_retry(result, &mut state_only_rounds)
1013 .await?;
1014 params.input_responses = input_responses;
1015 params.request_state = request_state;
1016 }
1017 }
1018 }
1019 Err(ServiceError::InputRequiredRoundsExceeded { max_rounds })
1020 }
1021
1022 pub async fn read_resource(
1032 &self,
1033 params: ReadResourceRequestParams,
1034 ) -> Result<ReadResourceResult, ServiceError> {
1035 self.read_resource_with_mrtr_max_rounds(params, DEFAULT_MRTR_MAX_ROUNDS)
1036 .await
1037 }
1038
1039 pub async fn read_resource_with_mrtr_max_rounds(
1048 &self,
1049 mut params: ReadResourceRequestParams,
1050 max_rounds: usize,
1051 ) -> Result<ReadResourceResult, ServiceError> {
1052 let mut state_only_rounds = 0usize;
1053 for _round in 0..max_rounds {
1054 match self.peer.read_resource_once(params.clone()).await? {
1055 ReadResourceResponse::Complete(result) => return Ok(result),
1056 ReadResourceResponse::InputRequired(result) => {
1057 let (input_responses, request_state) = self
1058 .prepare_input_required_retry(result, &mut state_only_rounds)
1059 .await?;
1060 params.input_responses = input_responses;
1061 params.request_state = request_state;
1062 }
1063 }
1064 }
1065 Err(ServiceError::InputRequiredRoundsExceeded { max_rounds })
1066 }
1067
1068 async fn prepare_input_required_retry(
1069 &self,
1070 result: InputRequiredResult,
1071 state_only_rounds: &mut usize,
1072 ) -> Result<(Option<InputResponses>, Option<String>), ServiceError> {
1073 let had_input_requests = result
1074 .input_requests
1075 .as_ref()
1076 .is_some_and(|requests| !requests.is_empty());
1077 if !had_input_requests && result.request_state.is_none() {
1078 return Err(ServiceError::UnexpectedResponse);
1079 }
1080
1081 let responses = self
1082 .fulfill_input_requests(result.input_requests.unwrap_or_default())
1083 .await?;
1084 if had_input_requests {
1085 *state_only_rounds = 0;
1086 } else {
1087 Self::sleep_state_only_round(*state_only_rounds).await;
1088 *state_only_rounds += 1;
1089 }
1090
1091 Ok((
1092 (!responses.is_empty()).then_some(responses),
1093 result.request_state,
1094 ))
1095 }
1096
1097 async fn fulfill_input_requests(
1098 &self,
1099 requests: crate::model::InputRequests,
1100 ) -> Result<InputResponses, ServiceError> {
1101 let responses = futures::future::try_join_all(
1102 requests
1103 .into_iter()
1104 .map(|(key, request)| self.fulfill_input_request(key, request)),
1105 )
1106 .await?;
1107 Ok(responses.into_iter().collect())
1108 }
1109
1110 async fn fulfill_input_request(
1111 &self,
1112 key: String,
1113 request: InputRequest,
1114 ) -> Result<(String, serde_json::Value), ServiceError> {
1115 let response = match request {
1116 InputRequest::CreateMessage(request) => {
1117 let mut request = ServerRequest::CreateMessageRequest(request);
1118 let context = self.input_request_context(&key, &mut request);
1119 match self
1120 .service
1121 .handle_request(request, context)
1122 .await
1123 .map_err(ServiceError::McpError)?
1124 {
1125 ClientResult::CreateMessageResult(result) => {
1126 serde_json::to_value(result).map_err(Self::serde_to_service_error)?
1127 }
1128 _ => return Err(ServiceError::UnexpectedResponse),
1129 }
1130 }
1131 InputRequest::Elicitation(request) => {
1132 let mut request = ServerRequest::ElicitRequest(request);
1133 let context = self.input_request_context(&key, &mut request);
1134 match self
1135 .service
1136 .handle_request(request, context)
1137 .await
1138 .map_err(ServiceError::McpError)?
1139 {
1140 ClientResult::ElicitResult(result) => {
1141 serde_json::to_value(result).map_err(Self::serde_to_service_error)?
1142 }
1143 _ => return Err(ServiceError::UnexpectedResponse),
1144 }
1145 }
1146 InputRequest::ListRoots(request) => {
1147 let mut request = ServerRequest::ListRootsRequest(request);
1148 let context = self.input_request_context(&key, &mut request);
1149 match self
1150 .service
1151 .handle_request(request, context)
1152 .await
1153 .map_err(ServiceError::McpError)?
1154 {
1155 ClientResult::ListRootsResult(result) => {
1156 serde_json::to_value(result).map_err(Self::serde_to_service_error)?
1157 }
1158 _ => return Err(ServiceError::UnexpectedResponse),
1159 }
1160 }
1161 };
1162 Ok((key, response))
1163 }
1164
1165 fn input_request_context<T>(&self, key: &str, request: &mut T) -> RequestContext<RoleClient>
1166 where
1167 T: GetMeta<Metadata = crate::model::RequestMetaObject> + GetExtensions,
1168 {
1169 let mut meta = Default::default();
1170 let mut extensions = Default::default();
1171 std::mem::swap(&mut meta, request.get_meta_mut());
1172 std::mem::swap(&mut extensions, request.extensions_mut());
1173 RequestContext {
1174 ct: tokio_util::sync::CancellationToken::new(),
1175 id: NumberOrString::String(Arc::from(key)),
1176 peer: self.peer.clone(),
1177 meta,
1178 extensions,
1179 }
1180 }
1181
1182 async fn sleep_state_only_round(state_only_rounds: usize) {
1183 let millis = (50u64.saturating_mul(1_u64 << state_only_rounds.min(3))).min(250);
1184 tokio::time::sleep(Duration::from_millis(millis)).await;
1185 }
1186
1187 fn serde_to_service_error(error: serde_json::Error) -> ServiceError {
1188 ServiceError::McpError(ErrorData::internal_error(
1189 format!("failed to serialize MRTR input response: {error}"),
1190 None,
1191 ))
1192 }
1193}