Compare commits

...
Author SHA1 Message Date
Christian Tzolov
5365bf4805 Release version 0.11.1
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-06 09:41:31 +01:00
Christian Tzolov
cc1b1c9936 refactor: downgrade unhandled notification logging from error to warn
- Change logger.error() to logger.warn() for unhandled notification methods
- Log full notification object instead of just method name for better context
- Affects McpClientSession, McpServerSession, and McpStreamableServerSession

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-06 08:36:43 +01:00
Yanming Zhou
c732040436 Use Last-Event-ID instead of last-event-id
see https://html.spec.whatwg.org/multipage/server-sent-events.html#the-last-event-id-header

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2025-08-06 08:14:02 +01:00
codezkk
9e959b72cb fix: handle empty JSON responses in ResponseSubscribers
- Remove length check in hookOnComplete() to always emit AggregateResponseEvent
- Ensures proper completion handling regardless of response content length
- Add test for empty application/json responses with 200 OK status
2025-08-06 08:10:36 +01:00
Yanming Zhou
69cf41b12f Remove duplicate header MCP_PROTOCOL_VERSION
Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2025-08-05 19:06:46 +01:00
Christian Tzolov
9949657ce3 fix: add backward compatibility for MCP servers returning older protocol versions
- Add ProtocolVersions interface with version constants
- Change protocolVersion() to protocolVersions() returning List<String>
- Streamable HTTP clients now support both 2024-11-05 and 2025-03-26
- Fixes compatibility with MCP servers that return 2024-11-05 instead of 2025-03-26

Resolves #436
Related to #438

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-04 14:28:53 +01:00
Yanming Zhou
5681f1ea4c Fix typo 2025-08-01 18:46:52 +01:00
Christian Tzolov
a49b9f5914 Update copyright headers to 2025 and clean up code
- Add copyright headers to files missing them
- Add blank lines after copyright headers for consistency
- Remove unused imports in test files
- Remove unnecessary keep-alive warning logs in WebFlux and WebMvc transport providers

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-01 16:07:24 +01:00
Christian Tzolov
1324730d95 Next development version
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-07-31 02:34:35 +02:00
Christian Tzolov
ff4630d932 Release version 0.11.0
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-07-31 02:34:13 +02:00
96 changed files with 409 additions and 113 deletions

View file

@ -7,7 +7,7 @@
<parent> <parent>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-parent</artifactId> <artifactId>mcp-parent</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
</parent> </parent>
<artifactId>mcp-bom</artifactId> <artifactId>mcp-bom</artifactId>

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-parent</artifactId> <artifactId>mcp-parent</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<artifactId>mcp-spring-webflux</artifactId> <artifactId>mcp-spring-webflux</artifactId>
@ -25,13 +25,13 @@
<dependency> <dependency>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId> <artifactId>mcp</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-test</artifactId> <artifactId>mcp-test</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>

View file

