You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
refactor: improve bidirectional capability handling and error reporting (spring-ai-community#73)
Major changes:
- Add capability check methods (rootsEnabled, elicitEnabled, sampleEnabled) to both sync and async request contexts
- Replace Optional return types with direct returns and throw IllegalStateException when capabilities not supported
- Change from warning logs to exceptions for unsupported operations in stateless contexts
- Removed stateless context implementations (StatelessAsyncRequestContext, StatelessMcpSyncRequestContext)
- Add bidirectional parameter filtering for stateless providers (tools, resources, prompts, completions)
- Update tests to verify new exception-based error handling
- Updated README
Breaking changes:
- McpSyncRequestContext methods now return direct types instead of Optional<T>
- McpAsyncRequestContext methods now return Mono.error() instead of Mono.empty() for unsupported operations
- Stateless context methods throw IllegalStateException instead of logging warnings
This improves API clarity by making capability checks explicit and error handling more predictable.
Signed-off-by: Christian Tzolov <[email protected]>
-`rootsEnabled()` - Check if roots capability is supported by the client
1070
+
-`roots()` - Access root directories (throws `IllegalStateException` if not supported)
1071
+
-`elicitEnabled()` - Check if elicitation capability is supported by the client
1072
+
-`elicit(TypeReference<T>)` - Request user input with default message, returns `StructuredElicitResult<T>` with action, typed content, and metadata (throws `IllegalStateException` if not supported)
1073
+
-`elicit(Class<T>)` - Request user input with default message using Class type, returns `StructuredElicitResult<T>` (throws `IllegalStateException` if not supported)
1074
+
-`elicit(Consumer<ElicitationSpec>, TypeReference<T>)` - Request user input with custom configuration, returns `StructuredElicitResult<T>` (throws `IllegalStateException` if not supported)
1075
+
-`elicit(Consumer<ElicitationSpec>, Class<T>)` - Request user input with custom configuration using Class type, returns `StructuredElicitResult<T>` (throws `IllegalStateException` if not supported)
1076
+
-`elicit(ElicitRequest)` - Request user input with full control over the elicitation request (throws `IllegalStateException` if not supported)
1077
+
-`sampleEnabled()` - Check if sampling capability is supported by the client
1078
+
-`sample(...)` - Request LLM sampling with various configuration options (throws `IllegalStateException` if not supported)
1069
1079
-`ping()` - Send ping to check connection
1070
1080
1071
-
`McpAsyncRequestContext` provides the same methods but with reactive return types (`Mono<T>` instead of `T` or `Optional<T>`).
1081
+
`McpAsyncRequestContext` provides the same methods but with reactive return types (`Mono<T>` instead of `T`). Methods that throw `IllegalStateException` in sync context return `Mono.error(IllegalStateException)` in async context.
1082
+
1083
+
**Important Notes on Capability Checking:**
1084
+
- Always check capability support using `rootsEnabled()`, `elicitEnabled()`, or `sampleEnabled()` before calling the corresponding methods
1085
+
- Calling capability methods when not supported will throw `IllegalStateException` (sync) or return `Mono.error()` (async)
1086
+
- Stateless servers do not support bidirectional operations (roots, elicitation, sampling) and will always return `false` for capability checks
1072
1087
1073
1088
This unified context approach simplifies method signatures and provides a consistent API across different operation types and execution modes (stateful vs stateless, sync vs async).
1074
1089
@@ -2104,6 +2119,9 @@ public class StatelessResourceProvider {
2104
2119
}
2105
2120
```
2106
2121
2122
+
**Important Note on Stateless Operations:**
2123
+
Stateless server methods cannot use bidirectional parameters like `McpSyncRequestContext`, `McpAsyncRequestContext`, `McpSyncServerExchange`, or `McpAsyncServerExchange`. These parameters require client capabilities (roots, elicitation, sampling) that are not available in stateless mode. Methods with these parameters will be automatically filtered out and not registered as stateless operations.
0 commit comments