spring-projects/spring-ai · warning

Tool name '<toolName>' already exists. Using unique tool nam

Error message

Tool name '<toolName>' already exists. Using unique tool name '<uniqueToolName>'

What it means

DefaultMcpToolNamePrefixGenerator.prefixedToolName() detected a tool name collision: after prefixing with connection info, the generated name was already used by another registered MCP tool. The generator appends an "alt_<counter>_" prefix to create a unique name and warns which original name was remapped, so callers referencing the old name will no longer resolve.

Source

Thrown at mcp/common/src/main/java/org/springframework/ai/mcp/DefaultMcpToolNamePrefixGenerator.java:73

	private final Set<ConnectionId> existingConnections = ConcurrentHashMap.newKeySet();

	private final Set<String> allUsedToolNames = ConcurrentHashMap.newKeySet();

	private final AtomicInteger counter = new AtomicInteger(1);

	@Override
	public String prefixedToolName(McpConnectionInfo mcpConnectionInfo, McpSchema.Tool tool) {

		String uniqueToolName = McpToolUtils.format(tool.name());

		if (this.existingConnections
			.add(new ConnectionId(mcpConnectionInfo.clientInfo(), (mcpConnectionInfo.initializeResult() != null)
					? mcpConnectionInfo.initializeResult().serverInfo() : null, tool))) {
			if (!this.allUsedToolNames.add(uniqueToolName)) {
				uniqueToolName = "alt_" + this.counter.getAndIncrement() + "_" + uniqueToolName;
				this.allUsedToolNames.add(uniqueToolName);
				if (logger.isWarnEnabled()) {
					logger.warn("Tool name '" + tool.name() + "' already exists. Using unique tool name '"
							+ uniqueToolName + "'");
				}
			}
		}

		return uniqueToolName;
	}

	private record ConnectionId(@Nullable Implementation clientInfo, @Nullable Implementation serverInfo, Tool tool) {
	}

}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Look up tools by the renamed unique name ('alt_<n>_<name>') reported in the warning when invoking them.
  2. Provide a custom ToolNamePrefixGenerator (or configure distinct connection ids) that yields stable, collision-free names.
  3. Rename tools on the conflicting MCP servers so their exposed names differ.
  4. Recreate the tool-name generator/registry when the set of MCP connections changes to keep mappings deterministic.

Example fix

// before: assuming prefixed name equals tool name
String name = prefixGenerator.prefixedToolName(connectionInfo, tool); // 'server1_search'
client.call(name, args); // may hit remapped tool
// after: keep the returned (possibly renamed) name
String name = prefixGenerator.prefixedToolName(connectionInfo, tool);
toolRegistry.put(name, tool); // always use the returned unique name
Defensive patterns

Strategy: validation

Validate before calling

Set<String> seen = new HashSet<>();
for (var conn : connections) {
    for (var tool : conn.listTools()) {
        String name = prefixGenerator.prefixedToolName(conn.info(), tool);
        if (!seen.add(name)) {
            logger.warn("collision on " + name + " — configure a custom prefix generator");
        }
    }
}

Type guard

boolean isRemapped(String expectedName, String actualName) {
    return actualName.startsWith("alt_") && !actualName.equals(expectedName);
}

Try / catch

// renamed tools won't throw; detect by absence
var tool = toolRegistry.get(name);
if (tool == null) {
    // name may have been remapped (alt_N_...); resolve from registry log/lookup
}

Prevention

When it happens

Trigger: Registering tools from multiple MCP connections/servers that expose identically named tools (e.g. two servers both exposing a 'search' tool) such that the prefix generator produces the same prefixed name twice within the same generator instance.

Common situations: Aggregating several MCP servers where tools share generic names; a server reconnecting/re-registering tools without a fresh name-prefix generator; similarly-named tools on the same server after prefix normalization.

Related errors


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