Skip to content

Commit

Permalink
feat: add structured logging support with severity levels
Browse files Browse the repository at this point in the history
- 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 #35
  • Loading branch information
tzolov committed Dec 31, 2024
1 parent a5394ff commit 8665934
Show file tree
Hide file tree
Showing 16 changed files with 861 additions and 228 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ The project consists of two main modules:

Java implementation of the Model Context Protocol specification. It includes:
- 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
- Standard MCP operations support (tool discovery, resource management, prompt handling). Support for request and notificaiotn handling.
- Standard MCP operations support (tool discovery, resource management, prompt handling, structured logging). Support for request and notification handling.
- [Stdio](https://spec.modelcontextprotocol.io/specification/basic/transports/#stdio) and [SSE](https://spec.modelcontextprotocol.io/specification/basic/transports/#http-with-sse) transport implementations.
- [Find more](./mcp/README.md).

Expand Down
60 changes: 56 additions & 4 deletions docs/ref-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,6 @@ McpServer.using(transport)
.sync();
```

### Implementation Notes

- The server factory uses a builder pattern for configuration
- Default server info is "mcp-server" version "1.0.0" if not specified
- Tool handlers must be thread-safe as they may be called concurrently
- The synchronous server is implemented as a wrapper around the asynchronous server
- Resource and prompt providers use cursor-based pagination
Expand All @@ -160,3 +156,59 @@ Tool handlers implement this interface to define:
- Tool name and description
- Input schema for validation
- Execution logic in the call method

### Logging Capabilities

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.

#### Enabling Logging

```java
McpServer.using(transport)
.serverInfo("my-server", "1.0.0")
.capabilities(ServerCapabilities.builder().logging().build())
.sync(); // or .async()
```

#### Logging Levels

The server supports the following logging levels:
- TRACE
- DEBUG
- INFO
- WARN
- ERROR
- FATAL

#### Sending Log Messages

For synchronous servers:
```java
LoggingMessageNotification notification = McpSchema.LoggingMessageNotification.builder()
.level(McpSchema.LoggingLevel.INFO)
.logger("my-logger")
.data("Log message")
.build();

mcpSyncServer.loggingNotification(notification);
```

For asynchronous servers:
```java
LoggingMessageNotification notification = McpSchema.LoggingMessageNotification.builder()
.level(McpSchema.LoggingLevel.INFO)
.logger("my-logger")
.data("Log message")
.build();

mcpAsyncServer.loggingNotification(notification)
.subscribe();
```

- Logging works even if the logging capability is not enabled
- Null notifications are rejected with a McpError
- Log messages include:
- Level: The severity level of the message
- Logger: The name of the logger (typically identifies the source)
- Data: The actual log message content
- The server implementation is transport-agnostic, allowing different transport mechanisms to handle the log messages
89 changes: 86 additions & 3 deletions mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,63 @@ McpTransport transport = new SseClientTransport(webClientBuilder);
```


### Client Capabilities

The client can be configured with various capabilities:

```java
var capabilities = ClientCapabilities.builder()
.roots(true) // Enable filesystem roots support with list changes notifications
.sampling() // Enable LLM sampling support
.build();
```

#### Roots Support

Roots define the boundaries of where servers can operate within the filesystem:

```java
// Add a root dynamically
client.addRoot(new Root("file:///path", "description"));

// Remove a root
client.removeRoot("file:///path");

// Notify server of roots changes
client.rootsListChangedNotification();
```

The roots capability allows servers to:
- Request the list of accessible filesystem roots
- Receive notifications when the root list changes
- Understand which directories and files they have access to

#### Sampling Support

Sampling enables servers to request LLM interactions ("completions" or "generations") through the client:

```java
// Configure sampling handler
Function<CreateMessageRequest, CreateMessageResult> samplingHandler = request -> {
// Sampling implementation that interfaces with LLM
return new CreateMessageResult(response);
};

// Create client with sampling support
var client = McpClient.using(transport)
.capabilities(ClientCapabilities.builder()
.sampling()
.build())
.samplingHandler(samplingHandler)
.build();
```

This capability allows:
- Servers to leverage AI capabilities without requiring API keys
- Clients to maintain control over model access and permissions
- Support for both text and image-based interactions
- Optional inclusion of MCP server context in prompts

## Server Usage Examples

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

### Tool Registration
#### Logging Support

The server provides structured logging capabilities that allow sending log messages to clients with different severity levels:

```java
// Send a log message to clients
server.loggingNotification(LoggingMessageNotification.builder()
.level(LoggingLevel.INFO)
.logger("custom-logger")
.data("Custom log message")
.build());
```

Supported logging levels (in order of increasing severity):
- DEBUG (0)
- INFO (1)
- NOTICE (2)
- WARNING (3)
- ERROR (4)
- CRITICAL (5)
- ALERT (6)
- EMERGENCY (7)

Clients can control the minimum logging level they receive through the `mcpClient.setLoggingLevel(level)` request. Messages below the set level will be filtered out.

#### Tool Registration

```java
var toolRegistration = new ToolRegistration(
Expand All @@ -326,7 +409,7 @@ var toolRegistration = new ToolRegistration(
);
```

### Resource Registration
#### Resource Registration

```java
var resourceRegistration = new ResourceRegistration(
Expand All @@ -338,7 +421,7 @@ var resourceRegistration = new ResourceRegistration(
);
```

### Prompt Registration
#### Prompt Registration

```java
var promptRegistration = new PromptRegistration(
Expand Down
Loading

0 comments on commit 8665934

Please sign in to comment.