{"record":{"id":"0c7aa42c7af0f68a","repo":"spring-projects/spring-ai","slug":"no-resource-methods-found-in-the-provided-resource-0c7aa4","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":"warning","filePath":"mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/resource/AsyncStatelessMcpResourceProvider.java","lineNumber":120,"sourceCode":"\t\t\t\t\tBiFunction<McpTransportContext, ReadResourceRequest, Mono<ReadResourceResult>> methodCallback = AsyncStatelessMcpResourceMethodCallback\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/AsyncStatelessMcpResourceProvider.java#L102-L138","documentation":"This is a warning logged by AsyncStatelessMcpResourceProvider.getResourceSpecifications when annotation scanning of the configured resource objects produced zero MCP resource specifications. The library did not fail: it logs this because a provider was constructed with @McpResource-annotated expectation but no methods matched, so the server will expose no resources. It almost always indicates misconfigured resource objects or missing/wrong annotations.","triggerScenarios":"Constructing AsyncStatelessMcpResourceProvider with resource objects that contain no methods annotated with @McpResource, or whose annotated methods are non-public/wrong signature so the reflection scan filters them out, or passing an empty resource objects list; the empty resourceSpecs list triggers the warn at AsyncStatelessMcpResourceProvider.java:120.","commonSituations":"Forgeting @McpResource on handler methods; annotating private/package-private methods; passing the wrong bean to the provider builder; Spring component scanning not picking up the resource class; a refactoring/upgrade renamed or moved the annotation so old imports no longer match.","solutions":["Verify each resource object has at least one public method annotated with @McpResource (with correct uri/description attributes).","Confirm the classes passed to the provider builder are the ones actually holding the annotated methods, and that the list is non-empty.","Check method visibility and signatures match what the annotation scanner requires (public, correct parameter types).","If the resource provider is intentionally empty, remove it or silence the warning rather than shipping a no-op provider."],"exampleFix":"// before\nnew AsyncStatelessMcpResourceProvider(List.of(new MyResources())); // MyResources has no @McpResource methods\n// after\npublic class MyResources {\n    @McpResource(uri = \"file:///docs/{name}\", description = \"Docs\")\n    public String getDoc(String name) { return \"...\"; }\n}","handlingStrategy":"validation","validationCode":"// Before registering the provider, assert the scan would find resources:\nlong resourceMethods = Arrays.stream(myResourceObject.getClass().getDeclaredMethods())\n    .filter(m -> m.isAnnotationPresent(McpResource.class) && Modifier.isPublic(m.getModifiers()))\n    .count();\nif (resourceMethods == 0) throw new IllegalStateException(myResourceObject + \" has no public @McpResource methods\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Unit-test each resource object for at least one public @McpResource method before wiring the provider.","Always register the exact bean instances holding the annotated methods.","Grep the codebase for @McpResource after refactors to ensure annotations survived.","Watch startup logs for this warning in CI so empty providers fail the build."],"tags":["mcp","annotation-scanning","resources","empty-specifications"],"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"}