diff --git a/mcp-bom/pom.xml b/mcp-bom/pom.xml
index 447c9e0bd..f3d76d819 100644
--- a/mcp-bom/pom.xml
+++ b/mcp-bom/pom.xml
@@ -40,13 +40,6 @@
${project.version}
-
-
- io.modelcontextprotocol.sdk
- mcp-json
- ${project.version}
-
-
io.modelcontextprotocol.sdk
diff --git a/mcp-core/pom.xml b/mcp-core/pom.xml
index 0c8650f46..1db05f9e4 100644
--- a/mcp-core/pom.xml
+++ b/mcp-core/pom.xml
@@ -65,11 +65,6 @@
-
- io.modelcontextprotocol.sdk
- mcp-json
- 0.18.0-SNAPSHOT
-
org.slf4j
@@ -97,14 +92,6 @@
provided
-
-
- io.modelcontextprotocol.sdk
- mcp-json-jackson3
- 0.18.0-SNAPSHOT
- test
-
-
org.springframework
spring-webmvc
@@ -112,6 +99,12 @@
test
+
+ tools.jackson.core
+ jackson-databind
+ ${jackson3.version}
+ test
+
io.projectreactor.netty
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
index c9989f832..1210b9078 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/McpClient.java
@@ -5,6 +5,7 @@
package io.modelcontextprotocol.client;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.schema.JsonSchemaValidator;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
@@ -491,9 +492,12 @@ public McpSyncClient build() {
McpClientFeatures.Async asyncFeatures = McpClientFeatures.Async.fromSync(syncFeatures);
- return new McpSyncClient(new McpAsyncClient(transport, this.requestTimeout, this.initializationTimeout,
- jsonSchemaValidator != null ? jsonSchemaValidator : JsonSchemaValidator.getDefault(),
- asyncFeatures), this.contextProvider);
+ return new McpSyncClient(
+ new McpAsyncClient(transport, this.requestTimeout, this.initializationTimeout,
+ jsonSchemaValidator != null ? jsonSchemaValidator
+ : McpJsonDefaults.getDefaultJsonSchemaValidator(),
+ asyncFeatures),
+ this.contextProvider);
}
}
@@ -826,7 +830,7 @@ public AsyncSpec enableCallToolSchemaCaching(boolean enableCallToolSchemaCaching
*/
public McpAsyncClient build() {
var jsonSchemaValidator = (this.jsonSchemaValidator != null) ? this.jsonSchemaValidator
- : JsonSchemaValidator.getDefault();
+ : McpJsonDefaults.getDefaultJsonSchemaValidator();
return new McpAsyncClient(this.transport, this.requestTimeout, this.initializationTimeout,
jsonSchemaValidator,
new McpClientFeatures.Async(this.clientInfo, this.capabilities, this.roots,
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java
index ae093316f..b9ed2711d 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java
@@ -22,6 +22,7 @@
import io.modelcontextprotocol.client.transport.customizer.McpAsyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.client.transport.customizer.McpSyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.HttpHeaders;
@@ -327,7 +328,7 @@ public Builder connectTimeout(Duration connectTimeout) {
public HttpClientSseClientTransport build() {
HttpClient httpClient = this.clientBuilder.connectTimeout(this.connectTimeout).build();
return new HttpClientSseClientTransport(httpClient, requestBuilder, baseUri, sseEndpoint,
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, httpRequestCustomizer);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, httpRequestCustomizer);
}
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java
index 0a8dff363..20ad02691 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java
@@ -25,6 +25,7 @@
import io.modelcontextprotocol.client.transport.customizer.McpAsyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.client.transport.customizer.McpSyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.ClosedMcpTransportSession;
@@ -822,9 +823,10 @@ public Builder supportedProtocolVersions(List supportedProtocolVersions)
*/
public HttpClientStreamableHttpTransport build() {
HttpClient httpClient = this.clientBuilder.connectTimeout(this.connectTimeout).build();
- return new HttpClientStreamableHttpTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- httpClient, requestBuilder, baseUri, endpoint, resumableStreams, openConnectionOnStartup,
- httpRequestCustomizer, supportedProtocolVersions);
+ return new HttpClientStreamableHttpTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, httpClient,
+ requestBuilder, baseUri, endpoint, resumableStreams, openConnectionOnStartup, httpRequestCustomizer,
+ supportedProtocolVersions);
}
}
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonDefaults.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonDefaults.java
new file mode 100644
index 000000000..7f8188be5
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonDefaults.java
@@ -0,0 +1,78 @@
+/**
+ * Copyright 2026 - 2026 the original author or authors.
+ */
+package io.modelcontextprotocol.json;
+
+import io.modelcontextprotocol.json.schema.JsonSchemaValidator;
+import io.modelcontextprotocol.json.schema.JsonSchemaValidatorSupplier;
+import io.modelcontextprotocol.util.McpServiceLoader;
+
+/**
+ * This class is to be used to provide access to the default
+ * McpJsonMapper and to the default JsonSchemaValidator instances via the
+ * static methods: getDefaultMcpJsonMapper and getDefaultJsonSchemaValidator.
+ *
+ * The initialization of (singleton) instances of this class is different
+ * in non-OSGi environments and OSGi environments. Specifically, in non-OSGi environments
+ * The McpJsonDefaults class will be loaded by whatever classloader is used
+ * to call one of the existing static get methods for the first time. For servers,
+ * this will usually be in response to the creation of the first McpServer instance.
+ * At that first time, the mcpMapperServiceLoader and mcpValidatorServiceLoader will be
+ * null, and the McpJsonDefaults constructor will be called, creating/initializing the
+ * mcpMapperServiceLoader and the mcpValidatorServiceLoader...which will then be used
+ * to call the ServiceLoader.load method.
+ * In OSGi environments, upon bundle activation SCR will create a new (singleton) instance
+ * of McpJsonDefaults (via the constructor), and then call then call the setMcpJsonMapperSupplier
+ * and setJsonSchemaValidatorSupplier methods with the SCR-discovered instances of those
+ * services. This does depend upon the jars/bundles providing those suppliers to be
+ * started/activated. This SCR behavior is dictated by xml files in OSGi-INF directory
+ * of mcp-core (this project/jar/bundle), and the jsonmapper and jsonschemvalidator provider
+ * jars/bundles (e.g. mcp-json-jackson2, 3, or others).
+ *
+ *
+ *
+ */
+public class McpJsonDefaults {
+
+ protected static McpServiceLoader mcpMapperServiceLoader;
+
+ protected static McpServiceLoader mcpValidatorServiceLoader;
+
+ public McpJsonDefaults() {
+ mcpMapperServiceLoader = new McpServiceLoader(
+ McpJsonMapperSupplier.class);
+ mcpValidatorServiceLoader = new McpServiceLoader(
+ JsonSchemaValidatorSupplier.class);
+ }
+
+ void setMcpJsonMapperSupplier(McpJsonMapperSupplier supplier) {
+ mcpMapperServiceLoader.setSupplier(supplier);
+ }
+
+ void unsetMcpJsonMapperSupplier(McpJsonMapperSupplier supplier) {
+ mcpMapperServiceLoader.unsetSupplier(supplier);
+ }
+
+ public synchronized static McpJsonMapper getDefaultMcpJsonMapper() {
+ if (mcpMapperServiceLoader == null) {
+ new McpJsonDefaults();
+ }
+ return mcpMapperServiceLoader.getDefault();
+ }
+
+ void setJsonSchemaValidatorSupplier(JsonSchemaValidatorSupplier supplier) {
+ mcpValidatorServiceLoader.setSupplier(supplier);
+ }
+
+ void unsetJsonSchemaValidatorSupplier(JsonSchemaValidatorSupplier supplier) {
+ mcpValidatorServiceLoader.unsetSupplier(supplier);
+ }
+
+ public synchronized static JsonSchemaValidator getDefaultJsonSchemaValidator() {
+ if (mcpValidatorServiceLoader == null) {
+ new McpJsonDefaults();
+ }
+ return mcpValidatorServiceLoader.getDefault();
+ }
+
+}
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java
similarity index 81%
rename from mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java
index 1e30cad16..8481d1703 100644
--- a/mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonMapper.java
@@ -87,24 +87,4 @@ public interface McpJsonMapper {
*/
byte[] writeValueAsBytes(Object value) throws IOException;
- /**
- * Returns the default {@link McpJsonMapper}.
- * @return The default {@link McpJsonMapper}
- * @throws IllegalStateException If no {@link McpJsonMapper} implementation exists on
- * the classpath.
- */
- static McpJsonMapper getDefault() {
- return McpJsonInternal.getDefaultMapper();
- }
-
- /**
- * Creates a new default {@link McpJsonMapper}.
- * @return The default {@link McpJsonMapper}
- * @throws IllegalStateException If no {@link McpJsonMapper} implementation exists on
- * the classpath.
- */
- static McpJsonMapper createDefault() {
- return McpJsonInternal.createDefaultMapper();
- }
-
}
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonMapperSupplier.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonMapperSupplier.java
similarity index 100%
rename from mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonMapperSupplier.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonMapperSupplier.java
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/TypeRef.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/TypeRef.java
similarity index 94%
rename from mcp-json/src/main/java/io/modelcontextprotocol/json/TypeRef.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/json/TypeRef.java
index ab37b43f3..725513c66 100644
--- a/mcp-json/src/main/java/io/modelcontextprotocol/json/TypeRef.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/TypeRef.java
@@ -9,7 +9,7 @@
/**
* Captures generic type information at runtime for parameterized JSON (de)serialization.
- * Usage: TypeRef<List<Foo>> ref = new TypeRef<>(){};
+ * Usage: TypeRef> ref = new TypeRef<>(){};
*/
public abstract class TypeRef {
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
similarity index 69%
rename from mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
index 8e35c0237..09fe604f4 100644
--- a/mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidator.java
@@ -41,24 +41,4 @@ public static ValidationResponse asInvalid(String message) {
*/
ValidationResponse validate(Map schema, Object structuredContent);
- /**
- * Creates the default {@link JsonSchemaValidator}.
- * @return The default {@link JsonSchemaValidator}
- * @throws IllegalStateException If no {@link JsonSchemaValidator} implementation
- * exists on the classpath.
- */
- static JsonSchemaValidator createDefault() {
- return JsonSchemaInternal.createDefaultValidator();
- }
-
- /**
- * Returns the default {@link JsonSchemaValidator}.
- * @return The default {@link JsonSchemaValidator}
- * @throws IllegalStateException If no {@link JsonSchemaValidator} implementation
- * exists on the classpath.
- */
- static JsonSchemaValidator getDefault() {
- return JsonSchemaInternal.getDefaultValidator();
- }
-
}
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java b/mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java
similarity index 100%
rename from mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java
rename to mcp-core/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorSupplier.java
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..ded3a2eb4
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/util/McpServiceLoader.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 2026 - 2026 the original author or authors.
+ */
+package io.modelcontextprotocol.util;
+
+import java.util.Optional;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.function.Supplier;
+
+/**
+ * Instance of this class are intended to be used differently in OSGi and
+ * non-OSGi environments. In all non-OSGi environments the supplier member
+ * will be null and the serviceLoad method will be called to
+ * use the ServiceLoader.load to find the first instance of the supplier (assuming
+ * one is present in the runtime),
+ * cache it, and call the supplier's get method.
+ * In OSGi environments, the Service component runtime (scr) will call
+ * the setSupplier method upon bundle activation (assuming one is present in
+ * the runtime), and subsequent calls will use the given supplier instance
+ * rather than the ServiceLoader.load.
+ *
+ * @param the type of the supplier
+ * @param the type of the supplier result/returned value
+ */
+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 %s available for creating McpJsonMapper".format(this.supplierType.getSimpleName()));
+ }
+ 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..04b058973 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpClientTransport.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpClientTransport.java
@@ -9,7 +9,7 @@
import java.util.function.BiConsumer;
import java.util.function.Function;
-import io.modelcontextprotocol.json.McpJsonMapper;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
@@ -100,7 +100,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..5fefb892d 100644
--- a/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpServerTransport.java
+++ b/mcp-core/src/test/java/io/modelcontextprotocol/MockMcpServerTransport.java
@@ -8,7 +8,7 @@
import java.util.List;
import java.util.function.BiConsumer;
-import io.modelcontextprotocol.json.McpJsonMapper;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.JSONRPCNotification;
@@ -68,7 +68,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 956a72c23..37384fea9 100644
--- a/mcp-json-jackson2/pom.xml
+++ b/mcp-json-jackson2/pom.xml
@@ -10,7 +10,7 @@
mcp-json-jackson2
jar
- Java MCP SDK JSON Jackson
+ Java MCP SDK JSON Jackson 2
Java MCP SDK JSON implementation based on Jackson 2
https://github.com/modelcontextprotocol/java-sdk
@@ -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.18.0-SNAPSHOT
-
com.fasterxml.jackson.core
jackson-databind
${jackson2.version}
+
+ io.modelcontextprotocol.sdk
+ mcp-core
+ 0.18.0-SNAPSHOT
+
com.networknt
json-schema-validator
diff --git a/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson2.JacksonMcpJsonMapperSupplier.xml b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson2.JacksonMcpJsonMapperSupplier.xml
new file mode 100644
index 000000000..1d6705f56
--- /dev/null
+++ b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson2.JacksonMcpJsonMapperSupplier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson2.JacksonJsonSchemaValidatorSupplier.xml b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson2.JacksonJsonSchemaValidatorSupplier.xml
new file mode 100644
index 000000000..ad628745f
--- /dev/null
+++ b/mcp-json-jackson2/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson2.JacksonJsonSchemaValidatorSupplier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java b/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java
index 062927587..bf865a087 100644
--- a/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java
+++ b/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java
@@ -14,7 +14,7 @@ class McpJsonMapperTest {
@Test
void shouldUseJackson2Mapper() {
- assertThat(McpJsonMapper.getDefault()).isInstanceOf(JacksonMcpJsonMapper.class);
+ assertThat(McpJsonDefaults.getDefaultMcpJsonMapper()).isInstanceOf(JacksonMcpJsonMapper.class);
}
}
diff --git a/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java b/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java
index 7b92eb7ee..0c5864a2e 100644
--- a/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java
+++ b/mcp-json-jackson2/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java
@@ -8,13 +8,14 @@
import org.junit.jupiter.api.Test;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.schema.jackson2.DefaultJsonSchemaValidator;
class JsonSchemaValidatorTest {
@Test
void shouldUseJackson2Mapper() {
- assertThat(JsonSchemaValidator.getDefault()).isInstanceOf(DefaultJsonSchemaValidator.class);
+ assertThat(McpJsonDefaults.getDefaultJsonSchemaValidator()).isInstanceOf(DefaultJsonSchemaValidator.class);
}
}
diff --git a/mcp-json-jackson3/pom.xml b/mcp-json-jackson3/pom.xml
index a3cc47048..c02bc375b 100644
--- a/mcp-json-jackson3/pom.xml
+++ b/mcp-json-jackson3/pom.xml
@@ -10,7 +10,7 @@
mcp-json-jackson3
jar
- Java MCP SDK JSON Jackson
+ Java MCP SDK JSON Jackson 3
Java MCP SDK JSON implementation based on Jackson 3
https://github.com/modelcontextprotocol/java-sdk
@@ -20,14 +20,42 @@
+
+ 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
@@ -35,9 +63,9 @@
- io.modelcontextprotocol.sdk
- mcp-json
- 0.18.0-SNAPSHOT
+ io.modelcontextprotocol.sdk
+ mcp-core
+ 0.18.0-SNAPSHOT
tools.jackson.core
diff --git a/mcp-json-jackson3/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapperSupplier.xml b/mcp-json-jackson3/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapperSupplier.xml
new file mode 100644
index 000000000..0ad8a7b42
--- /dev/null
+++ b/mcp-json-jackson3/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapperSupplier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/mcp-json-jackson3/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson3.JacksonJsonSchemaValidatorSupplier.xml b/mcp-json-jackson3/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson3.JacksonJsonSchemaValidatorSupplier.xml
new file mode 100644
index 000000000..d14d8bea3
--- /dev/null
+++ b/mcp-json-jackson3/src/main/resources/OSGI-INF/io.modelcontextprotocol.json.schema.jackson3.JacksonJsonSchemaValidatorSupplier.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java b/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java
index e2d0a1d55..58f7e01dc 100644
--- a/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java
+++ b/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/McpJsonMapperTest.java
@@ -14,7 +14,7 @@ class McpJsonMapperTest {
@Test
void shouldUseJackson2Mapper() {
- assertThat(McpJsonMapper.getDefault()).isInstanceOf(JacksonMcpJsonMapper.class);
+ assertThat(McpJsonDefaults.getDefaultMcpJsonMapper()).isInstanceOf(JacksonMcpJsonMapper.class);
}
}
diff --git a/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java b/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java
index 29c450d40..89197579b 100644
--- a/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java
+++ b/mcp-json-jackson3/src/test/java/io/modelcontextprotocol/json/schema/JsonSchemaValidatorTest.java
@@ -8,13 +8,14 @@
import org.junit.jupiter.api.Test;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.schema.jackson3.DefaultJsonSchemaValidator;
class JsonSchemaValidatorTest {
@Test
void shouldUseJackson2Mapper() {
- assertThat(JsonSchemaValidator.getDefault()).isInstanceOf(DefaultJsonSchemaValidator.class);
+ assertThat(McpJsonDefaults.getDefaultJsonSchemaValidator()).isInstanceOf(DefaultJsonSchemaValidator.class);
}
}
diff --git a/mcp-json/pom.xml b/mcp-json/pom.xml
deleted file mode 100644
index 2cbcf3516..000000000
--- a/mcp-json/pom.xml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
- 4.0.0
-
- io.modelcontextprotocol.sdk
- mcp-parent
- 0.18.0-SNAPSHOT
-
- mcp-json
- jar
- Java MCP SDK JSON Support
- Java MCP SDK JSON Support API
- https://github.com/modelcontextprotocol/java-sdk
-
- https://github.com/modelcontextprotocol/java-sdk
- git://github.com/modelcontextprotocol/java-sdk.git
- git@github.com/modelcontextprotocol/java-sdk.git
-
-
-
-
- org.apache.maven.plugins
- maven-jar-plugin
-
-
-
- true
-
-
-
-
-
-
-
-
-
-
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonInternal.java b/mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonInternal.java
deleted file mode 100644
index 31930ab33..000000000
--- a/mcp-json/src/main/java/io/modelcontextprotocol/json/McpJsonInternal.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2025 - 2025 the original author or authors.
- */
-
-package io.modelcontextprotocol.json;
-
-import java.util.ServiceLoader;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Stream;
-
-/**
- * Utility class for creating a default {@link McpJsonMapper} instance. This class
- * provides a single method to create a default mapper using the {@link ServiceLoader}
- * mechanism.
- */
-final class McpJsonInternal {
-
- private static McpJsonMapper defaultJsonMapper = null;
-
- /**
- * Returns the cached default {@link McpJsonMapper} instance. If the default mapper
- * has not been created yet, it will be initialized using the
- * {@link #createDefaultMapper()} method.
- * @return the default {@link McpJsonMapper} instance
- * @throws IllegalStateException if no default {@link McpJsonMapper} implementation is
- * found
- */
- static McpJsonMapper getDefaultMapper() {
- if (defaultJsonMapper == null) {
- defaultJsonMapper = McpJsonInternal.createDefaultMapper();
- }
- return defaultJsonMapper;
- }
-
- /**
- * Creates a default {@link McpJsonMapper} instance using the {@link ServiceLoader}
- * mechanism. The default mapper is resolved by loading the first available
- * {@link McpJsonMapperSupplier} implementation on the classpath.
- * @return the default {@link McpJsonMapper} instance
- * @throws IllegalStateException if no default {@link McpJsonMapper} implementation is
- * found
- */
- static McpJsonMapper createDefaultMapper() {
- AtomicReference ex = new AtomicReference<>();
- return ServiceLoader.load(McpJsonMapperSupplier.class).stream().flatMap(p -> {
- try {
- McpJsonMapperSupplier supplier = p.get();
- return Stream.ofNullable(supplier);
- }
- catch (Exception e) {
- addException(ex, e);
- return Stream.empty();
- }
- }).flatMap(jsonMapperSupplier -> {
- try {
- return Stream.ofNullable(jsonMapperSupplier.get());
- }
- catch (Exception e) {
- addException(ex, e);
- return Stream.empty();
- }
- }).findFirst().orElseThrow(() -> {
- if (ex.get() != null) {
- return ex.get();
- }
- else {
- return new IllegalStateException("No default McpJsonMapper implementation found");
- }
- });
- }
-
- private static void addException(AtomicReference ref, Exception toAdd) {
- ref.updateAndGet(existing -> {
- if (existing == null) {
- return new IllegalStateException("Failed to initialize default McpJsonMapper", toAdd);
- }
- else {
- existing.addSuppressed(toAdd);
- return existing;
- }
- });
- }
-
-}
diff --git a/mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaInternal.java b/mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaInternal.java
deleted file mode 100644
index 2497e7f80..000000000
--- a/mcp-json/src/main/java/io/modelcontextprotocol/json/schema/JsonSchemaInternal.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2025 - 2025 the original author or authors.
- */
-
-package io.modelcontextprotocol.json.schema;
-
-import java.util.ServiceLoader;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Stream;
-
-/**
- * Internal utility class for creating a default {@link JsonSchemaValidator} instance.
- * This class uses the {@link ServiceLoader} to discover and instantiate a
- * {@link JsonSchemaValidatorSupplier} implementation.
- */
-final class JsonSchemaInternal {
-
- private static JsonSchemaValidator defaultValidator = null;
-
- /**
- * Returns the default {@link JsonSchemaValidator} instance. If the default validator
- * has not been initialized, it will be created using the {@link ServiceLoader} to
- * discover and instantiate a {@link JsonSchemaValidatorSupplier} implementation.
- * @return The default {@link JsonSchemaValidator} instance.
- * @throws IllegalStateException If no {@link JsonSchemaValidatorSupplier}
- * implementation exists on the classpath or if an error occurs during instantiation.
- */
- static JsonSchemaValidator getDefaultValidator() {
- if (defaultValidator == null) {
- defaultValidator = JsonSchemaInternal.createDefaultValidator();
- }
- return defaultValidator;
- }
-
- /**
- * Creates a default {@link JsonSchemaValidator} instance by loading a
- * {@link JsonSchemaValidatorSupplier} implementation using the {@link ServiceLoader}.
- * @return A default {@link JsonSchemaValidator} instance.
- * @throws IllegalStateException If no {@link JsonSchemaValidatorSupplier}
- * implementation is found or if an error occurs during instantiation.
- */
- static JsonSchemaValidator createDefaultValidator() {
- AtomicReference ex = new AtomicReference<>();
- return ServiceLoader.load(JsonSchemaValidatorSupplier.class).stream().flatMap(p -> {
- try {
- JsonSchemaValidatorSupplier supplier = p.get();
- return Stream.ofNullable(supplier);
- }
- catch (Exception e) {
- addException(ex, e);
- return Stream.empty();
- }
- }).flatMap(jsonMapperSupplier -> {
- try {
- return Stream.of(jsonMapperSupplier.get());
- }
- catch (Exception e) {
- addException(ex, e);
- return Stream.empty();
- }
- }).findFirst().orElseThrow(() -> {
- if (ex.get() != null) {
- return ex.get();
- }
- else {
- return new IllegalStateException("No default JsonSchemaValidatorSupplier implementation found");
- }
- });
- }
-
- private static void addException(AtomicReference ref, Exception toAdd) {
- ref.updateAndGet(existing -> {
- if (existing == null) {
- return new IllegalStateException("Failed to initialize default JsonSchemaValidatorSupplier", toAdd);
- }
- else {
- existing.addSuppressed(toAdd);
- return existing;
- }
- });
- }
-
-}
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 5af98985d..f5b6ead89 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;
@@ -615,8 +616,9 @@ public Builder supportedProtocolVersions(List 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);
}
}
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..3c3a008b1 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,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;
@@ -404,7 +405,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/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 67b5f571c..244b17e59 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;
@@ -232,8 +233,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..8d54fd25b 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;
@@ -681,8 +682,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/src/main/java/io/modelcontextprotocol/MockMcpTransport.java b/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java
index cd8458311..7d71376b4 100644
--- a/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java
+++ b/mcp-test/src/main/java/io/modelcontextprotocol/MockMcpTransport.java
@@ -9,7 +9,7 @@
import java.util.function.BiConsumer;
import java.util.function.Function;
-import io.modelcontextprotocol.json.McpJsonMapper;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.TypeRef;
import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpSchema;
@@ -94,7 +94,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/pom.xml b/pom.xml
index faa2ad86e..f25f49275 100644
--- a/pom.xml
+++ b/pom.xml
@@ -109,7 +109,6 @@
mcp-core
mcp-json-jackson2
mcp-json-jackson3
- mcp-json
mcp-spring/mcp-spring-webflux
mcp-spring/mcp-spring-webmvc
mcp-test