Skip to content

Commit 3650446

Browse files
committed
feat: Introduce Slf4jLoggingConsumer
1 parent 713ee1a commit 3650446

File tree

1 file changed

+58
-0
lines changed

1 file changed

+58
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2025 the original author or authors.
3+
*/
4+
package io.modelcontextprotocol.client;
5+
6+
import java.util.function.Consumer;
7+
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
import org.slf4j.event.Level;
11+
12+
import io.modelcontextprotocol.client.McpClient.SyncSpec;
13+
import io.modelcontextprotocol.spec.McpSchema;
14+
import io.modelcontextprotocol.spec.McpSchema.LoggingMessageNotification;
15+
16+
/**
17+
* MCP Client-side consumer which logs received messages from MCP Servers using SLF4J.
18+
*
19+
* <p>
20+
* Use this for {@link SyncSpec#loggingConsumer(Consumer)} to log received MCP messages.
21+
*
22+
* @author <a href="http://www.vorburger.ch">Michael Vorburger.ch</a>
23+
*/
24+
public class Slf4jLoggingConsumer implements Consumer<McpSchema.LoggingMessageNotification> {
25+
26+
// This class originated in
27+
// https://github.com/enola-dev/enola/blob/ffc004666ea7f71357562ef12464d2b9fdbf9dbd/java/dev/enola/ai/mcp/McpServer.java#L29
28+
// where it was used for https://docs.enola.dev/concepts/mcp/.
29+
//
30+
// It then found its way into Google's Agent Development Kit (ADK) in
31+
// https://github.com/google/adk-java/pull/370. It's now been moved here to be useful
32+
// to others.
33+
34+
@Override
35+
public void accept(LoggingMessageNotification notif) {
36+
Logger log = LoggerFactory.getLogger(notif.logger());
37+
if (notif.meta().isEmpty()) {
38+
// If no meta, then just log the data as a message
39+
log.atLevel(convert(notif.level())).log(notif.data());
40+
}
41+
else {
42+
// If there is meta, then log it as a structured log message
43+
var builder = log.atLevel(convert(notif.level())).setMessage(notif.data());
44+
notif.meta().forEach((key, value) -> builder.addKeyValue(key, value));
45+
builder.log();
46+
}
47+
}
48+
49+
private Level convert(McpSchema.LoggingLevel level) {
50+
return switch (level) {
51+
case DEBUG -> Level.DEBUG;
52+
case INFO, NOTICE -> Level.INFO;
53+
case WARNING -> Level.WARN;
54+
case ERROR, CRITICAL, ALERT, EMERGENCY -> Level.ERROR;
55+
};
56+
}
57+
58+
}

0 commit comments

Comments
 (0)