Skip to content

Commit b26baf9

Browse files
committed
fix conflict
2 parents 94cf075 + 082444e commit b26baf9

File tree

44 files changed

+1488
-456
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1488
-456
lines changed

mcp-bom/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<parent>
88
<groupId>io.modelcontextprotocol.sdk</groupId>
99
<artifactId>mcp-parent</artifactId>
10-
<version>0.16.0-SNAPSHOT</version>
10+
<version>0.18.0-SNAPSHOT</version>
1111
</parent>
1212

1313
<artifactId>mcp-bom</artifactId>

mcp-core/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<parent>
77
<groupId>io.modelcontextprotocol.sdk</groupId>
88
<artifactId>mcp-parent</artifactId>
9-
<version>0.16.0-SNAPSHOT</version>
9+
<version>0.18.0-SNAPSHOT</version>
1010
</parent>
1111
<artifactId>mcp-core</artifactId>
1212
<packaging>jar</packaging>
@@ -68,7 +68,7 @@
6868
<dependency>
6969
<groupId>io.modelcontextprotocol.sdk</groupId>
7070
<artifactId>mcp-json</artifactId>
71-
<version>0.16.0-SNAPSHOT</version>
71+
<version>0.18.0-SNAPSHOT</version>
7272
</dependency>
7373

7474
<dependency>
@@ -101,7 +101,7 @@
101101
<dependency>
102102
<groupId>io.modelcontextprotocol.sdk</groupId>
103103
<artifactId>mcp-json-jackson2</artifactId>
104-
<version>0.16.0-SNAPSHOT</version>
104+
<version>0.18.0-SNAPSHOT</version>
105105
<scope>test</scope>
106106
</dependency>
107107

mcp-core/src/main/java/io/modelcontextprotocol/client/LifecycleInitializer.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,9 @@ public <T> Mono<T> withInitialization(String actionName, Function<Initialization
287287
this.initializationRef.compareAndSet(newInit, null);
288288
return Mono.error(new RuntimeException("Client failed to initialize " + actionName, ex));
289289
})
290-
.flatMap(operation);
290+
.flatMap(res -> operation.apply(res)
291+
.contextWrite(c -> c.put(McpAsyncClient.NEGOTIATED_PROTOCOL_VERSION,
292+
res.initializeResult().protocolVersion())));
291293
});
292294
}
293295

@@ -319,6 +321,8 @@ private Mono<McpSchema.InitializeResult> doInitialize(DefaultInitialization init
319321
}
320322

