{
+
+ private final Type type;
+
+ /**
+ * Constructs a new TypeRef instance, capturing the generic type information of the
+ * subclass. This constructor should be called from an anonymous subclass to capture
+ * the actual type arguments. For example:
+ * TypeRef<List<Foo>> ref = new TypeRef<>(){};
+ *
+ * @throws IllegalStateException if TypeRef is not subclassed with actual type
+ * information
+ */
+ protected TypeRef() {
+ Type superClass = getClass().getGenericSuperclass();
+ if (superClass instanceof Class) {
+ throw new IllegalStateException("TypeRef constructed without actual type information");
+ }
+ this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
+ }
+
+ /**
+ * Returns the captured type information.
+ * @return the Type representing the actual type argument captured by this TypeRef
+ * instance
+ */
+ public Type getType() {
+ return type;
+ }
+
+}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
new file mode 100644
index 000000000..09fe604f4
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2024-2024 the original author or authors.
+ */
+package io.modelcontextprotocol.json.schema;
+
+import java.util.Map;
+
+/**
+ * Interface for validating structured content against a JSON schema. This interface
+ * defines a method to validate structured content based on the provided output schema.
+ *
+ * @author Christian Tzolov
+ */
+public interface JsonSchemaValidator {
+
+ /**
+ * Represents the result of a validation operation.
+ *
+ * @param valid Indicates whether the validation was successful.
+ * @param errorMessage An error message if the validation failed, otherwise null.
+ * @param jsonStructuredOutput The text structured content in JSON format if the
+ * validation was successful, otherwise null.
+ */
+ record ValidationResponse(boolean valid, String errorMessage, String jsonStructuredOutput) {
+
+ public static ValidationResponse asValid(String jsonStructuredOutput) {
+ return new ValidationResponse(true, null, jsonStructuredOutput);
+ }
+
+ public static ValidationResponse asInvalid(String message) {
+ return new ValidationResponse(false, message, null);
+ }
+ }
+
+ /**
+ * Validates the structured content against the provided JSON schema.
+ * @param schema The JSON schema to validate against.
+ * @param structuredContent The structured content to validate.
+ * @return A ValidationResponse indicating whether the validation was successful or
+ * not.
+ */
+ ValidationResponse validate(Map schema, Object structuredContent);
+
+}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java
new file mode 100644
index 000000000..6f69169a0
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2025 - 2025 the original author or authors.
+ */
+
+package io.modelcontextprotocol.json.schema;
+
+import java.util.function.Supplier;
+
+/**
+ * A supplier interface that provides a {@link JsonSchemaValidator} instance.
+ * Implementations of this interface are expected to return a new or cached instance of
+ * {@link JsonSchemaValidator} when {@link #get()} is invoked.
+ *
+ * @see JsonSchemaValidator
+ * @see Supplier
+ */
+public interface JsonSchemaValidatorSupplier extends Supplier {
+
+}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java
index fe3125271..2e4026325 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java
@@ -14,6 +14,7 @@
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.schema.JsonSchemaValidator;
@@ -240,10 +241,11 @@ public McpAsyncServer build() {
this.instructions);
var jsonSchemaValidator = (this.jsonSchemaValidator != null) ? this.jsonSchemaValidator
- : JsonSchemaValidator.getDefault();
+ : McpJsonDefaults.getDefaultJsonSchemaValidator();
- return new McpAsyncServer(transportProvider, jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- features, requestTimeout, uriTemplateManagerFactory, jsonSchemaValidator);
+ return new McpAsyncServer(transportProvider,
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, features,
+ requestTimeout, uriTemplateManagerFactory, jsonSchemaValidator);
}
}
@@ -267,9 +269,10 @@ public McpAsyncServer build() {
this.resources, this.resourceTemplates, this.prompts, this.completions, this.rootsChangeHandlers,
this.instructions);
var jsonSchemaValidator = this.jsonSchemaValidator != null ? this.jsonSchemaValidator
- : JsonSchemaValidator.getDefault();
- return new McpAsyncServer(transportProvider, jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- features, requestTimeout, uriTemplateManagerFactory, jsonSchemaValidator);
+ : McpJsonDefaults.getDefaultJsonSchemaValidator();
+ return new McpAsyncServer(transportProvider,
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, features,
+ requestTimeout, uriTemplateManagerFactory, jsonSchemaValidator);
}
}
@@ -834,9 +837,9 @@ public McpSyncServer build() {
this.immediateExecution);
var asyncServer = new McpAsyncServer(transportProvider,
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, asyncFeatures, requestTimeout,
- uriTemplateManagerFactory,
- jsonSchemaValidator != null ? jsonSchemaValidator : JsonSchemaValidator.getDefault());
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, asyncFeatures,
+ requestTimeout, uriTemplateManagerFactory, jsonSchemaValidator != null ? jsonSchemaValidator
+ : McpJsonDefaults.getDefaultJsonSchemaValidator());
return new McpSyncServer(asyncServer, this.immediateExecution);
}
@@ -864,10 +867,10 @@ public McpSyncServer build() {
McpServerFeatures.Async asyncFeatures = McpServerFeatures.Async.fromSync(syncFeatures,
this.immediateExecution);
var jsonSchemaValidator = this.jsonSchemaValidator != null ? this.jsonSchemaValidator
- : JsonSchemaValidator.getDefault();
+ : McpJsonDefaults.getDefaultJsonSchemaValidator();
var asyncServer = new McpAsyncServer(transportProvider,
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, asyncFeatures, this.requestTimeout,
- this.uriTemplateManagerFactory, jsonSchemaValidator);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, asyncFeatures,
+ this.requestTimeout, this.uriTemplateManagerFactory, jsonSchemaValidator);
return new McpSyncServer(asyncServer, this.immediateExecution);
}
@@ -1871,9 +1874,10 @@ public StatelessAsyncSpecification jsonSchemaValidator(JsonSchemaValidator jsonS
public McpStatelessAsyncServer build() {
var features = new McpStatelessServerFeatures.Async(this.serverInfo, this.serverCapabilities, this.tools,
this.resources, this.resourceTemplates, this.prompts, this.completions, this.instructions);
- return new McpStatelessAsyncServer(transport, jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- features, requestTimeout, uriTemplateManagerFactory,
- jsonSchemaValidator != null ? jsonSchemaValidator : JsonSchemaValidator.getDefault());
+ return new McpStatelessAsyncServer(transport,
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, features,
+ requestTimeout, uriTemplateManagerFactory, jsonSchemaValidator != null ? jsonSchemaValidator
+ : McpJsonDefaults.getDefaultJsonSchemaValidator());
}
}
@@ -2351,9 +2355,9 @@ public McpStatelessSyncServer build() {
this.resources, this.resourceTemplates, this.prompts, this.completions, this.instructions);
var asyncFeatures = McpStatelessServerFeatures.Async.fromSync(syncFeatures, this.immediateExecution);
var asyncServer = new McpStatelessAsyncServer(transport,
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, asyncFeatures, requestTimeout,
- uriTemplateManagerFactory,
- this.jsonSchemaValidator != null ? this.jsonSchemaValidator : JsonSchemaValidator.getDefault());
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, asyncFeatures,
+ requestTimeout, uriTemplateManagerFactory, this.jsonSchemaValidator != null
+ ? this.jsonSchemaValidator : McpJsonDefaults.getDefaultJsonSchemaValidator());
return new McpStatelessSyncServer(asyncServer, this.immediateExecution);
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletSseServerTransportProvider.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletSseServerTransportProvider.java
index 96cebb74a..476aafafe 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletSseServerTransportProvider.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletSseServerTransportProvider.java
@@ -15,6 +15,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.server.McpTransportContextExtractor;
@@ -632,8 +633,8 @@ public HttpServletSseServerTransportProvider build() {
throw new IllegalStateException("MessageEndpoint must be set");
}
return new HttpServletSseServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, baseUrl, messageEndpoint, sseEndpoint,
- keepAliveInterval, contextExtractor);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, baseUrl,
+ messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor);
}
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStatelessServerTransport.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStatelessServerTransport.java
index 40767f416..ae74cf839 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStatelessServerTransport.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStatelessServerTransport.java
@@ -11,6 +11,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.common.McpTransportContext;
@@ -296,8 +297,9 @@ public Builder contextExtractor(McpTransportContextExtractor
*/
public HttpServletStatelessServerTransport build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
- return new HttpServletStatelessServerTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- mcpEndpoint, contextExtractor);
+ return new HttpServletStatelessServerTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor);
}
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java
index 34671c105..5ed308b0b 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/transport/HttpServletStreamableServerTransportProvider.java
@@ -28,6 +28,7 @@
import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.util.Assert;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.util.KeepAliveScheduler;
import jakarta.servlet.AsyncContext;
@@ -842,8 +843,8 @@ public Builder keepAliveInterval(Duration keepAliveInterval) {
public HttpServletStreamableServerTransportProvider build() {
Assert.notNull(this.mcpEndpoint, "MCP endpoint must be set");
return new HttpServletStreamableServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, mcpEndpoint, disallowDelete,
- contextExtractor, keepAliveInterval);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ disallowDelete, contextExtractor, keepAliveInterval);
}
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/util/McpServiceLoader.java b/mcp-core/src/main/java/io/modelcontextprotocol/util/McpServiceLoader.java
new file mode 100644
index 000000000..e67ff46d3
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/util/McpServiceLoader.java
@@ -0,0 +1,50 @@
+package io.modelcontextprotocol.util;
+
+import java.util.Optional;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.function.Supplier;
+
+public class McpServiceLoader, R> {
+
+ private Class supplierType;
+
+ private S supplier;
+
+ private R supplierResult;
+
+ public void setSupplier(S supplier) {
+ this.supplier = supplier;
+ this.supplierResult = null;
+ }
+
+ public void unsetSupplier(S supplier) {
+ this.supplier = null;
+ this.supplierResult = null;
+ }
+
+ public McpServiceLoader(Class supplierType) {
+ this.supplierType = supplierType;
+ }
+
+ protected Optional serviceLoad(Class type) {
+ return ServiceLoader.load(type).findFirst();
+ }
+
+ @SuppressWarnings("unchecked")
+ public synchronized R getDefault() {
+ if (this.supplierResult == null) {
+ if (this.supplier == null) {
+ // Use serviceloader
+ Optional> sl = serviceLoad(this.supplierType);
+ if (sl.isEmpty()) {
+ throw new ServiceConfigurationError("No JsonMapperSupplier available for creating McpJsonMapper");
+ }
+ this.supplier = (S) sl.get();
+ }
+ this.supplierResult = this.supplier.get();
+ }
+ return supplierResult;
+ }
+
+}
diff --git a/mcp-core/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.McpJsonDefaults.xml b/mcp-core/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.McpJsonDefaults.xml
new file mode 100644
index 000000000..1a10fdfb3
--- /dev/null
+++ b/mcp-core/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.McpJsonDefaults.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpClientTransport.java b/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpClientTransport.java
index 9854de210..326fa5339 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpClientTransport.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpClientTransport.java
@@ -9,6 +9,7 @@
import java.util.function.BiConsumer;
import java.util.function.Function;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.McpClientTransport;
@@ -100,7 +101,7 @@ public Mono closeGracefully() {
@Override
public T unmarshalFrom(Object data, TypeRef typeRef) {
- return McpJsonMapper.getDefault().convertValue(data, typeRef);
+ return McpJsonDefaults.getDefaultMcpJsonMapper().convertValue(data, typeRef);
}
}
diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpServerTransport.java b/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpServerTransport.java
index f3d6b77a7..dfb01b034 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpServerTransport.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpServerTransport.java
@@ -8,6 +8,7 @@
import java.util.List;
import java.util.function.BiConsumer;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.McpSchema;
@@ -68,7 +69,7 @@ public Mono closeGracefully() {
@Override
public T unmarshalFrom(Object data, TypeRef typeRef) {
- return McpJsonMapper.getDefault().convertValue(data, typeRef);
+ return McpJsonDefaults.getDefaultMcpJsonMapper().convertValue(data, typeRef);
}
}
diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/spec/CompleteCompletionSerializationTest.java b/mcp-core/src/test/java/io/modelcontextprotocol/spec/CompleteCompletionSerializationTest.java
index 55f71fea4..da5422e4e 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/spec/CompleteCompletionSerializationTest.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/spec/CompleteCompletionSerializationTest.java
@@ -1,5 +1,6 @@
package io.modelcontextprotocol.spec;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import org.junit.jupiter.api.Test;
import java.io.IOException;
@@ -10,7 +11,7 @@ class CompleteCompletionSerializationTest {
@Test
void codeCompletionSerialization() throws IOException {
- McpJsonMapper jsonMapper = McpJsonMapper.getDefault();
+ McpJsonMapper jsonMapper = McpJsonDefaults.getDefaultMcpJsonMapper();
McpSchema.CompleteResult.CompleteCompletion codeComplete = new McpSchema.CompleteResult.CompleteCompletion(
Collections.emptyList(), 0, false);
String json = jsonMapper.writeValueAsString(codeComplete);
diff --git a/mcp-core/src/test/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java b/mcp-core/src/test/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java
index 911506e01..0af4815c9 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java
@@ -1,5 +1,6 @@
package io.modelcontextprotocol.util;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
public final class McpJsonMapperUtils {
@@ -7,6 +8,6 @@ public final class McpJsonMapperUtils {
private McpJsonMapperUtils() {
}
- public static final McpJsonMapper JSON_MAPPER = McpJsonMapper.getDefault();
+ public static final McpJsonMapper JSON_MAPPER = McpJsonDefaults.getDefaultMcpJsonMapper();
}
diff --git a/mcp-json-jackson2/pom.xml b/mcp-json-jackson2/pom.xml
index 8ea1fa7d2..0766cc22e 100644
--- a/mcp-json-jackson2/pom.xml
+++ b/mcp-json-jackson2/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
mcp-json-jackson2
jar
@@ -20,30 +20,59 @@
+
+ biz.aQute.bnd
+ bnd-maven-plugin
+ ${bnd-maven-plugin.version}
+
+
+ bnd-process
+
+ bnd-process
+
+
+
+
+
+
+
+
+
org.apache.maven.plugins
maven-jar-plugin
-
- true
-
+ ${project.build.outputDirectory}/META-INF/MANIFEST.MF
-
- io.modelcontextprotocol.sdk
- mcp-json
- 0.17.0-SNAPSHOT
-
com.fasterxml.jackson.core
jackson-databind
${jackson.version}
+
+ io.modelcontextprotocol.sdk
+ mcp-core
+ 0.15.0-SNAPSHOT
+
com.networknt
json-schema-validator
diff --git a/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapperSupplier.xml b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapperSupplier.xml
new file mode 100644
index 000000000..4db58d344
--- /dev/null
+++ b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapperSupplier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson.JacksonJsonSchemaValidatorSupplier.xml b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson.JacksonJsonSchemaValidatorSupplier.xml
new file mode 100644
index 000000000..6e45d4277
--- /dev/null
+++ b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson.JacksonJsonSchemaValidatorSupplier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/mcp-json/pom.xml b/mcp-json/pom.xml
index 9fc850e11..2cbcf3516 100644
--- a/mcp-json/pom.xml
+++ b/mcp-json/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
mcp-json
jar
diff --git a/mcp-spring/mcp-spring-webflux/pom.xml b/mcp-spring/mcp-spring-webflux/pom.xml
index 594d95750..6d8d191be 100644
--- a/mcp-spring/mcp-spring-webflux/pom.xml
+++ b/mcp-spring/mcp-spring-webflux/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
../../pom.xml
mcp-spring-webflux
@@ -25,19 +25,19 @@
io.modelcontextprotocol.sdk
mcp-json-jackson2
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
io.modelcontextprotocol.sdk
- mcp
- 0.17.0-SNAPSHOT
+ mcp-core
+ 0.18.0-SNAPSHOT
io.modelcontextprotocol.sdk
mcp-test
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
test
diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java
index f0d3ad839..5956b66c0 100644
--- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java
+++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebClientStreamableHttpTransport.java
@@ -25,6 +25,7 @@
import org.springframework.web.reactive.function.client.WebClientResponseException;
import io.modelcontextprotocol.client.McpAsyncClient;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.ClosedMcpTransportSession;
@@ -313,7 +314,7 @@ public Mono sendMessage(McpSchema.JSONRPCMessage message) {
// The spec mentions only ACCEPTED, but the existing SDKs can return
// 200 OK for notifications
- if (is2xx(response)) {
+ if (response.statusCode().is2xxSuccessful()) {
Optional contentType = response.headers().contentType();
long contentLength = response.headers().contentLength().orElse(-1);
// Existing SDKs consume notifications with no response body nor
@@ -397,15 +398,14 @@ private Flux extractError(ClientResponse response, Str
}
catch (IOException ex) {
toPropagate = new McpTransportException("Sending request failed, " + e.getMessage(), e);
- logger.debug("Received content together with {} HTTP code response: {}", response.rawStatusCode(),
- body);
+ logger.debug("Received content together with {} HTTP code response: {}", response.statusCode(), body);
}
// Some implementations can return 400 when presented with a
// session id that it doesn't know about, so we will
// invalidate the session
// https://github.com/modelcontextprotocol/typescript-sdk/issues/389
- if (isBadRequest(responseException)) {
+ if (responseException.getStatusCode().isSameCodeAs(HttpStatus.BAD_REQUEST)) {
if (!sessionRepresentation.equals(MISSING_SESSION_ID)) {
return Mono.error(new McpTransportSessionNotFoundException(sessionRepresentation, toPropagate));
}
@@ -425,8 +425,16 @@ private Flux eventStream(McpTransportStream supportedProtocolVersions)
* @return a new instance of {@link WebClientStreamableHttpTransport}
*/
public WebClientStreamableHttpTransport build() {
- return new WebClientStreamableHttpTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- webClientBuilder, endpoint, resumableStreams, openConnectionOnStartup, supportedProtocolVersions);
+ return new WebClientStreamableHttpTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, webClientBuilder,
+ endpoint, resumableStreams, openConnectionOnStartup, supportedProtocolVersions);
}
}
- /**
- * Needed for Spring 5 compatibility
- */
- @SuppressWarnings("deprecation")
- private static boolean isBadRequest(final WebClientResponseException responseException) {
- return responseException.getRawStatusCode() == HttpStatus.BAD_REQUEST.value();
- }
-
- /**
- * Needed for Spring 5 compatibility
- */
- @SuppressWarnings("deprecation")
- private static boolean isNotFound(ClientResponse response) {
- return response.rawStatusCode() == HttpStatus.NOT_FOUND.value();
- }
-
- /**
- * Needed for Spring 5 compatibility
- */
- @SuppressWarnings("deprecation")
- private static boolean isNotAllowed(ClientResponse response) {
- return response.rawStatusCode() == HttpStatus.METHOD_NOT_ALLOWED.value();
- }
-
- /**
- * Needed for Spring 5 compatibility
- */
- @SuppressWarnings("deprecation")
- private static boolean is2xx(final ClientResponse response) {
- return response.rawStatusCode() >= 200 && response.rawStatusCode() < 300;
- }
-
}
diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebFluxSseClientTransport.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebFluxSseClientTransport.java
index 91b89d6d2..5549d07d6 100644
--- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebFluxSseClientTransport.java
+++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/client/transport/WebFluxSseClientTransport.java
@@ -9,9 +9,9 @@
import java.util.function.BiConsumer;
import java.util.function.Function;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
-
import io.modelcontextprotocol.spec.HttpHeaders;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
@@ -404,7 +404,7 @@ public Builder jsonMapper(McpJsonMapper jsonMapper) {
*/
public WebFluxSseClientTransport build() {
return new WebFluxSseClientTransport(webClientBuilder,
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, sseEndpoint);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, sseEndpoint);
}
}
diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransportProvider.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransportProvider.java
index 0c80c5b8b..b7b4f22a6 100644
--- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransportProvider.java
+++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxSseServerTransportProvider.java
@@ -10,6 +10,7 @@
import java.util.concurrent.ConcurrentHashMap;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.server.McpTransportContextExtractor;
@@ -521,8 +522,9 @@ public Builder contextExtractor(McpTransportContextExtractor cont
*/
public WebFluxSseServerTransportProvider build() {
Assert.notNull(messageEndpoint, "Message endpoint must be set");
- return new WebFluxSseServerTransportProvider(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- baseUrl, messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor);
+ return new WebFluxSseServerTransportProvider(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, baseUrl,
+ messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor);
}
}
diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStatelessServerTransport.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStatelessServerTransport.java
index 400be341e..78af45642 100644
--- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStatelessServerTransport.java
+++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStatelessServerTransport.java
@@ -4,6 +4,7 @@
package io.modelcontextprotocol.server.transport;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.server.McpStatelessServerHandler;
@@ -213,8 +214,9 @@ public Builder contextExtractor(McpTransportContextExtractor cont
*/
public WebFluxStatelessServerTransport build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
- return new WebFluxStatelessServerTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- mcpEndpoint, contextExtractor);
+ return new WebFluxStatelessServerTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor);
}
}
diff --git a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStreamableServerTransportProvider.java b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStreamableServerTransportProvider.java
index deebfc616..db171fe50 100644
--- a/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStreamableServerTransportProvider.java
+++ b/mcp-spring/mcp-spring-webflux/src/main/java/io/modelcontextprotocol/server/transport/WebFluxStreamableServerTransportProvider.java
@@ -4,6 +4,7 @@
package io.modelcontextprotocol.server.transport;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.common.McpTransportContext;
@@ -486,8 +487,8 @@ public Builder keepAliveInterval(Duration keepAliveInterval) {
public WebFluxStreamableServerTransportProvider build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
return new WebFluxStreamableServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, mcpEndpoint, contextExtractor,
- disallowDelete, keepAliveInterval);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor, disallowDelete, keepAliveInterval);
}
}
diff --git a/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/utils/McpJsonMapperUtils.java b/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/utils/McpJsonMapperUtils.java
index 67347573c..0177932cc 100644
--- a/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/utils/McpJsonMapperUtils.java
+++ b/mcp-spring/mcp-spring-webflux/src/test/java/io/modelcontextprotocol/utils/McpJsonMapperUtils.java
@@ -1,5 +1,6 @@
package io.modelcontextprotocol.utils;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
public final class McpJsonMapperUtils {
@@ -7,6 +8,6 @@ public final class McpJsonMapperUtils {
private McpJsonMapperUtils() {
}
- public static final McpJsonMapper JSON_MAPPER = McpJsonMapper.createDefault();
+ public static final McpJsonMapper JSON_MAPPER = McpJsonDefaults.getDefaultMcpJsonMapper();
}
\ No newline at end of file
diff --git a/mcp-spring/mcp-spring-webmvc/pom.xml b/mcp-spring/mcp-spring-webmvc/pom.xml
index 6460f652f..54e05a517 100644
--- a/mcp-spring/mcp-spring-webmvc/pom.xml
+++ b/mcp-spring/mcp-spring-webmvc/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
../../pom.xml
mcp-spring-webmvc
@@ -25,13 +25,13 @@
io.modelcontextprotocol.sdk
mcp-json-jackson2
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
io.modelcontextprotocol.sdk
- mcp
- 0.17.0-SNAPSHOT
+ mcp-core
+ 0.18.0-SNAPSHOT
@@ -43,14 +43,14 @@
io.modelcontextprotocol.sdk
mcp-test
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
test
io.modelcontextprotocol.sdk
mcp-spring-webflux
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
test
diff --git a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProvider.java b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProvider.java
index 6c35de56d..2a29075ae 100644
--- a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProvider.java
+++ b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProvider.java
@@ -11,6 +11,7 @@
import java.util.concurrent.locks.ReentrantLock;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.server.McpTransportContextExtractor;
@@ -559,8 +560,9 @@ public WebMvcSseServerTransportProvider build() {
if (messageEndpoint == null) {
throw new IllegalStateException("MessageEndpoint must be set");
}
- return new WebMvcSseServerTransportProvider(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- baseUrl, messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor);
+ return new WebMvcSseServerTransportProvider(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, baseUrl,
+ messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor);
}
}
diff --git a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStatelessServerTransport.java b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStatelessServerTransport.java
index 4223084ff..50156b0bc 100644
--- a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStatelessServerTransport.java
+++ b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStatelessServerTransport.java
@@ -5,6 +5,7 @@
package io.modelcontextprotocol.server.transport;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.server.McpStatelessServerHandler;
import io.modelcontextprotocol.server.McpTransportContextExtractor;
@@ -231,8 +232,9 @@ public Builder contextExtractor(McpTransportContextExtractor cont
*/
public WebMvcStatelessServerTransport build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
- return new WebMvcStatelessServerTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- mcpEndpoint, contextExtractor);
+ return new WebMvcStatelessServerTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor);
}
}
diff --git a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStreamableServerTransportProvider.java b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStreamableServerTransportProvider.java
index f2a58d4d8..4b4d97e88 100644
--- a/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStreamableServerTransportProvider.java
+++ b/mcp-spring/mcp-spring-webmvc/src/main/java/io/modelcontextprotocol/server/transport/WebMvcStreamableServerTransportProvider.java
@@ -10,6 +10,7 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -22,7 +23,6 @@
import org.springframework.web.servlet.function.ServerResponse.SseBuilder;
import io.modelcontextprotocol.json.TypeRef;
-
import io.modelcontextprotocol.common.McpTransportContext;
import io.modelcontextprotocol.server.McpTransportContextExtractor;
import io.modelcontextprotocol.spec.HttpHeaders;
@@ -681,8 +681,8 @@ public Builder keepAliveInterval(Duration keepAliveInterval) {
public WebMvcStreamableServerTransportProvider build() {
Assert.notNull(this.mcpEndpoint, "MCP endpoint must be set");
return new WebMvcStreamableServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, mcpEndpoint, disallowDelete,
- contextExtractor, keepAliveInterval);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ disallowDelete, contextExtractor, keepAliveInterval);
}
}
diff --git a/mcp-spring/mcp-spring-webmvc/src/test/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProviderTests.java b/mcp-spring/mcp-spring-webmvc/src/test/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProviderTests.java
index 1074e8a35..36ea2d354 100644
--- a/mcp-spring/mcp-spring-webmvc/src/test/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProviderTests.java
+++ b/mcp-spring/mcp-spring-webmvc/src/test/java/io/modelcontextprotocol/server/transport/WebMvcSseServerTransportProviderTests.java
@@ -7,6 +7,7 @@
import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.TestUtil;
@@ -104,7 +105,7 @@ public WebMvcSseServerTransportProvider webMvcSseServerTransportProvider() {
.baseUrl("http://localhost:" + PORT + "/")
.messageEndpoint(MESSAGE_ENDPOINT)
.sseEndpoint(WebMvcSseServerTransportProvider.DEFAULT_SSE_ENDPOINT)
- .jsonMapper(McpJsonMapper.getDefault())
+ .jsonMapper(McpJsonDefaults.getDefaultMcpJsonMapper())
.contextExtractor(req -> McpTransportContext.EMPTY)
.build();
}
diff --git a/mcp-test/pom.xml b/mcp-test/pom.xml
index 3fbd028f4..7fc22e5d2 100644
--- a/mcp-test/pom.xml
+++ b/mcp-test/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
mcp-test
jar
@@ -24,7 +24,7 @@
io.modelcontextprotocol.sdk
mcp
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java b/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java
index cd8458311..7168da3f8 100644
--- a/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java
+++ b/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java
@@ -9,6 +9,7 @@
import java.util.function.BiConsumer;
import java.util.function.Function;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.McpClientTransport;
@@ -94,7 +95,7 @@ public Mono closeGracefully() {
@Override
public T unmarshalFrom(Object data, TypeRef typeRef) {
- return McpJsonMapper.getDefault().convertValue(data, typeRef);
+ return McpJsonDefaults.getDefaultMcpJsonMapper().convertValue(data, typeRef);
}
}
diff --git a/mcp-test/src/main/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java b/mcp-test/src/main/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java
index 723965519..45e4a4e3c 100644
--- a/mcp-test/src/main/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java
+++ b/mcp-test/src/main/java/io/modelcontextprotocol/util/McpJsonMapperUtils.java
@@ -1,5 +1,6 @@
package io.modelcontextprotocol.util;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
public final class McpJsonMapperUtils {
@@ -7,6 +8,6 @@ public final class McpJsonMapperUtils {
private McpJsonMapperUtils() {
}
- public static final McpJsonMapper JSON_MAPPER = McpJsonMapper.getDefault();
+ public static final McpJsonMapper JSON_MAPPER = McpJsonDefaults.getDefaultMcpJsonMapper();
}
\ No newline at end of file
diff --git a/mcp/pom.xml b/mcp/pom.xml
index 270dc2a1f..0e0ed1288 100644
--- a/mcp/pom.xml
+++ b/mcp/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
mcp
jar
@@ -25,13 +25,13 @@
io.modelcontextprotocol.sdk
mcp-json-jackson2
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
io.modelcontextprotocol.sdk
mcp-core
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
diff --git a/pom.xml b/pom.xml
index ca9ce7be4..f7e00d4c8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdk
mcp-parent
- 0.17.0-SNAPSHOT
+ 0.18.0-SNAPSHOT
pom
https://github.com/modelcontextprotocol/java-sdk
@@ -105,7 +105,6 @@
mcp
mcp-core
mcp-json-jackson2
- mcp-json
mcp-spring/mcp-spring-webflux
mcp-spring/mcp-spring-webmvc
mcp-test