{"record":{"id":"fe45944427d64c32","repo":"spring-projects/spring-ai","slug":"no-resource-methods-found-in-the-provided-resource","errorCode":null,"errorMessage":"No resource methods found in the provided resource objects: <resourceObjects>","messagePattern":"No resource methods found in the provided resource objects: <resourceObjects>","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/resource/AsyncMcpResourceProvider.java","lineNumber":120,"sourceCode":"\t\t\t\t\tBiFunction<McpAsyncServerExchange, ReadResourceRequest, Mono<ReadResourceResult>> methodCallback = AsyncMcpResourceMethodCallback\n\t\t\t\t\t\t.builder()\n\t\t\t\t\t\t.method(mcpResourceMethod)\n\t\t\t\t\t\t.bean(resourceObject)\n\t\t\t\t\t\t.resource(mcpResource)\n\t\t\t\t\t\t.build();\n\n\t\t\t\t\tvar resourceSpec = new AsyncResourceSpecification(mcpResource, methodCallback);\n\n\t\t\t\t\treturn resourceSpec;\n\t\t\t\t})\n\t\t\t\t.filter(Objects::nonNull)\n\t\t\t\t.toList())\n\t\t\t.flatMap(List::stream)\n\t\t\t.toList();\n\n\t\tif (resourceSpecs.isEmpty()) {\n\t\t\tif (logger.isWarnEnabled()) {\n\t\t\t\tlogger.warn(\"No resource methods found in the provided resource objects: \" + this.resourceObjects);\n\t\t\t}\n\t\t}\n\n\t\treturn resourceSpecs;\n\t}\n\n\tpublic List<AsyncResourceTemplateSpecification> getResourceTemplateSpecifications() {\n\n\t\tList<AsyncResourceTemplateSpecification> resourceSpecs = this.resourceObjects.stream()\n\t\t\t.map(resourceObject -> Stream.of(doGetClassMethods(resourceObject))\n\t\t\t\t.filter(method -> method.isAnnotationPresent(McpResource.class))\n\t\t\t\t.filter(McpPredicates.filterNonReactiveReturnTypeMethod())\n\t\t\t\t.sorted((m1, m2) -> m1.getName().compareTo(m2.getName()))\n\t\t\t\t.map(mcpResourceMethod -> {\n\n\t\t\t\t\tvar resourceAnnotation = doGetMcpResourceAnnotation(mcpResourceMethod);\n\n\t\t\t\t\tvar uri = resourceAnnotation.uri();","sourceCodeStart":102,"sourceCodeEnd":138,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/resource/AsyncMcpResourceProvider.java#L102-L138","documentation":"AsyncMcpResourceProvider scans resourceObjects for @McpResource-annotated methods (resource reads) and converts them into resource specifications. If none are found it logs this warning naming the scanned objects; no exception is thrown and the server exposes no resources. The warning signals that registered resource objects produced zero resource methods, typically a configuration or annotation issue.","triggerScenarios":"getResourceSpecifications() finds no method annotated @McpResource in the supplied objects, or all candidates are filtered out (wrong sync/async style, methods inherited from a superclass, empty objects list).","commonSituations":"Resource beans registered before methods were implemented; using @McpResourceTemplate-only methods while expecting resource reads; sync handlers given to the async provider; annotations on interface methods.","solutions":["Annotate at least one method with @McpResource in the supplied objects with a signature matching the async provider's predicates","If you only have resource templates, ensure getResourceTemplateSpecifications is the intended path and register template methods with the correct annotation","Move annotated methods into the bean class itself","Remove resourceObjects registration when resources are intentionally absent"],"exampleFix":"// before\nnew AsyncMcpResourceProvider(List.of(new Resources())); // no @McpResource methods\n\n// after\nclass Resources {\n    @McpResource(uri = \"file:///docs/{id}\", name = \"doc\")\n    public ResourceSpec doc(String id) { ... }\n}\nnew AsyncMcpResourceProvider(List.of(new Resources()));","handlingStrategy":"validation","validationCode":"if (Arrays.stream(bean.getClass().getDeclaredMethods())\n        .noneMatch(m -> m.isAnnotationPresent(McpResource.class)\n            || m.isAnnotationPresent(McpResourceTemplate.class))) {\n    throw new IllegalStateException(\"No @McpResource/@McpResourceTemplate methods in \" + bean.getClass());\n}","typeGuard":"static boolean hasResourceMethods(Object bean) {\n    return Arrays.stream(bean.getClass().getDeclaredMethods())\n        .anyMatch(m -> m.isAnnotationPresent(McpResource.class));\n}","tryCatchPattern":null,"preventionTips":["Distinguish static resources (@McpResource) from URI templates (template annotation) and register each with the intended path","Keep resource methods on the concrete bean class","Verify resource specification counts at startup in tests"],"tags":["mcp","spring-ai","annotation-scanning","resource"],"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-14T05:17:10.506Z"}