Commit graph

502 commits

Author SHA1 Message Date
Christian Tzolov
c734b2a5c1 Next development version
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-10-02 00:03:36 +01:00
Anurag Pant
8e11fa82ae feat(client): add client tool output schema validation and caching (#302)
- Add JSON schema validation for tool call results against output schemas
- Implement automatic tool output schema caching during initialization
- Add `enableCallToolSchemaCaching` configuration option to enable/disable
  schema caching
- Add `JsonSchemaValidator` integration to McpClient builder APIs
- Introduce post-initialization hook mechanism for performing operations
  after successful client initialization
- Cache tool output schemas during `listTools` operations when caching
  is enabled
- Validate tool results against cached schemas in `callTool` operations
- Return error CallToolResult when validation fails
- Add test coverage
- Convert validateToolResult from Mono to synchronous method
- Throw IllegalArgumentException on validation errors

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>

Co-authored-by: Anurag Pant <pantanurag555@github>
Co-authored-by: Christian Tzolov <christian.tzolov@broadcom.com>
Co-authored-by: Daniel Garnier-Moiroux <git@garnier.wf>
Co-authored-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
2025-10-01 23:12:33 +01:00
Christian Tzolov
3f7578b3ce
fix: Handle non-compliant notification responses (#589)
Ensure warnings are logged for all non-compliant responses to JSON-RPC
notifications, including empty responses. Empty responses now display
as "[empty]" in log messages for better clarity.

Resolves #586

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-10-01 23:14:29 +02:00
Daniel Garnier-Moiroux
080098e48c Client: handle server responses with Content-Length: 0
- When the client sends `notification/initalized`, servers must respond
  with HTTP 202 and an empty body. We checked for the absence of a
  Content-Type header to verify whether the body was empty.
- However, some servers will send an empty body with a Content-Type
  header, and that header may have an unsupported, default type such as
  `text/html` or `text/plain`.
- Now we we also use the Content-Length header to check for an empty
  body. This header is optional in HTTP/2, so we do not make it our
  primary mechanism for detecting empty bodies.
- As part of this PR, we also move hard-coded HTTP header names to the
  HttpHeaders interface. While they are not defined by the MCP spec,
  they are used by it and are core to implementing the protocol.
  Therefore, they have their place in a core interface.
- Fixes #582

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2025-10-01 13:09:30 +02:00
Sergio del Amo
12292ab598
fix: when using JsonTypeInfo.DEDUCTION don’t add include (#587)
From the JSonTypeInfo Javadocs:

> If deduction is being used annotation properties visible, property and include are ignored.

This is causing issues with serialization downstream.
2025-09-30 15:59:17 +02:00
Christian Tzolov
c1cde20002
refactor: improve MCP server resilience and error handling (#579)
- Replace McpError with appropriate standard exceptions (IllegalArgumentException, IllegalStateException) for validation errors
- Change tool/prompt registration to replace existing items instead of rejecting duplicates with warningsi
  - Change addTool behavior to replace existing tools instead of throwing errors
  - Change addPrompt() to allow replacing existing prompts with warning instead of throwing error
- Make removal operations idempotent - log warnings instead of throwing errors for non-existent items
  - Change removePrompt() to log warning instead of throwing error for non-existent prompts
  - Change removeTool() to gracefully handle non-existent tools with warnings instead of errors
- Add listTools() and listPrompts() methods to all server variants (async, sync, stateless)
  - Add listTools() method to all server classes for tool enumeration
  - Add listPrompts() method to all server implementations for retrieving registered prompts
- Improve error construction using McpError.builder() pattern for protocol-specific errors
- Update error handling in session classes to properly propagate McpError JSON-RPC errors
  - Use proper error codes (INVALID_PARAMS) for prompt not found scenarios
- Update tests to reflect new lenient behavior for duplicate registrations and removals
- Add aggregateExceptionMessages() utility method utility to aggregate the exception chains
- Update McpServerSession and McpStreamableServerSession to use the aggregated errors in the json-rpc-error data section

This change makes the MCP server APIs more resilient and user-friendly by using appropriate exception types,
supporting item replacement, and providing listing capabilities while maintaining backward compatibility.

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-30 11:10:04 +02:00
Christian Tzolov
ff98e294f5 refactor: Improve resource template support (#576)
- Provide separation of concerns between static resources and parameterized resource templates.
- Add AsyncResourceTemplateSpecification and SyncResourceTemplateSpecification for both McpServerFeatures and McpStatelessServerFeatures
- Change resource template storage from List to Map to acomodate the resource read handler.
- Add runtime management methods: addResourceTemplate(), removeResourceTemplate(), listResourceTemplates()
- Improve error handling by using IllegalArgumentException/IllegalStateException instead of McpError
- Add new interfaces (Meta, Identifier) and reorganize schema hierarchy
- Enhance completion request validation with better error messages
- Add ResourceTemplate.Builder for easier template construction
- Update all server implementations (Async, Sync, Stateless) consistently
- Add type-safe constants for reference types (PromptReference.TYPE, ResourceReference.TYPE)
- Add tests for new resource template management functionality
- Clean up imports and remove unused dependencies

Co-authored-by: Pascal Vantrepote <pascal@confluent.io>

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-28 09:17:24 +02:00
Liujunjie
7f16cd0b9d
fix: typo MCP_SESSION_ID, keep consistent style with other identifiers (#564) 2025-09-22 17:18:53 +02:00
Christian Tzolov
a90b922be9
feat: add optional lastModified field to Annotations record with backward compatibility (#568)
Resolves #565

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-22 17:07:19 +02:00
Sergio del Amo
d327fff6f7
fix: handle resource not found according to spec (#567)
see: https://modelcontextprotocol.io/specification/2025-06-18/server/resources#error-handling

Resource not found should send a JSON RPC response such as:

```json
{
  "jsonrpc": "2.0",
  "id": 5,
  "error": {
    "code": -32002,
    "message": "Resource not found",
    "data": {
      "uri": "file:///nonexistent.txt"
    }
  }
}
```

This PR also changes some instances where a `McpError` was thrown instead of being passed in the reactive chain with `Mono.error`

functional style
2025-09-22 16:43:44 +02:00
Christian Tzolov
a0afdcd493 Next development version
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-18 19:28:56 +02:00
Christian Tzolov
7525a99693 simplify the mcp module pom
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-18 18:46:29 +02:00
Christian Tzolov
3d86539452
fix(mcp): skip source/javadoc generation for aggregator module (#559)
The mcp module packages dependencies but has no sources, causing
Maven release failures. Skip source and javadoc JAR generation
to fix deployment errors.

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-18 16:46:40 +02:00
Christian Tzolov
8159bcbb05
feat: add MCP protocol version 2025-06-18 support for streamable-http and stateless transports (#558)
- Set MCP_2025_06_18 as upper supported protocol version for streamable-http and stateless transport
- Update LATEST_PROTOCOL_VERSION constant to reflect new upper bound
- Update test expectations for new protocol version usage

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-18 08:57:10 +02:00
Christian Tzolov
8ac7eae47c
refactor: standardize test parameterization and fix package naming (#556)
- Replace @ValueSource with @MethodSource for parameterized tests
- Add clientsForTesting() methods to provide test arguments consistently
- Remove hardcoded Spring-related labels from framework-agnostic mcp-test module
- Move mcp-test's utility classes from io.modelcontextprotocol.utils to io.modelcontextprotocol.util

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-17 12:26:55 +02:00
Sergio del Amo
1499df22c7
extract mcp-core (#557)
* extract mcp-core
  - This change extracts classes previously in `mcp` to `mcp-core`; a new module which does not depend on `mcp-json-jackon2`.
  - `mcp` module is now an umbrella module that brings `mcp-json-jackon2` and `mcp-core`
* add mcp-core to bom

BREAKING CHANGE: All source code in the previously `mcp` module is moved to the `mcp-core`.  the `mcp` now is just an aggregation for `mcp-core` + `mcp-json-jackson2` for backward compatibility. 
This change won't affect the end users, but will cause conflicts for the existing PRs.
2025-09-17 11:32:08 +02:00
Graeme Rocher
80d0ad82a6 feat: Introduce McpJsonMapper interface to decouple from Jackson (#543)
This pull request creates two modules, `mcp-json` and `mcp-json-jackson`. It removes the `com.fasterxml.jackson.core:jackson-databind` and `com.networknt:json-schema-validator` dependencies from the `mcp` module. The `mcp` module now only depends on `com.fasterxml.jackson.core:jackson-annotations`.

To use Jackson, you have to add `mcp-jackson` to your dependencies in addition to `mcp`. I added the dependency `mcp-jackson` to both `mcp-spring-mvc` and `mcp-spring-webflux` to avoid a breaking change in those modules.

It provides two [SPI](https://docs.oracle.com/javase/tutorial/sound/SPI-intro.html) `JsonSchemaValidatorSupplier` and `JacksonJsonSchemaValidatorSupplier` to allow easy replacement for consumers who don't want to use Jackson.

This pull request also ensures no `McpJsonMapper` is instantiated if one is provided via a builder method. Only if the builders don't receive a `McpJsonMapper` mapper, one is instantiated in the `build` method of the builder.
The logic behind this is to allow frameworks to provide a `McpJsonMapper` mapper singleton implementation and feed it to the builders without paying the price of instantiating `McpJsonMappers`, which will not be used. The goal is to be able to use the `ObjectMapper` singleton of an application also for the MCP code.

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-15 15:51:06 +02:00
Christian Tzolov
d8959ef854
fix: support valid JSON value in tool structured content output (#551)
- Change CallToolResult.structuredContent type from Map<String,Object> to Object
  to support both objects and arrays
- Update JsonSchemaValidator to validate any Object type, not just Maps
- Add test cases for array-type structured output validation
- Fix type casting in existing tests to handle the more generic Object type
- Deprecate CallToolResult constructors in favor of builder pattern
- Update server implementations to use CallToolResult builder

This allows tools to return arrays as structured content, not just objects,
which is required by the MCP specification for tools with array-type output schemas.

It is realated to MPC spec fix: https://github.com/modelcontextprotocol/modelcontextprotocol/issues/834

Fixes #550

BREAKING CHANGE!

Migration Guide:
----------------
1. If you're accessing CallToolResult.structuredContent():
   - Add explicit casting when you know it's a Map:
     Before: result.structuredContent().get("key")
     After:  ((Map<String,Object>) result.structuredContent()).get("key")

   - Or check the type first:
     if (result.structuredContent() instanceof Map) {
         Map<String,Object> map = (Map<String,Object>) result.structuredContent();
         // use map
     } else if (result.structuredContent() instanceof List) {
         List<?> list = (List<?>) result.structuredContent();
         // use list
     }

2. If you're creating CallToolResult instances:
   - Switch to using the builder pattern:
     Before: new CallToolResult(content, isError, structuredContent)
     After:  CallToolResult.builder()
               .content(content)
               .isError(isError)
               .structuredContent(structuredContent)
               .build()

3. If you're implementing JsonSchemaValidator:
   - Update your validate() method signature:
     Before: validate(Map<String,Object> schema, Map<String,Object> structuredContent)
     After:  validate(Map<String,Object> schema, Object structuredContent)

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-15 14:22:06 +02:00
Christian Tzolov
7e3ea73815
fix: Add JsonInclude annotation to notification records for proper serialization (#552)
Add @JsonInclude(JsonInclude.Include.NON_ABSENT) to ResourcesUpdatedNotification
  and to LoggingMessageNotification

This ensures that absent (null/Optional.empty()) fields are excluded from JSON
serialization, preventing potential serialization issues with these MCP notification types.

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-14 12:07:54 +02:00
Daniel Garnier-Moiroux
bc3a925bdc LifecycleInitializer recovers from init failures (#549)
Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2025-09-12 14:00:23 +02:00
Christian Tzolov
3f70afd21f
Enhance README with project badges
Added badges for license, build status, Maven Central, and Java version to README.
2025-09-08 15:30:51 +02:00
Christian Tzolov
c7736b6ec6 fix: Skip structured output validation for error tool results
This ensures that when a tool handler returns an error result, the structured
output schema validation is skipped, preventing validation failures on error
responses that don't conform to the expected output schema.

- Add validation bypass when CallToolResult.isError() is true in async/stateless servers
- Fix async tool handler chaining to properly use then() instead of block()
- Add comprehensive tests for structured output with in-handler errors
- Improve error handling to use proper JSON-RPC error codes for unknown tools
- Add findRootCause utility method for better error diagnostics
- Increase test timeouts for stability in StdioMcp client tests. These tests use npx
  to download and run the MCP "everything" server locally. The first
  test execution will download the everything server scripts and cache them locally,
  which can take more than 15 seconds. Subsequent test runs will use the cached version
  and execute faster.

Resolves #538
Related to #422

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-08 13:48:53 +02:00
Yanming Zhou
d8cc189341 fix: Add null check for response ID to prevent memory leaks
- Check if response.id() is not null before processing in MCP session classes
- Log error when MCP response lacks session ID to warn about potential memory leaks
- Improve error handling in McpStreamableServerSession with proper error codes

The missing null check could lead to memory leaks as pending requests
would never be completed when responses lack session IDs. This fix ensures
proper handling of such cases with appropriate error logging.

Resolves #506

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2025-09-08 13:09:56 +02:00
Christian Tzolov
7cf5907da4 Next development version
Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-04 22:33:14 +02:00
Christian Tzolov
681fe7f90b
test: ensure proper resource cleanup in integration tests (#537)
- Add try-finally blocks to guarantee server cleanup on test completion
- Call closeGracefully().block() to ensure synchronous shutdown
- Use try-with-resources for client lifecycle management where applicable
- Prevent resource leaks and potential test flakiness

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-04 16:52:21 +02:00
Richie Caputo
2314238469 fix: filter template resources from standard resource listing (#528)
- Add filter to exclude resources with template parameters ({}) from resources/list
- Template resources should only appear in resources/templates/list per MCP spec
- Add comprehensive test coverage for resource/template separation
- Update mock transport utilities for better test support

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-04 15:30:56 +02:00
Christian Tzolov
ec4b329699
test: upgrade mcp-everything-server to v3 and fix resiliency test race condition (#536)
- Upgrade Docker test server image from v2 to v3 across all test files
- Updates all test files to use the latest version of the mcp-everything-server
Docker image (v3) for integration testing.
- Fix race condition in async client tests by not advertising roots capability during initialization
  - Prevents server from listing roots during init which could cause timing issues when disconnecting immediately after initialization
- Applied fix to AbstractMcpAsyncClientResiliencyTests (both mcp and mcp-test modules) and HttpSseMcpAsyncClientLostConnectionTests

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
Co-authored-by: Daniel Garnier-Moiroux <git@garnier.wf>
2025-09-04 14:46:08 +02:00
Daniel Garnier-Moiroux
4d779e139c
Fix flakey test in HttpClientStreamableHttpTransportErrorHandlingTest (#535) 2025-09-04 12:55:26 +02:00
Christian Tzolov
02b8c4bcff
test: Add additional MCP transport context integration tests (#529)
- Add integration tests for transport context propagation between MCP clients and servers
- Test both sync and async server implementations across all transport types (stateless, streamable, SSE)
- Cover Spring WebFlux and WebMVC environments with dedicated test suites
- Validate context flow through HTTP headers for authentication, correlation IDs, and metadata
- Rename existing McpTransportContextIntegrationTests to SyncServerMcpTransportContextIntegrationTests for clarity
- Add proper resource cleanup for async clients in teardown methods

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-09-04 09:27:01 +02:00
Daniel Garnier-Moiroux
a5fd1ebff5
Use static container in all client and transport tests (#531)
- This allows reusing the containerized MCP server for all tests in a
  single class, significantly speeding up the tests, roughly 10x.

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2025-09-03 16:36:46 +02:00
Daniel Garnier-Moiroux
629464b1d6
Add McpTransportContext to McpSyncClient (#522)
* McpSyncClient: introduce McpTransportContext

- McpSyncClient should be considered thread-agnostic, and therefore
  consumers cannot rely on thread locals to propagate "context", e.g.
  pass down the Servlet request reference in a server context.
- This PR introduces a mechanism for populating an McpTransportContext
  before executing client operations, and reworks the HTTP request
  customizers to leverage that McpTransportContext.
- Move McpTransportContext from server to common package for shared client/server usage
- Make McpTransportContext immutable by removing put() and copy() methods
- Add static create() factory method for creating contexts with predefined data
- Update McpTransportContextExtractor to return context instead of modifying one
- Replace DefaultMcpTransportContext mutable implementation with immutable version
- Update all transport implementations to use McpTransportContext.EMPTY as default
- Rename *HttpRequestCustomizer -> *HttpClientRequestCustomizer
- Add end-to-end McpTransportContextIntegrationTests
- This PR introduces a breaking change to the Sync/Async request
  customizers.

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2025-09-02 11:09:40 +02:00
Daniel Garnier-Moiroux
95ba8e77ec refactor: move and rename HTTP request customizers to dedicated package (#453)
- Move Mcp(Async)HttpRequestCustomizer from client.transport to client.transport.customizer
- Rename (Async)HttpRequestCustomizer to Mcp(Async)HttpRequestCustomizer
- Add DelegatingMcpAsyncHttpRequestCustomizer and DelegatingMcpSyncHttpRequestCustomizer for composing multiple customizers
- Update all references across transport classes and tests
- Improve package organization and naming consistency with MCP prefix
2025-08-28 16:26:11 +02:00
Kevin Stanton
b4fef5241f feat: Add transport context extraction support to all MCP servers (#477)
- Add McpTransportContextExtractor to WebFlux/WebMVC SSE and Streamable transport providers
- Enable extraction of HTTP transport metadata (headers, etc.) for use during request processing
- Pass transport context through reactive context chain using McpTransportContext.KEY
- Add contextExtractor() builder methods for configuring custom extractors
- Update HttpServlet transport providers with same context extraction capability
- Modify McpServerSession to properly propagate transport context to handlers
- Add test coverage with TEST_CONTEXT_EXTRACTOR in integration tests

This allows MCP feature implementations to access HTTP transport level metadata
that was present at request time, enabling use cases like authentication,
request tracing, and custom header processing.

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>

Co-authored-by: Christian Tzolov <christian.tzolov@broadcom.com>
Co-authored-by: Dariusz Jędrzejczyk <dariusz.jedrzejczyk@broadcom.com>
2025-08-26 18:32:11 +02:00
Christian Tzolov
9c9e2ebdf7
fix: disable logging capabilities for stateless servers (#517)
Remove LoggingCapabilities from McpStatelessServerFeatures.Async constructor
as stateless servers do not support setLogging operations. This aligns the
async implementation with the sync implementation which already has logging
disabled.

Follows up on #463

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-26 12:48:42 +02:00
Christian Tzolov
336f2024e7
feat: implement demand-based request handling in ResponseSubscribers (#516)
- Add hasRequestedDemand volatile boolean flag to AggregateSubscriber and BodilessResponseLineSubscriber
- Modify hookOnSubscribe to request Long.MAX_VALUE only on first demand request
- Guard event emission in hookOnComplete with hasRequestedDemand check
- Prevents unnecessary data processing when no downstream demand exists
- Improves backpressure handling and resource efficiency

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-26 10:30:31 +02:00
shaoyin.zj
6ec443c89a
fix: When call the MCP SSE endpoint, the Content-Type header not passed by default (#489) 2025-08-26 07:51:07 +02:00
Zizo
cc67d8fa76
fix: http streamable client connect timeout (#511)
* add http streamable client connect timeout
* add http sse client connect timeout

Co-authored-by: gongwn1 <gongwn1@lenovo.com>
2025-08-25 16:14:28 +02:00
He-Pin(kerr)
94c03505c1
fix: Fix SseLineSubscriber lacking request. (#507)
Signed-off-by: He-Pin <hepin1989@gmail.com>
2025-08-25 15:46:17 +02:00
Christian Tzolov
888e555026
feat: implement identifier-based equals/hashCode for PromptReference (#514)
Ensure PromptReference equality is based solely on identifier and type fields, ignoring other fields like title

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-25 12:46:59 +02:00
Jordan Zimmerman
713ee1add0 fix: ServerCapabilities should not enable logging by default (#463)
- Change LoggingCapabilities from default-initialized to nullable in ServerCapabilities
- Add check if server logging is enabled in McpAsyncClient before setting logging level
- Ensure McpAsyncServer always enables logging capabilities when built
- Ensure McpStatelessAsyncServer has disabled logging capability by default
- Update tests to verify logging capabilities can be null

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
Co-authored-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-11 23:03:25 +01:00
Christian Tzolov
6c38f37637 fix: improve streamable HTTP session reinitialization (#459)
Implements the MCP spec guidelines for streamable HTTP (re)initialization:
- Server MAY terminate session and MUST respond with HTTP 404 for terminated session IDs
- Client MUST start new session when receiving HTTP 404 for requests with session ID

Changes:
- Replace generic McpError with McpTransportException for transport-layer errors
- Only throw McpTransportSessionNotFoundException when session ID is present in request
  (per spec: 404 with session ID means session terminated, without means general error)
- Enhance error messages with more context (status codes, response events)
- Use RuntimeException for non-transport specific SSE endpoint failures
- Ensure consistent error handling across HTTP client transports

- Improve error handling with standard Java exceptions.
  Replace generic McpError with appropriate standard exceptions:
  - Use IllegalArgumentException for invalid input parameters
  - Use IllegalStateException for state-related issues
  - Use RuntimeException wrapper for initialization failures
  - Use McpError.builder() with proper error codes for protocol errors

Fixes #459

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-10 14:31:49 +01:00
Christian Tzolov
eb427add79 refactor: improve integration tests stability
- Replace inline StepVerifier assertions with AtomicReference pattern for better testability
- Add assertWith() usage for cleaner assertion blocks in async tests
- Simplify reactive chains using doOnNext() and thenReturn() patterns
- Remove unnecessary Thread.sleep() from elicitation handler
- Improve variable naming (rootsRef → toolsRef) for clarity
- Update timeout error message assertions to be more specific
- Clean up code formatting and remove redundant comments

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-09 18:41:13 +01:00
Christian Tzolov
cbfdb14e40
refactor: extract common integration test logic into abstract base classes (#473)
refactor: extract common integration test logic into abstract base classes

- Move duplicated test methods from WebFlux and WebMvc integration test classes to abstract base classes
- WebFluxSseIntegrationTests, WebFluxStreamableIntegrationTests now extend AbstractMcpClientServerIntegrationTests
- WebFluxStatelessIntegrationTests, WebMvcStatelessIntegrationTests now extend AbstractStatelessIntegrationTests  
- Each concrete test class now only implements transport-specific setup methods (prepareClients, prepareAsyncServerBuilder, prepareSyncServerBuilder)
- Eliminates ~1300+ lines of duplicated test code across multiple files
- Improves maintainability by centralizing test logic in reusable base classes
- Updates WebMvcSseServerTransportProvider to use builder pattern
- Adds new HttpServletSseIntegrationTests extending AbstractMcpClientServerIntegrationTests
  - Removes HttpServletSseServerTransportProviderIntegrationTests
- Standardizes timeout configurations and client setup across all integration tests

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-08 21:31:29 +02:00
Christian Tzolov
1edd1b64db feat: Add builder pattern for McpError and mutate method for capabilities
- Add builder pattern to McpError for structured error creation with validation
- Deprecate McpError(Object) constructor in favor of builder approach
- Add mutate() method to server capabilities for creating modified copies

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-08 09:36:40 +01:00
Jordan Zimmerman
a14ef425d6 If a handler throws McpError, use its values for the RPC error
Handlers should be able to throw RPC errors and `McpError` is the
right exception for that.

Improve `DefaultMcpStatelessServerHandler` error handler to check if the
exception is `McpError` and, if so, use it to build the RPC error
result instead of re-writing as `INTERNAL_ERROR`.
2025-08-08 10:20:53 +02:00
Christian Tzolov
4532b614e4 feat: handle SSE comment messages
- Add support for ignoring SSE comment lines that start with ':'
- Add debug logging for comment line processing

Resolves #443

Signed-off-by: Christian Tzolov <christian.tzolov@broadcom.com>
2025-08-07 11:36:16 +02:00
Daniel Garnier-Moiroux
032716546c Fix httpRequestCustomizer usage in HttpClientStreamableHttpTransport
- Closes #458

Signed-off-by: Daniel Garnier-Moiroux <git@garnier.wf>
2025-08-07 10:35:56 +02:00
Christian Tzolov
110a8d1940 refactor: downgrade unhandled notification logging from error to warn
- Change logger.error() to logger.warn() for unhandled notification methods
- Log full notification object instead of just method name for better context
- Affects McpClientSession, McpServerSession, and McpStreamableServerSession

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

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
2025-08-06 09:13:30 +02:00
codezkk
5aba8a0e8f fix: handle empty JSON responses in ResponseSubscribers
- Remove length check in hookOnComplete() to always emit AggregateResponseEvent
- Ensures proper completion handling regardless of response content length
- Add test for empty application/json responses with 200 OK status
2025-08-06 08:08:38 +01:00