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 c9989f8..1210b90 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 interface McpClient {
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 interface McpClient {
*/
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 ae09331..b9ed271 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.ResponseSubscribers.ResponseEven
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 class HttpClientSseClientTransport implements McpClientTransport {
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 400a8a2..00b80f1 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.ResponseSubscribers.ResponseEven
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;
@@ -842,9 +843,10 @@ public class HttpClientStreamableHttpTransport implements McpClientTransport {
*/
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 0000000..b8bdd90
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/json/McpJsonDefaults.java
@@ -0,0 +1,76 @@
+/**
+ * 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 inject suppliers via 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 1e30cad..8481d17 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 ab37b43..725513c 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 @@ import java.lang.reflect.Type;
/**
* 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 8e35c02..09fe604 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 interface JsonSchemaValidator {
*/
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 f4196c0..73a5016 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java
@@ -4,7 +4,17 @@
package io.modelcontextprotocol.server;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+
import io.modelcontextprotocol.common.McpTransportContext;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.json.schema.JsonSchemaValidator;
import io.modelcontextprotocol.spec.McpSchema;
@@ -18,11 +28,6 @@ import io.modelcontextprotocol.util.McpUriTemplateManagerFactory;
import io.modelcontextprotocol.util.ToolNameValidator;
import reactor.core.publisher.Mono;
-import java.time.Duration;
-import java.util.*;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-
/**
* Factory class for creating Model Context Protocol (MCP) servers. MCP servers expose
* tools, resources, and prompts to AI models through a standardized interface.
@@ -235,10 +240,11 @@ public interface McpServer {
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);
}
}
@@ -262,9 +268,10 @@ public interface McpServer {
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);
}
}
@@ -851,9 +858,9 @@ public interface McpServer {
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);
}
@@ -881,10 +888,10 @@ public interface McpServer {
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);
}
@@ -1931,9 +1938,10 @@ public interface McpServer {
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());
}
}
@@ -2432,9 +2440,9 @@ public interface McpServer {
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 d12fb8c..c07906b 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
@@ -18,6 +18,7 @@ import java.util.concurrent.ConcurrentHashMap;
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;
@@ -689,8 +690,8 @@ public class HttpServletSseServerTransportProvider extends HttpServlet implement
throw new IllegalStateException("MessageEndpoint must be set");
}
return new HttpServletSseServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, baseUrl, messageEndpoint, sseEndpoint,
- keepAliveInterval, contextExtractor, securityValidator);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, baseUrl,
+ messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor, securityValidator);
}
}
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 106f834..6431a2c 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
@@ -16,6 +16,7 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import io.modelcontextprotocol.json.McpJsonDefaults;
import io.modelcontextprotocol.json.McpJsonMapper;
import io.modelcontextprotocol.common.McpTransportContext;
@@ -347,8 +348,9 @@ public class HttpServletStatelessServerTransport extends HttpServlet implements
*/
public HttpServletStatelessServerTransport build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
- return new HttpServletStatelessServerTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- mcpEndpoint, contextExtractor, securityValidator);
+ return new HttpServletStatelessServerTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor, securityValidator);
}
}
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 d9c0916..18cdcff 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
@@ -32,6 +32,7 @@ import io.modelcontextprotocol.spec.McpStreamableServerTransport;
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;
@@ -912,8 +913,8 @@ public class HttpServletStreamableServerTransportProvider extends HttpServlet
public HttpServletStreamableServerTransportProvider build() {
Assert.notNull(this.mcpEndpoint, "MCP endpoint must be set");
return new HttpServletStreamableServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, mcpEndpoint, disallowDelete,
- contextExtractor, keepAliveInterval, securityValidator);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ disallowDelete, contextExtractor, keepAliveInterval, securityValidator);
}
}
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 0000000..f1c73a0
--- /dev/null
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/util/McpServiceLoader.java
@@ -0,0 +1,68 @@
+/**
+ * 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".formatted(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 0000000..1a10fdf
--- /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 9854de2..04b0589 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.List;
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 class MockMcpClientTransport implements McpClientTransport {
@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 f3d6b77..5fefb89 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.ArrayList;
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 class MockMcpServerTransport implements McpServerTransport {
@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 55f71fe..da5422e 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 911506e..0af4815 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 956a72c..37384fe 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 0000000..1d6705f
--- /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 0000000..ad62874
--- /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 0629275..bf865a0 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 7b92eb7..0c5864a 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 static org.assertj.core.api.Assertions.assertThat;
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 a3cc470..c02bc37 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 0000000..0ad8a7b
--- /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 0000000..d14d8be
--- /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 e2d0a1d..58f7e01 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 29c450d..8919757 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 static org.assertj.core.api.Assertions.assertThat;
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 2cbcf35..0000000
--- 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 31930ab..0000000
--- 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 2497e7f..0000000
--- 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 282745a..e3a7091 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.WebClient;
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 class WebClientStreamableHttpTransport implements McpClientTransport {
* @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 91b89d6..3c3a008 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.List;
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 class WebFluxSseClientTransport implements McpClientTransport {
*/
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 34d6e50..de2b0e2 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
@@ -11,6 +11,7 @@ import java.util.Map;
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;
@@ -561,8 +562,9 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
*/
public WebFluxSseServerTransportProvider build() {
Assert.notNull(messageEndpoint, "Message endpoint must be set");
- return new WebFluxSseServerTransportProvider(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- baseUrl, messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor, securityValidator);
+ return new WebFluxSseServerTransportProvider(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, baseUrl,
+ messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor, securityValidator);
}
}
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 b225ab6..7488217 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;
@@ -244,8 +245,9 @@ public class WebFluxStatelessServerTransport implements McpStatelessServerTransp
*/
public WebFluxStatelessServerTransport build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
- return new WebFluxStatelessServerTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- mcpEndpoint, contextExtractor, securityValidator);
+ return new WebFluxStatelessServerTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor, securityValidator);
}
}
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 0aed244..bb469b9 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;
@@ -532,8 +533,8 @@ public class WebFluxStreamableServerTransportProvider implements McpStreamableSe
public WebFluxStreamableServerTransportProvider build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
return new WebFluxStreamableServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, mcpEndpoint, contextExtractor,
- disallowDelete, keepAliveInterval, securityValidator);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor, disallowDelete, keepAliveInterval, securityValidator);
}
}
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 6734757..0177932 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 7e925a0..bd6d75c 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
@@ -12,6 +12,7 @@ import java.util.concurrent.ConcurrentHashMap;
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;
@@ -599,8 +600,9 @@ public class WebMvcSseServerTransportProvider implements McpServerTransportProvi
if (messageEndpoint == null) {
throw new IllegalStateException("MessageEndpoint must be set");
}
- return new WebMvcSseServerTransportProvider(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- baseUrl, messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor, securityValidator);
+ return new WebMvcSseServerTransportProvider(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, baseUrl,
+ messageEndpoint, sseEndpoint, keepAliveInterval, contextExtractor, securityValidator);
}
}
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 92a08a8..665d86e 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;
@@ -263,8 +264,9 @@ public class WebMvcStatelessServerTransport implements McpStatelessServerTranspo
*/
public WebMvcStatelessServerTransport build() {
Assert.notNull(mcpEndpoint, "Message endpoint must be set");
- return new WebMvcStatelessServerTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
- mcpEndpoint, contextExtractor, securityValidator);
+ return new WebMvcStatelessServerTransport(
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ contextExtractor, securityValidator);
}
}
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 411d9c2..4f8216c 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
@@ -11,6 +11,7 @@ import java.util.Map;
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;
@@ -112,8 +113,6 @@ public class WebMvcStreamableServerTransportProvider implements McpStreamableSer
* Constructs a new WebMvcStreamableServerTransportProvider instance.
* @param jsonMapper The McpJsonMapper to use for JSON serialization/deserialization
* of messages.
- * @param baseUrl The base URL for the message endpoint, used to construct the full
- * endpoint URL for clients.
* @param mcpEndpoint The endpoint URI where clients should send their JSON-RPC
* messages via HTTP. This endpoint will handle GET, POST, and DELETE requests.
* @param disallowDelete Whether to disallow DELETE requests on the endpoint.
@@ -732,8 +731,8 @@ public class WebMvcStreamableServerTransportProvider implements McpStreamableSer
public WebMvcStreamableServerTransportProvider build() {
Assert.notNull(this.mcpEndpoint, "MCP endpoint must be set");
return new WebMvcStreamableServerTransportProvider(
- jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper, mcpEndpoint, disallowDelete,
- contextExtractor, keepAliveInterval, securityValidator);
+ jsonMapper == null ? McpJsonDefaults.getDefaultMcpJsonMapper() : jsonMapper, mcpEndpoint,
+ disallowDelete, contextExtractor, keepAliveInterval, securityValidator);
}
}
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 1074e8a..36ea2d3 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 @@ package io.modelcontextprotocol.server.transport;
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 @@ class WebMvcSseServerTransportProviderTests {
.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 cd84583..7d71376 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.List;
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 class MockMcpTransport implements McpClientTransport, McpServerTransport
@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 7239655..45e4a4e 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 3e36b08..18b24ce 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,7 +108,6 @@
mcp-core
mcp-json-jackson2
mcp-json-jackson3
- mcp-json
mcp-spring/mcp-spring-webflux
mcp-spring/mcp-spring-webmvc
mcp-test