aether-mcp-utils 0.7.14

MCP client and server utilities for the Aether AI agent framework
Documentation
use super::{Elicitation, ElicitationSink};
use aether_auth::OAuthCredentialStorage;
use rmcp::model::{ClientCapabilities, ClientConfig, Implementation};
use std::sync::Arc;
use tokio::sync::mpsc;

#[derive(Clone)]
pub struct ClientOptions {
    pub(super) implementation: Implementation,
    pub(super) elicitation: Option<ElicitationSink>,
    pub(super) oauth_store: Option<Arc<dyn OAuthCredentialStorage>>,
    tasks: bool,
}

impl Default for ClientOptions {
    fn default() -> Self {
        Self {
            implementation: Implementation::new(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")),
            elicitation: None,
            oauth_store: None,
            tasks: true,
        }
    }
}

impl ClientOptions {
    pub fn implementation(mut self, implementation: Implementation) -> Self {
        self.implementation = implementation;
        self
    }

    pub fn elicitation(mut self, sink: ElicitationSink) -> Self {
        self.elicitation = Some(sink);
        self
    }

    pub fn oauth_store(mut self, store: Arc<dyn OAuthCredentialStorage>) -> Self {
        self.oauth_store = Some(store);
        self
    }

    #[cfg(any(test, feature = "testing"))]
    pub fn without_tasks(mut self) -> Self {
        self.tasks = false;
        self
    }

    pub(super) fn client_config(&self) -> ClientConfig {
        let mut capabilities = if self.tasks {
            ClientCapabilities::builder().enable_tasks().build()
        } else {
            ClientCapabilities::default()
        };
        capabilities.elicitation = self
            .elicitation
            .as_ref()
            .map(|sink| sink.capability.clone())
            .filter(|capability| capability.form.is_some() || capability.url.is_some());
        ClientConfig::new(capabilities, self.implementation.clone())
    }

    pub(super) fn elicitations(&self) -> Option<&mpsc::Sender<Elicitation>> {
        self.elicitation.as_ref().map(|sink| &sink.events)
    }

    pub(super) fn oauth_prompts(&self) -> Option<&mpsc::Sender<Elicitation>> {
        self.elicitation.as_ref().filter(|sink| sink.capability.url.is_some()).map(|sink| &sink.events)
    }
}