Skip to content

Commit

Permalink
Enhance DefaultMcpSession with request/response handling
Browse files Browse the repository at this point in the history
- Add comprehensive documentation for MCP session components in MCP-SESSION.md
- Add logging and error handling in McpAsyncClient
- Update test configurations and dependencies
- Add reactor-netty-http and spring-context test dependencies

Resolves #6
  • Loading branch information
tzolov committed Dec 17, 2024
1 parent 0ebb38c commit 716d1a0
Show file tree
Hide file tree
Showing 8 changed files with 535 additions and 32 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
<slf4j-api.version>2.0.16</slf4j-api.version>
<logback.version>1.5.12</logback.version>
<jackson.version>2.18.2</jackson.version>
<springframework.version>6.1.13</springframework.version>
<springframework.version>6.2.1</springframework.version>

<!-- plugin versions -->
<maven-compiler-plugin.version>3.11.0</maven-compiler-plugin.version>
Expand Down
78 changes: 78 additions & 0 deletions spring-ai-mcp-core/docs/MCP-SESSION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# MCP Session Components

## Overview

The MCP (Model Context Protocol) session components implement the [MCP specification](https://spec.modelcontextprotocol.io/) for managing bidirectional JSON-RPC communication between clients and model servers.
The implementation provides a robust foundation for request-response patterns and notification handling.

## Core Components

### McpSession Interface

The `McpSession` interface defines the contract for MCP communication with three primary operations:

1. Request-Response Communication
```java
<T> Mono<T> sendRequest(String method, Object requestParams, TypeReference<T> typeRef);
```

2. Notification Handling
```java
Mono<Void> sendNotification(String method, Map<String, Object> params);
```

3. Session Lifecycle Management
```java
Mono<Void> closeGracefully();
```

### DefaultMcpSession Implementation

The `DefaultMcpSession` provides the concrete implementation of the MCP session with the following key features:

#### 1. Message Correlation
- Uses unique request IDs combining session UUID prefix and atomic counter
- Maintains thread-safe tracking of pending responses
- Implements timeout management for requests

#### 2. Handler Registration
```java
public interface RequestHandler {
Mono<Object> handle(Object params);
}

public interface NotificationHandler {
Mono<Void> handle(Object params);
}
```

#### 3. Transport Integration
- Abstracts transport details through `McpTransport` interface
- Supports different transport implementations (SSE, STDIO)
- Manages message serialization using Jackson

## Implementation Details

- The session processes three types of messages: McpSchema.JSONRPCResponse, McpSchema.JSONRPCRequest, McpSchema.JSONRPCNotificaiton.
- The implementation ensures thread safety through

### Error Handling

WIP

## Integration Guidelines

1. **Transport Selection**
- Choose appropriate transport (SSE, STDIO) based on use case
- Configure transport-specific parameters
- Handle transport lifecycle properly

2. **Message Handling**
- Register handlers before starting session
- Use appropriate error codes from MCP specification
- Implement proper request/response correlation

3. **Type Safety**
- Use appropriate TypeReference for response deserialization
- Validate request parameters
- Handle type conversion errors
20 changes: 19 additions & 1 deletion spring-ai-mcp-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,30 @@
<artifactId>reactor-core</artifactId>
</dependency>


<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webflux</artifactId>
<version>${springframework.version}</version>
</dependency>


<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty-http</artifactId>
<scope>test</scope>
</dependency>

<!-- The Spring Context is required due to the reactor-netty connector being dependant on
the Spring Lifecycle, as discussed here:
https://github.com/spring-projects/spring-framework/issues/31180 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${springframework.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
Expand Down Expand Up @@ -83,4 +101,4 @@
</dependencies>


</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;

import org.springframework.ai.mcp.spec.DefaultMcpSession;
Expand All @@ -36,6 +38,8 @@
*/
public class McpAsyncClient extends DefaultMcpSession {

private final static Logger logger = LoggerFactory.getLogger(McpAsyncClient.class);

private static TypeReference<Void> VOID_TYPE_REFERENCE = new TypeReference<>() {
};

Expand Down Expand Up @@ -86,6 +90,11 @@ public Mono<McpSchema.InitializeResult> initialize() {
});

return result.flatMap(initializeResult -> {

logger.info("Server response with Protocol: {}, Capabilities: {}, Info: {} and Instructions {}",
initializeResult.protocolVersion(), initializeResult.capabilities(), initializeResult.serverInfo(),
initializeResult.instructions());

if (!McpSchema.LATEST_PROTOCOL_VERSION.equals(initializeResult.protocolVersion())) {
return Mono.error(new McpError(
"Unsupported protocol version from the server: " + initializeResult.protocolVersion()));
Expand Down
Loading

0 comments on commit 716d1a0

Please sign in to comment.