Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.transport.ServerParameters;
import io.modelcontextprotocol.client.transport.StdioClientTransport;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties;
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpStdioClientProperties;
Expand Down Expand Up @@ -79,7 +79,7 @@ public List<NamedClientMcpTransport> stdioTransports(McpStdioClientProperties st

for (Map.Entry<String, ServerParameters> serverParameters : stdioProperties.toServerParameters().entrySet()) {
var transport = new StdioClientTransport(serverParameters.getValue(),
new JacksonMcpJsonMapper(new ObjectMapper()));
new JacksonMcpJsonMapper(JsonMapper.shared()));
stdioTransports.add(new NamedClientMcpTransport(serverParameters.getKey(), transport));

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.transport.ServerParameters;
import org.jspecify.annotations.Nullable;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.io.Resource;
Expand Down Expand Up @@ -80,7 +80,7 @@ private Map<String, ServerParameters> resourceToServerParameters() {
return Collections.emptyMap();
}
try {
Map<String, Map<String, Parameters>> stdioConnection = new ObjectMapper()
Map<String, Map<String, Parameters>> stdioConnection = JsonMapper.shared()
.readValue(this.serversConfiguration.getInputStream(), new TypeReference<>() {
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import io.modelcontextprotocol.client.transport.customizer.McpAsyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.client.transport.customizer.McpSyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.McpSseClientConnectionDetails;
import org.springframework.ai.mcp.client.common.autoconfigure.NamedClientMcpTransport;
Expand Down Expand Up @@ -56,7 +56,7 @@
* Key features:
* <ul>
* <li>Creates HTTP client-based SSE transports for configured MCP server connections
* <li>Configures ObjectMapper for JSON serialization/deserialization
* <li>Configures JsonMapper for JSON serialization/deserialization
* <li>Supports multiple named server connections with different URLs
* </ul>
*
Expand Down Expand Up @@ -85,12 +85,12 @@ PropertiesMcpSseClientConnectionDetails mcpSseClientConnectionDetails(McpSseClie
* <ul>
* <li>A new HttpClient instance
* <li>Server URL from properties
* <li>ObjectMapper for JSON processing
* <li>JsonMapper for JSON processing
* <li>A sync or async HTTP request customizer. Sync takes precedence.
* </ul>
* @param connectionDetails the SSE client connection details containing server
* configurations
* @param objectMapperProvider the provider for ObjectMapper or a new instance if not
* @param jsonMapperProvider the provider for JsonMapper or a new instance if not
* available
* @param syncHttpRequestCustomizer provider for
* {@link McpSyncHttpClientRequestCustomizer} if available
Expand All @@ -100,11 +100,11 @@ PropertiesMcpSseClientConnectionDetails mcpSseClientConnectionDetails(McpSseClie
*/
@Bean
public List<NamedClientMcpTransport> sseHttpClientTransports(McpSseClientConnectionDetails connectionDetails,
ObjectProvider<ObjectMapper> objectMapperProvider,
ObjectProvider<JsonMapper> jsonMapperProvider,
ObjectProvider<McpSyncHttpClientRequestCustomizer> syncHttpRequestCustomizer,
ObjectProvider<McpAsyncHttpClientRequestCustomizer> asyncHttpRequestCustomizer) {

ObjectMapper objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new);
JsonMapper jsonMapper = jsonMapperProvider.getIfAvailable(JsonMapper::new);
Comment thread
sdeleuze marked this conversation as resolved.

List<NamedClientMcpTransport> sseTransports = new ArrayList<>();

Expand All @@ -123,7 +123,7 @@ public List<NamedClientMcpTransport> sseHttpClientTransports(McpSseClientConnect
var transportBuilder = HttpClientSseClientTransport.builder(baseUrl)
.sseEndpoint(sseEndpoint)
.clientBuilder(HttpClient.newBuilder())
.jsonMapper(new JacksonMcpJsonMapper(objectMapper));
.jsonMapper(new JacksonMcpJsonMapper(jsonMapper));

asyncHttpRequestCustomizer.ifUnique(transportBuilder::asyncHttpRequestCustomizer);
syncHttpRequestCustomizer.ifUnique(transportBuilder::httpRequestCustomizer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
import io.modelcontextprotocol.client.transport.customizer.McpAsyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.client.transport.customizer.McpSyncHttpClientRequestCustomizer;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapper;
import io.modelcontextprotocol.spec.McpSchema;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.NamedClientMcpTransport;
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties;
Expand Down Expand Up @@ -55,7 +55,7 @@
* <ul>
* <li>Creates HTTP client-based Streamable HTTP transports for configured MCP server
* connections
* <li>Configures ObjectMapper for JSON serialization/deserialization
* <li>Configures JsonMapper for JSON serialization/deserialization
* <li>Supports multiple named server connections with different URLs
* <li>Adds a sync or async HTTP request customizer. Sync takes precedence.
* </ul>
Expand All @@ -81,11 +81,11 @@ public class StreamableHttpHttpClientTransportAutoConfiguration {
* <ul>
* <li>A new HttpClient instance
* <li>Server URL from properties
* <li>ObjectMapper for JSON processing
* <li>JsonMapper for JSON processing
* </ul>
* @param streamableProperties the Streamable HTTP client properties containing server
* configurations
* @param objectMapperProvider the provider for ObjectMapper or a new instance if not
* @param jsonMapperProvider the provider for JsonMapper or a new instance if not
* available
* @param syncHttpRequestCustomizer provider for
* {@link McpSyncHttpClientRequestCustomizer} if available
Expand All @@ -95,11 +95,11 @@ public class StreamableHttpHttpClientTransportAutoConfiguration {
*/
@Bean
public List<NamedClientMcpTransport> streamableHttpHttpClientTransports(
McpStreamableHttpClientProperties streamableProperties, ObjectProvider<ObjectMapper> objectMapperProvider,
McpStreamableHttpClientProperties streamableProperties, ObjectProvider<JsonMapper> jsonMapperProvider,
ObjectProvider<McpSyncHttpClientRequestCustomizer> syncHttpRequestCustomizer,
ObjectProvider<McpAsyncHttpClientRequestCustomizer> asyncHttpRequestCustomizer) {

ObjectMapper objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new);
JsonMapper jsonMapper = jsonMapperProvider.getIfAvailable(JsonMapper::shared);

List<NamedClientMcpTransport> streamableHttpTransports = new ArrayList<>();

Expand All @@ -114,7 +114,7 @@ public List<NamedClientMcpTransport> streamableHttpHttpClientTransports(
.builder(baseUrl)
.endpoint(streamableHttpEndpoint)
.clientBuilder(HttpClient.newBuilder())
.jsonMapper(new JacksonMcpJsonMapper(objectMapper));
.jsonMapper(new JacksonMcpJsonMapper(jsonMapper));

asyncHttpRequestCustomizer.ifUnique(transportBuilder::asyncHttpRequestCustomizer);
syncHttpRequestCustomizer.ifUnique(transportBuilder::httpRequestCustomizer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import java.lang.reflect.Field;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.transport.HttpClientSseClientTransport;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.NamedClientMcpTransport;
import org.springframework.ai.mcp.client.httpclient.autoconfigure.SseHttpClientTransportAutoConfiguration;
Expand Down Expand Up @@ -104,11 +104,11 @@ void customSseEndpointIsRespected() {
}

@Test
void customObjectMapperIsUsed() {
this.applicationContext.withUserConfiguration(CustomObjectMapperConfiguration.class)
void customJsonMapperIsUsed() {
this.applicationContext.withUserConfiguration(CustomJsonMapperConfiguration.class)
.withPropertyValues("spring.ai.mcp.client.sse.connections.server1.url=http://localhost:8080")
.run(context -> {
assertThat(context.getBean(ObjectMapper.class)).isNotNull();
assertThat(context.getBean(JsonMapper.class)).isNotNull();
List<NamedClientMcpTransport> transports = context.getBean("sseHttpClientTransports", List.class);
assertThat(transports).hasSize(1);
});
Expand Down Expand Up @@ -160,11 +160,11 @@ private String getSseEndpoint(HttpClientSseClientTransport transport) {
}

@Configuration
static class CustomObjectMapperConfiguration {
static class CustomJsonMapperConfiguration {

@Bean
ObjectMapper objectMapper() {
return new ObjectMapper();
JsonMapper jsonMapper() {
return new JsonMapper();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
import java.lang.reflect.Field;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
import org.junit.jupiter.api.Test;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.NamedClientMcpTransport;
import org.springframework.ai.mcp.client.httpclient.autoconfigure.StreamableHttpHttpClientTransportAutoConfiguration;
Expand Down Expand Up @@ -109,11 +109,11 @@ void customEndpointIsRespected() {
}

@Test
void customObjectMapperIsUsed() {
this.applicationContext.withUserConfiguration(CustomObjectMapperConfiguration.class)
void customJsonMapperIsUsed() {
this.applicationContext.withUserConfiguration(CustomJsonMapperConfiguration.class)
.withPropertyValues("spring.ai.mcp.client.streamable-http.connections.server1.url=http://localhost:8080")
.run(context -> {
assertThat(context.getBean(ObjectMapper.class)).isNotNull();
assertThat(context.getBean(JsonMapper.class)).isNotNull();
List<NamedClientMcpTransport> transports = context.getBean("streamableHttpHttpClientTransports",
List.class);
assertThat(transports).hasSize(1);
Expand Down Expand Up @@ -169,11 +169,11 @@ private String getStreamableHttpEndpoint(HttpClientStreamableHttpTransport trans
}

@Configuration
static class CustomObjectMapperConfiguration {
static class CustomJsonMapperConfiguration {

@Bean
ObjectMapper objectMapper() {
return new ObjectMapper();
JsonMapper jsonMapper() {
return new JsonMapper();
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.transport.WebFluxSseClientTransport;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapper;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.McpSseClientConnectionDetails;
import org.springframework.ai.mcp.client.common.autoconfigure.NamedClientMcpTransport;
Expand Down Expand Up @@ -53,7 +53,7 @@
* <ul>
* <li>Creates WebFlux-based SSE transports for configured MCP server connections
* <li>Configures WebClient.Builder for HTTP client operations
* <li>Sets up ObjectMapper for JSON serialization/deserialization
* <li>Sets up JsonMapper for JSON serialization/deserialization
* <li>Supports multiple named server connections with different base URLs
* </ul>
*
Expand All @@ -79,24 +79,23 @@ PropertiesMcpSseClientConnectionDetails mcpSseClientConnectionDetails(McpSseClie
* Each transport is configured with:
* <ul>
* <li>A cloned WebClient.Builder with server-specific base URL
* <li>ObjectMapper for JSON processing
* <li>JsonMapper for JSON processing
* <li>Server connection parameters from properties
* </ul>
* @param connectionDetails the SSE client properties containing server configurations
* @param webClientBuilderProvider the provider for WebClient.Builder
* @param objectMapperProvider the provider for ObjectMapper or a new instance if not
* @param jsonMapperProvider the provider for JsonMapper or a new instance if not
* available
* @return list of named MCP transports
*/
@Bean
public List<NamedClientMcpTransport> sseWebFluxClientTransports(McpSseClientConnectionDetails connectionDetails,
ObjectProvider<WebClient.Builder> webClientBuilderProvider,
ObjectProvider<ObjectMapper> objectMapperProvider) {
ObjectProvider<WebClient.Builder> webClientBuilderProvider, ObjectProvider<JsonMapper> jsonMapperProvider) {

List<NamedClientMcpTransport> sseTransports = new ArrayList<>();

var webClientBuilderTemplate = webClientBuilderProvider.getIfAvailable(WebClient::builder);
var objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new);
var jsonMapper = jsonMapperProvider.getIfAvailable(JsonMapper::shared);

for (Map.Entry<String, SseParameters> serverParameters : connectionDetails.getConnections().entrySet()) {
String url = Objects.requireNonNull(serverParameters.getValue().url(),
Expand All @@ -105,7 +104,7 @@ public List<NamedClientMcpTransport> sseWebFluxClientTransports(McpSseClientConn
String sseEndpoint = Objects.requireNonNullElse(serverParameters.getValue().sseEndpoint(), "/sse");
var transport = WebFluxSseClientTransport.builder(webClientBuilder)
.sseEndpoint(sseEndpoint)
.jsonMapper(new JacksonMcpJsonMapper(objectMapper))
.jsonMapper(new JacksonMcpJsonMapper(jsonMapper))
.build();
sseTransports.add(new NamedClientMcpTransport(serverParameters.getKey(), transport));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
import java.util.Map;
import java.util.Objects;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.transport.WebClientStreamableHttpTransport;
import io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper;
import io.modelcontextprotocol.json.jackson3.JacksonMcpJsonMapper;
import tools.jackson.databind.json.JsonMapper;

import org.springframework.ai.mcp.client.common.autoconfigure.NamedClientMcpTransport;
import org.springframework.ai.mcp.client.common.autoconfigure.properties.McpClientCommonProperties;
Expand Down Expand Up @@ -52,7 +52,7 @@
* <li>Creates WebFlux-based Streamable HTTP transports for configured MCP server
* connections
* <li>Configures WebClient.Builder for HTTP client operations
* <li>Sets up ObjectMapper for JSON serialization/deserialization
* <li>Sets up JsonMapper for JSON serialization/deserialization
* <li>Supports multiple named server connections with different base URLs
* </ul>
*
Expand All @@ -73,26 +73,25 @@ public class StreamableHttpWebFluxTransportAutoConfiguration {
* Each transport is configured with:
* <ul>
* <li>A cloned WebClient.Builder with server-specific base URL
* <li>ObjectMapper for JSON processing
* <li>JsonMapper for JSON processing
* <li>Server connection parameters from properties
* </ul>
* @param streamableProperties the Streamable HTTP client properties containing server
* configurations
* @param webClientBuilderProvider the provider for WebClient.Builder
* @param objectMapperProvider the provider for ObjectMapper or a new instance if not
* @param jsonMapperProvider the provider for JsonMapper or a new instance if not
* available
* @return list of named MCP transports
*/
@Bean
public List<NamedClientMcpTransport> streamableHttpWebFluxClientTransports(
McpStreamableHttpClientProperties streamableProperties,
ObjectProvider<WebClient.Builder> webClientBuilderProvider,
ObjectProvider<ObjectMapper> objectMapperProvider) {
ObjectProvider<WebClient.Builder> webClientBuilderProvider, ObjectProvider<JsonMapper> jsonMapperProvider) {

List<NamedClientMcpTransport> streamableHttpTransports = new ArrayList<>();

var webClientBuilderTemplate = webClientBuilderProvider.getIfAvailable(WebClient::builder);
var objectMapper = objectMapperProvider.getIfAvailable(ObjectMapper::new);
var jsonMapper = jsonMapperProvider.getIfAvailable(JsonMapper::new);
Comment thread
sdeleuze marked this conversation as resolved.

for (Map.Entry<String, ConnectionParameters> serverParameters : streamableProperties.getConnections()
.entrySet()) {
Expand All @@ -103,7 +102,7 @@ public List<NamedClientMcpTransport> streamableHttpWebFluxClientTransports(

var transport = WebClientStreamableHttpTransport.builder(webClientBuilder)
.endpoint(streamableHttpEndpoint)
.jsonMapper(new JacksonMcpJsonMapper(objectMapper))
.jsonMapper(new JacksonMcpJsonMapper(jsonMapper))
.build();

streamableHttpTransports.add(new NamedClientMcpTransport(serverParameters.getKey(), transport));
Expand Down
Loading