Skip to content
This repository was archived by the owner on Feb 14, 2025. It is now read-only.

Commit 82c64f5

Browse files
committed
feat(core): add roots list support and improve documentation
- Add roots list capability to allow servers to understand filesystem boundaries - Move architecture diagram and add detailed documentation for transports and sessions - Enhance client capabilities with roots and sampling features - Rename withRequestTimeout to requestTimeout for better API consistency - Add tests for roots list functionality Resolves #8
1 parent 7a98a93 commit 82c64f5

19 files changed

+810
-45
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Java SDK for the Model Context Protocol (MCP), providing seamless integration be
66

77
Spring AI MCP is an experimental project that provides Java and Spring Framework integration for the [Model Context Protocol](https://modelcontextprotocol.org/docs/concepts/architecture). It enables Java applications to interact with AI models and tools through a standardized interface, supporting both synchronous and asynchronous communication patterns.
88

9-
<img src="spring-ai-mcp-architecture.jpg" width="600">
9+
<img src="docs/spring-ai-mcp-architecture.jpg" width="600">
1010

1111
## Modules
1212

docs/CLIENT.SSE.TRANSPORT.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# SSE Server Transport Implementation for MCP
2+
3+
## Overview
4+
5+
The `SseClientTransport` class implements the Model Context Protocol (MCP) HTTP with SSE transport specification, providing a bidirectional communication channel between clients and servers. This implementation is part of the Spring AI MCP Core library and follows the [MCP HTTP with SSE Transport Specification](https://spec.modelcontextprotocol.io/specification/basic/transports/#http-with-sse).
6+
7+
## Key Features
8+
9+
- **Bidirectional Communication**:
10+
- Inbound: Receives messages through SSE connection
11+
- Outbound: Sends messages via HTTP POST requests
12+
13+
- **Error Handling**:
14+
- Automatic reconnection for transient failures
15+
- Graceful shutdown capabilities
16+
- Comprehensive error reporting
17+
18+
- **Message Flow**:
19+
1. Client establishes SSE connection to `/sse` endpoint
20+
2. Server sends 'endpoint' event with message URI
21+
3. Client uses provided URI for outbound messages
22+
23+
## Technical Details
24+
25+
### Transport Architecture
26+
27+
The transport consists of two main processing pipelines:
28+
29+
1. **Inbound Processing**:
30+
- Establishes SSE connection to `/sse` endpoint
31+
- Handles two types of events:
32+
- `message`: JSON-RPC protocol messages
33+
- `endpoint`: Server-provided URI for outbound messages
34+
- Implements automatic retry logic for connection failures
35+
36+
2. **Outbound Processing**:
37+
- Sends messages via HTTP POST to server-provided endpoint
38+
- Uses dedicated scheduler for sequential message processing
39+
- Handles JSON serialization and HTTP communication
40+
41+
### Key Components
42+
43+
- **WebClient**: Handles HTTP communications for both SSE and POST requests
44+
- **ObjectMapper**: Manages JSON serialization/deserialization
45+
- **Scheduler**: Ensures sequential outbound message processing
46+
- **Message Endpoint Sink**: Manages server-provided endpoint URI
47+
48+
## Usage Example
49+
50+
```java
51+
// Create WebClient builder with base URL
52+
WebClient.Builder webClientBuilder = WebClient.builder()
53+
.baseUrl("http://localhost:3001");
54+
55+
// Initialize transport
56+
SseClientTransport transport = new SseClientTransport(webClientBuilder);
57+
58+
// Create a JSON-RPC request
59+
JSONRPCRequest request = new JSONRPCRequest(
60+
McpSchema.JSONRPC_VERSION,
61+
"method-name",
62+
"request-id",
63+
Map.of("key", "value")
64+
);
65+
66+
// Send message
67+
transport.sendMessage(request)
68+
.subscribe(
69+
success -> System.out.println("Message sent successfully"),
70+
error -> System.err.println("Error sending message: " + error)
71+
);
72+
73+
// Graceful shutdown when done
74+
transport.closeGracefully()
75+
.subscribe();
76+
```
77+
78+
## Implementation Details
79+
80+
### Message Processing
81+
82+
1. **Inbound Messages**:
83+
- Received through SSE connection
84+
- Automatically deserialized from JSON
85+
- Routed to appropriate handlers based on event type
86+
87+
2. **Outbound Messages**:
88+
- Serialized to JSON
89+
- Sent via HTTP POST
90+
- Processed sequentially on dedicated thread
91+
92+
### Error Handling
93+
94+
- **Connection Failures**:
95+
- Automatic retry for transient failures
96+
- Configurable retry policies
97+
- Graceful handling of permanent failures
98+
99+
- **Message Processing Errors**:
100+
- Comprehensive error reporting
101+
- Clean failure handling
102+
- Maintains system stability
103+
104+
### Shutdown Process
105+
106+
The transport implements a graceful shutdown mechanism that:
107+
1. Marks transport as closing
108+
2. Disposes of all subscriptions
109+
3. Cleans up schedulers
110+
4. Completes message endpoint sink
111+
112+
## Technical Specifications
113+
114+
- **Protocol**: HTTP with Server-Sent Events (SSE)
115+
- **Message Format**: JSON-RPC 2.0
116+
- **Content Type**: application/json for outbound, text/event-stream for inbound
117+
- **Endpoints**:
118+
- SSE Connection: `/sse`
119+
- Message Endpoint: Dynamically provided by server
120+
121+
## Dependencies
122+
123+
- Spring WebFlux for reactive HTTP client
124+
- Jackson for JSON processing
125+
- Project Reactor for reactive streams
126+
- SLF4J for logging
127+
128+
## Thread Safety
129+
130+
The implementation is thread-safe and designed for concurrent use:
131+
- Inbound processing uses SSE event loop
132+
- Outbound processing uses dedicated single-threaded scheduler
133+
- State management uses thread-safe constructs
134+
135+
## Testing
136+
137+
The implementation includes comprehensive tests covering:
138+
- Message processing
139+
- Error handling
140+
- Connection management
141+
- Shutdown procedures
142+
- Edge cases and failure scenarios
143+
144+
For detailed test examples, see `SseClientTransportTests.java`.

docs/CLIENT.STDIO.TRANSPORT.md

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# StdioClientTransport
2+
3+
The `StdioClientTransport` class implements the [MCP Stdio Transport](https://spec.modelcontextprotocol.io/specification/basic/transports/#stdio) specification, providing communication with MCP servers over standard input/output streams.
4+
5+
## Overview
6+
7+
The Stdio transport uses standard input/output streams for bidirectional communication between the client and server:
8+
- Messages are sent to the server via stdout
9+
- Messages are received from the server via stdin
10+
- Error and debug information is sent via stderr
11+
12+
## Message Format
13+
14+
Messages are exchanged as newline-delimited JSON-RPC messages:
15+
- Each message is a single line of JSON text
16+
- Messages are terminated with a newline character (`\n`)
17+
- Messages follow the JSON-RPC 2.0 specification
18+
- UTF-8 encoding is used for all messages
19+
20+
### Message Types
21+
22+
The transport handles three types of JSON-RPC messages:
23+
24+
1. **Requests** - Messages with both `method` and `id` fields:
25+
```json
26+
{
27+
"jsonrpc": "2.0",
28+
"id": 1,
29+
"method": "example.method",
30+
"params": {}
31+
}
32+
```
33+
34+
2. **Notifications** - Messages with `method` but no `id` field:
35+
```json
36+
{
37+
"jsonrpc": "2.0",
38+
"method": "example.notification",
39+
"params": {}
40+
}
41+
```
42+
43+
3. **Responses** - Messages with either `result` or `error` fields:
44+
```json
45+
{
46+
"jsonrpc": "2.0",
47+
"id": 1,
48+
"result": {}
49+
}
50+
```
51+
52+
## Implementation Details
53+
54+
### Process Management
55+
56+
The transport manages a server process with:
57+
- Command and arguments specified via `ServerParameters`
58+
- Environment variables for configuration
59+
- Proper process cleanup on shutdown
60+
61+
### Threading Model
62+
63+
The implementation uses three dedicated threads:
64+
1. **Inbound** - Reads and processes messages from stdin
65+
2. **Outbound** - Writes messages to stdout
66+
3. **Error** - Handles stderr messages
67+
68+
### Error Handling
69+
70+
Errors are handled at multiple levels:
71+
- Process startup failures
72+
- Stream I/O errors
73+
- Message parsing errors
74+
- Process termination handling
75+
76+
## Usage Example
77+
78+
```java
79+
// Create server parameters
80+
ServerParameters params = ServerParameters.builder()
81+
.command("path/to/server")
82+
.args(List.of("--arg1", "value1"))
83+
.env(Map.of("ENV_VAR", "value"))
84+
.build();
85+
86+
// Create transport
87+
StdioClientTransport transport = new StdioClientTransport(params);
88+
89+
// Start transport
90+
transport.start();
91+
92+
// Send message
93+
JSONRPCRequest request = new JSONRPCRequest();
94+
request.setId(1);
95+
request.setMethod("example.method");
96+
request.setParams(new HashMap<>());
97+
transport.send(request);
98+
99+
// Close transport
100+
transport.closeGracefully().block();
101+
```
102+
103+
## Error Messages
104+
105+
Error messages from the server process are:
106+
- Written to stderr
107+
- Logged at ERROR level
108+
- Emitted through the error sink for handling
109+
- UTF-8 encoded
110+
111+
## Debugging
112+
113+
For debugging purposes:
114+
1. Enable DEBUG level logging to see detailed message flow
115+
2. Monitor stderr for server process errors
116+
3. Check process exit codes for abnormal termination
117+
118+
## Implementation Notes
119+
120+
- The transport ensures thread safety through dedicated schedulers
121+
- Messages are processed asynchronously using Project Reactor
122+
- Resources are properly cleaned up on shutdown
123+
- The implementation is resilient to various failure modes

docs/MCP-SESSION.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# MCP Session Components
2+
3+
## Overview
4+
5+
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.
6+
The implementation provides a robust foundation for request-response patterns and notification handling.
7+
8+
## Core Components
9+
10+
### McpSession Interface
11+
12+
The `McpSession` interface defines the contract for MCP communication with three primary operations:
13+
14+
1. Request-Response Communication
15+
```java
16+
<T> Mono<T> sendRequest(String method, Object requestParams, TypeReference<T> typeRef);
17+
```
18+
19+
2. Notification Handling
20+
```java
21+
Mono<Void> sendNotification(String method, Map<String, Object> params);
22+
```
23+
24+
3. Session Lifecycle Management
25+
```java
26+
Mono<Void> closeGracefully();
27+
```
28+
29+
### DefaultMcpSession Implementation
30+
31+
The `DefaultMcpSession` provides the concrete implementation of the MCP session with the following key features:
32+
33+
#### 1. Message Correlation
34+
- Uses unique request IDs combining session UUID prefix and atomic counter
35+
- Maintains thread-safe tracking of pending responses
36+
- Implements timeout management for requests
37+
38+
#### 2. Handler Registration
39+
```java
40+
public interface RequestHandler {
41+
Mono<Object> handle(Object params);
42+
}
43+
44+
public interface NotificationHandler {
45+
Mono<Void> handle(Object params);
46+
}
47+
```
48+
49+
#### 3. Transport Integration
50+
- Abstracts transport details through `McpTransport` interface
51+
- Supports different transport implementations (SSE, STDIO)
52+
- Manages message serialization using Jackson
53+
54+
## Implementation Details
55+
56+
- The session processes three types of messages: McpSchema.JSONRPCResponse, McpSchema.JSONRPCRequest, McpSchema.JSONRPCNotificaiton.
57+
- The implementation ensures thread safety through
58+
59+
### Error Handling
60+
61+
WIP
62+
63+
## Integration Guidelines
64+
65+
1. **Transport Selection**
66+
- Choose appropriate transport (SSE, STDIO) based on use case
67+
- Configure transport-specific parameters
68+
- Handle transport lifecycle properly
69+
70+
2. **Message Handling**
71+
- Register handlers before starting session
72+
- Use appropriate error codes from MCP specification
73+
- Implement proper request/response correlation
74+
75+
3. **Type Safety**
76+
- Use appropriate TypeReference for response deserialization
77+
- Validate request parameters
78+
- Handle type conversion errors

0 commit comments

Comments
 (0)