321323
return mcpClientSession.sendNotification(McpSchema.METHOD_NOTIFICATION_INITIALIZED, null)
324+
.contextWrite(
325+
c -> c.put(McpAsyncClient.NEGOTIATED_PROTOCOL_VERSION, initializeResult.protocolVersion()))
322326
.thenReturn(initializeResult);
323327
}).flatMap(initializeResult -> {
324328
initialization.cacheResult(initializeResult);

mcp-core/src/main/java/io/modelcontextprotocol/client/McpAsyncClient.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ public class McpAsyncClient {
106106
public static final TypeRef<McpSchema.ProgressNotification> PROGRESS_NOTIFICATION_TYPE_REF = new TypeRef<>() {
107107
};
108108

109+
public static final String NEGOTIATED_PROTOCOL_VERSION = "io.modelcontextprotocol.client.negotiated-protocol-version";
110+
109111
/**
110112
* Client capabilities.
111113
*/

mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientSseClientTransport.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import java.util.function.Consumer;
1717
import java.util.function.Function;
1818

19-
import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport.Builder;
2019
import io.modelcontextprotocol.client.transport.ResponseSubscribers.SseResponseEvent;
2120
import org.slf4j.Logger;
2221
import org.slf4j.LoggerFactory;

mcp-core/src/main/java/io/modelcontextprotocol/client/transport/HttpClientStreamableHttpTransport.java

Lines changed: 68 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,30 @@
44

55
package io.modelcontextprotocol.client.transport;
66

7+
import java.io.IOException;
8+
import java.net.URI;
9+
import java.net.http.HttpClient;
10+
import java.net.http.HttpRequest;
11+
import java.net.http.HttpResponse;
12+
import java.net.http.HttpResponse.BodyHandler;
13+
import java.time.Duration;
14+
import java.util.Collections;
15+
import java.util.Comparator;
16+
import java.util.List;
17+
import java.util.Optional;
18+
import java.util.concurrent.CompletionException;
19+
import java.util.concurrent.atomic.AtomicReference;
20+
import java.util.function.Consumer;
21+
import java.util.function.Function;
22+
23+
import io.modelcontextprotocol.client.McpAsyncClient;
24+
import io.modelcontextprotocol.client.transport.ResponseSubscribers.ResponseEvent;
725
import io.modelcontextprotocol.client.transport.ResponseSubscribers.ResponseEvent;
826
import io.modelcontextprotocol.client.transport.customizer.McpAsyncHttpClientRequestCustomizer;
927
import io.modelcontextprotocol.client.transport.customizer.McpSyncHttpClientRequestCustomizer;
1028
import io.modelcontextprotocol.common.McpTransportContext;
29+
import io.modelcontextprotocol.json.McpJsonMapper;
30+
import io.modelcontextprotocol.json.TypeRef;
1131
import io.modelcontextprotocol.spec.ClosedMcpTransportSession;
1232
import io.modelcontextprotocol.json.McpJsonMapper;
1333
import io.modelcontextprotocol.json.TypeRef;
@@ -76,8 +96,6 @@ public class HttpClientStreamableHttpTransport implements McpClientTransport {
7696

7797
private static final Logger logger = LoggerFactory.getLogger(HttpClientStreamableHttpTransport.class);
7898

79-
private static final String MCP_PROTOCOL_VERSION = ProtocolVersions.MCP_2025_06_18;
80-
8199
private static final String DEFAULT_ENDPOINT = "/mcp";
82100

83101
/**
@@ -125,10 +143,14 @@ public class HttpClientStreamableHttpTransport implements McpClientTransport {
125143

126144
private final AtomicReference<Consumer<Void>> connectionClosedHandler = new AtomicReference<>();
127145

146+
private final List<String> supportedProtocolVersions;
147+
148+
private final String latestSupportedProtocolVersion;
149+
128150
private HttpClientStreamableHttpTransport(McpJsonMapper jsonMapper, HttpClient httpClient,
129151
HttpRequest.Builder requestBuilder, String baseUri, String endpoint, boolean resumableStreams,
130152
boolean openConnectionOnStartup, McpAsyncHttpClientRequestCustomizer httpRequestCustomizer,
131-
Consumer<Void> connectionClosedHandler) {
153+
Consumer<Void> connectionClosedHandler, List<String> supportedProtocolVersions) {
132154
this.jsonMapper = jsonMapper;
133155
this.httpClient = httpClient;
134156
this.requestBuilder = requestBuilder;
@@ -139,12 +161,16 @@ private HttpClientStreamableHttpTransport(McpJsonMapper jsonMapper, HttpClient h
139161
this.activeSession.set(createTransportSession());
140162
this.httpRequestCustomizer = httpRequestCustomizer;
141163
this.connectionClosedHandler.set(connectionClosedHandler);
164+
this.supportedProtocolVersions = Collections.unmodifiableList(supportedProtocolVersions);
165+
this.latestSupportedProtocolVersion = this.supportedProtocolVersions.stream()
166+
.sorted(Comparator.reverseOrder())
167+
.findFirst()
168+
.get();
142169
}
143170

144171
@Override
145172
public List<String> protocolVersions() {
146-
return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26,
147-
ProtocolVersions.MCP_2025_06_18);
173+
return supportedProtocolVersions;
148174
}
149175

150176
public static Builder builder(String baseUri) {
@@ -188,7 +214,9 @@ private Publisher<Void> createDelete(String sessionId) {
188214
.uri(uri)
189215
.header("Cache-Control", "no-cache")
190216
.header(HttpHeaders.MCP_SESSION_ID, sessionId)
191-
.header(HttpHeaders.PROTOCOL_VERSION, MCP_PROTOCOL_VERSION)
217+
.header(HttpHeaders.PROTOCOL_VERSION,
218+
ctx.getOrDefault(McpAsyncClient.NEGOTIATED_PROTOCOL_VERSION,
219+
this.latestSupportedProtocolVersion))
192220
.DELETE();
193221
var transportContext = ctx.getOrDefault(McpTransportContext.KEY, McpTransportContext.EMPTY);
194222
return Mono.from(this.httpRequestCustomizer.customize(builder, "DELETE", uri, null, transportContext));
@@ -273,7 +301,9 @@ private Mono<Disposable> reconnect(McpTransportStream<Disposable> stream) {
273301
var builder = requestBuilder.uri(uri)
274302
.header(HttpHeaders.ACCEPT, TEXT_EVENT_STREAM)
275303
.header("Cache-Control", "no-cache")
276-
.header(HttpHeaders.PROTOCOL_VERSION, MCP_PROTOCOL_VERSION)
304+
.header(HttpHeaders.PROTOCOL_VERSION,
305+
connectionCtx.getOrDefault(McpAsyncClient.NEGOTIATED_PROTOCOL_VERSION,
306+
this.latestSupportedProtocolVersion))
277307
.GET();
278308
var transportContext = connectionCtx.getOrDefault(McpTransportContext.KEY, McpTransportContext.EMPTY);
279309
return Mono.from(this.httpRequestCustomizer.customize(builder, "GET", uri, null, transportContext));
@@ -449,7 +479,9 @@ public Mono<Void> sendMessage(McpSchema.JSONRPCMessage sentMessage) {
449479
.header(HttpHeaders.ACCEPT, APPLICATION_JSON + ", " + TEXT_EVENT_STREAM)
450480
.header(HttpHeaders.CONTENT_TYPE, APPLICATION_JSON)
451481
.header(HttpHeaders.CACHE_CONTROL, "no-cache")
452-
.header(HttpHeaders.PROTOCOL_VERSION, MCP_PROTOCOL_VERSION)
482+
.header(HttpHeaders.PROTOCOL_VERSION,
483+
ctx.getOrDefault(McpAsyncClient.NEGOTIATED_PROTOCOL_VERSION,
484+
this.latestSupportedProtocolVersion))
453485
.POST(HttpRequest.BodyPublishers.ofString(jsonBody));
454486
var transportContext = ctx.getOrDefault(McpTransportContext.KEY, McpTransportContext.EMPTY);
455487
return Mono
@@ -643,6 +675,9 @@ public static class Builder {
643675

644676
private Consumer<Void> connectionClosedHandler = null;
645677

678+
private List<String> supportedProtocolVersions = List.of(ProtocolVersions.MCP_2024_11_05,
679+
ProtocolVersions.MCP_2025_03_26, ProtocolVersions.MCP_2025_06_18);
680+
646681
/**
647682
* Creates a new builder with the specified base URI.
648683
* @param baseUri the base URI of the MCP server
@@ -791,6 +826,30 @@ public Builder connectTimeout(Duration connectTimeout) {
791826
return this;
792827
}
793828

829+
/**
830+
* Sets the list of supported protocol versions used in version negotiation. By
831+
* default, the client will send the latest of those versions in the
832+
* {@code MCP-Protocol-Version} header.
833+
* <p>
834+
* Setting this value only updates the values used in version negotiation, and
835+
* does NOT impact the actual capabilities of the transport. It should only be
836+
* used for compatibility with servers having strict requirements around the
837+
* {@code MCP-Protocol-Version} header.
838+
* @param supportedProtocolVersions protocol versions supported by this transport
839+
* @return this builder
840+
* @see <a href=
841+
* "https://modelcontextprotocol.io/specification/2024-11-05/basic/lifecycle#version-negotiation">version
842+
* negotiation specification</a>
843+
* @see <a href=
844+
* "https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#protocol-version-header">Protocol
845+
* Version Header</a>
846+
*/
847+
public Builder supportedProtocolVersions(List<String> supportedProtocolVersions) {
848+
Assert.notEmpty(supportedProtocolVersions, "supportedProtocolVersions must not be empty");
849+
this.supportedProtocolVersions = Collections.unmodifiableList(supportedProtocolVersions);
850+
return this;
851+
}
852+
794853
/**
795854
* Set the connection closed handler.
796855
* @param connectionClosedHandler the connection closed handler
@@ -811,7 +870,7 @@ public HttpClientStreamableHttpTransport build() {
811870
HttpClient httpClient = this.clientBuilder.connectTimeout(this.connectTimeout).build();
812871
return new HttpClientStreamableHttpTransport(jsonMapper == null ? McpJsonMapper.getDefault() : jsonMapper,
813872
httpClient, requestBuilder, baseUri, endpoint, resumableStreams, openConnectionOnStartup,
814-
httpRequestCustomizer, connectionClosedHandler);
873+
httpRequestCustomizer, connectionClosedHandler, supportedProtocolVersions);
815874
}
816875

817876
}

mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import io.modelcontextprotocol.spec.McpSchema.CallToolResult;
2525
import io.modelcontextprotocol.spec.McpSchema.CompleteResult.CompleteCompletion;
2626
import io.modelcontextprotocol.spec.McpSchema.ErrorCodes;
27-
import io.modelcontextprotocol.spec.McpSchema.JSONRPCResponse;
2827
import io.modelcontextprotocol.spec.McpSchema.LoggingLevel;
2928
import io.modelcontextprotocol.spec.McpSchema.LoggingMessageNotification;
3029
import io.modelcontextprotocol.spec.McpSchema.PromptReference;
@@ -398,19 +397,23 @@ public Mono<CallToolResult> apply(McpAsyncServerExchange exchange, McpSchema.Cal
398397
// results that conform to this schema.
399398
// https://modelcontextprotocol.io/specification/2025-06-18/server/tools#output-schema
400399
if (result.structuredContent() == null) {
401-
logger.warn(
402-
"Response missing structured content which is expected when calling tool with non-empty outputSchema");
403-
return new CallToolResult(
404-
"Response missing structured content which is expected when calling tool with non-empty outputSchema",
405-
true);
400+
String content = "Response missing structured content which is expected when calling tool with non-empty outputSchema";
401+
logger.warn(content);
402+
return CallToolResult.builder()
403+
.content(List.of(new McpSchema.TextContent(content)))
404+
.isError(true)
405+
.build();
406406
}
407407

408408
// Validate the result against the output schema
409409
var validation = this.jsonSchemaValidator.validate(outputSchema, result.structuredContent());
410410

411411
if (!validation.valid()) {
412412
logger.warn("Tool call result validation failed: {}", validation.errorMessage());
413-
return new CallToolResult(validation.errorMessage(), true);
413+
return CallToolResult.builder()
414+
.content(List.of(new McpSchema.TextContent(validation.errorMessage())))
415+
.isError(true)
416+
.build();
414417
}
415418

416419
if (Utils.isEmpty(result.content())) {

mcp-core/src/main/java/io/modelcontextprotocol/server/McpServer.java

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@
6767
* McpServer.sync(transportProvider)
6868
* .serverInfo("my-server", "1.0.0")
6969
* .tool(Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
70-
* (exchange, args) -> new CallToolResult("Result: " + calculate(args)))
70+
* (exchange, args) -> CallToolResult.builder()
71+
* .content(List.of(new McpSchema.TextContent("Result: " + calculate(args))))
72+
* .isError(false)
73+
* .build())
7174
* .build();
7275
* }</pre>
7376
*
@@ -76,7 +79,10 @@
7679
* .serverInfo("my-server", "1.0.0")
7780
* .tool(Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
7881
* (exchange, args) -> Mono.fromSupplier(() -> calculate(args))
79-
* .map(result -> new CallToolResult("Result: " + result)))
82+
* .map(result -> CallToolResult.builder()
83+
* .content(List.of(new McpSchema.TextContent("Result: " + result)))
84+
* .isError(false)
85+
* .build()))
8086
* .build();
8187
* }</pre>
8288
*
@@ -90,12 +96,18 @@
9096
* McpServerFeatures.AsyncToolSpecification.builder()
9197
* .tool(calculatorTool)
9298
* .callTool((exchange, args) -> Mono.fromSupplier(() -> calculate(args.arguments()))
93-
* .map(result -> new CallToolResult("Result: " + result))))
99+
* .map(result -> CallToolResult.builder()
100+
* .content(List.of(new McpSchema.TextContent("Result: " + result)))
101+
* .isError(false)
102+
* .build()))
94103
*. .build(),
95104
* McpServerFeatures.AsyncToolSpecification.builder()
96105
* .tool((weatherTool)
97106
* .callTool((exchange, args) -> Mono.fromSupplier(() -> getWeather(args.arguments()))
98-
* .map(result -> new CallToolResult("Weather: " + result))))
107+
* .map(result -> CallToolResult.builder()
108+
* .content(List.of(new McpSchema.TextContent("Weather: " + result)))
109+
* .isError(false)
110+
* .build()))
99111
* .build()
100112
* )
101113
* // Register resources
@@ -425,7 +437,10 @@ public AsyncSpecification<S> capabilities(McpSchema.ServerCapabilities serverCap
425437
* .tool(
426438
* Tool.builder().name("calculator").title("Performs calculations").inputSchema(schema).build(),
427439
* (exchange, args) -> Mono.fromSupplier(() -> calculate(args))
428-
* .map(result -> new CallToolResult("Result: " + result))
440+
* .map(result -> CallToolResult.builder()
441+
* .content(List.of(new McpSchema.TextContent("Result: " + result)))
442+
* .isError(false)
443+
* .build()))
429444
* )
430445
* }</pre>
431446
* @param tool The tool definition including name, description, and schema. Must
@@ -598,7 +613,6 @@ public AsyncSpecification<S> resources(McpServerFeatures.AsyncResourceSpecificat
598613
* null.
599614
* @return This builder instance for method chaining
600615
* @throws IllegalArgumentException if resourceTemplates is null.
601-
* @see #resourceTemplates(ResourceTemplate...)
602616
*/
603617
public AsyncSpecification<S> resourceTemplates(
604618
List<McpServerFeatures.AsyncResourceTemplateSpecification> resourceTemplates) {
@@ -1023,7 +1037,10 @@ public SyncSpecification<S> capabilities(McpSchema.ServerCapabilities serverCapa
10231037
* Example usage: <pre>{@code
10241038
* .tool(
10251039
* Tool.builder().name("calculator").title("Performs calculations".inputSchema(schema).build(),
1026-
* (exchange, args) -> new CallToolResult("Result: " + calculate(args))
1040+
* (exchange, args) -> CallToolResult.builder()
1041+
* .content(List.of(new McpSchema.TextContent("Result: " + calculate(args))))
1042+
* .isError(false)
1043+
* .build())
10271044
* )
10281045
* }</pre>
10291046
* @param tool The tool definition including name, description, and schema. Must
@@ -1195,7 +1212,6 @@ public SyncSpecification<S> resources(McpServerFeatures.SyncResourceSpecificatio
11951212
* null.
11961213
* @return This builder instance for method chaining
11971214
* @throws IllegalArgumentException if resourceTemplates is null.
1198-
* @see #resourceTemplates(ResourceTemplate...)
11991215
*/
12001216
public SyncSpecification<S> resourceTemplates(
12011217
List<McpServerFeatures.SyncResourceTemplateSpecification> resourceTemplates) {
@@ -1703,7 +1719,6 @@ public StatelessAsyncSpecification resources(
17031719
* templates.
17041720
* @return This builder instance for method chaining
17051721
* @throws IllegalArgumentException if resourceTemplates is null.
1706-
* @see #resourceTemplates(ResourceTemplate...)
17071722
*/
17081723
public StatelessAsyncSpecification resourceTemplates(
17091724
List<McpStatelessServerFeatures.AsyncResourceTemplateSpecification> resourceTemplates) {
@@ -2166,7 +2181,6 @@ public StatelessSyncSpecification resources(
21662181
* existing templates.
21672182
* @return This builder instance for method chaining
21682183
* @throws IllegalArgumentException if resourceTemplates is null.
2169-
* @see #resourceTemplates(ResourceTemplate...)
21702184
*/
21712185
public StatelessSyncSpecification resourceTemplates(
21722186
List<McpStatelessServerFeatures.SyncResourceTemplateSpecification> resourceTemplatesSpec) {

0 commit comments

Comments
 (0)