refactor: Split transport implementations into modules

Split the  transport implementations into dedicated modules to improve modularity
and reduce core dependencies.

Added shared test module for common test utilities.

Key changes:

- Create mcp-transport/mcp-webflux-sse-transport module
 - Move SseClientTransport → WebFluxSseClientTransport
 - Move SseServerTransport → WebFluxSseServerTransport
 - Move related tests and utilities

- Create mcp-transport/mcp-webmvc-sse-transport module
 - Add new WebMvcSseServerTransport implementation
 - Add corresponding tests and integration tests

- Add framework-independent SSE client implementations to core module
 - Add FlowSseClient using java.net.http
 - Add HttpClientSseClientTransport using java.net.http

- Keep StdioClientTransport/StdioServerTransport in core (no external deps)

- Create mcp-test module for shared test infrastructure
 - Move abstract test base classes
 - Move shared test utilities and mocks
 - Update test dependencies

The modular approach allows users to choose between:

- Framework-specific implementations (WebFlux/WebMVC)
- Pure Java implementations (java.net.http)
- Basic implementations (STDIO)

Add breaking changes readme: 0.5.0-BREAKING-CHANGES.md

Resolves #54
This commit is contained in:
Christian Tzolov 2025-01-08 16:21:21 +01:00
commit 611f3258d6
5 changed files with 5002 additions and 1588 deletions

View file

