use std::sync::atomic::{AtomicU8, Ordering};
use rmcp::Peer;
use rmcp::RoleServer;
use rmcp::model::{LoggingLevel, LoggingMessageNotificationParam, ProgressNotificationParam};
use serde_json::Value;
pub(super) fn level_ordinal(level: LoggingLevel) -> u8 {
match level {
LoggingLevel::Debug => 0,
LoggingLevel::Info => 1,
LoggingLevel::Notice => 2,
LoggingLevel::Warning => 3,
LoggingLevel::Error => 4,
LoggingLevel::Critical => 5,
LoggingLevel::Alert => 6,
LoggingLevel::Emergency => 7,
}
}
pub(super) const DEFAULT_LOG_ORDINAL: u8 = 1;
pub(super) fn should_log(threshold: &AtomicU8, level: LoggingLevel) -> bool {
level_ordinal(level) >= threshold.load(Ordering::Relaxed)
}
pub(super) async fn emit_log(
peer: &Peer<RoleServer>,
threshold: &AtomicU8,
level: LoggingLevel,
logger: &'static str,
data: Value,
) {
if !should_log(threshold, level) {
return;
}
if let Err(error) = peer
.notify_logging_message(LoggingMessageNotificationParam {
level,
logger: Some(logger.to_string()),
data,
})
.await
{
tracing::debug!(?error, "logging notification dropped");
}
}
pub(super) async fn emit_progress(
peer: &Peer<RoleServer>,
token: rmcp::model::ProgressToken,
progress: f64,
total: Option<f64>,
message: impl Into<String>,
) {
if let Err(error) = peer
.notify_progress(ProgressNotificationParam {
progress_token: token,
progress,
total,
message: Some(message.into()),
})
.await
{
tracing::debug!(?error, "progress notification dropped");
}
}