Codex Handbook
rmcp-client/src/logging_client_handler.rs 136 lines
use std::sync::Arc;use rmcp::ClientHandler;use rmcp::RoleClient;use rmcp::model::CancelledNotificationParam;use rmcp::model::ClientInfo;use rmcp::model::CreateElicitationRequestParams;use rmcp::model::CreateElicitationResult;use rmcp::model::LoggingLevel;use rmcp::model::LoggingMessageNotificationParam;use rmcp::model::ProgressNotificationParam;use rmcp::model::ResourceUpdatedNotificationParam;use rmcp::service::NotificationContext;use rmcp::service::RequestContext;use tracing::debug;use tracing::error;use tracing::info;use tracing::warn;use crate::rmcp_client::SendElicitation;#[derive(Clone)]pub(crate) struct LoggingClientHandler {    client_info: ClientInfo,    send_elicitation: Arc<SendElicitation>,}impl LoggingClientHandler {    pub(crate) fn new(client_info: ClientInfo, send_elicitation: SendElicitation) -> Self {        Self {            client_info,            send_elicitation: Arc::new(send_elicitation),        }    }}impl ClientHandler for LoggingClientHandler {    async fn create_elicitation(        &self,        request: CreateElicitationRequestParams,        context: RequestContext<RoleClient>,    ) -> Result<CreateElicitationResult, rmcp::ErrorData> {        (self.send_elicitation)(context.id, request)            .await            .map(Into::into)            .map_err(|err| rmcp::ErrorData::internal_error(err.to_string(), None))    }    async fn on_cancelled(        &self,        params: CancelledNotificationParam,        _context: NotificationContext<RoleClient>,    ) {        info!(            "MCP server cancelled request (request_id: {}, reason: {:?})",            params.request_id, params.reason        );    }    async fn on_progress(        &self,        params: ProgressNotificationParam,        _context: NotificationContext<RoleClient>,    ) {        info!(            "MCP server progress notification (token: {:?}, progress: {}, total: {:?}, message: {:?})",            params.progress_token, params.progress, params.total, params.message        );    }    async fn on_resource_updated(        &self,        params: ResourceUpdatedNotificationParam,        _context: NotificationContext<RoleClient>,    ) {        info!("MCP server resource updated (uri: {})", params.uri);    }    async fn on_resource_list_changed(&self, _context: NotificationContext<RoleClient>) {        info!("MCP server resource list changed");    }    async fn on_tool_list_changed(&self, _context: NotificationContext<RoleClient>) {        info!("MCP server tool list changed");    }    async fn on_prompt_list_changed(&self, _context: NotificationContext<RoleClient>) {        info!("MCP server prompt list changed");    }    fn get_info(&self) -> ClientInfo {        self.client_info.clone()    }    async fn on_logging_message(        &self,        params: LoggingMessageNotificationParam,        _context: NotificationContext<RoleClient>,    ) {        let LoggingMessageNotificationParam {            level,            logger,            data,        } = params;        let logger = logger.as_deref();        match level {            LoggingLevel::Emergency            | LoggingLevel::Alert            | LoggingLevel::Critical            | LoggingLevel::Error => {                error!(                    "MCP server log message (level: {:?}, logger: {:?}, data: {})",                    level, logger, data                );            }            LoggingLevel::Warning => {                warn!(                    "MCP server log message (level: {:?}, logger: {:?}, data: {})",                    level, logger, data                );            }            LoggingLevel::Notice | LoggingLevel::Info => {                info!(                    "MCP server log message (level: {:?}, logger: {:?}, data: {})",                    level, logger, data                );            }            LoggingLevel::Debug => {                debug!(                    "MCP server log message (level: {:?}, logger: {:?}, data: {})",                    level, logger, data                );            }        }    }}