synwire_mcp_adapters/
callbacks.rs1use std::sync::Arc;
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7use synwire_core::BoxFuture;
8use synwire_core::agents::error::AgentError;
9use synwire_core::mcp::elicitation::{ElicitationRequest, ElicitationResult, OnElicitation};
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
17#[non_exhaustive]
18pub enum McpLogLevel {
19 Debug,
21 Info,
23 Warning,
25 Error,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct McpLoggingMessage {
32 pub level: McpLogLevel,
34 pub logger: Option<String>,
36 pub data: Value,
38}
39
40pub trait OnMcpLogging: Send + Sync {
42 fn on_log(&self, server_name: &str, message: McpLoggingMessage);
44}
45
46#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct McpProgressNotification {
53 pub progress_token: String,
55 pub progress: u64,
57 pub total: Option<u64>,
59 pub message: Option<String>,
61}
62
63pub trait OnMcpProgress: Send + Sync {
65 fn on_progress(&self, server_name: &str, notification: McpProgressNotification);
67}
68
69#[derive(Debug, Default, Clone)]
75pub struct DiscardLogging;
76
77impl OnMcpLogging for DiscardLogging {
78 fn on_log(&self, _server_name: &str, _message: McpLoggingMessage) {}
79}
80
81#[derive(Debug, Default, Clone)]
83pub struct DiscardProgress;
84
85impl OnMcpProgress for DiscardProgress {
86 fn on_progress(&self, _server_name: &str, _notification: McpProgressNotification) {}
87}
88
89#[derive(Debug, Default, Clone)]
91pub struct TracingLogging;
92
93impl OnMcpLogging for TracingLogging {
94 fn on_log(&self, server_name: &str, message: McpLoggingMessage) {
95 match message.level {
96 McpLogLevel::Debug => {
97 tracing::debug!(server = %server_name, logger = ?message.logger, data = ?message.data, "MCP log");
98 }
99 McpLogLevel::Info => {
100 tracing::info!(server = %server_name, logger = ?message.logger, data = ?message.data, "MCP log");
101 }
102 McpLogLevel::Warning => {
103 tracing::warn!(server = %server_name, logger = ?message.logger, data = ?message.data, "MCP log");
104 }
105 McpLogLevel::Error => {
106 tracing::error!(server = %server_name, logger = ?message.logger, data = ?message.data, "MCP log");
107 }
108 }
109 }
110}
111
112pub struct McpCallbacks {
121 pub logging: Arc<dyn OnMcpLogging>,
123 pub progress: Arc<dyn OnMcpProgress>,
125 pub elicitation: Arc<dyn OnElicitation>,
127}
128
129impl std::fmt::Debug for McpCallbacks {
130 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
131 f.debug_struct("McpCallbacks")
132 .field("logging", &"<handler>")
133 .field("progress", &"<handler>")
134 .field("elicitation", &"<handler>")
135 .finish()
136 }
137}
138
139impl Default for McpCallbacks {
140 fn default() -> Self {
141 Self {
142 logging: Arc::new(DiscardLogging),
143 progress: Arc::new(DiscardProgress),
144 elicitation: Arc::new(CancelAllElicitationsAdapter),
145 }
146 }
147}
148
149impl McpCallbacks {
150 #[must_use]
152 pub fn new() -> Self {
153 Self::default()
154 }
155
156 #[must_use]
158 pub fn with_logging(mut self, logging: Arc<dyn OnMcpLogging>) -> Self {
159 self.logging = logging;
160 self
161 }
162
163 #[must_use]
165 pub fn with_progress(mut self, progress: Arc<dyn OnMcpProgress>) -> Self {
166 self.progress = progress;
167 self
168 }
169
170 #[must_use]
172 pub fn with_elicitation(mut self, elicitation: Arc<dyn OnElicitation>) -> Self {
173 self.elicitation = elicitation;
174 self
175 }
176}
177
178#[derive(Debug)]
184struct CancelAllElicitationsAdapter;
185
186impl OnElicitation for CancelAllElicitationsAdapter {
187 fn elicit(
188 &self,
189 request: ElicitationRequest,
190 ) -> BoxFuture<'_, Result<ElicitationResult, AgentError>> {
191 Box::pin(async move {
192 Ok(ElicitationResult::Cancelled {
193 request_id: request.request_id,
194 })
195 })
196 }
197}