{"record":{"id":"acdbfcc8ca617116","repo":"spring-projects/spring-ai","slug":"stateless-servers-doesn-t-support-bidirectional-pa","errorCode":null,"errorMessage":"Stateless servers doesn't support bidirectional parameters. Skipping method <method> with bidirectional parameters","messagePattern":"Stateless servers doesn't support bidirectional parameters\\. Skipping method <method> with bidirectional parameters","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/common/McpPredicates.java","lineNumber":102,"sourceCode":"\t\t\tif (McpSyncRequestContext.class.isAssignableFrom(paramType)\n\t\t\t\t\t|| McpAsyncRequestContext.class.isAssignableFrom(paramType)\n\t\t\t\t\t|| McpSyncServerExchange.class.isAssignableFrom(paramType)\n\t\t\t\t\t|| McpAsyncServerExchange.class.isAssignableFrom(paramType)) {\n\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tpublic static Predicate<Method> filterMethodWithBidirectionalParameters() {\n\t\treturn method -> {\n\t\t\tif (!hasBidirectionalParameters(method)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\tif (logger.isWarnEnabled()) {\n\t\t\t\tlogger.warn(\"Stateless servers doesn't support bidirectional parameters. Skipping method \" + method\n\t\t\t\t\t\t+ \" with bidirectional parameters\");\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\t}\n\n}\n","sourceCodeStart":84,"sourceCodeEnd":110,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/common/McpPredicates.java#L84-L110","documentation":"Stateless MCP servers cannot correlate the client callback that bidirectional parameters require. When a method on a stateless server declares parameters that support bidirectional communication (e.g. McpSyncRequestContext/McpAsyncRequestContext exchange with callbacks), the method is skipped and a warning is logged rather than thrown.","triggerScenarios":"Declaring a method parameter of type McpSyncRequestContext (or the async equivalent) that performs bidirectional operations like sampling or elicitation, then registering it with a STATELESS MCP server.","commonSituations":"Configuring a stateless (McpServer.StatelessAsyncSpecification/StatelessSyncSpecification) server while copying tool examples that use request contexts for sampling/progress; stateful-to-stateless migration.","solutions":["Use a stateful server builder (McpServer.async()/sync() stateful variant) so bidirectional parameters are supported","Remove the bidirectional context parameter from the method, or restrict the method to stateless-safe operations (no sampling/elicitation/progress)","Keep bidirectional methods in a separate service registered only with stateful servers"],"exampleFix":"// before (stateless server)\n@McpTool(description = \"Ask\")\npublic String ask(McpSyncRequestContext ctx, String q) { return ctx.sample(s -> s.prompt(\"Think: \" + q)).block(); }\n\n// after (stateless-safe)\n@McpTool(description = \"Ask\")\npublic String ask(String q) { return staticAnswer(q); }","handlingStrategy":"validation","validationCode":"boolean stateless = builder instanceof McpServer.StatelessSyncSpecification || builder instanceof McpServer.StatelessAsyncSpecification;\nif (stateless) {\n  for (Method m : service.getClass().getDeclaredMethods()) {\n    for (Class<?> p : m.getParameterTypes()) {\n      if (McpSyncRequestContext.class == p || McpAsyncRequestContext.class == p) {\n        throw new IllegalStateException(m + \" uses bidirectional context; needs a stateful server\");\n      }\n    }\n  }\n}","typeGuard":"static boolean usesBidirectionalContext(Method m) {\n  return java.util.Arrays.stream(m.getParameterTypes())\n    .anyMatch(p -> p == McpSyncRequestContext.class || p == McpAsyncRequestContext.class);\n}","tryCatchPattern":null,"preventionTips":["Match server statefulness to tool capabilities: stateful if sampling/elicitation/progress are used","Document which services require bidirectional context parameters","Check startup warnings about skipped methods with bidirectional parameters"],"tags":["spring-ai","mcp","stateless-server","bidirectional","request-context"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}