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 6 commits into
base: main
Choose a base branch
from

Conversation

Aliaksie
Copy link
Contributor

@Aliaksie Aliaksie commented Apr 21, 2025

This PR introduces the first version of the mcp-spi module to define a transport-agnostic, reactive-compatible interface for the Model Context Protocol Java SDK.

Refactor mcp to optionally log via a pluggable logger interface (McpTransportLogger interface in mcp-spi instead of hard SLF4J dependency).
Key changes:

  • New mcp-spi (transport interfaces, Jackson-free schema types, McpSchemaCodec abstraction, McpClient/McpServer abstraction, McpLogger pluggable logger interface)
  • New mcp-schema-jackson Jackson-based schema + McpSchemaCodec implementation
  • New mcp-logging-slf4j slf4j-based implementation of McpLogger
  • Renamed mcp to mcp-reactor
  • adapts mcp-reactor to use mcp-spi and mcp-schema-jackson (as default codec implementation) and mcp-logging-slf4j (as default McpLogger implementation)
  • makes it possible to use own codec implementation and logger for mcp-reactor
  • minor changes...

Motivation and Context

The motivation behind this change is to make the SDK modular, implementation-agnostic, and easier to integrate with diverse runtime environments.

How Has This Been Tested?

Breaking Changes

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Possible Future Work:

  • Introduce TCK (Technology Compatibility Kit) for validating McpClientTransport and McpMessageCodec implementations (mcp-spi-tck).
  • Add support for other runtime environments, e.g.(Vert.x-based transport(mcp-vertx), Java 11+ Flow.Publisher HTTP client(mcp-flow)
  • Provide alternative serialization support (e.g., mcp-schema-gson, mcp-schema-cbor, mcp-schema-protobuf).
  • Allow ServiceLoader-based discove.

p.s. if these changes don't make sense no problem just close this pr :-)

@Aliaksie Aliaksie force-pushed the feat/mcp-spi branch 2 times, most recently from efa638e to 9d7ed54 Compare April 23, 2025 15:18
@Aliaksie Aliaksie changed the title feat: adds mcp-spi feat(spi): adds implementation-neutral SPI module Apr 25, 2025
@Aliaksie
Copy link
Contributor Author

Hey @tzolov, hope you're doing well! Just wanted to check in — have you had a chance to review this PR? I’d appreciate any feedback when you get a moment. Looking forward to your thoughts!

@Aliaksie Aliaksie force-pushed the feat/mcp-spi branch 2 times, most recently from 9432f3c to 58173e5 Compare May 5, 2025 18:56
@Aliaksie Aliaksie force-pushed the feat/mcp-spi branch 2 times, most recently from 2dac2b3 to 62b6f8a Compare May 14, 2025 07:37
@Aliaksie
Copy link
Contributor Author

Aliaksie commented May 16, 2025

Hi @tzolov👋 Just checking in to see if there’s been a chance to review this PR

I’d love to get your thoughts on whether this is a direction the project is open to, or if there’s anything I should revise to help move it forward. Happy to discuss further or break it into smaller pieces if that helps with review.
Thanks a lot for your time!

@Aliaksie Aliaksie mentioned this pull request Jun 10, 2025
8 tasks
<version>${project.version}</version>
</dependency>

<!-- MCP Jacson Schema -->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<!-- MCP Jacson Schema -->
<!-- MCP Jackson Schema -->

A nit typo!


byte[] encode(McpSchema.JSONRPCMessage message);

String encodeAsString(Object message) throws IOException;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is only ever used for McpSchema.JSONRPCMessage and McpError instances. It may make more sense to change the signature to String encodeAsString(McpSchea.JSONRPCMessage message) (which would match decodeFromString) and add a separate method or overload for encoding McpError instances.

Copy link

@DRayX DRayX Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on second thought, I'm not sure why this is used with McpError at all; maybe those lines could just avoid going through the codec.

/**
* @author Aliaksei Darafeyeu
*/
public interface McpType<T> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This interface doesn't quite make sense. It's always used to wrap a Class instance, never a ParameterizedType or GenericArray. Unlike Jackson TypeReference, this class doesn't support obtaining full type information by sub-classing, so I don't really see the value in having this wrapper. It seems like it would make more sense to just use Class<T> in it's place.

/**
* @author Aliaksei Darafeyeu
*/
public interface McpLogger {
Copy link

@DRayX DRayX Jun 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logging interface doesn't seem ideal; it feels like all logging levels should support attaching a Throwable cause, the number of methods seems excessive, and there's no way to lazily evaluate string parameters if the message is omitted. Maybe a single void log(McpSchema.LoggingLevel level, Supplier<String> messageSupplier, @Nullable Throwable cause) method would make more sense.

*
* @author Aliaksei Darafeyeu
*/
public interface McpSchemaCodec {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The byte[] base encode and decode as well as decodeBytes never seem to be used. The actual encoded type of the data is likely dependent on the specific transport being used. I wonder if it might make more sense to change this to something like:

public interface McpSchemaCodec<T> {
  T encode(McpSchema.JSONRPCMessage message) throws IOException;
  McpSchema.JSONRPCMessage decode(T message) throws IOException;
  <U> U unmarshalFrom(Object data, Class<T> clazz);
}

Then, each transport would be capable of using the codecs for the encoded data types it understands instead of each codec needing to support all possible encodings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants