Skip to content

Commit d92c1e0

Browse files
authored
Merge branch 'main' into claude/mcpmux-branding-auth-pages-mlfih
2 parents 10dd6d1 + 0587741 commit d92c1e0

9 files changed

Lines changed: 202 additions & 143 deletions

File tree

Cargo.lock

Lines changed: 5 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/desktop/src/components/ServerLogViewer.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const SOURCE_COLORS: Record<string, string> = {
2929
'sse-event': 'text-indigo-400',
3030
connection: 'text-green-300',
3131
oauth: 'text-pink-400',
32+
server: 'text-cyan-400',
3233
};
3334

3435
export function ServerLogViewer({ serverId, serverName, onClose }: ServerLogViewerProps) {

crates/mcpmux-core/src/domain/server_log.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ pub enum LogSource {
101101
Connection,
102102
/// OAuth flow
103103
OAuth,
104+
/// MCP protocol logging notifications (notifications/message from server)
105+
Server,
104106
}
105107

106108
impl LogSource {
@@ -114,6 +116,7 @@ impl LogSource {
114116
Self::SseEvent => "sse-event",
115117
Self::Connection => "connection",
116118
Self::OAuth => "oauth",
119+
Self::Server => "server",
117120
}
118121
}
119122
}

crates/mcpmux-gateway/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ zeroize = "1.8"
5252
which = "7.0"
5353
open = "5.3"
5454
dirs = "5.0"
55-
os_pipe = { workspace = true }
5655

5756
# MCP SDK
5857
rmcp.workspace = true

crates/mcpmux-gateway/src/pool/instance.rs

Lines changed: 70 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
use std::collections::HashMap;
77
use std::time::Instant;
88

9-
use mcpmux_core::DomainEvent;
9+
use std::sync::Arc;
10+
11+
use mcpmux_core::{DomainEvent, LogLevel, LogSource, ServerLog, ServerLogManager};
1012
use parking_lot::RwLock;
11-
use rmcp::model::{ClientCapabilities, ClientInfo, Implementation};
13+
use rmcp::model::{ClientCapabilities, ClientInfo, Implementation, LoggingLevel};
1214
use rmcp::service::{NotificationContext, RunningService};
1315
use rmcp::RoleClient;
1416
use serde::{Deserialize, Serialize};
@@ -22,19 +24,31 @@ pub use mcpmux_core::TransportType;
2224
pub type McpClient = RunningService<RoleClient, McpClientHandler>;
2325

2426
/// Client handler for MCP connections
25-
#[derive(Clone, Debug)]
27+
#[derive(Clone)]
2628
pub struct McpClientHandler {
2729
info: ClientInfo,
2830
server_id: String,
2931
space_id: Uuid,
3032
event_tx: Option<tokio::sync::broadcast::Sender<DomainEvent>>,
33+
log_manager: Option<Arc<ServerLogManager>>,
34+
}
35+
36+
impl std::fmt::Debug for McpClientHandler {
37+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38+
f.debug_struct("McpClientHandler")
39+
.field("server_id", &self.server_id)
40+
.field("space_id", &self.space_id)
41+
.field("log_manager", &self.log_manager.is_some())
42+
.finish()
43+
}
3144
}
3245