@ -1,3 +1,7 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.client.transport; package io.modelcontextprotocol.client.transport;
import java.io.IOException; import java.io.IOException;
@ -30,6 +34,7 @@ import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpTransportSession; import io.modelcontextprotocol.spec.McpTransportSession;
import io.modelcontextprotocol.spec.McpTransportSessionNotFoundException; import io.modelcontextprotocol.spec.McpTransportSessionNotFoundException;
import io.modelcontextprotocol.spec.McpTransportStream; import io.modelcontextprotocol.spec.McpTransportStream;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.util.Assert; import io.modelcontextprotocol.util.Assert;
import io.modelcontextprotocol.util.Utils; import io.modelcontextprotocol.util.Utils;
import reactor.core.Disposable; import reactor.core.Disposable;
@ -67,7 +72,7 @@ public class WebClientStreamableHttpTransport implements McpClientTransport {
private static final Logger logger = LoggerFactory.getLogger(WebClientStreamableHttpTransport.class); private static final Logger logger = LoggerFactory.getLogger(WebClientStreamableHttpTransport.class);
private static final String MCP_PROTOCOL_VERSION = "2025-03-26"; private static final String MCP_PROTOCOL_VERSION = ProtocolVersions.MCP_2025_03_26;
private static final String DEFAULT_ENDPOINT = "/mcp"; private static final String DEFAULT_ENDPOINT = "/mcp";
@ -107,8 +112,8 @@ public class WebClientStreamableHttpTransport implements McpClientTransport {
} }
@Override @Override
public String protocolVersion() { public List<String> protocolVersions() {
return MCP_PROTOCOL_VERSION; return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26);
} }
/** /**
@ -138,11 +143,8 @@ public class WebClientStreamableHttpTransport implements McpClientTransport {
Function<String, Publisher<Void>> onClose = sessionId -> sessionId == null ? Mono.empty() Function<String, Publisher<Void>> onClose = sessionId -> sessionId == null ? Mono.empty()
: webClient.delete() : webClient.delete()
.uri(this.endpoint) .uri(this.endpoint)
.header(HttpHeaders.MCP_SESSION_ID, sessionId)
.header(HttpHeaders.PROTOCOL_VERSION, MCP_PROTOCOL_VERSION) .header(HttpHeaders.PROTOCOL_VERSION, MCP_PROTOCOL_VERSION)
.headers(httpHeaders -> {
httpHeaders.add(HttpHeaders.MCP_SESSION_ID, sessionId);
httpHeaders.add(HttpHeaders.PROTOCOL_VERSION, MCP_PROTOCOL_VERSION);
})
.retrieve() .retrieve()
.toBodilessEntity() .toBodilessEntity()
.onErrorComplete(e -> { .onErrorComplete(e -> {

View file

@ -1,9 +1,11 @@
/* /*
* Copyright 2024 - 2024 the original author or authors. * Copyright 2024 - 2024 the original author or authors.
*/ */
package io.modelcontextprotocol.client.transport; package io.modelcontextprotocol.client.transport;
import java.io.IOException; import java.io.IOException;
import java.util.List;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
@ -15,6 +17,7 @@ import io.modelcontextprotocol.spec.McpClientTransport;
import io.modelcontextprotocol.spec.McpError; import io.modelcontextprotocol.spec.McpError;
import io.modelcontextprotocol.spec.McpSchema; import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpSchema.JSONRPCMessage; import io.modelcontextprotocol.spec.McpSchema.JSONRPCMessage;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.util.Assert; import io.modelcontextprotocol.util.Assert;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -64,7 +67,7 @@ public class WebFluxSseClientTransport implements McpClientTransport {
private static final Logger logger = LoggerFactory.getLogger(WebFluxSseClientTransport.class); private static final Logger logger = LoggerFactory.getLogger(WebFluxSseClientTransport.class);
private static final String MCP_PROTOCOL_VERSION = "2024-11-05"; private static final String MCP_PROTOCOL_VERSION = ProtocolVersions.MCP_2024_11_05;
/** /**
* Event type for JSON-RPC messages received through the SSE connection. The server * Event type for JSON-RPC messages received through the SSE connection. The server
@ -171,8 +174,8 @@ public class WebFluxSseClientTransport implements McpClientTransport {
} }
@Override @Override
public String protocolVersion() { public List<String> protocolVersions() {
return MCP_PROTOCOL_VERSION; return List.of(MCP_PROTOCOL_VERSION);
} }
/** /**

View file

@ -1,7 +1,12 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.server.transport; package io.modelcontextprotocol.server.transport;
import java.io.IOException; import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
@ -11,6 +16,7 @@ import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpServerSession; import io.modelcontextprotocol.spec.McpServerSession;
import io.modelcontextprotocol.spec.McpServerTransport; import io.modelcontextprotocol.spec.McpServerTransport;
import io.modelcontextprotocol.spec.McpServerTransportProvider; import io.modelcontextprotocol.spec.McpServerTransportProvider;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.util.Assert; import io.modelcontextprotocol.util.Assert;
import io.modelcontextprotocol.util.KeepAliveScheduler; import io.modelcontextprotocol.util.KeepAliveScheduler;
@ -215,8 +221,8 @@ public class WebFluxSseServerTransportProvider implements McpServerTransportProv
} }
@Override @Override
public String protocolVersion() { public List<String> protocolVersions() {
return "2024-11-05"; return List.of(ProtocolVersions.MCP_2024_11_05);
} }
@Override @Override

View file

@ -1,3 +1,7 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.server.transport; package io.modelcontextprotocol.server.transport;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;

View file

@ -1,3 +1,7 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.server.transport; package io.modelcontextprotocol.server.transport;
import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.core.type.TypeReference;
@ -10,6 +14,7 @@ import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpStreamableServerSession; import io.modelcontextprotocol.spec.McpStreamableServerSession;
import io.modelcontextprotocol.spec.McpStreamableServerTransport; import io.modelcontextprotocol.spec.McpStreamableServerTransport;
import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider; import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.server.McpTransportContext; import io.modelcontextprotocol.server.McpTransportContext;
import io.modelcontextprotocol.util.Assert; import io.modelcontextprotocol.util.Assert;
import io.modelcontextprotocol.util.KeepAliveScheduler; import io.modelcontextprotocol.util.KeepAliveScheduler;
@ -89,15 +94,11 @@ public class WebFluxStreamableServerTransportProvider implements McpStreamableSe
this.keepAliveScheduler.start(); this.keepAliveScheduler.start();
} }
else {
logger.warn("Keep-alive interval is not set or invalid. No keep-alive will be scheduled.");
}
} }
@Override @Override
public String protocolVersion() { public List<String> protocolVersions() {
return "2025-03-26"; return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
/* /*
* Copyright 2024 - 2024 the original author or authors. * Copyright 2024 - 2024 the original author or authors.
*/ */
package io.modelcontextprotocol; package io.modelcontextprotocol;
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson; import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;

View file

@ -1,6 +1,7 @@
/* /*
* Copyright 2024 - 2024 the original author or authors. * Copyright 2024 - 2024 the original author or authors.
*/ */
package io.modelcontextprotocol; package io.modelcontextprotocol;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;

View file

@ -1,6 +1,7 @@
/* /*
* Copyright 2024 - 2024 the original author or authors. * Copyright 2024 - 2024 the original author or authors.
*/ */
package io.modelcontextprotocol; package io.modelcontextprotocol;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;

View file

@ -1,3 +1,7 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.client; package io.modelcontextprotocol.client;
import io.modelcontextprotocol.client.transport.WebClientStreamableHttpTransport; import io.modelcontextprotocol.client.transport.WebClientStreamableHttpTransport;

View file

@ -1,3 +1,7 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.client; package io.modelcontextprotocol.client;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;

View file

@ -1,3 +1,7 @@
/*
* Copyright 2025-2025 the original author or authors.
*/
package io.modelcontextprotocol.client; package io.modelcontextprotocol.client;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;

View file

@ -5,9 +5,7 @@
package io.modelcontextprotocol.server; package io.modelcontextprotocol.server;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
import io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider; import io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider;
import io.modelcontextprotocol.spec.McpServerTransportProvider;
import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider; import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;
import org.springframework.http.server.reactive.HttpHandler; import org.springframework.http.server.reactive.HttpHandler;

View file

@ -5,7 +5,6 @@
package io.modelcontextprotocol.server; package io.modelcontextprotocol.server;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.transport.WebFluxSseServerTransportProvider;
import io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider; import io.modelcontextprotocol.server.transport.WebFluxStreamableServerTransportProvider;
import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider; import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;

View file

@ -1,6 +1,7 @@
/* /*
* Copyright 2024 - 2024 the original author or authors. * Copyright 2024 - 2024 the original author or authors.
*/ */
package io.modelcontextprotocol.server.transport; package io.modelcontextprotocol.server.transport;
import java.io.IOException; import java.io.IOException;

View file

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-parent</artifactId> <artifactId>mcp-parent</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<artifactId>mcp-spring-webmvc</artifactId> <artifactId>mcp-spring-webmvc</artifactId>
@ -25,7 +25,7 @@
<dependency> <dependency>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId> <artifactId>mcp</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
</dependency> </dependency>
<dependency> <dependency>
@ -37,14 +37,14 @@
<dependency> <dependency>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-test</artifactId> <artifactId>mcp-test</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.modelcontextprotocol.sdk</groupId> <groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-spring-webflux</artifactId> <artifactId>mcp-spring-webflux</artifactId>
<version>0.11.0-SNAPSHOT</version> <version>0.11.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>

View file

@ -6,6 +6,7 @@ package io.modelcontextprotocol.server.transport;
import java.io.IOException; import java.io.IOException;
import java.time.Duration; import java.time.Duration;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -16,6 +17,7 @@ import io.modelcontextprotocol.spec.McpError;
import io.modelcontextprotocol.spec.McpSchema; import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpServerTransport; import io.modelcontextprotocol.spec.McpServerTransport;
import io.modelcontextprotocol.spec.McpServerTransportProvider; import io.modelcontextprotocol.spec.McpServerTransportProvider;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.spec.McpServerSession; import io.modelcontextprotocol.spec.McpServerSession;
import io.modelcontextprotocol.util.Assert; import io.modelcontextprotocol.util.Assert;
import io.modelcontextprotocol.util.KeepAliveScheduler; import io.modelcontextprotocol.util.KeepAliveScheduler;
@ -210,8 +212,8 @@ public class WebMvcSseServerTransportProvider implements McpServerTransportProvi
} }
@Override @Override
public String protocolVersion() { public List<String> protocolVersions() {
return "2024-11-05"; return List.of(ProtocolVersions.MCP_2024_11_05);
} }
@Override @Override

