Skip to main content

mcp_utils/client/
options.rs

1use super::{Elicitation, ElicitationSink};
2use aether_auth::OAuthCredentialStorage;
3use rmcp::model::{ClientCapabilities, ClientConfig, Implementation};
4use std::sync::Arc;
5use tokio::sync::mpsc;
6
7#[derive(Clone)]
8pub struct ClientOptions {
9    pub(super) implementation: Implementation,
10    pub(super) elicitation: Option<ElicitationSink>,
11    pub(super) oauth_store: Option<Arc<dyn OAuthCredentialStorage>>,
12    tasks: bool,
13}
14
15impl Default for ClientOptions {
16    fn default() -> Self {
17        Self {
18            implementation: Implementation::new(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")),
19            elicitation: None,
20            oauth_store: None,
21            tasks: true,
22        }
23    }
24}
25
26impl ClientOptions {
27    pub fn implementation(mut self, implementation: Implementation) -> Self {
28        self.implementation = implementation;
29        self
30    }
31
32    pub fn elicitation(mut self, sink: ElicitationSink) -> Self {
33        self.elicitation = Some(sink);
34        self
35    }
36
37    pub fn oauth_store(mut self, store: Arc<dyn OAuthCredentialStorage>) -> Self {
38        self.oauth_store = Some(store);
39        self
40    }
41
42    #[cfg(any(test, feature = "testing"))]
43    pub fn without_tasks(mut self) -> Self {
44        self.tasks = false;
45        self
46    }
47
48    pub(super) fn client_config(&self) -> ClientConfig {
49        let mut capabilities = if self.tasks {
50            ClientCapabilities::builder().enable_tasks().build()
51        } else {
52            ClientCapabilities::default()
53        };
54        capabilities.elicitation = self
55            .elicitation
56            .as_ref()
57            .map(|sink| sink.capability.clone())
58            .filter(|capability| capability.form.is_some() || capability.url.is_some());
59        ClientConfig::new(capabilities, self.implementation.clone())
60    }
61
62    pub(super) fn elicitations(&self) -> Option<&mpsc::Sender<Elicitation>> {
63        self.elicitation.as_ref().map(|sink| &sink.events)
64    }
65
66    pub(super) fn oauth_prompts(&self) -> Option<&mpsc::Sender<Elicitation>> {
67        self.elicitation.as_ref().filter(|sink| sink.capability.url.is_some()).map(|sink| &sink.events)
68    }
69}