@ -149,16 +149,27 @@ class StdioClientTransport implements ClientMcpTransport {
+Sinks.Many<String> getErrorSink()
}
class SseClientTransport implements ClientMcpTransport {
}
class StdioServerTransport implements ServerMcpTransport {
}
class SseServerTransport implements ServerMcpTransport {
class HttpClientSseClientTransport implements ClientMcpTransport {
}
class WebFluxSseClientTransport implements ClientMcpTransport {
}
class WebFluxSseServerTransport implements ServerMcpTransport {
+RouterFunction<?> getRouterFunction()
}
class WebMvcSseServerTransport implements ServerMcpTransport {
+RouterFunction<?> getRouterFunction()
}
' Schema and Error Classes
class McpSchema {
+class ErrorCodes

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Before After
Before After

View file

@ -1,25 +1,35 @@
= Java MCP SDK
Java SDK implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools.
Java SDK implementation of the link:https://modelcontextprotocol.io/introduction[Model Context Protocol], enabling seamless integration with language models and AI tools.
== Features
* Synchronous and Asynchronous MCP Client and MCP Server implementations
* Standard MCP operations support:
** Protocol version compatibility negotiation
** Tool discovery, execution, list change notifications
** Resource management with URI templates
** Roots list management and notifications
** Prompt handling and management
** Smampling support for AI model interactions
** Protocol link:https://spec.modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle/#initialization[version compatibility negotiation]
** link:https://spec.modelcontextprotocol.io/specification/2024-11-05/server/tools/[Tool] discovery, execution, list change notifications
** link:https://spec.modelcontextprotocol.io/specification/2024-11-05/server/resources/[Resource] management with URI templates
** link:https://spec.modelcontextprotocol.io/specification/2024-11-05/client/roots/[Roots] list management and notifications
** link:https://spec.modelcontextprotocol.io/specification/2024-11-05/server/prompts/[Prompt] handling and management
** link:https://spec.modelcontextprotocol.io/specification/2024-11-05/client/sampling/[Sampling] support for AI model interactions
* Multiple transport implementations:
** Stdio-based transport for process-based communication
** SSE-based transport for HTTP streaming
** Core transports:
*** Stdio-based transport for process-based communication
*** Java HttpClient-based SSE transport for HTTP streaming
** Spring-based transports:
*** WebFlux SSE transport for reactive HTTP streaming
*** WebMVC SSE transport for servlet-based HTTP streaming
=== Dependencies
Add the following dependency to your Maven project:
[tabs]
======
Maven::
+
The core MCP functionality:
+
[source,xml]
----
<dependency>
@ -28,6 +38,51 @@ Add the following dependency to your Maven project:
<version>0.5.0-SNAPSHOT</version>
</dependency>
----
+
For HTTP SSE transport implementations, add one of the following dependencies
(Note that you already have HTTP Client SSE client transport in the core module):
+
[source,xml]
----
<!-- Spring WebFlux-based SSE client and server transport -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>mcp-webflux-sse-transport</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
<!-- Spring WebMVC-based SSE server transport -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>mcp-webmvc-sse-transport</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
----
Gradle::
+
The core MCP functionality:
+
[source,groovy]
----
dependencies {
implementation 'org.springframework.experimental:mcp'
}
----
+
For HTTP SSE transport implementations, add one of the following dependencies
(note that you already have HTTP Client SSE client transport in the core module):
+
[source,groovy]
----
// Spring WebFlux-based SSE client and server transport
implementation 'org.springframework.experimental:mcp-webflux-sse-transport'
// Spring WebMVC-based SSE server transport
implementation 'org.springframework.experimental:mcp-webmvc-sse-transport'
----
======
== Architecture
@ -37,7 +92,9 @@ The SDK follows a layered architecture with clear separation of concerns:
* *Client/Server Layer*: Both use McpSession for sync/async operations, with McpClient handling client-side protocol operations and McpServer managing server-side protocol operations.
* *Session Layer (McpSession)*: Manages communication patterns and state using DefaultMcpSession implementation.
* *Transport Layer (McpTransport)*: Handles JSON-RPC message serialization/deserialization via StdioTransport (stdin/stdout) and SseTransport (HTTP streaming).
* *Transport Layer (McpTransport)*: Handles JSON-RPC message serialization/deserialization via:
** StdioTransport (stdin/stdout) in the core module
** HTTP SSE transports in dedicated transport modules (Java HttpClient, Spring WebFlux, Spring WebMVC)
Following class diagram illustrates the layered architecture of the MCP SDK, showing the relationships between core interfaces (McpTransport, McpSession), their implementations, and the client/server components. It highlights how the transport layer connects to sessions, which in turn support both synchronous and asynchronous client/server implementations.
@ -187,23 +244,36 @@ The transport layer handles the communication between MCP clients and servers, p
======
STDIO::
+
Creates transport for in-process based communication
+
[source,java]
----
// Create transport for process-based communication
ServerParameters params = ServerParameters.builder("npx")
.args("-y", "@modelcontextprotocol/server-everything", "dir")
.build();
McpTransport transport = new StdioClientTransport(params);
----
SSE::
+
SSE (HttpClient)::
+
Creates a framework agnostic (pure Java API) SSE client transport.
Included in the core `mcp` module.
+
[source,java]
----
McpTransport transport = new HttpClientSseClientTransport("http://your-mcp-server");
----
+
SSE (WebFlux)::
+
Creates WebFlux-based SSE client transport.
Requires the `mcp-webflux-sse-transport` dependency.
+
[source,java]
----
// Create transport for HTTP streaming
WebClient.Builder webClientBuilder = WebClient.builder()
.baseUrl("http://your-mcp-server");
McpTransport transport = new SseClientTransport(webClientBuilder);
McpTransport transport = new WebFluxSseClientTransport(webClientBuilder);
----
======
@ -381,29 +451,72 @@ The server transport layer implements the server-side communication protocols, e
======
STDIO::
+
Create in-process based transport
+
[source,java]
----
// Create transport with custom ObjectMapper
ObjectMapper mapper = new ObjectMapper();
StdioServerTransport transport = new StdioServerTransport(mapper);
StdioServerTransport transport = new StdioServerTransport(new ObjectMapper());
----
+
Provides bidirectional JSON-RPC message handling over standard input/output streams with non-blocking message processing, serialization/deserialization, and graceful shutdown support.
SSE::
SSE (WebFlux)::
+
Creates WebFlux-based SSE server transport.
Requires the `mcp-webflux-sse-transport` dependency.
+
[source,java]
----
// Create SSE transport
ObjectMapper mapper = new ObjectMapper();
String messageEndpoint = "/mcp/message";
SseServerTransport transport = new SseServerTransport(mapper, messageEndpoint);
@Configuration
class McpConfig {
@Bean
WebFluxSseServerTransport webFluxSseServerTransport(ObjectMapper mapper) {
return new WebFluxSseServerTransport(mapper, "/mcp/message");
}
// Get router function for web server configuration
RouterFunction<?> router = transport.getRouterFunction();
@Bean
RouterFunction<?> mcpRouterFunction(WebFluxSseServerTransport transport) {
return transport.getRouterFunction();
}
}
----
+
Implements the MCP HTTP with SSE transport specification, providing concurrent client connections through SSE endpoints with message routing, session management, and graceful shutdown capabilities.
Implements the MCP HTTP with SSE transport specification, providing:
+
* Reactive HTTP streaming with WebFlux
* Concurrent client connections through SSE endpoints
* Message routing and session management
* Graceful shutdown capabilities
SSE (WebMvc)::
+
Creates WebMvc-based SSE server transport.
Requires the `mcp-webmvc-sse-transport` dependency.
+
[source,java]
----
@Configuration
@EnableWebMvc
class McpConfig {
@Bean
WebMvcSseServerTransport webMvcSseServerTransport(ObjectMapper mapper) {
return new WebMvcSseServerTransport(mapper, "/mcp/message");
}
@Bean
RouterFunction<ServerResponse> mcpRouterFunction(WebMvcSseServerTransport transport) {
return transport.getRouterFunction();
}
}
----
+
Implements the MCP HTTP with SSE transport specification, providing:
+
* Servlet-based HTTP streaming with Spring MVC
* Concurrent client connections through SSE endpoints
* Message routing and session management
* Graceful shutdown capabilities
======
=== Server Capabilities

View file

@ -13,19 +13,38 @@ There are two main projects in this repository:
Java implementation of the Model Context Protocol specification. It includes:
* Synchronous and asynchronous link:https://github.com/spring-projects-experimental/spring-ai-mcp/blob/main/mcp/README.md#client-usage-examples[MCP Client] and link:https://github.com/spring-projects-experimental/spring-ai-mcp/blob/main/mcp/README.md#server-usage-examples[MCP Server] implementations
* Standard MCP operations support (tool discovery, resource management, prompt handling, structured logging). Support for request and notification handling.
* link:https://spec.modelcontextprotocol.io/specification/basic/transports/#stdio[Stdio] and link:https://spec.modelcontextprotocol.io/specification/basic/transports/#http-with-sse[SSE] transport implementations.
* Synchronous and asynchronous xref:mcp.adoc#mcp-client[MCP Client] and xref:mcp.adoc#mcp-server[MCP Server] implementations
* Standard MCP operations support:
** Tool discovery and execution
** Resource management with URI templates
** Prompt handling and management
** Structured logging
** Request and notification handling
* Multiple transport implementations:
** Core transports:
*** Stdio-based transport for process-based communication
*** Java HttpClient-based SSE transport for HTTP streaming
** Spring-based transports:
*** WebFlux SSE transport for reactive HTTP streaming
*** WebMVC SSE transport for servlet-based HTTP streaming
==== WebFlux SSE Transport
The link:https://github.com/spring-projects-experimental/spring-ai-mcp/tree/main/mcp-transport/mcp-webflux-sse-transport[mcp-webflux-sse-transport] project provides WebFlux-based implementation for the SSE client and server transports, enabling reactive HTTP streaming with Spring WebFlux.
==== WebMvc SSE Transport
The link:https://github.com/spring-projects-experimental/spring-ai-mcp/tree/main/mcp-transport/mcp-webmvc-sse-transport[mcp-webmvc-sse-transport] project provides WebMvc-based implementation for the SSE server transport. The core module's HttpClientSseClientTransport can be used for client-side communication.
=== xref:spring-mcp.adoc[Spring AI MCP]
The Spring integration module provides Spring-specific functionality:
* Integration with Spring AI's function calling system
* Bidirectional conversion between Spring AI function callbacks and MCP tools
* JSON schema generation for tool input validation
* Automatic type conversion and error handling
* Spring-friendly abstractions for MCP clients
* Auto-configurations (WIP)
== Installation
Add the following dependencies to your Maven project:
@ -34,9 +53,10 @@ Add the following dependencies to your Maven project:
======
Maven::
+
The core MCP functionality:
+
[source,xml]
----
<!-- For core MCP functionality -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>mcp</artifactId>
@ -44,9 +64,29 @@ Maven::
</dependency>
----
+
For HTTP SSE transport implementations, add one or more of the following dependencies:
+
[source,xml]
----
<!-- Spring WebFlux-based SSE client and server transport -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>mcp-webflux-sse-transport</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
<!-- Spring WebMVC-based SSE server transport -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>mcp-webmvc-sse-transport</artifactId>
<version>0.5.0-SNAPSHOT</version>
</dependency>
----
+
For Spring AI integration:
+
[source,xml]
----
<!-- For Spring AI integration -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-ai-mcp</artifactId>
@ -55,31 +95,45 @@ Maven::
----
+
This is a milestone release, not available on Maven Central.
Add this repository to your POM:
Add the Spring milestone repository to your POM:
+
[source,xml]
----
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone-local</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
----
Gradle::
+
The core MCP functionality:
+
[source,groovy]
----
dependencies {
implementation 'org.springframework.experimental:mcp'
}
----
Or for Spring AI integration:
+
For HTTP SSE transport implementations, add one or more of the following dependencies:
+
[source,groovy]
----
// Spring WebFlux-based SSE client and server transport
implementation 'org.springframework.experimental:mcp-webflux-sse-transport'
// Spring WebMVC-based SSE server transport
implementation 'org.springframework.experimental:mcp-webmvc-sse-transport'
----
+
For Spring AI integration:
+
[source,groovy]
----
@ -87,6 +141,16 @@ dependencies {
implementation 'org.springframework.experimental:spring-ai-mcp'
}
----
+
This is a milestone release, not available on Maven Central.
Add the Spring milestone repository to your build:
+
[source,groovy]
----
repositories {
maven { url 'https://repo.spring.io/milestone' }
}
----
======
== Examples
@ -96,14 +160,14 @@ Explore these MCP examples in the link:https://github.com/spring-projects/spring
* link:https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/sqlite/simple[SQLite Simple] - Demonstrates LLM integration with a database
* link:https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/sqlite/chatbot[SQLite Chatbot] - Interactive chatbot with SQLite database interaction
* link:https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/filesystem[Filesystem] - Enables LLM interaction with local filesystem folders and files
* link:https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/brave[Brave] - Enables natural language interactions with Brave Search, allowing you to perform internet searches.
* link:./spring-ai-mcp-sample/[Spring-ai-mcp-sample] - Showcases how to create and use MCP servers and clients with different transport modes and capabilities.
* link:https://github.com/spring-projects/spring-ai-examples/tree/main/model-context-protocol/brave[Brave] - Enables natural language interactions with Brave Search
* link:https://github.com/spring-projects-experimental/spring-ai-mcp/tree/main/samples/spring-ai-mcp-sample[Spring-ai-mcp-sample] - Showcases MCP servers and clients with different transport modes and capabilities
* link:https://github.com/habuma/spring-ai-examples/tree/main/spring-ai-mcp[Theme Park API Example] - Shows how to create an MCP server and client with Spring AI, exposing Theme Park API tools
== Documentation
* link:mcp/README.md[Java MCP SDK documentation]
** link:docs/ref-index.md[Reference documentation]
* link:spring-ai-mcp/README.md[Spring Integration documentation]
* xref:mcp.adoc[Java MCP SDK Documentation]
* xref:spring-mcp.adoc[Spring Integration Documentation]
== Development

View file

@ -14,18 +14,100 @@ The `spring-ai-mcp` module is part of the https://github.com/spring-projects-exp
== Features
* Spring integration for MCP clients
* Function callback implementation for tool invocations
* Seamless integration with Spring AI's function calling capabilities
* Bidirectional conversion between Spring AI function callbacks and MCP tools
* JSON schema generation for tool input validation
* Automatic type conversion and error handling
* Integration with Spring AI's function calling capabilities
== Main Components
=== McpFunctionCallback
The `McpFunctionCallback` class is the primary component of this module. It implements Spring AI's `FunctionCallback` interface and provides:
The `McpFunctionCallback` class implements Spring AI's `FunctionCallback` interface and provides integration between Spring AI's function calling system and MCP tools. Key features include:
* Integration between Spring AI's function calling system and MCP tools
* Automatic conversion between JSON and Java objects for tool arguments
* Synchronous tool execution support
* Error handling and result formatting
* Integration with Spring AI's function calling system
Example usage:
[source,java]
----
// Create an MCP client
McpSyncClient mcpClient = McpClient.using(transport)
.sync();
// Create a function callback for an MCP tool
Tool calculatorTool = new Tool("calculator", "Basic calculator",
Map.of("operation", "string", "a", "number", "b", "number"));
FunctionCallback callback = new McpFunctionCallback(mcpClient, calculatorTool);
// Use the callback with Spring AI
String result = callback.call("{\"operation\": \"add\", \"a\": 2, \"b\": 3}");
----
=== ToolHelper
The `ToolHelper` utility class facilitates the integration between Spring AI's function callbacks and MCP's tool system. It provides methods for:
* Converting Spring AI's `FunctionCallback` instances to MCP tool registrations
* Generating JSON schemas for tool input validation
* Handling error cases and result formatting
Example usage:
[source,java]
----
// Convert Spring AI function callbacks to MCP tool registrations
List<FunctionCallback> callbacks = List.of(
new CalculatorFunction(),
new WeatherFunction()
);
List<ToolRegistration> tools = ToolHelper.toToolRegistration(callbacks);
// Generate JSON schema for tool inputs
Map<String, Class<?>> inputTypes = Map.of(
"calculator", CalculatorInput.class,
"weather", WeatherInput.class
);
String schema = ToolHelper.generateJsonSchema(inputTypes);
----
==== Converting Function Callbacks to Tools
The `ToolHelper` provides several methods to convert Spring AI function callbacks to MCP tools:
[source,java]
----
// Convert a single function callback
ToolRegistration tool = ToolHelper.toToolRegistration(myCallback);
// Convert multiple callbacks
List<ToolRegistration> tools = ToolHelper.toToolRegistration(callback1, callback2);
// Convert a list of callbacks
List<ToolRegistration> tools = ToolHelper.toToolRegistration(callbackList);
----
==== JSON Schema Generation
The `ToolHelper` can generate JSON schemas for tool input validation:
[source,java]
----
// Using default ObjectMapper
String schema = ToolHelper.generateJsonSchema(inputTypes);
// Using custom ObjectMapper
ObjectMapper mapper = new ObjectMapper();
String schema = ToolHelper.generateJsonSchema(inputTypes, mapper);
----
The generated schema follows the JSON Schema Draft 2020-12 specification and:
* Validates the structure of tool inputs
* Excludes ToolContext class from schema generation
* Uses Jackson's JsonSchemaGenerator for accurate type representation
== Usage
@ -39,3 +121,41 @@ To use this module, add the following dependency to your Maven project:
<version>0.5.0-SNAPSHOT</version>
</dependency>
----
=== Example: Creating an MCP Tool Server with Spring AI Functions
[source,java]
----
@Configuration
class McpConfig {
@Bean
McpServer mcpServer(List<FunctionCallback> callbacks) {
// Convert Spring AI callbacks to MCP tools
List<ToolRegistration> tools = ToolHelper.toToolRegistration(callbacks);
return McpServer.using(transport)
.info("spring-ai-server", "1.0.0")
.tools(tools)
.sync();
}
@Bean
FunctionCallback calculatorFunction() {
return FunctionCallback.builder()
.name("calculator")
.description("Basic calculator")
.function(input -> {
// Function implementation
return result;
})
.build();
}
}
----
This configuration:
1. Creates Spring AI function callbacks
2. Converts them to MCP tools using ToolHelper
3. Registers the tools with an MCP server
4. Makes the tools available for discovery and execution by MCP clients