diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index a07b6a840..c903204cd 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Questions and Community Support
- url: https://stackoverflow.com/questions/tagged/spring-ai-mcp
- about: Please ask and answer questions on StackOverflow with the spring-ai tag
+ url: https://stackoverflow.com/questions/tagged/mcp-java-sdk
+ about: Please ask and answer questions on StackOverflow with the mcp-java-sdk tag
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 000000000..c25de745b
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,22 @@
+version: 2
+updates:
+ - package-ecosystem: 'github-actions'
+ directory: '/'
+ schedule:
+ interval: monthly
+ - package-ecosystem: 'maven'
+ directory: '/'
+ schedule:
+ interval: monthly
+ open-pull-requests-limit: 10
+ ignore:
+ # Freeze production dependencies of mcp-core
+ - dependency-name: 'org.slf4j:slf4j-api'
+ - dependency-name: 'com.fasterxml.jackson.core:jackson-annotations'
+ - dependency-name: 'tools.jackson.core:jackson-databind'
+ - dependency-name: 'io.projectreactor:reactor-bom'
+ - dependency-name: 'io.projectreactor:reactor-core'
+ - dependency-name: 'jakarta.servlet:jakarta.servlet-api'
+ # mcp-json-jackson2 and mcp-json-jackson3 dependencies
+ - dependency-name: 'com.fasterxml.jackson.core:jackson-databind'
+ - dependency-name: 'com.networknt:json-schema-validator'
\ No newline at end of file
diff --git a/.github/workflows/conformance.yml b/.github/workflows/conformance.yml
index 82db97f76..efd06938f 100644
--- a/.github/workflows/conformance.yml
+++ b/.github/workflows/conformance.yml
@@ -57,6 +57,48 @@ jobs:
uses: modelcontextprotocol/conformance@v0.1.11
with:
mode: client
- command: 'java -jar conformance-tests/client-jdk-http-client/target/client-jdk-http-client-1.0.0-SNAPSHOT.jar'
+ command: 'java -jar conformance-tests/client-jdk-http-client/target/client-jdk-http-client-*-SNAPSHOT.jar'
scenario: ${{ matrix.scenario }}
expected-failures: ./conformance-tests/conformance-baseline.yml
+
+ auth:
+ name: Auth Conformance
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ scenario:
+ - auth/metadata-default
+ - auth/metadata-var1
+ - auth/metadata-var2
+ - auth/metadata-var3
+ - auth/basic-cimd
+ - auth/scope-from-www-authenticate
+ - auth/scope-from-scopes-supported
+ - auth/scope-omitted-when-undefined
+ - auth/scope-step-up
+ - auth/scope-retry-limit
+ - auth/token-endpoint-auth-basic
+ - auth/token-endpoint-auth-post
+ - auth/token-endpoint-auth-none
+ - auth/pre-registration
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Set up JDK 17
+ uses: actions/setup-java@v4
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ cache: 'maven'
+
+ - name: Build client
+ run: mvn clean install -DskipTests
+
+ - name: Run conformance test
+ uses: modelcontextprotocol/conformance@v0.1.15
+ with:
+ node-version: '22' # see https://github.com/modelcontextprotocol/conformance/pull/162
+ mode: client
+ command: 'java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-*-SNAPSHOT.jar'
+ scenario: ${{ matrix.scenario }}
+ expected-failures: ./conformance-tests/conformance-baseline.yml
\ No newline at end of file
diff --git a/DEPENDENCY_POLICY.md b/DEPENDENCY_POLICY.md
new file mode 100644
index 000000000..5714a6b57
--- /dev/null
+++ b/DEPENDENCY_POLICY.md
@@ -0,0 +1,26 @@
+# Dependency Policy
+
+As a library consumed by downstream projects, the MCP Java SDK takes a conservative approach to dependency updates. Dependencies are kept stable unless there is a specific reason to update, such as a security vulnerability, a bug fix, or a need for new functionality.
+
+## Update Triggers
+
+Dependencies are updated when:
+
+- A **security vulnerability** is disclosed (via GitHub security alerts).
+- A bug in a dependency directly affects the SDK.
+- A new dependency feature is needed for SDK development.
+- A dependency drops support for a Java version the SDK still targets.
+
+Routine version bumps without a clear motivation are avoided to minimize churn for downstream consumers.
+
+## What We Don't Do
+
+The SDK does not run scheduled version bumps for production Maven dependencies. Updating a dependency can force downstream consumers to adopt that update transitively, which can be disruptive for projects with strict dependency policies.
+
+Dependencies are only updated when there is a concrete reason, not simply because a newer version is available.
+
+## Automated Tooling
+
+- **GitHub security updates** are enabled at the repository level and automatically open pull requests for Maven packages with known vulnerabilities. This is a GitHub repo setting, separate from the `dependabot.yml` configuration.
+- **GitHub Actions versions** are kept up to date via Dependabot on a monthly schedule (see `.github/dependabot.yml`).
+- **Maven dependencies** are monitored via Dependabot on a monthly schedule for non-production updates only (see `.github/dependabot.yml`).
diff --git a/MIGRATION-1.0.md b/MIGRATION-1.0.md
new file mode 100644
index 000000000..d1ef0fae8
--- /dev/null
+++ b/MIGRATION-1.0.md
@@ -0,0 +1,300 @@
+# MCP Java SDK Migration Guide: 0.18.1 → 1.0.0
+
+This document covers the breaking changes between **0.18.1** and **1.0.0** of the MCP Java SDK. All items listed here were already deprecated (with `@Deprecated` or `@Deprecated(forRemoval = true)`) in 0.18.1 and are now removed.
+
+> **If you are on a version earlier than 0.18.1**, upgrade progressively to **0.18.1** first. That release already provides the replacement APIs described below alongside the deprecated ones, so you can resolve all deprecation warnings before moving to 1.0.0. Many types and APIs that existed in older 0.x versions (e.g., `ClientMcpTransport`, `ServerMcpTransport`, `DefaultMcpSession`, `StdioServerTransport`, `HttpServletSseServerTransport`, `FlowSseClient`) were already removed well before 0.18.1 and are not covered here.
+
+---
+
+## 1. The `mcp` aggregator module now defaults to Jackson 3
+
+The module structure (`mcp-core`, `mcp-json-jackson2`, `mcp-json-jackson3`, `mcp`) is unchanged. What changes is the default JSON binding in the `mcp` convenience artifact:
+
+| Version | `mcp` artifact includes |
+|---|---|
+| 0.18.1 | `mcp-core` + `mcp-json-jackson2` |
+| 1.0.0 | `mcp-core` + `mcp-json-jackson3` |
+
+If your project uses **Jackson 2** (the `com.fasterxml.jackson` 2.x line), stop depending on the `mcp` aggregator and depend on the individual modules instead:
+
+```xml
+
+ io.modelcontextprotocol.sdk
+ mcp-core
+ 1.0.0-RC3
+
+
+ io.modelcontextprotocol.sdk
+ mcp-json-jackson2
+ 1.0.0-RC3
+
+```
+
+If you are ready to adopt **Jackson 3**, you can simply continue using the `mcp` aggregator:
+
+```xml
+
+ io.modelcontextprotocol.sdk
+ mcp
+ 1.0.0-RC3
+
+```
+
+### Deprecated `io.modelcontextprotocol.json.jackson` package removed
+
+In `mcp-json-jackson2`, the classes under the old `io.modelcontextprotocol.json.jackson` package (deprecated in 0.18.1) have been removed. Use the equivalent classes under `io.modelcontextprotocol.json.jackson2`:
+
+| Removed (old package) | Replacement (already available in 0.18.1) |
+|---|---|
+| `io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapper` | `io.modelcontextprotocol.json.jackson2.JacksonMcpJsonMapper` |
+| `io.modelcontextprotocol.json.jackson.JacksonMcpJsonMapperSupplier` | `io.modelcontextprotocol.json.jackson2.JacksonMcpJsonMapperSupplier` |
+| `io.modelcontextprotocol.json.schema.jackson.DefaultJsonSchemaValidator` | `io.modelcontextprotocol.json.schema.jackson2.DefaultJsonSchemaValidator` |
+| `io.modelcontextprotocol.json.schema.jackson.JacksonJsonSchemaValidatorSupplier` | `io.modelcontextprotocol.json.schema.jackson2.JacksonJsonSchemaValidatorSupplier` |
+
+---
+
+## 2. Spring transport modules (`mcp-spring-webflux`, `mcp-spring-webmvc`)
+
+These modules have been moved to the **Spring AI** project starting with Spring AI 2.0. The artifact names remain the same but the **Maven group has changed**:
+
+| 0.18.1 (MCP Java SDK) | 1.0.0+ (Spring AI 2.0) |
+|---|---|
+| `io.modelcontextprotocol.sdk:mcp-spring-webflux` | `org.springframework.ai:mcp-spring-webflux` |
+| `io.modelcontextprotocol.sdk:mcp-spring-webmvc` | `org.springframework.ai:mcp-spring-webmvc` |
+
+Update your dependency coordinates:
+
+```xml
+
+
+ io.modelcontextprotocol.sdk
+ mcp-spring-webflux
+ 0.18.1
+
+
+
+
+ org.springframework.ai
+ mcp-spring-webflux
+ ${spring-ai.version}
+
+```
+
+The Java package names and class names within these artifacts are unchanged — no source code modifications are needed beyond updating the dependency coordinates.
+
+---
+
+## 3. Tool handler signature — `tool()` removed, use `toolCall()`
+
+The `tool()` method on the `McpServer` builder (both sync and async variants) has been removed. It was deprecated in 0.18.1 in favor of `toolCall()`, which accepts a handler that receives the full `CallToolRequest` instead of a raw `Map`.
+
+#### Before (deprecated, removed in 1.0.0):
+
+```java
+McpServer.sync(transportProvider)
+ .tool(
+ myTool,
+ (exchange, args) -> new CallToolResult(List.of(new TextContent("Result: " + calculate(args))), false)
+ )
+ .build();
+```
+
+#### After (already available in 0.18.1):
+
+```java
+McpServer.sync(transportProvider)
+ .toolCall(
+ myTool,
+ (exchange, request) -> CallToolResult.builder()
+ .content(List.of(new TextContent("Result: " + calculate(request.arguments()))))
+ .isError(false)
+ .build()
+ )
+ .build();
+```
+
+---
+
+## 4. `AsyncToolSpecification` / `SyncToolSpecification` — `call` field removed
+
+The deprecated `call` record component (which accepted `Map`) has been removed from both `AsyncToolSpecification` and `SyncToolSpecification`. Only `callHandler` (which accepts `CallToolRequest`) remains.
+
+The deprecated constructors that accepted a `call` function have also been removed. Use the builder:
+
+```java
+McpServerFeatures.AsyncToolSpecification.builder()
+ .tool(tool)
+ .callHandler((exchange, request) -> Mono.just(
+ CallToolResult.builder()
+ .content(List.of(new TextContent("Done")))
+ .build()))
+ .build();
+```
+
+---
+
+## 5. Content types — deprecated `audience`/`priority` constructors and accessors removed
+
+`TextContent`, `ImageContent`, and `EmbeddedResource` previously had constructors and accessors that took inline `List audience` and `Double priority` parameters. These were deprecated in favor of the `Annotations` record. The deprecated forms are now removed.
+
+#### Before (deprecated, removed in 1.0.0):
+
+```java
+new TextContent(List.of(Role.USER), 0.8, "Hello world")
+textContent.audience() // deprecated accessor
+textContent.priority() // deprecated accessor
+```
+
+#### After (already available in 0.18.1):
+
+```java
+new TextContent(new Annotations(List.of(Role.USER), 0.8), "Hello world")
+textContent.annotations().audience()
+textContent.annotations().priority()
+```
+
+The simple `new TextContent("text")` constructor continues to work.
+
+---
+
+## 6. `CallToolResult` and `Resource` — deprecated constructors removed
+
+The constructors on `CallToolResult` and `Resource` that were deprecated in 0.18.1 have been removed. Use the builders instead.
+
+#### `CallToolResult`
+
+```java
+// Removed:
+new CallToolResult(List.of(new TextContent("result")), false);
+new CallToolResult("result text", false);
+new CallToolResult(content, isError, structuredContent);
+
+// Use instead:
+CallToolResult.builder()
+ .content(List.of(new TextContent("result")))
+ .isError(false)
+ .build();
+```
+
+#### `Resource`
+
+```java
+// Removed:
+new Resource(uri, name, description, mimeType, annotations);
+new Resource(uri, name, title, description, mimeType, size, annotations);
+
+// Use instead:
+Resource.builder()
+ .uri(uri)
+ .name(name)
+ .title(title)
+ .description(description)
+ .mimeType(mimeType)
+ .size(size)
+ .annotations(annotations)
+ .build();
+```
+
+---
+
+## 7. `McpError(Object)` constructor removed
+
+The deprecated `McpError(Object error)` constructor, which was commonly used as `new McpError("message string")`, has been removed. Construct `McpError` instances using the builder with a JSON-RPC error code:
+
+```java
+// Removed:
+throw new McpError("Something went wrong");
+
+// Use instead:
+throw McpError.builder(McpSchema.ErrorCodes.INTERNAL_ERROR)
+ .message("Something went wrong")
+ .build();
+```
+
+Additionally, several places in the SDK that previously threw `McpError` for validation or state-checking purposes now throw standard Java exceptions (`IllegalStateException`, `IllegalArgumentException`). If you were catching `McpError` in those scenarios, update your catch blocks accordingly.
+
+---
+
+## 8. `McpSchema.LATEST_PROTOCOL_VERSION` constant removed
+
+The deprecated `McpSchema.LATEST_PROTOCOL_VERSION` constant has been removed. Use the `ProtocolVersions` interface directly:
+
+```java
+// Removed:
+McpSchema.LATEST_PROTOCOL_VERSION
+
+// Use instead:
+ProtocolVersions.MCP_2025_11_25
+```
+
+---
+
+## 9. Deprecated session constructors and inner interfaces removed
+
+The following deprecated constructors and inner interfaces, all of which already had replacements available in 0.18.1, have been removed:
+
+### `McpServerSession`
+
+| Removed | Replacement (available since 0.18.1) |
+|---|---|
+| Constructor with `InitNotificationHandler` parameter | Constructor without `InitNotificationHandler` — use `McpInitRequestHandler` in the map |
+| `McpServerSession.InitRequestHandler` (inner interface) | `McpInitRequestHandler` (top-level interface) |
+| `McpServerSession.RequestHandler` (inner interface) | `McpRequestHandler` (top-level interface) |
+| `McpServerSession.NotificationHandler` (inner interface) | `McpNotificationHandler` (top-level interface) |
+
+### `McpClientSession`
+
+| Removed | Replacement (available since 0.18.1) |
+|---|---|
+| Constructor without `connectHook` parameter | Constructor that accepts a `Function super Mono, ? extends Publisher> connectHook` |
+
+### `McpAsyncServerExchange`
+
+| Removed | Replacement (available since 0.18.1) |
+|---|---|
+| Constructor `McpAsyncServerExchange(McpSession, ClientCapabilities, Implementation)` | Constructor `McpAsyncServerExchange(String, McpLoggableSession, ClientCapabilities, Implementation, McpTransportContext)` |
+
+---
+
+## 10. `McpAsyncServer.loggingNotification()` / `McpSyncServer.loggingNotification()` removed
+
+The `loggingNotification(LoggingMessageNotification)` methods on `McpAsyncServer` and `McpSyncServer` were deprecated because they incorrectly broadcast to all connected clients. They have been removed. Use the per-session exchange method instead:
+
+```java
+// Removed:
+server.loggingNotification(notification);
+
+// Use instead (inside a handler with access to the exchange):
+exchange.loggingNotification(notification);
+```
+
+---
+
+## 11. `HttpClientSseClientTransport.Builder` — deprecated constructor removed
+
+The deprecated `new HttpClientSseClientTransport.Builder(String baseUri)` constructor has been removed. Use the static factory method:
+
+```java
+// Removed:
+new HttpClientSseClientTransport.Builder("http://localhost:8080")
+
+// Use instead:
+HttpClientSseClientTransport.builder("http://localhost:8080")
+```
+
+---
+
+## Summary checklist
+
+Before upgrading to 1.0.0, verify that your 0.18.1 build has **zero deprecation warnings** related to the MCP SDK. Every removal in 1.0.0 was preceded by a deprecation in 0.18.1 with a pointer to the replacement. Once you are clean on 0.18.1:
+
+1. Update your dependency versions — either bump the `mcp-bom` version, or bump the specific module dependencies you use (e.g., `mcp-core`, `mcp-json-jackson2`). If you were relying on the `mcp` aggregator, note it now pulls in Jackson 3 — switch to `mcp-core` + `mcp-json-jackson2` if you need to stay on Jackson 2.
+2. Replace `io.modelcontextprotocol.sdk:mcp-spring-webflux` / `mcp-spring-webmvc` with `org.springframework.ai:mcp-spring-webflux` / `mcp-spring-webmvc`.
+3. If you use the `mcp-json-jackson2` module, update imports from `io.modelcontextprotocol.json.jackson` to `io.modelcontextprotocol.json.jackson2` (and similarly for the schema validator package).
+4. Compile and verify — no further source changes should be needed.
+
+---
+
+## Need help?
+
+If you run into issues during migration or have questions, please open an issue or start a discussion in the [MCP Java SDK GitHub repository](https://github.com/modelcontextprotocol/java-sdk).
diff --git a/README.md b/README.md
index c1f5f10c6..34133a796 100644
--- a/README.md
+++ b/README.md
@@ -20,9 +20,9 @@ For comprehensive guides and SDK API documentation
- [Java MCP Server](https://modelcontextprotocol.github.io/java-sdk/server/) - Learn how to implement and configure a MCP servers.
#### Spring AI MCP documentation
-[Spring AI MCP](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-overview.html) extends the MCP Java SDK with Spring Boot integration, providing both [client](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html) and [server](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html) starters.
-The [MCP Annotations](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-annotations-overview.html) - provides annotation-based method handling for MCP servers and clients in Java.
-The [MCP Security](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-security.html) - provides comprehensive OAuth 2.0 and API key-based security support for Model Context Protocol implementations in Spring AI.
+[Spring AI MCP](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) extends the MCP Java SDK with Spring Boot integration, providing both [client](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-client-boot-starter-docs.html) and [server](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-server-boot-starter-docs.html) starters.
+The [MCP Annotations](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-annotations-overview.html) - provides annotation-based method handling for MCP servers and clients in Java.
+The [MCP Security](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-security.html) - provides comprehensive OAuth 2.0 and API key-based security support for Model Context Protocol implementations in Spring AI.
Bootstrap your AI applications with MCP support using [Spring Initializer](https://start.spring.io).
## Development
@@ -139,21 +139,21 @@ MCP supports both clients (applications consuming MCP servers) and servers (appl
#### Client Transport in the SDK
-* **SDK Choice**: JDK HttpClient (Java 11+) as the default client, with optional Spring WebClient support
+* **SDK Choice**: JDK HttpClient (Java 11+) as the default client
-* **Why**: The JDK HttpClient is built-in, portable, and supports streaming responses. This keeps the default lightweight with no extra dependencies. Spring WebClient support is available for Spring-based projects.
+* **Why**: The JDK HttpClient is built-in, portable, and supports streaming responses. This keeps the default lightweight with no extra dependencies.
-* **How we expose it**: MCP Client APIs are transport-agnostic. The core module ships with JDK HttpClient transport. A Spring module provides WebClient integration.
+* **How we expose it**: MCP Client APIs are transport-agnostic. The core module ships with JDK HttpClient transport. Spring WebClient-based transport is available in [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+.
* **How it fits the SDK**: This ensures all applications can talk to MCP servers out of the box, while allowing richer integration in Spring and other environments.
#### Server Transport in the SDK
-* **SDK Choice**: Jakarta Servlet implementation in core, with optional Spring WebFlux and Spring WebMVC providers
+* **SDK Choice**: Jakarta Servlet implementation in core
-* **Why**: Servlet is the most widely deployed Java server API. WebFlux and WebMVC cover a significant part of the Spring community. Together these provide reach across blocking and non-blocking models.
+* **Why**: Servlet is the most widely deployed Java server API, providing broad reach across blocking and non-blocking models without additional dependencies.
-* **How we expose it**: Server APIs are transport-agnostic. Core includes Servlet support. Spring modules extend support for WebFlux and WebMVC.
+* **How we expose it**: Server APIs are transport-agnostic. Core includes Servlet support. Spring WebFlux and WebMVC server transports are available in [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+.
* **How it fits the SDK**: This allows developers to expose MCP servers in the most common Java environments today, while enabling other transport implementations such as Netty, Vert.x, or Helidon.
@@ -176,9 +176,10 @@ The SDK is organized into modules to separate concerns and allow adopters to bri
* `mcp-json-jackson3` – Jackson 3 implementation of JSON binding
* `mcp` – Convenience bundle (core + Jackson 3)
* `mcp-test` – Shared testing utilities
-* `mcp-spring` – Spring integrations (WebClient, WebFlux, WebMVC)
-For example, a minimal adopter may depend only on `mcp` (core + Jackson), while a Spring-based application can use `mcp-spring` for deeper framework integration.
+Spring integrations (WebClient, WebFlux, WebMVC) are now part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`).
+
+For example, a minimal adopter may depend only on `mcp` (core + Jackson), while a Spring-based application can use the Spring AI `mcp-spring-webflux` or `mcp-spring-webmvc` artifacts for deeper framework integration.
Additionally, `mcp-test` contains integration tests for `mcp-core`.
`mcp-core` needs a JSON implementation to run full integration tests.
diff --git a/ROADMAP.md b/ROADMAP.md
new file mode 100644
index 000000000..b5b7dc4d7
--- /dev/null
+++ b/ROADMAP.md
@@ -0,0 +1,45 @@
+# Roadmap
+
+## Spec Implementation Tracking
+
+The SDK tracks implementation of MCP spec components via GitHub Projects, with a dedicated project board for each spec revision. For example, see the [2025-11-25 spec revision board](https://github.com/orgs/modelcontextprotocol/projects/26/views/1).
+
+## Current Focus Areas
+
+### 2025-11-25 Spec Implementation
+
+The Java SDK is actively implementing the [2025-11-25 MCP specification revision](https://github.com/orgs/modelcontextprotocol/projects/26/views/1).
+
+Key features in this revision include:
+
+- **Tasks**: Experimental support for tracking durable requests with polling and deferred result retrieval
+- **Tool calling in sampling**: Support for `tools` and `toolChoice` parameters
+- **URL mode elicitation**: Client-side URL elicitation requests
+- **Icons metadata**: Servers can expose icons for tools, resources, resource templates, and prompts
+- **Enhanced schemas**: JSON Schema 2020-12 as default, improved enum support, default values for elicitation
+- **Security improvements**: Updated security best practices, enhanced authorization flows, enabling OAuth integrations
+
+See the full [changelog](https://modelcontextprotocol.io/specification/2025-11-25/changelog) for details.
+
+### Tier 1 SDK Support
+
+Once we catch up on the most recent MCP specification revision we aim to fully support all the upcoming specification features on the day of its release.
+
+### v1.x Development
+
+The Java SDK is currently in active development as v1.x, following a recent stable 1.0.0 release. The SDK provides:
+
+- MCP protocol implementation
+- Synchronous and asynchronous programming models
+- Multiple transport options (STDIO, HTTP/SSE, Servlet)
+- Pluggable JSON serialization (Jackson 2 and Jackson 3)
+
+Development is tracked via [GitHub Issues](https://github.com/modelcontextprotocol/java-sdk/issues) and [GitHub Projects](https://github.com/orgs/modelcontextprotocol/projects).
+
+### Future Versions
+
+Major version updates will align with MCP specification changes and breaking API changes as needed. The SDK is designed to evolve with the Java ecosystem, including:
+
+- Virtual Threads and Structured Concurrency support
+- Additional transport implementations
+- Performance optimizations
diff --git a/VERSIONING.md b/VERSIONING.md
new file mode 100644
index 000000000..331c6d05e
--- /dev/null
+++ b/VERSIONING.md
@@ -0,0 +1,46 @@
+# Versioning Policy
+
+The MCP Java SDK (`io.modelcontextprotocol.sdk`) follows [Semantic Versioning 2.0.0](https://semver.org/).
+
+## Version Format
+
+`MAJOR.MINOR.PATCH`
+
+- **MAJOR**: Incremented for breaking changes (see below).
+- **MINOR**: Incremented for new features that are backward-compatible.
+- **PATCH**: Incremented for backward-compatible bug fixes.
+
+## What Constitutes a Breaking Change
+
+The following changes are considered breaking and require a major version bump:
+
+- Removing or renaming a public API (class, interface, method, or constant).
+- Changing the signature of a public method in a way that breaks existing callers (removing parameters, changing required/optional status, changing types).
+- Removing or renaming a public interface method or field.
+- Changing the behavior of an existing API in a way that breaks documented contracts.
+- Dropping support for a Java LTS version.
+- Removing support for a transport type.
+- Changes to the MCP protocol version that require client/server code changes.
+- Removing a module from the SDK.
+
+The following are **not** considered breaking:
+
+- Adding new methods with default implementations to interfaces.
+- Adding new public APIs, classes, interfaces, or methods.
+- Adding new optional parameters to existing methods (through method overloading).
+- Bug fixes that correct behavior to match documented intent.
+- Internal refactoring that does not affect the public API.
+- Adding support for new MCP spec features.
+- Changes to test dependencies or build tooling.
+- Adding new modules to the SDK.
+
+## How Breaking Changes Are Communicated
+
+1. **Changelog**: All breaking changes are documented in the GitHub release notes with migration instructions.
+2. **Deprecation**: When feasible, APIs are deprecated for at least one minor release before removal using `@Deprecated` annotations, which surface warnings through Java tooling and IDEs.
+3. **Migration guide**: Major version releases include a migration guide describing what changed and how to update.
+4. **PR labels**: Pull requests containing breaking changes are labeled with `breaking change`.
+
+## Maven Coordinates
+
+All SDK modules share the same version number and are released together. The BOM (`mcp-bom`) provides dependency management for all SDK modules to ensure version consistency.
diff --git a/conformance-tests/VALIDATION_RESULTS.md b/conformance-tests/VALIDATION_RESULTS.md
index 7be75e6e5..19e74330c 100644
--- a/conformance-tests/VALIDATION_RESULTS.md
+++ b/conformance-tests/VALIDATION_RESULTS.md
@@ -2,8 +2,9 @@
## Summary
-**Server Tests:** 37/40 passed (92.5%)
+**Server Tests:** 37/40 passed (92.5%)
**Client Tests:** 3/4 scenarios passed (9/10 checks passed)
+**Auth Tests:** 12/14 scenarios fully passing (178 passed, 1 failed, 1 warning, 85.7% scenarios, 98.9% checks)
## Server Test Results
@@ -20,7 +21,7 @@
### Failing (3/40)
1. **resources-subscribe** - Not implemented in SDK
-2. **resources-unsubscribe** - Not implemented in SDK
+2. **resources-unsubscribe** - Not implemented in SDK
## Client Test Results
@@ -32,17 +33,45 @@
### Partially Passing (1/4 scenarios, 1/2 checks)
-- **sse-retry (1/2 + 1 warning):**
+- **sse-retry (1/2 + 1 warning):**
- ✅ Reconnects after stream closure
- ❌ Does not respect retry timing
- ⚠️ Does not send Last-Event-ID header (SHOULD requirement)
**Issue:** Client treats `retry:` SSE field as invalid instead of parsing it for reconnection timing.
+## Auth Test Results (Spring HTTP Client)
+
+**Status: 178 passed, 1 failed, 1 warning across 14 scenarios**
+
+Uses the `client-spring-http-client` module with Spring Security OAuth2 and the [mcp-client-security](https://github.com/springaicommunity/mcp-client-security) library.
+
+### Fully Passing (12/14 scenarios)
+
+- **auth/metadata-default (12/12):** Default metadata discovery
+- **auth/metadata-var1 (12/12):** Metadata discovery variant 1
+- **auth/metadata-var2 (12/12):** Metadata discovery variant 2
+- **auth/metadata-var3 (12/12):** Metadata discovery variant 3
+- **auth/scope-from-www-authenticate (13/13):** Scope extraction from WWW-Authenticate header
+- **auth/scope-from-scopes-supported (13/13):** Scope extraction from scopes_supported
+- **auth/scope-omitted-when-undefined (13/13):** Scope omitted when not defined
+- **auth/scope-retry-limit (11/11):** Scope retry limit handling
+- **auth/token-endpoint-auth-basic (17/17):** Token endpoint with HTTP Basic auth
+- **auth/token-endpoint-auth-post (17/17):** Token endpoint with POST body auth
+- **auth/token-endpoint-auth-none (17/17):** Token endpoint with no client auth
+- **auth/pre-registration (6/6):** Pre-registered client credentials flow
+
+### Partially Passing (2/14 scenarios)
+
+- **auth/basic-cimd (12/12 + 1 warning):** Basic Client-Initiated Metadata Discovery — all checks pass, minor warning
+- **auth/scope-step-up (11/12):** Scope step-up challenge — 1 failure, client does not fully handle scope escalation after initial authorization
+
## Known Limitations
1. **Resource Subscriptions:** SDK doesn't implement `resources/subscribe` and `resources/unsubscribe` handlers
2. **Client SSE Retry:** Client doesn't parse or respect the `retry:` field, reconnects immediately, and doesn't send Last-Event-ID header
+3. **Auth Scope Step-Up:** Client does not fully handle scope step-up challenges where the server requests additional scopes after initial authorization
+4. **Auth Basic CIMD:** Minor conformance warning in the basic Client-Initiated Metadata Discovery flow
## Running Tests
@@ -70,11 +99,26 @@ for scenario in initialize tools_call elicitation-sep1034-client-defaults sse-re
done
```
+### Auth (Spring HTTP Client)
+
+Ensure you run with the conformance testing suite `0.1.15` or higher.
+
+```bash
+# Build
+cd conformance-tests/client-spring-http-client
+../../mvnw clean package -DskipTests
+
+# Run auth suite
+npx @modelcontextprotocol/conformance@0.1.15 client \
+ --spec-version 2025-11-25 \
+ --command "java -jar target/client-spring-http-client-0.18.0-SNAPSHOT.jar" \
+ --suite auth
+```
+
## Recommendations
### High Priority
1. Fix client SSE retry field handling in `HttpClientStreamableHttpTransport`
2. Implement resource subscription handlers in `McpStatelessAsyncServer`
-
-### Medium Priority
-3. Add Host/Origin validation in `HttpServletStreamableServerTransportProvider` for DNS rebinding protection
+3. Implement CIMD
+4. Implement scope step up
diff --git a/conformance-tests/client-jdk-http-client/pom.xml b/conformance-tests/client-jdk-http-client/pom.xml
index d5a1e843a..f30361438 100644
--- a/conformance-tests/client-jdk-http-client/pom.xml
+++ b/conformance-tests/client-jdk-http-client/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdkconformance-tests
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOTclient-jdk-http-clientjar
@@ -20,11 +20,15 @@
git@github.com/modelcontextprotocol/java-sdk.git
+
+ true
+
+
io.modelcontextprotocol.sdkmcp
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOT
diff --git a/conformance-tests/client-spring-http-client/README.md b/conformance-tests/client-spring-http-client/README.md
new file mode 100644
index 000000000..876a86e1d
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/README.md
@@ -0,0 +1,124 @@
+# MCP Conformance Tests - Spring HTTP Client (Auth Suite)
+
+This module provides a conformance test client implementation for the Java MCP SDK's **auth** suite.
+
+OAuth2 support is not implemented in the SDK itself, but we provide hooks to implement the Authorization section of the specification. One such implementation is done in Spring, with Sprign AI and the [mcp-client-security](https://github.com/springaicommunity/mcp-client-security) library.
+
+This is a Spring web application, we interact with it through a normal HTTP-client that follows redirects and performs OAuth2 authorization flows.
+
+## Overview
+
+The conformance test client is designed to work with the [MCP Conformance Test Framework](https://github.com/modelcontextprotocol/conformance). It validates that the Java MCP SDK client, combined with Spring Security's OAuth2 support, properly implements the MCP authorization specification.
+
+Test with @modelcontextprotocol/conformance@0.1.15.
+
+## Conformance Test Results
+
+**Status: 178 passed, 1 failed, 1 warning across 14 scenarios**
+
+| Scenario | Result | Details |
+|---|---|---|
+| auth/metadata-default | ✅ Pass | 12/12 |
+| auth/metadata-var1 | ✅ Pass | 12/12 |
+| auth/metadata-var2 | ✅ Pass | 12/12 |
+| auth/metadata-var3 | ✅ Pass | 12/12 |
+| auth/basic-cimd | ⚠️ Warning | 12/12 passed, 1 warning |
+| auth/scope-from-www-authenticate | ✅ Pass | 13/13 |
+| auth/scope-from-scopes-supported | ✅ Pass | 13/13 |
+| auth/scope-omitted-when-undefined | ✅ Pass | 13/13 |
+| auth/scope-step-up | ❌ Fail | 11/12 (1 failed) |
+| auth/scope-retry-limit | ✅ Pass | 11/11 |
+| auth/token-endpoint-auth-basic | ✅ Pass | 17/17 |
+| auth/token-endpoint-auth-post | ✅ Pass | 17/17 |
+| auth/token-endpoint-auth-none | ✅ Pass | 17/17 |
+| auth/pre-registration | ✅ Pass | 6/6 |
+
+See [VALIDATION_RESULTS.md](../VALIDATION_RESULTS.md) for the full project validation results.
+
+## Architecture
+
+The client is a Spring Boot application that reads test scenarios from environment variables and accepts the server URL as a command-line argument, following the conformance framework's conventions:
+
+- **MCP_CONFORMANCE_SCENARIO**: Environment variable specifying which test scenario to run
+- **MCP_CONFORMANCE_CONTEXT**: Environment variable with JSON context (used by `auth/pre-registration`)
+- **Server URL**: Passed as the last command-line argument
+
+### Scenario Routing
+
+The application uses Spring's conditional configuration to select the appropriate scenario at startup:
+
+- **`DefaultConfiguration`** — Activated for all scenarios except `auth/pre-registration`. Uses the OAuth2 Authorization Code flow with dynamic client registration via `McpClientOAuth2Configurer`.
+- **`PreRegistrationConfiguration`** — Activated only for `auth/pre-registration`. Uses the Client Credentials flow with pre-registered client credentials read from `MCP_CONFORMANCE_CONTEXT`.
+
+### Key Dependencies
+
+- **Spring Boot 4.0** with Spring Security OAuth2 Client
+- **Spring AI MCP Client** (`spring-ai-starter-mcp-client`)
+- **mcp-client-security** — Community library providing MCP-specific OAuth2 integration (metadata discovery, dynamic client registration, transport context)
+
+## Building
+
+Build the executable JAR:
+
+```bash
+cd conformance-tests/client-spring-http-client
+../../mvnw clean package -DskipTests
+```
+
+This creates an executable JAR at:
+```
+target/client-spring-http-client-0.18.0-SNAPSHOT.jar
+```
+
+## Running Tests
+
+### Using the Conformance Framework
+
+Run the full auth suite:
+
+```bash
+npx @modelcontextprotocol/conformance@0.1.15 client \
+ --spec-version 2025-11-25 \
+ --command "java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-0.18.0-SNAPSHOT.jar" \
+ --suite auth
+```
+
+Run a single scenario:
+
+```bash
+npx @modelcontextprotocol/conformance@0.1.15 client \
+ --spec-version 2025-11-25 \
+ --command "java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-0.18.0-SNAPSHOT.jar" \
+ --scenario auth/metadata-default
+```
+
+Run with verbose output:
+
+```bash
+npx @modelcontextprotocol/conformance@0.1.15 client \
+ --spec-version 2025-11-25 \
+ --command "java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-0.18.0-SNAPSHOT.jar" \
+ --scenario auth/metadata-default \
+ --verbose
+```
+
+### Manual Testing
+
+You can also run the client manually if you have a test server:
+
+```bash
+export MCP_CONFORMANCE_SCENARIO=auth/metadata-default
+java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-0.18.0-SNAPSHOT.jar http://localhost:3000/mcp
+```
+
+## Known Issues
+
+1. **auth/scope-step-up** (1 failure) — The client does not fully handle scope step-up challenges where the server requests additional scopes after initial authorization.
+2. **auth/basic-cimd** (1 warning) — Minor conformance warning in the basic Client-Initiated Metadata Discovery flow.
+
+## References
+
+- [MCP Specification — Authorization](https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization)
+- [MCP Conformance Tests](https://github.com/modelcontextprotocol/conformance)
+- [mcp-client-security Library](https://github.com/springaicommunity/mcp-client-security)
+- [SDK Integration Guide](https://github.com/modelcontextprotocol/conformance/blob/main/SDK_INTEGRATION.md)
diff --git a/conformance-tests/client-spring-http-client/pom.xml b/conformance-tests/client-spring-http-client/pom.xml
new file mode 100644
index 000000000..94923fb5c
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/pom.xml
@@ -0,0 +1,91 @@
+
+
+ 4.0.0
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 4.0.2
+
+
+ io.modelcontextprotocol.sdk
+ client-spring-http-client
+ 1.0.0-SNAPSHOT
+ jar
+ MCP Conformance Tests - Spring HTTP Client
+ Spring HTTP Client conformance tests for the Java MCP SDK
+ 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
+
+
+
+ 17
+ 2.0.0-M2
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-webmvc
+
+
+
+ org.springframework.boot
+ spring-boot-starter-restclient
+
+
+
+ org.springframework.ai
+ spring-ai-starter-mcp-client
+ ${spring-ai.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-oauth2-client
+
+
+
+ org.springaicommunity
+ mcp-client-security
+ 0.1.2
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
+
+ maven-central
+ https://repo.maven.apache.org/maven2/
+
+ false
+
+
+ true
+
+
+
+ spring-milestones
+ Spring Milestones
+ https://repo.spring.io/milestone
+
+ false
+
+
+
+
+
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/ConformanceSpringClientApplication.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/ConformanceSpringClientApplication.java
new file mode 100644
index 000000000..00582c9f2
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/ConformanceSpringClientApplication.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client;
+
+import java.util.Optional;
+
+import io.modelcontextprotocol.conformance.client.scenario.Scenario;
+import org.springaicommunity.mcp.security.client.sync.oauth2.metadata.McpMetadataDiscoveryService;
+import org.springaicommunity.mcp.security.client.sync.oauth2.registration.DynamicClientRegistrationService;
+import org.springaicommunity.mcp.security.client.sync.oauth2.registration.InMemoryMcpClientRegistrationRepository;
+
+import org.springframework.boot.ApplicationArguments;
+import org.springframework.boot.ApplicationRunner;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+
+/**
+ * MCP Conformance Test Client - Spring HTTP Client Implementation.
+ *
+ *
+ * This client is designed to work with the MCP conformance test framework. It reads the
+ * test scenario from the MCP_CONFORMANCE_SCENARIO environment variable and the server URL
+ * from command-line arguments.
+ *
+ *
+ * It specifically tests the {@code auth} conformance suite. It requires Spring to work.
+ *
+ *
+ * Usage: java -jar client-spring-http-client.jar <server-url>
+ *
+ * @see MCP Conformance
+ * Test Framework
+ */
+@SpringBootApplication
+public class ConformanceSpringClientApplication {
+
+ public static final String REGISTRATION_ID = "default_registration";
+
+ public static void main(String[] args) {
+ SpringApplication.run(ConformanceSpringClientApplication.class, args);
+ }
+
+ @Bean
+ McpMetadataDiscoveryService discovery() {
+ return new McpMetadataDiscoveryService();
+ }
+
+ @Bean
+ InMemoryMcpClientRegistrationRepository clientRegistrationRepository(McpMetadataDiscoveryService discovery) {
+ return new InMemoryMcpClientRegistrationRepository(new DynamicClientRegistrationService(), discovery);
+ }
+
+ @Bean
+ ApplicationRunner conformanceRunner(Optional scenario, ServerUrl serverUrl) {
+ return args -> {
+ String scenarioName = System.getenv("MCP_CONFORMANCE_SCENARIO");
+ if (scenarioName == null || scenarioName.isEmpty()) {
+ System.err.println("Error: MCP_CONFORMANCE_SCENARIO environment variable is not set");
+ System.exit(1);
+ }
+
+ if (scenario.isEmpty()) {
+ System.err.println("Unsupported scenario type");
+ System.exit(1);
+ }
+
+ try {
+ System.out.println("Executing " + scenarioName);
+ scenario.get().execute(serverUrl.value());
+ System.exit(0);
+ }
+ catch (Exception e) {
+ System.err.println("Error: " + e.getMessage());
+ e.printStackTrace();
+ System.exit(1);
+ }
+ };
+ }
+
+ public record ServerUrl(String value) {
+ }
+
+ @Bean
+ ServerUrl serverUrl(ApplicationArguments args) {
+ var nonOptionArgs = args.getNonOptionArgs();
+ if (nonOptionArgs.isEmpty()) {
+ System.err.println("Usage: ConformanceSpringClientApplication ");
+ System.err.println("The server URL must be provided as a command-line argument.");
+ System.err.println("The MCP_CONFORMANCE_SCENARIO environment variable must be set.");
+ System.exit(1);
+ }
+
+ return new ServerUrl(nonOptionArgs.get(nonOptionArgs.size() - 1));
+ }
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/McpClientController.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/McpClientController.java
new file mode 100644
index 000000000..e02cfd416
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/McpClientController.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client;
+
+import io.modelcontextprotocol.conformance.client.scenario.Scenario;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Expose MCP client in a web environment.
+ */
+@RestController
+class McpClientController {
+
+ private final Scenario scenario;
+
+ McpClientController(Scenario scenario) {
+ this.scenario = scenario;
+ }
+
+ @GetMapping("/initialize-mcp-client")
+ public String execute() {
+ this.scenario.getMcpClient().initialize();
+ return "OK";
+ }
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/configuration/DefaultConfiguration.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/configuration/DefaultConfiguration.java
new file mode 100644
index 000000000..acf26d94e
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/configuration/DefaultConfiguration.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client.configuration;
+
+import io.modelcontextprotocol.conformance.client.ConformanceSpringClientApplication;
+import io.modelcontextprotocol.conformance.client.scenario.DefaultScenario;
+import org.springaicommunity.mcp.security.client.sync.config.McpClientOAuth2Configurer;
+import org.springaicommunity.mcp.security.client.sync.oauth2.registration.McpClientRegistrationRepository;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.boot.web.server.servlet.context.ServletWebServerApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
+import org.springframework.security.web.SecurityFilterChain;
+import static io.modelcontextprotocol.conformance.client.ConformanceSpringClientApplication.REGISTRATION_ID;
+
+@Configuration
+@ConditionalOnExpression("#{environment['MCP_CONFORMANCE_SCENARIO'] != 'auth/pre-registration'}")
+public class DefaultConfiguration {
+
+ @Bean
+ DefaultScenario defaultScenario(McpClientRegistrationRepository clientRegistrationRepository,
+ ServletWebServerApplicationContext serverCtx,
+ OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository) {
+ return new DefaultScenario(clientRegistrationRepository, serverCtx, oAuth2AuthorizedClientRepository);
+ }
+
+ @Bean
+ SecurityFilterChain securityFilterChain(HttpSecurity http, ConformanceSpringClientApplication.ServerUrl serverUrl) {
+ return http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll())
+ .with(new McpClientOAuth2Configurer(),
+ mcp -> mcp.registerMcpOAuth2Client(REGISTRATION_ID, serverUrl.value()))
+ .build();
+ }
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/configuration/PreRegistrationConfiguration.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/configuration/PreRegistrationConfiguration.java
new file mode 100644
index 000000000..afe03f85a
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/configuration/PreRegistrationConfiguration.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client.configuration;
+
+import io.modelcontextprotocol.conformance.client.scenario.PreRegistrationScenario;
+import org.springaicommunity.mcp.security.client.sync.config.McpClientOAuth2Configurer;
+import org.springaicommunity.mcp.security.client.sync.oauth2.metadata.McpMetadataDiscoveryService;
+import org.springaicommunity.mcp.security.client.sync.oauth2.registration.McpClientRegistrationRepository;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.Customizer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
+import org.springframework.security.web.SecurityFilterChain;
+
+@Configuration
+@ConditionalOnProperty(name = "mcp.conformance.scenario", havingValue = "auth/pre-registration")
+public class PreRegistrationConfiguration {
+
+ @Bean
+ PreRegistrationScenario defaultScenario(McpClientRegistrationRepository clientRegistrationRepository,
+ McpMetadataDiscoveryService mcpMetadataDiscovery,
+ OAuth2AuthorizedClientService oAuth2AuthorizedClientService) {
+ return new PreRegistrationScenario(clientRegistrationRepository, mcpMetadataDiscovery,
+ oAuth2AuthorizedClientService);
+ }
+
+ @Bean
+ SecurityFilterChain securityFilterChain(HttpSecurity http) {
+ return http.authorizeHttpRequests(authz -> authz.anyRequest().permitAll())
+ .with(new McpClientOAuth2Configurer(), Customizer.withDefaults())
+ .build();
+ }
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/DefaultScenario.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/DefaultScenario.java
new file mode 100644
index 000000000..d82637de9
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/DefaultScenario.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client.scenario;
+
+import java.net.CookieManager;
+import java.net.CookiePolicy;
+import java.net.http.HttpClient;
+import java.time.Duration;
+
+import io.modelcontextprotocol.client.McpClient;
+import io.modelcontextprotocol.client.McpSyncClient;
+import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
+import io.modelcontextprotocol.spec.McpSchema;
+import org.jspecify.annotations.NonNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springaicommunity.mcp.security.client.sync.AuthenticationMcpTransportContextProvider;
+import org.springaicommunity.mcp.security.client.sync.oauth2.http.client.OAuth2AuthorizationCodeSyncHttpRequestCustomizer;
+import org.springaicommunity.mcp.security.client.sync.oauth2.registration.McpClientRegistrationRepository;
+
+import org.springframework.boot.web.server.servlet.context.ServletWebServerApplicationContext;
+import org.springframework.http.client.JdkClientHttpRequestFactory;
+import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
+import org.springframework.web.client.RestClient;
+import static io.modelcontextprotocol.conformance.client.ConformanceSpringClientApplication.REGISTRATION_ID;
+
+public class DefaultScenario implements Scenario {
+
+ private static final Logger log = LoggerFactory
+ .getLogger(DefaultScenario.class);
+
+ private final ServletWebServerApplicationContext serverCtx;
+
+ private final DefaultOAuth2AuthorizedClientManager authorizedClientManager;
+
+ private McpSyncClient client;
+
+ public DefaultScenario(McpClientRegistrationRepository clientRegistrationRepository,
+ ServletWebServerApplicationContext serverCtx,
+ OAuth2AuthorizedClientRepository oAuth2AuthorizedClientRepository) {
+ this.serverCtx = serverCtx;
+ this.authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository,
+ oAuth2AuthorizedClientRepository);
+ }
+
+ @Override
+ public void execute(String serverUrl) {
+ log.info("Executing DefaultScenario");
+ var testServerUrl = "http://localhost:" + serverCtx.getWebServer().getPort();
+ var testClient = buildTestClient(testServerUrl);
+
+ var customizer = new OAuth2AuthorizationCodeSyncHttpRequestCustomizer(authorizedClientManager, REGISTRATION_ID);
+ HttpClientStreamableHttpTransport transport = HttpClientStreamableHttpTransport.builder(serverUrl)
+ .httpRequestCustomizer(customizer)
+ .build();
+
+ this.client = McpClient.sync(transport)
+ .transportContextProvider(new AuthenticationMcpTransportContextProvider())
+ .clientInfo(new McpSchema.Implementation("test-client", "1.0.0"))
+ .requestTimeout(Duration.ofSeconds(30))
+ .build();
+
+ try {
+ testClient.get().uri("/initialize-mcp-client").retrieve().toBodilessEntity();
+ }
+ finally {
+ // Close the client (which will close the transport)
+ this.client.close();
+
+ System.out.println("Connection closed successfully");
+ }
+ }
+
+ private static @NonNull RestClient buildTestClient(String testServerUrl) {
+ var cookieManager = new CookieManager();
+ cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
+ var httpClient = HttpClient.newBuilder()
+ .cookieHandler(cookieManager)
+ .followRedirects(HttpClient.Redirect.ALWAYS)
+ .build();
+ var testClient = RestClient.builder()
+ .baseUrl(testServerUrl)
+ .requestFactory(new JdkClientHttpRequestFactory(httpClient))
+ .build();
+ return testClient;
+ }
+
+ @Override
+ public McpSyncClient getMcpClient() {
+ if (this.client == null) {
+ return Scenario.super.getMcpClient();
+ }
+
+ return this.client;
+ }
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/PreRegistrationScenario.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/PreRegistrationScenario.java
new file mode 100644
index 000000000..8e6bbe228
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/PreRegistrationScenario.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client.scenario;
+
+import java.time.Duration;
+
+import io.modelcontextprotocol.client.McpClient;
+import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
+import io.modelcontextprotocol.spec.McpSchema;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springaicommunity.mcp.security.client.sync.AuthenticationMcpTransportContextProvider;
+import org.springaicommunity.mcp.security.client.sync.oauth2.http.client.OAuth2ClientCredentialsSyncHttpRequestCustomizer;
+import org.springaicommunity.mcp.security.client.sync.oauth2.metadata.McpMetadataDiscoveryService;
+import org.springaicommunity.mcp.security.client.sync.oauth2.registration.McpClientRegistrationRepository;
+import tools.jackson.databind.PropertyNamingStrategies;
+import tools.jackson.databind.annotation.JsonNaming;
+import tools.jackson.databind.json.JsonMapper;
+
+import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
+import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
+import org.springframework.security.oauth2.client.registration.ClientRegistrations;
+import org.springframework.security.oauth2.core.AuthorizationGrantType;
+import static io.modelcontextprotocol.conformance.client.ConformanceSpringClientApplication.REGISTRATION_ID;
+
+public class PreRegistrationScenario implements Scenario {
+
+ private static final Logger log = LoggerFactory.getLogger(PreRegistrationScenario.class);
+
+ private final JsonMapper mapper;
+
+ private final McpClientRegistrationRepository clientRegistrationRepository;
+
+ private final AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager;
+
+ private final McpMetadataDiscoveryService mcpMetadataDiscovery;
+
+ public PreRegistrationScenario(McpClientRegistrationRepository clientRegistrationRepository,
+ McpMetadataDiscoveryService mcpMetadataDiscovery, OAuth2AuthorizedClientService authorizedClientService) {
+ this.mapper = JsonMapper.shared();
+ this.clientRegistrationRepository = clientRegistrationRepository;
+ this.authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager(
+ clientRegistrationRepository, authorizedClientService);
+ this.mcpMetadataDiscovery = mcpMetadataDiscovery;
+ }
+
+ @Override
+ public void execute(String serverUrl) {
+ log.info("Executing PreRegistrationScenario");
+
+ var oauthCredentials = extractCredentialsFromContext();
+ setClientRegistration(serverUrl, oauthCredentials);
+
+ var customizer = new OAuth2ClientCredentialsSyncHttpRequestCustomizer(authorizedClientManager, REGISTRATION_ID);
+ HttpClientStreamableHttpTransport transport = HttpClientStreamableHttpTransport.builder(serverUrl)
+ .httpRequestCustomizer(customizer)
+ .build();
+
+ var client = McpClient.sync(transport)
+ .transportContextProvider(new AuthenticationMcpTransportContextProvider())
+ .clientInfo(new McpSchema.Implementation("test-client", "1.0.0"))
+ .requestTimeout(Duration.ofSeconds(30))
+ .build();
+
+ try {
+ // Initialize client
+ client.initialize();
+
+ System.out.println("Successfully connected to MCP server");
+ }
+ finally {
+ // Close the client (which will close the transport)
+ client.close();
+
+ System.out.println("Connection closed successfully");
+ }
+ }
+
+ private void setClientRegistration(String mcpServerUrl, PreRegistrationContext oauthCredentials) {
+ var metadata = this.mcpMetadataDiscovery.getMcpMetadata(mcpServerUrl);
+ var registration = ClientRegistrations
+ .fromIssuerLocation(metadata.protectedResourceMetadata().authorizationServers().get(0))
+ .registrationId(REGISTRATION_ID)
+ .clientId(oauthCredentials.clientId())
+ .clientSecret(oauthCredentials.clientSecret())
+ .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
+ .build();
+ clientRegistrationRepository.addPreRegisteredClient(registration,
+ metadata.protectedResourceMetadata().resource());
+ }
+
+ private PreRegistrationContext extractCredentialsFromContext() {
+ String contextEnv = System.getenv("MCP_CONFORMANCE_CONTEXT");
+ if (contextEnv == null || contextEnv.isEmpty()) {
+ var errorMessage = "Error: MCP_CONFORMANCE_CONTEXT environment variable is not set";
+ System.err.println(errorMessage);
+ throw new RuntimeException(errorMessage);
+ }
+
+ return mapper.readValue(contextEnv, PreRegistrationContext.class);
+ }
+
+ @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
+ private record PreRegistrationContext(String clientId, String clientSecret) {
+
+ }
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/Scenario.java b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/Scenario.java
new file mode 100644
index 000000000..9054db83b
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/java/io/modelcontextprotocol/conformance/client/scenario/Scenario.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2026-2026 the original author or authors.
+ */
+
+package io.modelcontextprotocol.conformance.client.scenario;
+
+import io.modelcontextprotocol.client.McpSyncClient;
+
+public interface Scenario {
+
+ default McpSyncClient getMcpClient() {
+ throw new IllegalStateException("Client not set");
+ }
+
+ void execute(String serverUrl);
+
+}
diff --git a/conformance-tests/client-spring-http-client/src/main/resources/application.properties b/conformance-tests/client-spring-http-client/src/main/resources/application.properties
new file mode 100644
index 000000000..0c4a77438
--- /dev/null
+++ b/conformance-tests/client-spring-http-client/src/main/resources/application.properties
@@ -0,0 +1,4 @@
+# Server runs on random port
+server.port=0
+# Disable Spring AI MCP client auto-configuration (we configure the client manually)
+spring.ai.mcp.client.enabled=false
diff --git a/conformance-tests/conformance-baseline.yml b/conformance-tests/conformance-baseline.yml
index 920e8401c..4ab144063 100644
--- a/conformance-tests/conformance-baseline.yml
+++ b/conformance-tests/conformance-baseline.yml
@@ -12,3 +12,7 @@ client:
# - Client does not parse or respect retry: field timing
# - Client does not send Last-Event-ID header
- sse-retry
+ # CIMD not implemented yet
+ - auth/basic-cimd
+ # Scope step up beyond initial authorization request not implemented
+ - auth/scope-step-up
diff --git a/conformance-tests/pom.xml b/conformance-tests/pom.xml
index 141ac6299..d1bef2a24 100644
--- a/conformance-tests/pom.xml
+++ b/conformance-tests/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdkmcp-parent
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOTconformance-testspom
@@ -20,8 +20,13 @@
git@github.com/modelcontextprotocol/java-sdk.git
+
+ true
+
+
client-jdk-http-client
+ client-spring-http-clientserver-servlet
diff --git a/conformance-tests/server-servlet/pom.xml b/conformance-tests/server-servlet/pom.xml
index 793cc7533..68da42158 100644
--- a/conformance-tests/server-servlet/pom.xml
+++ b/conformance-tests/server-servlet/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdkconformance-tests
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOTserver-servletjar
@@ -20,11 +20,15 @@
git@github.com/modelcontextprotocol/java-sdk.git
+
+ true
+
+
io.modelcontextprotocol.sdkmcp
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOT
@@ -66,4 +70,4 @@
-
+
\ No newline at end of file
diff --git a/docs/blog/index.md b/docs/blog/index.md
index 05761ac57..e61459078 100644
--- a/docs/blog/index.md
+++ b/docs/blog/index.md
@@ -1 +1 @@
-# Blog
+# News
diff --git a/docs/client.md b/docs/client.md
index 29cfcc3b7..6a99928c5 100644
--- a/docs/client.md
+++ b/docs/client.md
@@ -19,7 +19,8 @@ The MCP Client is a key component in the Model Context Protocol (MCP) architectu
!!! tip
The core `io.modelcontextprotocol.sdk:mcp` module provides STDIO, SSE, and Streamable HTTP client transport implementations without requiring external web frameworks.
- Spring-specific transport implementations are available as an **optional** dependency `io.modelcontextprotocol.sdk:mcp-spring-webflux` for [Spring Framework](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html) users.
+ The Spring-specific WebFlux transport (`mcp-spring-webflux`) is now part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`) and is no longer shipped by this SDK.
+ See the [MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-client-boot-starter-docs.html) documentation for Spring-based client setup.
The client provides both synchronous and asynchronous APIs for flexibility in different application contexts.
@@ -135,26 +136,20 @@ The client provides both synchronous and asynchronous APIs for flexibility in di
The transport layer handles the communication between MCP clients and servers, providing different implementations for various use cases. The client transport manages message serialization, connection establishment, and protocol-specific communication patterns.
-=== "STDIO"
+### STDIO
- Creates transport for process-based communication using stdin/stdout:
+Creates transport for process-based communication using stdin/stdout:
- ```java
- ServerParameters params = ServerParameters.builder("npx")
- .args("-y", "@modelcontextprotocol/server-everything", "dir")
- .build();
- McpTransport transport = new StdioClientTransport(params);
- ```
-
-=== "SSE (HttpClient)"
-
- Creates a framework-agnostic (pure Java API) SSE client transport. Included in the core `mcp` module:
+```java
+ServerParameters params = ServerParameters.builder("npx")
+ .args("-y", "@modelcontextprotocol/server-everything", "dir")
+ .build();
+McpTransport transport = new StdioClientTransport(params);
+```
- ```java
- McpTransport transport = new HttpClientSseClientTransport("http://your-mcp-server");
- ```
+### Streamable HTTP
-=== "Streamable HTTP"
+=== "Streamable HttpClient"
Creates a Streamable HTTP client transport for efficient bidirectional communication. Included in the core `mcp` module:
@@ -172,9 +167,28 @@ The transport layer handles the communication between MCP clients and servers, p
- Custom HTTP request customization
- Multiple protocol version negotiation
-=== "SSE (WebFlux)"
+=== "Streamable WebClient (external)"
+
+ Creates Streamable HTTP WebClient-based client transport. Requires the `mcp-spring-webflux` dependency from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
- Creates WebFlux-based SSE client transport. Requires the `mcp-spring-webflux` dependency:
+ ```java
+ McpTransport transport = WebFluxSseClientTransport
+ .builder(WebClient.builder().baseUrl("http://your-mcp-server"))
+ .build();
+ ```
+
+### SSE HTTP (Legacy)
+
+=== "SSE HttpClient"
+
+ Creates a framework-agnostic (pure Java API) SSE client transport. Included in the core `mcp` module:
+
+ ```java
+ McpTransport transport = new HttpClientSseClientTransport("http://your-mcp-server");
+ ```
+=== "SSE WebClient (external)"
+
+ Creates WebFlux-based SSE client transport. Requires the `mcp-spring-webflux` dependency from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```java
WebClient.Builder webClientBuilder = WebClient.builder()
@@ -182,6 +196,7 @@ The transport layer handles the communication between MCP clients and servers, p
McpTransport transport = new WebFluxSseClientTransport(webClientBuilder);
```
+
## Client Capabilities
The client can be configured with various capabilities:
diff --git a/docs/index.md b/docs/index.md
index 71dcecfa1..e6062b5ff 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,5 +1,5 @@
---
-title: Overview
+title: Index
description: Introduction to the Model Context Protocol (MCP) Java SDK
---
@@ -27,7 +27,7 @@ enables standardized integration between AI models and tools.
- Java HttpClient-based SSE client transport for HTTP SSE Client-side streaming
- Servlet-based SSE server transport for HTTP SSE Server streaming
- [Streamable HTTP](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#streamable-http) transport for efficient bidirectional communication (client and server)
- - Optional Spring-based transports (convenience if using Spring Framework):
+ - Optional Spring-based transports (available in [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+, no longer part of this SDK):
- WebFlux SSE client and server transports for reactive HTTP streaming
- WebFlux Streamable HTTP server transport
- WebMVC SSE server transport for servlet-based HTTP streaming
@@ -41,56 +41,9 @@ enables standardized integration between AI models and tools.
!!! tip
The core `io.modelcontextprotocol.sdk:mcp` module provides default STDIO, SSE, and Streamable HTTP client and server transport implementations without requiring external web frameworks.
- Spring-specific transports are available as optional dependencies for convenience when using the [MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html) and [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html).
- Also consider the [MCP Annotations](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-annotations-overview.html) and [MCP Security](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-security.html).
-
-## Architecture
-
-The SDK follows a layered architecture with clear separation of concerns:
-
-
-
-- **Client/Server Layer (McpClient/McpServer)**: Both use McpSession for sync/async operations,
- with McpClient handling client-side protocol operations and McpServer managing server-side protocol operations.
-- **Session Layer (McpSession)**: Manages communication patterns and state.
-- **Transport Layer (McpTransport)**: Handles JSON-RPC message serialization/deserialization via:
- - StdioTransport (stdin/stdout) in the core module
- - HTTP SSE transports in dedicated transport modules (Java HttpClient, Spring WebFlux, Spring WebMVC)
- - Streamable HTTP transports for efficient bidirectional communication
-
-The MCP Client is a key component in the Model Context Protocol (MCP) architecture, responsible for establishing and managing connections with MCP servers.
-It implements the client-side of the protocol.
-
-
-
-The MCP Server is a foundational component in the Model Context Protocol (MCP) architecture that provides tools, resources, and capabilities to clients.
-It implements the server-side of the protocol.
-
-
-
-Key Interactions:
-
-- **Client/Server Initialization**: Transport setup, protocol compatibility check, capability negotiation, and implementation details exchange.
-- **Message Flow**: JSON-RPC message handling with validation, type-safe response processing, and error handling.
-- **Resource Management**: Resource discovery, URI template-based access, subscription system, and content retrieval.
-
-## Module Structure
-
-The SDK is organized into modules to separate concerns and allow adopters to bring in only what they need:
-
-| Module | Artifact ID | Purpose |
-|--------|------------|---------|
-| `mcp-bom` | `mcp-bom` | Bill of Materials for dependency management |
-| `mcp-core` | `mcp-core` | Core reference implementation (STDIO, JDK HttpClient, Servlet, Streamable HTTP) |
-| `mcp-json-jackson2` | `mcp-json-jackson2` | Jackson 2.x JSON serialization implementation |
-| `mcp-json-jackson3` | `mcp-json-jackson3` | Jackson 3.x JSON serialization implementation |
-| `mcp` | `mcp` | Convenience bundle (`mcp-core` + `mcp-json-jackson3`) |
-| `mcp-test` | `mcp-test` | Shared testing utilities and integration tests |
-| `mcp-spring-webflux` | `mcp-spring-webflux` | Spring WebFlux integration (SSE and Streamable HTTP) |
-| `mcp-spring-webmvc` | `mcp-spring-webmvc` | Spring WebMVC integration (SSE and Streamable HTTP) |
-
-!!! tip
- A minimal adopter may depend only on `mcp` (core + Jackson 3), while a Spring-based application can add `mcp-spring-webflux` or `mcp-spring-webmvc` for deeper framework integration.
+ Spring-specific transports (WebFlux, WebMVC) are now part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ and are no longer shipped by this SDK.
+ Use the [MCP Client Boot Starter](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-client-boot-starter-docs.html) and [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-server-boot-starter-docs.html) from Spring AI.
+ Also consider the [MCP Annotations](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-annotations-overview.html) and [MCP Security](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-security.html).
## Next Steps
diff --git a/docs/overview.md b/docs/overview.md
new file mode 100644
index 000000000..9084b6a6a
--- /dev/null
+++ b/docs/overview.md
@@ -0,0 +1,93 @@
+---
+title: Overview
+description: Introduction to the Model Context Protocol (MCP) Java SDK
+---
+
+# Overview
+
+## Architecture
+
+The SDK follows a layered architecture with clear separation of concerns:
+
+
+
+- **Client/Server Layer (McpClient/McpServer)**: Both use McpSession for sync/async operations,
+ with McpClient handling client-side protocol operations and McpServer managing server-side protocol operations.
+- **Session Layer (McpSession)**: Manages communication patterns and state.
+- **Transport Layer (McpTransport)**: Handles JSON-RPC message serialization/deserialization via:
+ - StdioTransport (stdin/stdout) in the core module
+ - HTTP SSE transports in dedicated transport modules (Java HttpClient, Servlet)
+ - Streamable HTTP transports for efficient bidirectional communication
+ - Spring WebFlux and Spring WebMVC transports (available in [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+)
+
+The MCP Client is a key component in the Model Context Protocol (MCP) architecture, responsible for establishing and managing connections with MCP servers.
+It implements the client-side of the protocol.
+
+
+
+The MCP Server is a foundational component in the Model Context Protocol (MCP) architecture that provides tools, resources, and capabilities to clients.
+It implements the server-side of the protocol.
+
+
+
+Key Interactions:
+
+- **Client/Server Initialization**: Transport setup, protocol compatibility check, capability negotiation, and implementation details exchange.
+- **Message Flow**: JSON-RPC message handling with validation, type-safe response processing, and error handling.
+- **Resource Management**: Resource discovery, URI template-based access, subscription system, and content retrieval.
+
+## Module Structure
+
+The SDK is organized into modules to separate concerns and allow adopters to bring in only what they need:
+
+| Module | Artifact ID | Group | Purpose |
+|--------|------------|-------|---------|
+| `mcp-bom` | `mcp-bom` | `io.modelcontextprotocol.sdk` | Bill of Materials for dependency management |
+| `mcp-core` | `mcp-core` | `io.modelcontextprotocol.sdk` | Core reference implementation (STDIO, JDK HttpClient, Servlet, Streamable HTTP) |
+| `mcp-json-jackson2` | `mcp-json-jackson2` | `io.modelcontextprotocol.sdk` | Jackson 2.x JSON serialization implementation |
+| `mcp-json-jackson3` | `mcp-json-jackson3` | `io.modelcontextprotocol.sdk` | Jackson 3.x JSON serialization implementation |
+| `mcp` | `mcp` | `io.modelcontextprotocol.sdk` | Convenience bundle (`mcp-core` + `mcp-json-jackson3`) |
+| `mcp-test` | `mcp-test` | `io.modelcontextprotocol.sdk` | Shared testing utilities and integration tests |
+| `mcp-spring-webflux` _(external)_ | `mcp-spring-webflux` | `org.springframework.ai` | Spring WebFlux integration — part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ |
+| `mcp-spring-webmvc` _(external)_ | `mcp-spring-webmvc` | `org.springframework.ai` | Spring WebMVC integration — part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ |
+
+!!! tip
+ A minimal adopter may depend only on `mcp` (core + Jackson 3). Spring-based applications should use the `mcp-spring-webflux` or `mcp-spring-webmvc` artifacts from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`), no longer part of this SDK.
+
+## Next Steps
+
+
+
+- :rocket:{ .lg .middle } **Quickstart**
+
+ ---
+
+ Get started with dependencies and BOM configuration.
+
+ [:octicons-arrow-right-24: Quickstart](quickstart.md)
+
+- :material-monitor:{ .lg .middle } **MCP Client**
+
+ ---
+
+ Learn how to create and configure MCP clients.
+
+ [:octicons-arrow-right-24: Client](client.md)
+
+- :material-server:{ .lg .middle } **MCP Server**
+
+ ---
+
+ Learn how to implement and configure MCP servers.
+
+ [:octicons-arrow-right-24: Server](server.md)
+
+- :fontawesome-brands-github:{ .lg .middle } **GitHub**
+
+ ---
+
+ View the source code and contribute.
+
+ [:octicons-arrow-right-24: Repository](https://github.com/modelcontextprotocol/java-sdk)
+
+
diff --git a/docs/quickstart.md b/docs/quickstart.md
index 23cf2f75b..e7e76bc88 100644
--- a/docs/quickstart.md
+++ b/docs/quickstart.md
@@ -44,22 +44,25 @@ Add the following dependency to your project:
```
- If you're using the Spring Framework and want Spring-specific transport implementations, add one of the following optional dependencies:
+ If you're using Spring Framework, the Spring-specific transport implementations are now part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```xml
-
+
- io.modelcontextprotocol.sdk
+ org.springframework.aimcp-spring-webflux
-
+
- io.modelcontextprotocol.sdk
+ org.springframework.aimcp-spring-webmvc
```
+ !!! note
+ When using the `spring-ai-bom` or Spring AI starter dependencies (`spring-ai-starter-mcp-server-webflux`, `spring-ai-starter-mcp-server-webmvc`, `spring-ai-starter-mcp-client-webflux`) no explicit version is needed — the BOM manages it automatically.
+
=== "Gradle"
The convenience `mcp` module bundles `mcp-core` with Jackson 3.x JSON serialization:
@@ -89,17 +92,17 @@ Add the following dependency to your project:
}
```
- If you're using the Spring Framework and want Spring-specific transport implementations, add one of the following optional dependencies:
+ If you're using Spring Framework, the Spring-specific transport implementations are now part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```groovy
- // Optional: Spring WebFlux-based SSE and Streamable HTTP client and server transport
+ // Optional: Spring WebFlux-based SSE and Streamable HTTP client and server transport (Spring AI 2.0+)
dependencies {
- implementation "io.modelcontextprotocol.sdk:mcp-spring-webflux"
+ implementation "org.springframework.ai:mcp-spring-webflux"
}
- // Optional: Spring WebMVC-based SSE and Streamable HTTP server transport
+ // Optional: Spring WebMVC-based SSE and Streamable HTTP server transport (Spring AI 2.0+)
dependencies {
- implementation "io.modelcontextprotocol.sdk:mcp-spring-webmvc"
+ implementation "org.springframework.ai:mcp-spring-webmvc"
}
```
@@ -120,7 +123,7 @@ Add the BOM to your project:
io.modelcontextprotocol.sdkmcp-bom
- 1.0.0-RC1
+ 1.0.0pomimport
@@ -132,7 +135,7 @@ Add the BOM to your project:
```groovy
dependencies {
- implementation platform("io.modelcontextprotocol.sdk:mcp-bom:latest")
+ implementation platform("io.modelcontextprotocol.sdk:mcp-bom:1.0.0")
//...
}
```
@@ -153,8 +156,8 @@ The following dependencies are available and managed by the BOM:
- **JSON Serialization**
- `io.modelcontextprotocol.sdk:mcp-json-jackson3` - Jackson 3.x JSON serialization implementation (included in `mcp` bundle).
- `io.modelcontextprotocol.sdk:mcp-json-jackson2` - Jackson 2.x JSON serialization implementation for projects that require Jackson 2.x compatibility.
-- **Optional Transport Dependencies** (convenience if using Spring Framework)
- - `io.modelcontextprotocol.sdk:mcp-spring-webflux` - WebFlux-based SSE and Streamable HTTP transport implementation for reactive applications.
- - `io.modelcontextprotocol.sdk:mcp-spring-webmvc` - WebMVC-based SSE and Streamable HTTP transport implementation for servlet-based applications.
+- **Optional Spring Transport Dependencies** (part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+, group `org.springframework.ai`)
+ - `org.springframework.ai:mcp-spring-webflux` - WebFlux-based SSE and Streamable HTTP transport implementation for reactive applications.
+ - `org.springframework.ai:mcp-spring-webmvc` - WebMVC-based SSE and Streamable HTTP transport implementation for servlet-based applications.
- **Testing Dependencies**
- `io.modelcontextprotocol.sdk:mcp-test` - Testing utilities and support for MCP-based applications.
diff --git a/docs/server.md b/docs/server.md
index 3c05aee30..0753726e2 100644
--- a/docs/server.md
+++ b/docs/server.md
@@ -21,7 +21,8 @@ The MCP Server is a foundational component in the Model Context Protocol (MCP) a
!!! tip
The core `io.modelcontextprotocol.sdk:mcp` module provides STDIO, SSE, and Streamable HTTP server transport implementations without requiring external web frameworks.
- Spring-specific transport implementations are available as **optional** dependencies `io.modelcontextprotocol.sdk:mcp-spring-webflux`, `io.modelcontextprotocol.sdk:mcp-spring-webmvc` for [Spring Framework](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-client-boot-starter-docs.html) users.
+ Spring-specific transport implementations (`mcp-spring-webflux`, `mcp-spring-webmvc`) are now part of [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`) and are no longer shipped by this SDK.
+ See the [MCP Server Boot Starter](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-server-boot-starter-docs.html) documentation for Spring-based server setup.
The server supports both synchronous and asynchronous APIs, allowing for flexible integration in different application contexts.
@@ -104,25 +105,27 @@ The transport layer in the MCP SDK is responsible for handling the communication
It provides different implementations to support various communication protocols and patterns.
The SDK includes several built-in transport provider implementations:
-=== "STDIO"
+### STDIO
- Create process-based transport using stdin/stdout:
+Create process-based transport using stdin/stdout:
- ```java
- StdioServerTransportProvider transportProvider =
- new StdioServerTransportProvider(new ObjectMapper());
- ```
+```java
+StdioServerTransportProvider transportProvider =
+ new StdioServerTransportProvider(new ObjectMapper());
+```
- Provides bidirectional JSON-RPC message handling over standard input/output streams with non-blocking message processing, serialization/deserialization, and graceful shutdown support.
+Provides bidirectional JSON-RPC message handling over standard input/output streams with non-blocking message processing, serialization/deserialization, and graceful shutdown support.
- Key features:
+Key features:
- - Bidirectional communication through stdin/stdout
- - Process-based integration support
- - Simple setup and configuration
- - Lightweight implementation
+- Bidirectional communication through stdin/stdout
+- Process-based integration support
+- Simple setup and configuration
+- Lightweight implementation
-=== "Streamable HTTP (Servlet)"
+### Streamable HTTP
+
+=== "Streamable HTTP Servlet"
Creates a Servlet-based Streamable HTTP server transport. Included in the core `mcp` module:
@@ -165,9 +168,9 @@ The SDK includes several built-in transport provider implementations:
- Security validation support
- Graceful shutdown support
-=== "Streamable HTTP (WebFlux)"
+=== "Streamable HTTP WebFlux (external)"
- Creates WebFlux-based Streamable HTTP server transport. Requires the `mcp-spring-webflux` dependency:
+ Creates WebFlux-based Streamable HTTP server transport. Requires the `mcp-spring-webflux` dependency from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```java
@Configuration
@@ -195,9 +198,9 @@ The SDK includes several built-in transport provider implementations:
- Configurable keep-alive intervals
- Security validation support
-=== "Streamable HTTP (WebMvc)"
+=== "Streamable HTTP WebMvc (external)"
- Creates WebMvc-based Streamable HTTP server transport. Requires the `mcp-spring-webmvc` dependency:
+ Creates WebMvc-based Streamable HTTP server transport. Requires the `mcp-spring-webmvc` dependency from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```java
@Configuration
@@ -219,9 +222,45 @@ The SDK includes several built-in transport provider implementations:
}
```
-=== "SSE (WebFlux)"
+### SSE HTTP (Legacy)
+
+=== "SSE Servlet"
+
+ Creates a Servlet-based SSE server transport. Included in the core `mcp` module.
+ The `HttpServletSseServerTransportProvider` can be used with any Servlet container.
+ To use it with a Spring Web application, you can register it as a Servlet bean:
+
+ ```java
+ @Configuration
+ @EnableWebMvc
+ public class McpServerConfig implements WebMvcConfigurer {
+
+ @Bean
+ public HttpServletSseServerTransportProvider servletSseServerTransportProvider() {
+ return new HttpServletSseServerTransportProvider(new ObjectMapper(), "/mcp/message");
+ }
+
+ @Bean
+ public ServletRegistrationBean> customServletBean(
+ HttpServletSseServerTransportProvider transportProvider) {
+ return new ServletRegistrationBean<>(transportProvider);
+ }
+ }
+ ```
+
+ Implements the MCP HTTP with SSE transport specification using the traditional Servlet API, providing:
+
+ - Asynchronous message handling using Servlet 6.0 async support
+ - Session management for multiple client connections
+ - Two types of endpoints:
+ - SSE endpoint (`/sse`) for server-to-client events
+ - Message endpoint (configurable) for client-to-server requests
+ - Error handling and response formatting
+ - Graceful shutdown support
+
+=== "SSE WebFlux (external)"
- Creates WebFlux-based SSE server transport. Requires the `mcp-spring-webflux` dependency:
+ Creates WebFlux-based SSE server transport. Requires the `mcp-spring-webflux` dependency from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```java
@Configuration
@@ -245,9 +284,9 @@ The SDK includes several built-in transport provider implementations:
- Message routing and session management
- Graceful shutdown capabilities
-=== "SSE (WebMvc)"
+=== "SSE WebMvc (external)"
- Creates WebMvc-based SSE server transport. Requires the `mcp-spring-webmvc` dependency:
+ Creates WebMvc-based SSE server transport. Requires the `mcp-spring-webmvc` dependency from [Spring AI](https://docs.spring.io/spring-ai/reference/2.0-SNAPSHOT/api/mcp/mcp-overview.html) 2.0+ (group `org.springframework.ai`):
```java
@Configuration
@@ -273,39 +312,6 @@ The SDK includes several built-in transport provider implementations:
- Support for traditional web applications
- Synchronous operation handling
-=== "SSE (Servlet)"
-
- Creates a Servlet-based SSE server transport. Included in the core `mcp` module.
- The `HttpServletSseServerTransportProvider` can be used with any Servlet container.
- To use it with a Spring Web application, you can register it as a Servlet bean:
-
- ```java
- @Configuration
- @EnableWebMvc
- public class McpServerConfig implements WebMvcConfigurer {
-
- @Bean
- public HttpServletSseServerTransportProvider servletSseServerTransportProvider() {
- return new HttpServletSseServerTransportProvider(new ObjectMapper(), "/mcp/message");
- }
-
- @Bean
- public ServletRegistrationBean> customServletBean(
- HttpServletSseServerTransportProvider transportProvider) {
- return new ServletRegistrationBean<>(transportProvider);
- }
- }
- ```
-
- Implements the MCP HTTP with SSE transport specification using the traditional Servlet API, providing:
-
- - Asynchronous message handling using Servlet 6.0 async support
- - Session management for multiple client connections
- - Two types of endpoints:
- - SSE endpoint (`/sse`) for server-to-client events
- - Message endpoint (configurable) for client-to-server requests
- - Error handling and response formatting
- - Graceful shutdown support
## Server Capabilities
diff --git a/mcp-bom/pom.xml b/mcp-bom/pom.xml
index ce24f9b11..fb6f3a32a 100644
--- a/mcp-bom/pom.xml
+++ b/mcp-bom/pom.xml
@@ -7,7 +7,7 @@
io.modelcontextprotocol.sdkmcp-parent
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOTmcp-bom
@@ -54,20 +54,6 @@
${project.version}
-
-
- io.modelcontextprotocol.sdk
- mcp-spring-webflux
- ${project.version}
-
-
-
-
- io.modelcontextprotocol.sdk
- mcp-spring-webmvc
- ${project.version}
-
-
diff --git a/mcp-core/pom.xml b/mcp-core/pom.xml
index 67ed015bd..4de0fba2b 100644
--- a/mcp-core/pom.xml
+++ b/mcp-core/pom.xml
@@ -6,7 +6,7 @@
io.modelcontextprotocol.sdkmcp-parent
- 1.0.0-SNAPSHOT
+ 1.1.0-SNAPSHOTmcp-corejar
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 66e0b9d44..be4e4cf97 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
@@ -185,19 +185,6 @@ public static class Builder {
// Default constructor
}
- /**
- * Creates a new builder with the specified base URI.
- * @param baseUri the base URI of the MCP server
- * @deprecated Use {@link HttpClientSseClientTransport#builder(String)} instead.
- * This constructor is deprecated and will be removed or made {@code protected} or
- * {@code private} in a future release.
- */
- @Deprecated(forRemoval = true)
- public Builder(String baseUri) {
- Assert.hasText(baseUri, "baseUri must not be empty");
- this.baseUri = baseUri;
- }
-
/**
* Sets the base URI.
* @param baseUri the base URI
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/DefaultMcpStatelessServerHandler.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/DefaultMcpStatelessServerHandler.java
index d1b55f594..660a15e6a 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/DefaultMcpStatelessServerHandler.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/DefaultMcpStatelessServerHandler.java
@@ -32,7 +32,9 @@ public Mono handleRequest(McpTransportContext transpo
McpSchema.JSONRPCRequest request) {
McpStatelessRequestHandler> requestHandler = this.requestHandlers.get(request.method());
if (requestHandler == null) {
- return Mono.error(new McpError("Missing handler for request type: " + request.method()));
+ return Mono.error(McpError.builder(McpSchema.ErrorCodes.METHOD_NOT_FOUND)
+ .message("Missing handler for request type: " + request.method())
+ .build());
}
return requestHandler.handle(transportContext, request.params())
.map(result -> new McpSchema.JSONRPCResponse(McpSchema.JSONRPC_VERSION, request.id(), result, null))
diff --git a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java
index 23285d514..32256987a 100644
--- a/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java
+++ b/mcp-core/src/main/java/io/modelcontextprotocol/server/McpAsyncServer.java
@@ -326,7 +326,7 @@ public Mono addTool(McpServerFeatures.AsyncToolSpecification toolSpecifica
if (toolSpecification.tool() == null) {
return Mono.error(new IllegalArgumentException("Tool must not be null"));
}
- if (toolSpecification.call() == null && toolSpecification.callHandler() == null) {
+ if (toolSpecification.callHandler() == null) {
return Mono.error(new IllegalArgumentException("Tool call handler must not be null"));
}
if (this.serverCapabilities.tools() == null) {
@@ -869,32 +869,6 @@ private McpRequestHandler promptsGetRequestHandler()
// Logging Management
// ---------------------------------------
- /**
- * This implementation would, incorrectly, broadcast the logging message to all
- * connected clients, using a single minLoggingLevel for all of them. Similar to the
- * sampling and roots, the logging level should be set per client session and use the
- * ServerExchange to send the logging message to the right client.
- * @param loggingMessageNotification The logging message to send
- * @return A Mono that completes when the notification has been sent
- * @deprecated Use
- * {@link McpAsyncServerExchange#loggingNotification(LoggingMessageNotification)}
- * instead.
- */
- @Deprecated
- public Mono loggingNotification(LoggingMessageNotification loggingMessageNotification) {
-
- if (loggingMessageNotification == null) {
- return Mono.error(new McpError("Logging message must not be null"));
- }
-
- if (loggingMessageNotification.level().level() < minLoggingLevel.level()) {
- return Mono.empty();
- }
-
- return this.mcpTransportProvider.notifyClients(McpSchema.METHOD_NOTIFICATION_MESSAGE,
- loggingMessageNotification);
- }
-
private McpRequestHandler