{"record":{"id":"534e2a82b0ac0f21","repo":"spring-projects/spring-ai","slug":"no-resource-methods-found-in-the-provided-resource-534e2a","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/SyncStatelessMcpResourceProvider.java","lineNumber":119,"sourceCode":"\t\t\t\t\tBiFunction<McpTransportContext, ReadResourceRequest, ReadResourceResult> methodCallback = SyncStatelessMcpResourceMethodCallback\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 SyncResourceSpecification(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<SyncResourceTemplateSpecification> getResourceTemplateSpecifications() {\n\n\t\tList<SyncResourceTemplateSpecification> 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.filterReactiveReturnTypeMethod())\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":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/resource/SyncStatelessMcpResourceProvider.java#L101-L137","documentation":"SyncStatelessMcpResourceProvider.getResourceSpecifications logs this warning when annotation scanning of the supplied resource objects finds no @McpResource-annotated methods, producing an empty resource specification list. The server will advertise zero resources; the library treats a fully empty provider as a likely configuration mistake worth surfacing.","triggerScenarios":"Passing resource objects without any public @McpResource methods to SyncStatelessMcpResourceProvider, methods annotated but not visible/signature-incompatible to the scanner, or an empty resource objects list — empty resourceSpecs triggers the warn at SyncStatelessMcpResourceProvider.java:119.","commonSituations":"Missing @McpResource annotation after a copy-paste; wrong bean wired into the provider; annotation on a non-public method; package rename broke the annotation import (e.g. importing a similarly named annotation from another library).","solutions":["Add or fix @McpResource annotations on public methods inside the resource objects given to the provider.","Verify the object list passed to the SyncStatelessMcpResourceProvider constructor is non-empty and contains the annotated classes.","Check the annotation import resolves to org.springframework.ai.mcp annotation, not a different one.","If intentional, drop the provider registration to avoid a no-op resource provider."],"exampleFix":"// before\nclass DocResources { public String read(String id) { ... } } // no annotation\n// after\nclass DocResources { @McpResource(uri = \"doc://{id}\") public String read(String id) { ... } }","handlingStrategy":"validation","validationCode":"// Guard before constructing the sync provider:\nList<Object> annotated = resourceObjects.stream()\n    .filter(o -> Arrays.stream(o.getClass().getDeclaredMethods())\n        .anyMatch(m -> m.isAnnotationPresent(McpResource.class)))\n    .toList();\nif (annotated.isEmpty()) throw new IllegalArgumentException(\"No resource objects with @McpResource methods\");","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Verify the annotation import is org.springframework.ai.mcp.annotation.McpResource, not a same-named class.","Keep resource methods public.","Add a smoke test that builds the provider and asserts non-empty specifications.","Register only beans that actually own annotated methods."],"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"}