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 method

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Drop the McpSyncRequestContext parameter from the tool method signature.
  2. Use McpTransportContext as the parameter if some context is needed — stateless callbacks resolve and pass it.
  3. 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

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


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/53aaf077ba621d47. Report an issue: GitHub.