spring-projects/spring-ai · warning

No tool methods found in the provided tool objects: <toolObj

Error message

No tool methods found in the provided tool objects: <toolObjects>

What it means

AsyncMcpToolProvider.getToolSpecifications logs this warning when scanning the configured tool objects yields zero @McpTool-annotated methods, producing an empty tool specification list. The MCP server will expose no tools from this provider; the library flags it because a registered tool provider with no tools is almost always a wiring mistake.

Source

Thrown at mcp/mcp-annotations/src/main/java/org/springframework/ai/mcp/annotation/provider/tool/AsyncMcpToolProvider.java:161

									: ReturnMode.TEXT;

					BiFunction<McpAsyncServerExchange, CallToolRequest, Mono<CallToolResult>> methodCallback = new AsyncMcpToolMethodCallback(
							returnMode, mcpToolMethod, toolObject);

					AsyncToolSpecification toolSpec = AsyncToolSpecification.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. Verify each tool object has at least one public method annotated with @McpTool.
  2. Confirm the tool object list passed to AsyncMcpToolProvider is non-empty and contains the intended beans.
  3. Check method visibility and signatures match the scanner's requirements.
  4. Remove the tool provider if no tools are intended.

Example fix

// before
class Tools { public String weather(String city) { ... } } // no @McpTool
// after
class Tools { @McpTool(description = "Get weather") public String weather(@McpToolParam String city) { ... } }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-flight check for tool methods before creating AsyncMcpToolProvider:
long tools = Arrays.stream(toolObject.getClass().getDeclaredMethods())
    .filter(m -> m.isAnnotationPresent(McpTool.class) && Modifier.isPublic(m.getModifiers()))
    .count();
if (tools == 0) throw new IllegalStateException(toolObject + " exposes no @McpTool methods");

Prevention

When it happens

Trigger: Passing objects without any public @McpTool methods to AsyncMcpToolProvider, annotated methods filtered out (visibility/signature), or an empty toolObjects list — empty toolSpecs triggers the warn at AsyncMcpToolProvider.java:161.

Common situations: Tool class not registered with the provider; @McpTool annotation missing or wrong import; tool methods private; upgrade renamed annotation attributes causing scan mismatch.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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