Skip to content

Commit 8665934

Browse files
committed
feat: add structured logging support with severity levels
- Add client and server-side logging capabilities with configurable severity levels - Implement logging message notifications with DEBUG to EMERGENCY levels - Add logging consumers for client-side log handling - Update documentation with logging examples and configuration - Add comprehensive tests for logging functionality - Fix typo in README.md (notificaiotn -> notification) - Centralize MCP method names as constants - Move all JSON-RPC method names to McpSchema class as static constants - Replace hardcoded method strings with constant references in McpAsyncClient and McpAsyncServer - Update test cases to use new method name constants Resolves modelcontextprotocol#35
1 parent a5394ff commit 8665934

File tree

16 files changed

+861
-228
lines changed

16 files changed

+861
-228
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ The project consists of two main modules:
1616

1717
Java implementation of the Model Context Protocol specification. It includes:
1818
- Synchronous and asynchronous [MCP Client](https://github.com/spring-projects-experimental/spring-ai-mcp/blob/main/mcp/README.md#client-usage-examples) and [MCP Server](https://github.com/spring-projects-experimental/spring-ai-mcp/blob/main/mcp/README.md#server-usage-examples) implementations
19-
- Standard MCP operations support (tool discovery, resource management, prompt handling). Support for request and notificaiotn handling.
19+
- Standard MCP operations support (tool discovery, resource management, prompt handling, structured logging). Support for request and notification handling.
2020
- [Stdio](https://spec.modelcontextprotocol.io/specification/basic/transports/#stdio) and [SSE](https://spec.modelcontextprotocol.io/specification/basic/transports/#http-with-sse) transport implementations.
2121
- [Find more](./mcp/README.md).
2222

docs/ref-server.md

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,10 +136,6 @@ McpServer.using(transport)
136136
.sync();
137137
```
138138

139-
### Implementation Notes
140-
141-
- The server factory uses a builder pattern for configuration
142-
- Default server info is "mcp-server" version "1.0.0" if not specified
143139
- Tool handlers must be thread-safe as they may be called concurrently
144140
- The synchronous server is implemented as a wrapper around the asynchronous server
145141
- Resource and prompt providers use cursor-based pagination
@@ -160,3 +156,59 @@ Tool handlers implement this interface to define:
160156
- Tool name and description
161157
- Input schema for validation
162158
- Execution logic in the call method
159+
160+
### Logging Capabilities
161+
162+
The MCP Server supports logging functionality that allows sending log messages with different severity levels to the Client. This feature can be enabled through server capabilities configuration.
163+
164+
#### Enabling Logging
165+
166+
```java
167+
McpServer.using(transport)
168+
.serverInfo("my-server", "1.0.0")
169+
.capabilities(ServerCapabilities.builder().logging().build())
170+
.sync(); // or .async()
171+
```
172+
173+
#### Logging Levels
174+
175+
The server supports the following logging levels:
176+
- TRACE
177+
- DEBUG
178+
- INFO
179+
- WARN
180+
- ERROR
181+
- FATAL
182+
183+
#### Sending Log Messages
184+
185+
For synchronous servers:
186+
```java
187+
LoggingMessageNotification notification = McpSchema.LoggingMessageNotification.builder()
188+
.level(McpSchema.LoggingLevel.INFO)
189+
.logger("my-logger")
190+
.data("Log message")
191+
.build();
192+
193+
mcpSyncServer.loggingNotification(notification);
194+
```
195+
196+
For asynchronous servers:
197+
```java
198+
LoggingMessageNotification notification = McpSchema.LoggingMessageNotification.builder()
199+
.level(McpSchema.LoggingLevel.INFO)
200+
.logger("my-logger")
201+
.data("Log message")
202+
.build();
203+
204+
mcpAsyncServer.loggingNotification(notification)
205+
.subscribe();
206+
```
207+
208+
- Logging works even if the logging capability is not enabled
209+
- Null notifications are rejected with a McpError
210+
- Log messages include:
211+
- Level: The severity level of the message
212+
- Logger: The name of the logger (typically identifies the source)
213+
- Data: The actual log message content
214+
- The server implementation is transport-agnostic, allowing different transport mechanisms to handle the log messages

mcp/README.md

Lines changed: 86 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,63 @@ McpTransport transport = new SseClientTransport(webClientBuilder);
186186
```
187187

188188

189+
### Client Capabilities
190+
191+
The client can be configured with various capabilities:
192+
193+
```java
194+
var capabilities = ClientCapabilities.builder()
195+
.roots(true) // Enable filesystem roots support with list changes notifications
196+
.sampling() // Enable LLM sampling support
197+
.build();
198+
```
199+
200+
#### Roots Support
201+
202+
Roots define the boundaries of where servers can operate within the filesystem:
203+
204+
```java
205+
// Add a root dynamically
206+
client.addRoot(new Root("file:///path", "description"));
207+
208+
// Remove a root
209+
client.removeRoot("file:///path");
210+
211+
// Notify server of roots changes
212+
client.rootsListChangedNotification();
213+
```
214+
215+
The roots capability allows servers to:
216+
- Request the list of accessible filesystem roots
217+
- Receive notifications when the root list changes
218+
- Understand which directories and files they have access to
219+
220+
#### Sampling Support
221+
222+
Sampling enables servers to request LLM interactions ("completions" or "generations") through the client:
223+
224+
```java
225+
// Configure sampling handler
226+
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
227+
// Sampling implementation that interfaces with LLM
228+
return new CreateMessageResult(response);
229+
};
230+
231+
// Create client with sampling support
232+
var client = McpClient.using(transport)
233+
.capabilities(ClientCapabilities.builder()
234+
.sampling()
235+
.build())
236+
.samplingHandler(samplingHandler)
237+
.build();
238+
```
239+
240+
This capability allows:
241+
- Servers to leverage AI capabilities without requiring API keys
242+
- Clients to maintain control over model access and permissions
243+
- Support for both text and image-based interactions
244+
- Optional inclusion of MCP server context in prompts
245+
189246
## Server Usage Examples
190247

191248
### MCP Server (Sync API)
@@ -307,10 +364,36 @@ var capabilities = ServerCapabilities.builder()
307364
.resources(false, true) // Resource support with list changes notifications
308365
.tools(true) // Tool support with list changes notifications
309366
.prompts(true) // Prompt support with list changes notifications
367+
.logging() // Enable logging support (enabled by default with loging level INFO)
310368
.build();
311369
```
312370

313-
### Tool Registration
371+
#### Logging Support
372+
373+
The server provides structured logging capabilities that allow sending log messages to clients with different severity levels:
374+
375+
```java
376+
// Send a log message to clients
377+
server.loggingNotification(LoggingMessageNotification.builder()
378+
.level(LoggingLevel.INFO)
379+
.logger("custom-logger")
380+
.data("Custom log message")
381+
.build());
382+
```
383+
384+
Supported logging levels (in order of increasing severity):
385+
- DEBUG (0)
386+
- INFO (1)
387+
- NOTICE (2)
388+
- WARNING (3)
389+
- ERROR (4)
390+
- CRITICAL (5)
391+
- ALERT (6)
392+
- EMERGENCY (7)
393+
394+
Clients can control the minimum logging level they receive through the `mcpClient.setLoggingLevel(level)` request. Messages below the set level will be filtered out.
395+
396+
#### Tool Registration
314397

315398
```java
316399
var toolRegistration = new ToolRegistration(
@@ -326,7 +409,7 @@ var toolRegistration = new ToolRegistration(
326409
);
327410
```
328411

329-
### Resource Registration
412+
#### Resource Registration
330413

331414
```java
332415
var resourceRegistration = new ResourceRegistration(
@@ -338,7 +421,7 @@ var resourceRegistration = new ResourceRegistration(
338421
);
339422
```
340423

341-
### Prompt Registration
424+
#### Prompt Registration
342425

343426
```java
344427
var promptRegistration = new PromptRegistration(

0 commit comments

Comments
 (0)