Skip to content

feat(spi): adds implementation-neutral SPI module #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions mcp-bom/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,24 @@

<dependencyManagement>
<dependencies>
<!-- Core MCP -->
<!-- MCP Spec -->
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
<artifactId>mcp-spi</artifactId>
<version>${project.version}</version>
</dependency>

<!-- MCP Jacson Schema -->
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-schema-jackson</artifactId>
<version>${project.version}</version>
</dependency>

<!-- MCP Reactor -->
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-reactor</artifactId>
<version>${project.version}</version>
</dependency>

Expand Down
2 changes: 1 addition & 1 deletion mcp/README.md → mcp-reactor/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Java MCP SDK

Java SDK implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools.
Java SDK Reactor implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools.
For comprehensive guides and API documentation, visit the [MCP Java SDK Reference Documentation](https://modelcontextprotocol.io/sdk/java/mcp-overview).

116 changes: 31 additions & 85 deletions mcp/pom.xml → mcp-reactor/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
<artifactId>mcp-parent</artifactId>
<version>0.10.0-SNAPSHOT</version>
</parent>
<artifactId>mcp</artifactId>
<artifactId>mcp-reactor</artifactId>
<packaging>jar</packaging>
<name>Java MCP SDK</name>
<description>Java SDK implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools</description>
<name>Java SDK MCP Reactor</name>
<description>Java SDK Reactor implementation of the Model Context Protocol, enabling seamless integration with language models and AI tools</description>
<url>https://github.com/modelcontextprotocol/java-sdk</url>

<scm>
Expand Down Expand Up @@ -65,61 +65,53 @@
</build>

<dependencies>

<!--MCP-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-spi</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-schema-jackson</artifactId>
<version>${project.version}</version>
</dependency>

<!--Reactor-->
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<groupId>org.reactivestreams</groupId>
<artifactId>reactive-streams</artifactId>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${springframework.version}</version>
<scope>test</scope>
</dependency>


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

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

<!--Logs-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${springframework.version}</version>
<scope>test</scope>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version>
</dependency>

<!--For test-->
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assert4j.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
Expand All @@ -138,70 +130,24 @@
<version>${mockito.version}</version>
<scope>test</scope>
</dependency>

<!-- Mockito cannot mock this class: class java.net.http.HttpClient. the bytebuddy helps. -->
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>${byte-buddy.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>${testcontainers.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>${awaitility.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>net.javacrumbs.json-unit</groupId>
<artifactId>json-unit-assertj</artifactId>
<version>${json-unit-assertj.version}</version>
<scope>test</scope>
</dependency>


<!-- Used by the HttpServletSseServerTransport -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${jakarta.servlet.version}</version>
<scope>provided</scope>
</dependency>

<!-- Tomcat dependencies for testing -->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
<version>${tomcat.version}</version>
<scope>test</scope>
</dependency>

</dependencies>


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;

import com.fasterxml.jackson.core.type.TypeReference;
import io.modelcontextprotocol.spec.McpClientSession;
import io.modelcontextprotocol.spec.McpClientSession.NotificationHandler;
import io.modelcontextprotocol.spec.McpClientSession.RequestHandler;
import io.modelcontextprotocol.schema.McpType;
import io.modelcontextprotocol.session.McpClientSession;
import io.modelcontextprotocol.session.McpClientSession.NotificationHandler;
import io.modelcontextprotocol.session.McpClientSession.RequestHandler;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpError;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.ClientCapabilities;
import io.modelcontextprotocol.spec.McpSchema.CreateMessageRequest;
import io.modelcontextprotocol.spec.McpSchema.CreateMessageResult;
import io.modelcontextprotocol.spec.McpSchema.GetPromptRequest;
import io.modelcontextprotocol.spec.McpSchema.GetPromptResult;
import io.modelcontextprotocol.spec.McpSchema.ListPromptsResult;
import io.modelcontextprotocol.spec.McpSchema.LoggingLevel;
import io.modelcontextprotocol.spec.McpSchema.LoggingMessageNotification;
import io.modelcontextprotocol.spec.McpSchema.PaginatedRequest;
import io.modelcontextprotocol.spec.McpSchema.Root;
import io.modelcontextprotocol.schema.McpSchema;
import io.modelcontextprotocol.schema.McpSchema.ClientCapabilities;
import io.modelcontextprotocol.schema.McpSchema.CreateMessageRequest;
import io.modelcontextprotocol.schema.McpSchema.CreateMessageResult;
import io.modelcontextprotocol.schema.McpSchema.GetPromptRequest;
import io.modelcontextprotocol.schema.McpSchema.GetPromptResult;
import io.modelcontextprotocol.schema.McpSchema.ListPromptsResult;
import io.modelcontextprotocol.schema.McpSchema.LoggingLevel;
import io.modelcontextprotocol.schema.McpSchema.LoggingMessageNotification;
import io.modelcontextprotocol.schema.McpSchema.PaginatedRequest;
import io.modelcontextprotocol.schema.McpSchema.Root;
import io.modelcontextprotocol.spec.McpTransport;
import io.modelcontextprotocol.util.Assert;
import io.modelcontextprotocol.util.Utils;
Expand Down Expand Up @@ -80,8 +80,7 @@ public class McpAsyncClient {

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

private static TypeReference<Void> VOID_TYPE_REFERENCE = new TypeReference<>() {
};
private static final McpType<Void> VOID_TYPE_REFERENCE = McpType.of(Void.class);

protected final Sinks.One<McpSchema.InitializeResult> initializedSink = Sinks.one();

Expand Down Expand Up @@ -337,8 +336,7 @@ public Mono<McpSchema.InitializeResult> initialize() {
this.clientInfo); // @formatter:on

Mono<McpSchema.InitializeResult> result = this.mcpSession.sendRequest(McpSchema.METHOD_INITIALIZE,
initializeRequest, new TypeReference<McpSchema.InitializeResult>() {
});
initializeRequest, McpType.of(McpSchema.InitializeResult.class));

return result.flatMap(initializeResult -> {

Expand Down Expand Up @@ -389,8 +387,7 @@ private <T> Mono<T> withInitializationCheck(String actionName,
*/
public Mono<Object> ping() {
return this.withInitializationCheck("pinging the server", initializedResult -> this.mcpSession
.sendRequest(McpSchema.METHOD_PING, null, new TypeReference<Object>() {
}));
.sendRequest(McpSchema.METHOD_PING, null, McpType.of(Object.class)));
}

// --------------------------
Expand Down Expand Up @@ -471,15 +468,15 @@ public Mono<Void> removeRoot(String rootUri) {
*/
public Mono<Void> rootsListChangedNotification() {
return this.withInitializationCheck("sending roots list changed notification",
initResult -> this.mcpSession.sendNotification(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED));
initResult -> (Mono<Void>) this.mcpSession
.sendNotification(McpSchema.METHOD_NOTIFICATION_ROOTS_LIST_CHANGED));
}

private RequestHandler<McpSchema.ListRootsResult> rootsListRequestHandler() {
return params -> {
@SuppressWarnings("unused")
McpSchema.PaginatedRequest request = transport.unmarshalFrom(params,
new TypeReference<McpSchema.PaginatedRequest>() {
});
McpType.of(McpSchema.PaginatedRequest.class));

List<Root> roots = this.roots.values().stream().toList();

Expand All @@ -493,8 +490,7 @@ private RequestHandler<McpSchema.ListRootsResult> rootsListRequestHandler() {
private RequestHandler<CreateMessageResult> samplingCreateMessageHandler() {
return params -> {
McpSchema.CreateMessageRequest request = transport.unmarshalFrom(params,
new TypeReference<McpSchema.CreateMessageRequest>() {
});
McpType.of(McpSchema.CreateMessageRequest.class));

return this.samplingHandler.apply(request);
};
Expand All @@ -503,11 +499,11 @@ private RequestHandler<CreateMessageResult> samplingCreateMessageHandler() {
// --------------------------
// Tools
// --------------------------
private static final TypeReference<McpSchema.CallToolResult> CALL_TOOL_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.CallToolResult> CALL_TOOL_RESULT_TYPE_REF = McpType
.of(McpSchema.CallToolResult.class);

private static final TypeReference<McpSchema.ListToolsResult> LIST_TOOLS_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.ListToolsResult> LIST_TOOLS_RESULT_TYPE_REF = McpType
.of(McpSchema.ListToolsResult.class);

/**
* Calls a tool provided by the server. Tools enable servers to expose executable
Expand Down Expand Up @@ -569,14 +565,14 @@ private NotificationHandler asyncToolsChangeNotificationHandler(
// Resources
// --------------------------

private static final TypeReference<McpSchema.ListResourcesResult> LIST_RESOURCES_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.ListResourcesResult> LIST_RESOURCES_RESULT_TYPE_REF = McpType
.of(McpSchema.ListResourcesResult.class);

private static final TypeReference<McpSchema.ReadResourceResult> READ_RESOURCE_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.ReadResourceResult> READ_RESOURCE_RESULT_TYPE_REF = McpType
.of(McpSchema.ReadResourceResult.class);

private static final TypeReference<McpSchema.ListResourceTemplatesResult> LIST_RESOURCE_TEMPLATES_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.ListResourceTemplatesResult> LIST_RESOURCE_TEMPLATES_RESULT_TYPE_REF = McpType
.of(McpSchema.ListResourceTemplatesResult.class);

/**
* Retrieves the list of all resources provided by the server. Resources represent any
Expand Down Expand Up @@ -711,11 +707,11 @@ private NotificationHandler asyncResourcesChangeNotificationHandler(
// --------------------------
// Prompts
// --------------------------
private static final TypeReference<McpSchema.ListPromptsResult> LIST_PROMPTS_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.ListPromptsResult> LIST_PROMPTS_RESULT_TYPE_REF = McpType
.of(McpSchema.ListPromptsResult.class);

private static final TypeReference<McpSchema.GetPromptResult> GET_PROMPT_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.GetPromptResult> GET_PROMPT_RESULT_TYPE_REF = McpType
.of(McpSchema.GetPromptResult.class);

/**
* Retrieves the list of all prompts provided by the server.
Expand Down Expand Up @@ -780,8 +776,7 @@ private NotificationHandler asyncLoggingNotificationHandler(

return params -> {
McpSchema.LoggingMessageNotification loggingMessageNotification = transport.unmarshalFrom(params,
new TypeReference<McpSchema.LoggingMessageNotification>() {
});
McpType.of(McpSchema.LoggingMessageNotification.class));

return Flux.fromIterable(loggingConsumers)
.flatMap(consumer -> consumer.apply(loggingMessageNotification))
Expand All @@ -803,8 +798,8 @@ public Mono<Void> setLoggingLevel(LoggingLevel loggingLevel) {

return this.withInitializationCheck("setting logging level", initializedResult -> {
var params = new McpSchema.SetLevelRequest(loggingLevel);
return this.mcpSession.sendRequest(McpSchema.METHOD_LOGGING_SET_LEVEL, params, new TypeReference<Object>() {
}).then();
return this.mcpSession.sendRequest(McpSchema.METHOD_LOGGING_SET_LEVEL, params, McpType.of(Object.class))
.then();
});
}

Expand All @@ -815,13 +810,14 @@ public Mono<Void> setLoggingLevel(LoggingLevel loggingLevel) {
*/
void setProtocolVersions(List<String> protocolVersions) {
this.protocolVersions = protocolVersions;

}

// --------------------------
// Completions
// --------------------------
private static final TypeReference<McpSchema.CompleteResult> COMPLETION_COMPLETE_RESULT_TYPE_REF = new TypeReference<>() {
};
private static final McpType<McpSchema.CompleteResult> COMPLETION_COMPLETE_RESULT_TYPE_REF = McpType
.of(McpSchema.CompleteResult.class);

/**
* Sends a completion/complete request to generate value suggestions based on a given
Expand Down
Loading