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

  1. Confirm every tool object exposes at least one @McpTool-annotated method
  2. Inspect the bean wiring (e.g. Spring config) feeding toolObjects to ensure real tool beans are injected
  3. Align mcp-annotations and spring-ai-mcp module versions
  4. 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

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


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/451c6b78e3e06e5e. Report an issue: GitHub.