{"record":{"id":"d90ecd8d396f8090","repo":"spring-projects/spring-ai","slug":"no-async-complete-methods-found-in-the-provided-co","errorCode":null,"errorMessage":"No async complete methods found in the provided complete objects: <completeObjects>","messagePattern":"No async complete methods found in the provided complete objects: <completeObjects>","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/complete/AsyncMcpCompleteProvider.java","lineNumber":90,"sourceCode":"\t\t\t\t\tvar completeRef = CompleteAdapter.asCompleteReference(completeAnnotation, mcpCompleteMethod);\n\n\t\t\t\t\tvar methodCallback = AsyncMcpCompleteMethodCallback.builder()\n\t\t\t\t\t\t.method(mcpCompleteMethod)\n\t\t\t\t\t\t.bean(completeObject)\n\t\t\t\t\t\t.prompt(completeAnnotation.prompt().isEmpty() ? null : completeAnnotation.prompt())\n\t\t\t\t\t\t.uri(completeAnnotation.uri().isEmpty() ? null : completeAnnotation.uri())\n\t\t\t\t\t\t.build();\n\n\t\t\t\t\treturn new AsyncCompletionSpecification(completeRef, methodCallback);\n\t\t\t\t})\n\t\t\t\t.toList())\n\t\t\t.flatMap(List::stream)\n\t\t\t.toList();\n\n\t\tif (asyncCompleteSpecification.isEmpty()) {\n\t\t\tif (logger.isWarnEnabled()) {\n\t\t\t\tlogger\n\t\t\t\t\t.warn(\"No async complete methods found in the provided complete objects: \" + this.completeObjects);\n\t\t\t}\n\t\t}\n\n\t\treturn asyncCompleteSpecification;\n\t}\n\n\t/**\n\t * Returns the methods of the given bean class.\n\t * @param bean the bean instance\n\t * @return the methods of the bean class\n\t */\n\tprotected Method[] doGetClassMethods(Object bean) {\n\t\treturn bean.getClass().getDeclaredMethods();\n\t}\n\n}\n","sourceCodeStart":72,"sourceCodeEnd":107,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/complete/AsyncMcpCompleteProvider.java#L72-L107","documentation":"AsyncMcpCompleteProvider.getCompleteSpecifications() scans the supplied completion provider objects for methods annotated as completion handlers (e.g. @McpComplete). If none of the objects expose a matching async complete method, an empty specification list results and this warning is logged. The provider is built with zero completions, so completion requests will find nothing.","triggerScenarios":"Registering complete objects with the async completion provider where no method carries the completion annotation, the annotation is misplaced (wrong package/import), or the method signature does not match the expected complete shape.","commonSituations":"Typos or wrong @McpComplete import (e.g. from another library); methods returning reactive types scanned by a sync scanner or vice versa; forgetting the annotation entirely while passing a plain object as a complete provider.","solutions":["Annotate at least one method in each complete object with @McpComplete and verify the import is org.springframework.ai.mcp.annotation.*","Verify the method signature matches what the provider scans for (prompt-name argument plus completion String argument) and uses reactive return types for the async provider","Check the log/scan setup so the annotated object is actually passed to the provider (not a different instance/class)"],"exampleFix":"// before\npublic class MyCompletes { public List<String> complete(String prefix) { return List.of(prefix + \"!\"); } }\n// after\npublic class MyCompletes {\n  @McpComplete(prompt = \"my-prompt\")\n  public Mono<List<String>> complete(String prefix) { return Mono.just(List.of(prefix + \"!\")); }\n}","handlingStrategy":"validation","validationCode":"boolean hasComplete = java.util.Arrays.stream(completeObject.getClass().getDeclaredMethods())\n  .anyMatch(m -> m.isAnnotationPresent(McpComplete.class));\nif (!hasComplete) {\n  throw new IllegalStateException(\"Complete object \" + completeObject + \" has no @McpComplete methods\");\n}","typeGuard":"static boolean hasAnnotatedCompleteMethods(Object o) {\n  return java.util.Arrays.stream(o.getClass().getDeclaredMethods())\n    .anyMatch(m -> m.isAnnotationPresent(McpComplete.class));\n}","tryCatchPattern":null,"preventionTips":["Annotate completion methods with @McpComplete and verify imports","Use reactive signatures for async providers (Mono/Flux)","Review startup warnings for 'No async complete methods found'"],"tags":["spring-ai","mcp","completion","annotation-scan","async-provider"],"backgroundTag":"empty-result-set","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"}