{"record":{"id":"b0fc51f6a3c957ae","repo":"spring-projects/spring-ai","slug":"method-can-have-at-most-3-input-parameters-exclud","errorCode":null,"errorMessage":"Method can have at most 3 input parameters (excluding @McpProgressToken and McpMeta): ","messagePattern":"Method can have at most 3 input parameters \\(excluding @McpProgressToken and McpMeta\\): ","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java","lineNumber":162,"sourceCode":"\t * delegates exchange type checking to subclasses.\n\t * @param method The method to validate\n\t * @throws IllegalArgumentException if the parameters are not compatible\n\t */\n\tprotected void validateParameters(Method method) {\n\t\tParameter[] parameters = method.getParameters();\n\n\t\t// Count non-special parameters (excluding @McpProgressToken and McpMeta)\n\t\tint nonSpecialParamCount = 0;\n\t\tfor (Parameter param : parameters) {\n\t\t\tif (!param.isAnnotationPresent(McpProgressToken.class)\n\t\t\t\t\t&& !McpMeta.class.isAssignableFrom(param.getType())) {\n\t\t\t\tnonSpecialParamCount++;\n\t\t\t}\n\t\t}\n\n\t\t// Check parameter count - must have at most 3 non-special parameters\n\t\tif (nonSpecialParamCount > 3) {\n\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\"Method can have at most 3 input parameters (excluding @McpProgressToken and McpMeta): \"\n\t\t\t\t\t\t\t+ method.getName() + \" in \" + method.getDeclaringClass().getName() + \" has \"\n\t\t\t\t\t\t\t+ nonSpecialParamCount + \" parameters\");\n\t\t}\n\n\t\t// Check parameter types\n\t\tboolean hasExchangeParam = false;\n\t\tboolean hasTransportContext = false;\n\t\tboolean hasRequestParam = false;\n\t\tboolean hasArgumentParam = false;\n\t\tboolean hasProgressTokenParam = false;\n\t\tboolean hasMetaParam = false;\n\t\tboolean hasRequestContextParam = false;\n\n\t\tfor (Parameter param : parameters) {\n\t\t\tClass<?> paramType = param.getType();\n\n\t\t\t// Skip @McpProgressToken annotated parameters from validation","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/method/complete/AbstractMcpCompleteMethodCallback.java#L144-L180","documentation":"validateParameters() in AbstractMcpCompleteMethodCallback counts non-special parameters (excluding @McpProgressToken-annotated and McpMeta parameters) and rejects methods with more than 3, since the completion input can supply at most the completion value, related argument context, and a request. Extra parameters make the signature unbindable.","triggerScenarios":"Annotating a completion method whose signature has 4+ ordinary parameters (beyond progress-token and McpMeta) and registering it with the annotation callback.","commonSituations":"Reusing a generic service method with many arguments as a completion handler; adding client/context parameters beyond what the framework supports; merging multiple handler concerns into one method.","solutions":["Reduce the method to at most 3 non-special parameters matching the supported completion argument types.","Move auxiliary data into McpMeta or access it via the request context parameter instead of extra parameters.","Split the logic into a thin completion handler that delegates to a richer internal method."],"exampleFix":"// before\n@McpComplete(prompt = \"p\")\npublic void complete(String value, String arg, Client c, Config cfg) { } // 4 params\n// after\n@McpComplete(prompt = \"p\")\npublic void complete(String value, McpMeta meta) {\n    Config cfg = (Config) meta.get(\"config\");\n}","handlingStrategy":"validation","validationCode":"long ordinary = Arrays.stream(method.getParameters())\n    .filter(p -> !p.isAnnotationPresent(McpProgressToken.class))\n    .filter(p -> !McpMeta.class.isAssignableFrom(p.getType()))\n    .count();\nif (ordinary > 3) throw new IllegalStateException(\"too many completion parameters: \" + method.getName());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Design completion handlers with at most 3 ordinary parameters.","Pass extra data via McpMeta or the request context.","Keep handlers thin; delegate to richer internal service methods."],"tags":["mcp","validation","parameter-count","completion"],"backgroundTag":"invalid-argument-value","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"}