Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
81a18ed
Client Auth Conformance Tests - change parent POM (#827)
Kehrlann Mar 2, 2026
d4c4a25
Fix instructions for running conformance tests
Kehrlann Mar 2, 2026
ce2c747
Bump spring-javaformat 0.0.43 -> 0.0.47
Kehrlann Mar 2, 2026
7f68ea5
Support resource subscriptions (#839)
chemicL Mar 2, 2026
05f37ad
Use explicit UTF-8 charset in StdioServerTransportProvider (#826)
xxxxxxjun Mar 2, 2026
ed02736
Update dependabot PR labels
chemicL Mar 2, 2026
26304a7
Document resource subscription support in server and client guides (#…
tzolov Mar 3, 2026
6e4ce1c
Fix elicitation and resource subscription tests that deadlock on a si…
chemicL Mar 5, 2026
abcd19c
HttpClientStreamHttpTransport: add authorization error handler (#861)
Kehrlann Mar 13, 2026
c4b5857
fix: prepare POMs for Maven Central release readiness (#863)
tzolov Mar 13, 2026
cbb235f
Next development version
tzolov Mar 13, 2026
665ed51
feat: Add Enterprise Managed Authorization (SEP-990) support
prachi-okta Mar 2, 2026
443e6e5
Address PR review comments for enterprise managed authorization
prachi-okta Mar 16, 2026
649a426
Split EnterpriseAuthProvider tests into separate test class
prachi-okta Mar 16, 2026
20c5628
Add auth/cross-app-access-complete-flow to JDK conformance client (SE…
prachi-okta Mar 18, 2026
685b189
Merge commit from fork
Kehrlann Mar 27, 2026
3a78182
Fixed URL links from README.md to 'Java Dependencies', 'Java MCP Clie…
sleepytomcat Apr 1, 2026
c2c168f
Merge branch 'main' into feature/enterprise-managed-authorization
prachi-okta Apr 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ updates:
directory: '/'
schedule:
interval: monthly
labels:
- 'github_actions'
- 'waiting for triage'
- package-ecosystem: 'maven'
directory: '/'
schedule:
interval: monthly
open-pull-requests-limit: 10
labels:
- 'dependencies'
- 'waiting for triage'
ignore:
# Freeze production dependencies of mcp-core
- dependency-name: 'org.slf4j:slf4j-api'
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ For comprehensive guides and SDK API documentation

- [Features](https://modelcontextprotocol.github.io/java-sdk/#features) - Overview the features provided by the Java MCP SDK
- [Architecture](https://modelcontextprotocol.github.io/java-sdk/#architecture) - Java MCP SDK architecture overview.
- [Java Dependencies / BOM](https://modelcontextprotocol.github.io/java-sdk/quickstart/#dependencies) - Java dependencies and BOM.
- [Java MCP Client](https://modelcontextprotocol.github.io/java-sdk/client/) - Learn how to use the MCP client to interact with MCP servers.
- [Java MCP Server](https://modelcontextprotocol.github.io/java-sdk/server/) - Learn how to implement and configure a MCP servers.
- [Java Dependencies / BOM](https://java.sdk.modelcontextprotocol.io/latest/quickstart/#dependencies) - Java dependencies and BOM.
- [Java MCP Client](https://java.sdk.modelcontextprotocol.io/latest/client/) - Learn how to use the MCP client to interact with MCP servers.
- [Java MCP Server](https://java.sdk.modelcontextprotocol.io/latest/server/) - Learn how to implement and configure a MCP servers.

#### Spring AI MCP documentation
[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.
Expand Down
30 changes: 11 additions & 19 deletions conformance-tests/VALIDATION_RESULTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,22 @@

## Summary

**Server Tests:** 37/40 passed (92.5%)
**Server Tests:** 40/40 passed (100%)
**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

### Passing (37/40)
### Passing (40/40)

- **Lifecycle & Utilities (4/4):** initialize, ping, logging-set-level, completion-complete
- **Tools (11/11):** All scenarios including progress notifications ✨
- **Elicitation (10/10):** SEP-1034 defaults (5 checks), SEP-1330 enums (5 checks)
- **Resources (4/6):** list, read-text, read-binary, templates-read
- **Resources (6/6):** list, read-text, read-binary, templates-read, subscribe, unsubscribe
- **Prompts (4/4):** list, simple, with-args, embedded-resource, with-image
- **SSE Transport (2/2):** Multiple streams
- **Security (2/2):** Localhost validation passes, DNS rebinding protection

### Failing (3/40)

1. **resources-subscribe** - Not implemented in SDK
2. **resources-unsubscribe** - Not implemented in SDK

## Client Test Results

### Passing (3/4 scenarios, 9/10 checks)
Expand Down Expand Up @@ -68,18 +63,16 @@ Uses the `client-spring-http-client` module with Spring Security OAuth2 and the

## 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
1. **Client SSE Retry:** Client doesn't parse or respect the `retry:` field, reconnects immediately, and doesn't send Last-Event-ID header
2. **Auth Scope Step-Up:** Client does not fully handle scope step-up challenges where the server requests additional scopes after initial authorization
3. **Auth Basic CIMD:** Minor conformance warning in the basic Client-Initiated Metadata Discovery flow

## Running Tests

### Server
```bash
# Start server
cd conformance-tests/server-servlet
../../mvnw compile exec:java -Dexec.mainClass="io.modelcontextprotocol.conformance.server.ConformanceServlet"
./mvnw compile -pl conformance-tests/server-servlet -am exec:java

# Run tests (in another terminal)
npx @modelcontextprotocol/conformance server --url http://localhost:8080/mcp --suite active
Expand All @@ -94,7 +87,7 @@ cd conformance-tests/client-jdk-http-client
# Run all scenarios
for scenario in initialize tools_call elicitation-sep1034-client-defaults sse-retry; do
npx @modelcontextprotocol/conformance client \
--command "java -jar target/client-jdk-http-client-1.0.0-SNAPSHOT.jar" \
--command "java -jar target/client-jdk-http-client-1.1.0-SNAPSHOT.jar" \
--scenario $scenario
done
```
Expand All @@ -111,14 +104,13 @@ cd conformance-tests/client-spring-http-client
# 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" \
--command "java -jar target/client-spring-http-client-1.1.0-SNAPSHOT.jar" \
--suite auth
```

## Recommendations

### High Priority
1. Fix client SSE retry field handling in `HttpClientStreamableHttpTransport`
2. Implement resource subscription handlers in `McpStatelessAsyncServer`
3. Implement CIMD
4. Implement scope step up
2. Implement CIMD
3. Implement scope step up
14 changes: 7 additions & 7 deletions conformance-tests/client-jdk-http-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ cd conformance-tests/client-jdk-http-client

This creates an executable JAR at:
```
target/client-jdk-http-client-1.0.0-SNAPSHOT.jar
target/client-jdk-http-client-1.1.0-SNAPSHOT.jar
```

## Running Tests
Expand All @@ -65,27 +65,27 @@ Run a single scenario:

```bash
npx @modelcontextprotocol/conformance 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-1.1.0-SNAPSHOT.jar" \
--scenario initialize

npx @modelcontextprotocol/conformance 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-1.1.0-SNAPSHOT.jar" \
--scenario tools_call

npx @modelcontextprotocol/conformance 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-1.1.0-SNAPSHOT.jar" \
--scenario elicitation-sep1034-client-defaults

npx @modelcontextprotocol/conformance 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-1.1.0-SNAPSHOT.jar" \
--scenario sse-retry
```

Run with verbose output:

```bash
npx @modelcontextprotocol/conformance 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-1.1.0-SNAPSHOT.jar" \
--scenario initialize \
--verbose
```
Expand All @@ -96,7 +96,7 @@ You can also run the client manually if you have a test server:

```bash
export MCP_CONFORMANCE_SCENARIO=initialize
java -jar conformance-tests/client-jdk-http-client/target/client-jdk-http-client-1.0.0-SNAPSHOT.jar http://localhost:3000/mcp
java -jar conformance-tests/client-jdk-http-client/target/client-jdk-http-client-1.1.0-SNAPSHOT.jar http://localhost:3000/mcp
```

## Test Results
Expand Down
22 changes: 15 additions & 7 deletions conformance-tests/client-jdk-http-client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>conformance-tests</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
</parent>
<artifactId>client-jdk-http-client</artifactId>
<packaging>jar</packaging>
Expand All @@ -16,19 +16,26 @@

<scm>
<url>https://github.com/modelcontextprotocol/java-sdk</url>
<connection>git://github.com/modelcontextprotocol/java-sdk.git</connection>
<developerConnection>git@github.com/modelcontextprotocol/java-sdk.git</developerConnection>
<connection>scm:git:git://github.com/modelcontextprotocol/java-sdk.git</connection>
<developerConnection>scm:git:ssh://git@github.com/modelcontextprotocol/java-sdk.git</developerConnection>
</scm>

<properties>
<maven.deploy.skip>true</maven.deploy.skip>
</properties>

<dependencies>
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp</artifactId>
<version>1.1.0-SNAPSHOT</version>
<version>2.0.0-SNAPSHOT</version>
</dependency>

<!-- mcp-core for EnterpriseAuth / EnterpriseAuthProvider (SEP-990) -->
<dependency>
<groupId>io.modelcontextprotocol.sdk</groupId>
<artifactId>mcp-core</artifactId>
<version>2.0.0-SNAPSHOT</version>
</dependency>

<!-- Logging -->
Expand Down Expand Up @@ -57,7 +64,8 @@
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>io.modelcontextprotocol.conformance.client.ConformanceJdkClientMcpClient</mainClass>
<mainClass>
io.modelcontextprotocol.conformance.client.ConformanceJdkClientMcpClient</mainClass>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
Expand All @@ -79,4 +87,4 @@
</plugins>
</build>

</project>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@

import java.time.Duration;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.client.McpClient;
import io.modelcontextprotocol.client.McpSyncClient;
import io.modelcontextprotocol.client.auth.DiscoverAndRequestJwtAuthGrantOptions;
import io.modelcontextprotocol.client.auth.EnterpriseAuth;
import io.modelcontextprotocol.client.auth.EnterpriseAuthProvider;
import io.modelcontextprotocol.client.auth.EnterpriseAuthProviderOptions;
import io.modelcontextprotocol.client.transport.HttpClientStreamableHttpTransport;
import io.modelcontextprotocol.spec.McpSchema;

Expand Down Expand Up @@ -53,13 +60,17 @@ public static void main(String[] args) {
case "sse-retry":
runSSERetryScenario(serverUrl);
break;
case "auth/cross-app-access-complete-flow":
runCrossAppAccessCompleteFlowScenario(serverUrl);
break;
default:
System.err.println("Unknown scenario: " + scenario);
System.err.println("Available scenarios:");
System.err.println(" - initialize");
System.err.println(" - tools_call");
System.err.println(" - elicitation-sep1034-client-defaults");
System.err.println(" - sse-retry");
System.err.println(" - auth/cross-app-access-complete-flow");
System.exit(1);
}
System.exit(0);
Expand Down Expand Up @@ -283,4 +294,82 @@ private static void runSSERetryScenario(String serverUrl) throws Exception {
}
}

/**
* Cross-App Access scenario: Tests SEP-990 Enterprise Managed Authorization flow.
* <p>
* Reads context from {@code MCP_CONFORMANCE_CONTEXT} (JSON) containing:
* {@code client_id}, {@code client_secret}, {@code idp_client_id},
* {@code idp_id_token}, {@code idp_issuer}, {@code idp_token_endpoint}.
* <p>
* Uses {@link EnterpriseAuthProvider} with an assertion callback that performs RFC
* 8693 token exchange at the IdP, then exchanges the ID-JAG for an access token at
* the MCP authorization server via RFC 7523 JWT Bearer grant.
* @param serverUrl the URL of the MCP server
* @throws Exception if any error occurs during execution
*/
private static void runCrossAppAccessCompleteFlowScenario(String serverUrl) throws Exception {
String contextEnv = System.getenv("MCP_CONFORMANCE_CONTEXT");
if (contextEnv == null || contextEnv.isEmpty()) {
System.err.println("Error: MCP_CONFORMANCE_CONTEXT environment variable is not set");
System.exit(1);
}

CrossAppAccessContext ctx = new ObjectMapper().readValue(contextEnv, CrossAppAccessContext.class);

java.net.http.HttpClient httpClient = java.net.http.HttpClient.newHttpClient();

EnterpriseAuthProviderOptions options = EnterpriseAuthProviderOptions.builder()
.clientId(ctx.clientId())
.clientSecret(ctx.clientSecret())
.assertionCallback(assertionCtx -> {
// RFC 8693 token exchange at the IdP: ID Token → ID-JAG
DiscoverAndRequestJwtAuthGrantOptions jagOptions = DiscoverAndRequestJwtAuthGrantOptions
.builder()
.idpUrl(ctx.idpIssuer())
.idpTokenEndpoint(ctx.idpTokenEndpoint())
.idToken(ctx.idpIdToken())
.clientId(ctx.idpClientId())
.audience(assertionCtx.getAuthorizationServerUrl().toString())
.resource(assertionCtx.getResourceUrl().toString())
.build();
return EnterpriseAuth.discoverAndRequestJwtAuthorizationGrant(jagOptions, httpClient);
})
.build();

EnterpriseAuthProvider provider = new EnterpriseAuthProvider(options, httpClient);

HttpClientStreamableHttpTransport transport = HttpClientStreamableHttpTransport.builder(serverUrl)
.httpRequestCustomizer(provider)
.build();

McpSyncClient client = McpClient.sync(transport)
.clientInfo(new McpSchema.Implementation("test-client", "1.0.0"))
.requestTimeout(Duration.ofSeconds(30))
.build();

try {
client.initialize();
System.out.println("Successfully connected to MCP server");

client.listTools();
System.out.println("Successfully listed tools");
}
finally {
client.close();
System.out.println("Connection closed successfully");
}
}

/**
* Context provided by the conformance suite for the cross-app-access-complete-flow
* scenario via the {@code MCP_CONFORMANCE_CONTEXT} environment variable.
*/
@JsonIgnoreProperties(ignoreUnknown = true)
private record CrossAppAccessContext(@JsonProperty("client_id") String clientId,
@JsonProperty("client_secret") String clientSecret,
@JsonProperty("idp_client_id") String idpClientId,
@JsonProperty("idp_id_token") String idpIdToken, @JsonProperty("idp_issuer") String idpIssuer,
@JsonProperty("idp_token_endpoint") String idpTokenEndpoint) {
}

}
10 changes: 5 additions & 5 deletions conformance-tests/client-spring-http-client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ cd conformance-tests/client-spring-http-client

This creates an executable JAR at:
```
target/client-spring-http-client-0.18.0-SNAPSHOT.jar
target/client-spring-http-client-1.1.0-SNAPSHOT.jar
```

## Running Tests
Expand All @@ -79,7 +79,7 @@ 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" \
--command "java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-1.1.0-SNAPSHOT.jar" \
--suite auth
```

Expand All @@ -88,7 +88,7 @@ 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" \
--command "java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-1.1.0-SNAPSHOT.jar" \
--scenario auth/metadata-default
```

Expand All @@ -97,7 +97,7 @@ 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" \
--command "java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-1.1.0-SNAPSHOT.jar" \
--scenario auth/metadata-default \
--verbose
```
Expand All @@ -108,7 +108,7 @@ 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
java -jar conformance-tests/client-spring-http-client/target/client-spring-http-client-1.1.0-SNAPSHOT.jar http://localhost:3000/mcp
```

## Known Issues
Expand Down
Loading