View file

@ -1,3 +1,7 @@
/*
* Copyright 2024-2024 the original author or authors.
*/
package io.modelcontextprotocol.server.transport; package io.modelcontextprotocol.server.transport;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;

View file

@ -32,6 +32,7 @@ import io.modelcontextprotocol.spec.McpSchema;
import io.modelcontextprotocol.spec.McpStreamableServerSession; import io.modelcontextprotocol.spec.McpStreamableServerSession;
import io.modelcontextprotocol.spec.McpStreamableServerTransport; import io.modelcontextprotocol.spec.McpStreamableServerTransport;
import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider; import io.modelcontextprotocol.spec.McpStreamableServerTransportProvider;
import io.modelcontextprotocol.spec.ProtocolVersions;
import io.modelcontextprotocol.util.Assert; import io.modelcontextprotocol.util.Assert;
import io.modelcontextprotocol.util.KeepAliveScheduler; import io.modelcontextprotocol.util.KeepAliveScheduler;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
@ -95,9 +96,6 @@ public class WebMvcStreamableServerTransportProvider implements McpStreamableSer
private McpTransportContextExtractor<ServerRequest> contextExtractor; private McpTransportContextExtractor<ServerRequest> contextExtractor;
// private Function<ServerRequest, McpTransportContext> contextExtractor = req -> new
// DefaultMcpTransportContext();
/** /**
* Flag indicating if the transport is shutting down. * Flag indicating if the transport is shutting down.
*/ */
@ -142,14 +140,11 @@ public class WebMvcStreamableServerTransportProvider implements McpStreamableSer
this.keepAliveScheduler.start(); this.keepAliveScheduler.start();
} }
else {
logger.warn("Keep-alive interval is not set or invalid. No keep-alive will be scheduled.");
}
} }
@Override @Override
public String protocolVersion() { public List<String> protocolVersions() {
return "2025-03-26"; return List.of(ProtocolVersions.MCP_2024_11_05, ProtocolVersions.MCP_2025_03_26);
} }
@Override @Override

Some files were not shown because too many files have changed in this diff Show more