spring-projects/spring-ai · error · UnsupportedOperationException
Stateless tool methods do not support McpSyncRequestContext
Error message
Stateless tool methods do not support McpSyncRequestContext parameter.
What it means
SyncStatelessMcpToolMethodCallback serves @McpTool methods on a stateless sync client. Since stateless callbacks have no active MCP exchange, McpSyncRequestContext cannot be instantiated; createRequestContext always throws UnsupportedOperationException. Methods may only declare McpTransportContext (or no context) parameters.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/tool/SyncStatelessMcpToolMethodCallback.java:69
* The {@code toolCallExceptionClass} argument is ignored: exception handling now
* follows the {@code @Tool} contract based on the exception type. Will be removed in
* 2.1.0.
*/
@Deprecated
public SyncStatelessMcpToolMethodCallback(ReturnMode returnMode, java.lang.reflect.Method toolMethod,
Object toolObject, Class<? extends Throwable> toolCallExceptionClass) {
super(returnMode, toolMethod, toolObject, toolCallExceptionClass);
}
@Override
protected boolean isExchangeOrContextType(Class<?> paramType) {
return McpTransportContext.class.isAssignableFrom(paramType)
|| McpSyncRequestContext.class.isAssignableFrom(paramType);
}
@Override
protected McpSyncRequestContext createRequestContext(McpTransportContext exchange, CallToolRequest request) {
throw new UnsupportedOperationException(
"Stateless tool methods do not support McpSyncRequestContext parameter.");
}
@Override
protected McpTransportContext resolveTransportContext(McpTransportContext context) {
return context;
}
@Override
public CallToolResult apply(McpTransportContext mcpTransportContext, CallToolRequest callToolRequest) {
validateSyncRequest(callToolRequest);
try {
// Build arguments for the method call
Object[] args = this.buildMethodArguments(mcpTransportContext, callToolRequest.arguments(),
callToolRequest);
// Invoke the methodView on GitHub (pinned to 98a7beda4f)
Solutions
- Drop the McpSyncRequestContext parameter from the tool method signature.
- Use McpTransportContext as the parameter if some context is needed — stateless callbacks resolve and pass it.
- Switch the registration to the stateful sync callback (SyncMcpToolMethodCallback) if exchange-aware elicitation/progress features are required.
Example fix
// before
@McpTool(name = "search")
String search(String query, McpSyncRequestContext ctx) { ... }
// after
@McpTool(name = "search")
String search(String query) { ... } Defensive patterns
Strategy: validation
Validate before calling
// Fail fast at startup if a stateless sync tool method declares McpSyncRequestContext
for (Method m : bean.getClass().getDeclaredMethods()) {
if (m.isAnnotationPresent(McpTool.class)) {
for (Class<?> p : m.getParameterTypes()) {
if (McpSyncRequestContext.class.isAssignableFrom(p)) {
throw new IllegalStateException("@McpTool " + m.getName() + " cannot take McpSyncRequestContext in a stateless callback");
}
}
}
} Prevention
- Never declare McpSyncRequestContext parameters in stateless tool methods.
- Use McpTransportContext as the context parameter instead.
- When migrating between stateful/stateless setups, audit all @McpTool signatures.
When it happens
Trigger: Declaring a @McpTool method with a McpSyncRequestContext parameter (e.g. @McpTool(name="x") String tool(String arg, McpSyncRequestContext ctx)) and registering it with a stateless sync tool callback, then calling it.
Common situations: Copy-pasting a stateful tool method into a stateless configuration; tutorials mixing stateful examples with stateless client setup; refactoring that changed the registry type but not method signatures.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Stateless tool methods do not support McpAsyncRequestContext
- Roots not supported by the client:
- Currently only methods with a single ElicitRequest parameter
- Method must return ElicitResult or StructuredElicitResult:
- Synchronous progress methods must return void: {method.getNa
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/53aaf077ba621d47.
Report an issue: GitHub.