Skip to content

[WIP] feat: Add Spring WebMVC streamable server transport provider #425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 19 commits into
base: main
Choose a base branch
from

Conversation

tzolov
Copy link
Contributor

@tzolov tzolov commented Jul 26, 2025

  • Add WebMvcStreamableServerTransportProvider for non-reactive MCP server support
  • Implement HTTP/SSE transport with session management and graceful shutdown
  • Support GET, POST, DELETE endpoints for MCP protocol operations
  • Add test suite including integration tests with Tomcat
  • Refactor AbstractMcpAsyncServerTests to support multiple transport implementations
  • Provide WebMVC alternative to existing WebFlux streamable transport

Related to #72

NOTE: built on top and depending on the #420

This PR adds Spring WebMVC streamable server transport provider support to the MCP Java SDK, providing a non-reactive alternative to the existing WebFlux implementation for HTTP/SSE-based MCP servers.

How Has This Been Tested?

The implementation has been thoroughly tested with:

  • Unit tests: WebMcpStreamableMcpAsyncServerTests extending the abstract test suite
  • Integration tests: WebMvcStreamableIntegrationTests with comprehensive scenarios including:

Breaking Changes

No breaking changes.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

Implementation Details:

  • WebMvcStreamableServerTransportProvider implements McpStreamableServerTransportProvider
  • Uses Spring WebMVC's RouterFunction for endpoint handling (GET, POST, DELETE)
  • Leverages Server-Sent Events (SSE) via ServerResponse.sse() for streaming responses
  • Maintains session state using ConcurrentHashMap for thread safety
  • Supports message replay functionality for connection recovery
  • Includes builder pattern for easy configuration

Key Features:

  • Session management with unique session IDs
  • Graceful shutdown with proper resource cleanup
  • Message replay support for connection resilience
  • Configurable endpoint paths and DELETE request handling
  • Full compatibility with existing MCP protocol features (tools, resources, prompts, sampling, elicitation)

Testing Strategy:

  • Refactored AbstractMcpAsyncServerTests to use prepareAsyncServerBuilder() pattern
  • This allows the same test suite to validate both WebFlux and WebMVC implementations
  • Added transport-specific integration tests for WebMVC-specific functionality
  • Comprehensive error handling and edge case coverage

chemicL added 9 commits July 18, 2025 12:01
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
…sync server tests

Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
return ServerResponse.status(HttpStatus.SERVICE_UNAVAILABLE).body("Server is shutting down");
}

McpTransportContext transportContext = this.contextExtractor.apply(request);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How to make use of this?

return ServerResponse.notFound().build();
}

return session.delete().then(ServerResponse.ok().build());
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we need to remove the session from the sessions maps as well?
e.g. this.sessions.remove(sessionId);

chemicL and others added 9 commits July 28, 2025 13:18
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
Signed-off-by: Dariusz Jędrzejczyk <[email protected]>
- Add WebMvcStreamableServerTransportProvider for non-reactive MCP server support
- Implement HTTP/SSE transport with session management and graceful shutdown
- Support GET, POST, DELETE endpoints for MCP protocol operations
- Add test suite including integration tests with Tomcat
- Refactor AbstractMcpAsyncServerTests to support multiple transport implementations
- Provide WebMVC alternative to existing WebFlux streamable transport

Related to modelcontextprotocol#72

Signed-off-by: Christian Tzolov <[email protected]>
- Enhance McpStreamableServerSession error handling with proper JSON-RPC error responses
- Add mcp-spring-webflux test dependency to webmvc module
- Refactor WebMvcStreamableIntegrationTests to use parameterized tests
- Support testing with both HttpClient and WebFlux transports
- Add WebClientStreamableHttpTransport integration
- Improve error handling in McpStreamableServerSession
- Add proper timeout configurations for test clients
- Clean up test structure and imports organization

This enables comprehensive testing of WebMVC functionality with multiple
transport mechanisms, ensuring compatibility across different client types.

Signed-off-by: Christian Tzolov <[email protected]>
…ble transport

- Add ReentrantLock synchronization to prevent race conditions in concurrent sseBuilder usage
- Add volatile closed flag to track session state and prevent operations on closed sessions
- Move SSE onComplete callback to properly close listening stream when connection completes
- Refactor closeGracefully to delegate to close() method for consistent cleanup
- Update class documentation to reflect thread-safety guarantees

This ensures safe concurrent access to SSE builder and proper cleanup of streaming resources.

Signed-off-by: Christian Tzolov <[email protected]>
… class

- Extract common test logic from WebMvcSseIntegrationTests and WebMvcStreamableIntegrationTests into AbstractMcpClientServerIntegrationTests
- Add json-unit-assertj dependency to mcp-test module for JSON assertion support
- Make McpServer.SyncSpecification abstract to enforce proper inheritance
- Remove duplicate test implementations (~2000+ lines of code deduplicated)
- Maintain parameterized testing across different client transport types (httpclient, webflux)

This refactoring eliminates significant code duplication between Spring WebMVC integration test classes while maintaining full test coverage and functionality.

Signed-off-by: Christian Tzolov <[email protected]>
@tzolov tzolov force-pushed the streamable-server-webmvc branch from 5c1d0d5 to 5290f39 Compare July 28, 2025 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants