{"record":{"id":"853b9fa226c06ba6","repo":"spring-projects/spring-ai","slug":"sync-prompt-method-must-not-declare-parameter-of-t","errorCode":null,"errorMessage":"Sync prompt method must not declare parameter of type: {paramType.getName()}. Use McpSyncServerExchange instead. Method: {this.method.getName()} in {this.method.getDeclaringClass().getName()}","messagePattern":"Sync prompt method must not declare parameter of type: (.+?)\\. Use McpSyncServerExchange instead\\. Method: (.+?) in (.+?)","errorType":"validation","errorClass":"java.lang.IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java","lineNumber":55,"sourceCode":" *\n * This class provides a way to convert methods annotated with {@link McpPrompt} into\n * callback functions that can be used to handle prompt requests. It supports various\n * method signatures and return types.\n *\n * @author Christian Tzolov\n */\npublic final class SyncMcpPromptMethodCallback extends AbstractMcpPromptMethodCallback\n\t\timplements BiFunction<McpSyncServerExchange, GetPromptRequest, GetPromptResult> {\n\n\tprivate SyncMcpPromptMethodCallback(Builder builder) {\n\t\tsuper(builder.method, builder.bean, builder.prompt);\n\t}\n\n\t@Override\n\tprotected void validateParamType(Class<?> paramType) {\n\n\t\tif (McpAsyncServerExchange.class.isAssignableFrom(paramType)) {\n\t\t\tthrow new IllegalArgumentException(\"Sync prompt method must not declare parameter of type: \"\n\t\t\t\t\t+ paramType.getName() + \". Use McpSyncServerExchange instead.\" + \" Method: \" + this.method.getName()\n\t\t\t\t\t+ \" in \" + this.method.getDeclaringClass().getName());\n\t\t}\n\t}\n\n\t@Override\n\tprotected Object assignExchangeType(Class<?> paramType, Object exchange) {\n\n\t\tif (McpTransportContext.class.isAssignableFrom(paramType)) {\n\t\t\tif (exchange instanceof McpTransportContext transportContext) {\n\t\t\t\treturn transportContext;\n\t\t\t}\n\t\t\telse if (exchange instanceof McpSyncServerExchange syncServerExchange) {\n\t\t\t\treturn syncServerExchange.transportContext();\n\t\t\t}\n\t\t\telse if (exchange instanceof McpAsyncServerExchange asyncServerExchange) {\n\t\t\t\tthrow new IllegalArgumentException(\"Unsupported Async exchange type: \"\n\t\t\t\t\t\t+ asyncServerExchange.getClass().getName() + \" for Sync method: \" + method.getName() + \" in \"","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/prompt/SyncMcpPromptMethodCallback.java#L37-L73","documentation":"Sync prompt methods may receive an McpSyncServerExchange but not an McpAsyncServerExchange, since a synchronous server cannot provide the async exchange. SyncMcpPromptMethodCallback validates each parameter type at registration and throws IllegalArgumentException if it finds the async exchange type.","triggerScenarios":"Declaring an @McpPrompt method with an McpAsyncServerExchange parameter while registering it with SyncMcpPromptMethodCallback (sync MCP server).","commonSituations":"Copy-pasting a method signature from async MCP examples into a sync server setup; converting an app from async to sync without changing signatures.","solutions":["Change the parameter type to McpSyncServerExchange","Remove the exchange parameter if not needed","Register the bean with the async server (AsyncMcpPromptMethodCallback) if the method must stay async"],"exampleFix":"// before\npublic GetPromptResult p(McpAsyncServerExchange exchange, Request req) {...}\n// after\npublic GetPromptResult p(McpSyncServerExchange exchange, Request req) {...}","handlingStrategy":"validation","validationCode":"boolean syncSafe(Method m) { return Arrays.stream(m.getParameterTypes()).noneMatch(t -> McpAsyncServerExchange.class.isAssignableFrom(t)); }","typeGuard":null,"tryCatchPattern":"try { syncServer.addPrompt(cb); } catch (IllegalArgumentException e) { log.error(\"Sync method misconfigured: {}\", e.getMessage()); }","preventionTips":["Use McpSyncServerExchange in sync prompt methods","Keep async signatures out of sync server configurations","Add a unit test scanning @McpPrompt parameter types per server mode"],"tags":["mcp","sync-async-mismatch","parameter-type","prompt-method"],"backgroundTag":"type-mismatch","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}