3346
impl McpClientHandler {
3447
pub fn new(
3548
server_id: &str,
3649
space_id: Uuid,
3750
event_tx: Option<tokio::sync::broadcast::Sender<DomainEvent>>,
51+
log_manager: Option<Arc<ServerLogManager>>,
3852
) -> Self {
3953
Self {
4054
info: ClientInfo {
@@ -53,6 +67,20 @@ impl McpClientHandler {
5367
server_id: server_id.to_string(),
5468
space_id,
5569
event_tx,
70+
log_manager,
71+
}
72+
}
73+
74+
/// Convert MCP protocol LoggingLevel to our internal LogLevel
75+
fn convert_logging_level(level: &LoggingLevel) -> LogLevel {
76+
match level {
77+
LoggingLevel::Debug => LogLevel::Debug,
78+
LoggingLevel::Info | LoggingLevel::Notice => LogLevel::Info,
79+
LoggingLevel::Warning => LogLevel::Warn,
80+
LoggingLevel::Error
81+
| LoggingLevel::Critical
82+
| LoggingLevel::Alert
83+
| LoggingLevel::Emergency => LogLevel::Error,
5684
}
5785
}
5886
}
@@ -191,6 +219,45 @@ impl rmcp::ClientHandler for McpClientHandler {
191219
}
192220
}
193221
}
222+
223+
fn on_logging_message(
224+
&self,
225+
params: rmcp::model::LoggingMessageNotificationParam,
226+
_context: NotificationContext<RoleClient>,
227+
) -> impl std::future::Future<Output = ()> + Send + '_ {
228+
let server_id = self.server_id.clone();
229+
let space_id = self.space_id;
230+
let log_manager = self.log_manager.clone();
231+
async move {
232+
// Format the log message from the MCP data field
233+
let message = match &params.data {
234+
serde_json::Value::String(s) => s.clone(),
235+
other => other.to_string(),
236+
};
237+
238+
let level = Self::convert_logging_level(&params.level);
239+
240+
debug!(
241+
server_id = %server_id,
242+
space_id = %space_id,
243+
level = ?params.level,
244+
logger = ?params.logger,
245+
"[McpClientHandler] Server log: {}",
246+
message
247+
);
248+
249+
if let Some(log_manager) = &log_manager {
250+
let mut log = ServerLog::new(level, LogSource::Server, &message);
251+
// Include logger name in metadata if present
252+
if let Some(logger) = &params.logger {
253+
log = log.with_metadata(serde_json::json!({ "logger": logger }));
254+
}
255+
let _ = log_manager
256+
.append(&space_id.to_string(), &server_id, log)
257+
.await;
258+
}
259+
}
260+
}
194261
}
195262

196263
/// Instance key - identifies a server instance for debugging/logging.

crates/mcpmux-gateway/src/pool/transport/http.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,12 @@ impl HttpTransport {
243243
let transport_config = StreamableHttpClientTransportConfig::with_uri(self.url.as_str());
244244
let transport = StreamableHttpClientTransport::with_client(auth_client, transport_config);
245245

246-
let client_handler =
247-
create_client_handler(&self.server_id, self.space_id, self.event_tx.clone());
246+
let client_handler = create_client_handler(
247+
&self.server_id,
248+
self.space_id,
249+
self.event_tx.clone(),
250+
self.log_manager.clone(),
251+
);
248252

249253
let connect_future = client_handler.serve(transport);
250254
match tokio::time::timeout(self.connect_timeout, connect_future).await {
@@ -363,8 +367,12 @@ impl HttpTransport {
363367
let transport_config = StreamableHttpClientTransportConfig::with_uri(self.url.as_str());
364368
let transport = StreamableHttpClientTransport::with_client(client, transport_config);
365369

366-
let client_handler =
367-
create_client_handler(&self.server_id, self.space_id, self.event_tx.clone());
370+
let client_handler = create_client_handler(
371+
&self.server_id,
372+
self.space_id,
373+
self.event_tx.clone(),
374+
self.log_manager.clone(),
375+
);
368376

369377
let connect_future = client_handler.serve(transport);
370378
match tokio::time::timeout(self.connect_timeout, connect_future).await {
@@ -430,8 +438,12 @@ impl HttpTransport {
430438
.await;
431439

432440
let transport = StreamableHttpClientTransport::from_uri(self.url.as_str());
433-
let client_handler =
434-
create_client_handler(&self.server_id, self.space_id, self.event_tx.clone());
441+
let client_handler = create_client_handler(
442+
&self.server_id,
443+
self.space_id,
444+
self.event_tx.clone(),
445+
self.log_manager.clone(),
446+
);
435447

436448
let connect_future = client_handler.serve(transport);
437449
match tokio::time::timeout(self.connect_timeout, connect_future).await {

crates/mcpmux-gateway/src/pool/transport/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,7 @@ pub fn create_client_handler(
170170
server_id: &str,
171171
space_id: uuid::Uuid,
172172
event_tx: Option<tokio::sync::broadcast::Sender<mcpmux_core::DomainEvent>>,
173+
log_manager: Option<Arc<ServerLogManager>>,
173174
) -> McpClientHandler {
174-
McpClientHandler::new(server_id, space_id, event_tx)
175+
McpClientHandler::new(server_id, space_id, event_tx, log_manager)
175176
}

0 commit comments

Comments
 (0)