spring-projects/spring-ai · warning
No tool methods found in the provided tool objects: + this.t
Error message
No tool methods found in the provided tool objects: + this.toolObjects
What it means
Same warning as the sync provider, logged by SyncStatelessMcpToolProvider.getToolSpecifications when reflection over the supplied tool objects produces no tool specifications. Because this is the stateless provider, each request will run with an empty tool set rather than failing fast.
Source
Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/tool/SyncStatelessMcpToolProvider.java:158
ReturnMode returnMode = useStructuredOtput ? ReturnMode.STRUCTURED
: (methodReturnType == Void.TYPE || methodReturnType == void.class ? ReturnMode.VOID
: ReturnMode.TEXT);
BiFunction<McpTransportContext, CallToolRequest, CallToolResult> methodCallback = new SyncStatelessMcpToolMethodCallback(
returnMode, mcpToolMethod, toolObject);
var toolSpec = SyncToolSpecification.builder().tool(tool).callHandler(methodCallback).build();
return toolSpec;
})
.toList())
.flatMap(List::stream)
.toList();
if (toolSpecs.isEmpty()) {
if (logger.isWarnEnabled()) {
logger.warn("No tool methods found in the provided tool objects: " + this.toolObjects);
}
}
return toolSpecs;
}
}
View on GitHub (pinned to 98a7beda4f)
Solutions
- Confirm every tool object exposes at least one @McpTool-annotated method
- Inspect the bean wiring (e.g. Spring config) feeding toolObjects to ensure real tool beans are injected
- Align mcp-annotations and spring-ai-mcp module versions
- Check annotation imports — @McpTool must come from org.springframework.ai.mcp.annotation, not a similarly named class
Example fix
// before
@Bean
SyncStatelessMcpToolProvider provider() {
return SyncStatelessMcpToolProvider.builder()
.toolObjects(new Object()) // no @McpTool methods
.build();
}
// after
@Bean
SyncStatelessMcpToolProvider provider(WeatherTools weatherTools) {
return SyncStatelessMcpToolProvider.builder()
.toolObjects(weatherTools) // class with @McpTool methods
.build();
} Defensive patterns
Strategy: validation
Validate before calling
// validate before wiring the stateless provider
if (toolObjects == null || toolObjects.length == 0)
throw new IllegalArgumentException("toolObjects must not be empty");
boolean anyTools = Arrays.stream(toolObjects)
.flatMap(o -> Arrays.stream(o.getClass().getDeclaredMethods()))
.anyMatch(m -> m.isAnnotationPresent(McpTool.class));
if (!anyTools) throw new IllegalStateException("No @McpTool methods in tool objects"); Prevention
- Keep tool classes dedicated and clearly annotated with @McpTool
- Add a unit test asserting getToolSpecifications().size() > 0
- Pin consistent versions of mcp-annotations and provider modules
- Review Spring config profiles that might swap in empty tool bean lists
When it happens
Trigger: Constructing SyncStatelessMcpToolProvider with objects lacking @McpTool-annotated methods; annotation scanning fails due to missing mcp-annotations metadata or wrong annotation import; toolObjects list is empty or contains unrelated beans.
Common situations: Stateless HTTP MCP deployments where tool beans are wired by configuration and a profile/config change drops the real tool beans; refactoring removed the @McpTool annotations; version mismatch between the annotation and provider modules.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- No tool methods found in the provided tool objects: + this.t
- Method cannot have more than one @McpProgressToken parameter
- Method cannot have more than one McpMeta parameter: {method.
- Method cannot have more than one request context parameter:
- Stateless Streamable-Http prompt method must not declare par
AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11).
Data as JSON: /api/errors/451c6b78e3e06e5e.
Report an issue: GitHub.