{"record":{"id":"af6b8f3bc0fc9fc4","repo":"alibaba/spring-ai-alibaba","slug":"llm-may-have-adapted-the-tool-name-especiall","errorCode":null,"errorMessage":"LLM may have adapted the tool name '{}', especially if the name was truncated due to length limits. If this is the case, you can customize the prefixing and processing logic using McpToolNamePrefixGenerator","messagePattern":"LLM may have adapted the tool name '(.+?)', especially if the name was truncated due to length limits\\. If this is the case, you can customize the prefixing and processing logic using McpToolNamePrefixGenerator","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/DefaultBuilder.java","lineNumber":263,"sourceCode":"\t\t\t}\n\t\t}\n\t\t\n\t\tif (CollectionUtils.isNotEmpty(toolNames)) {\n\t\t\tfor (String toolName : toolNames) {\n\t\t\t\t// Skip the tool if it is already present in the request toolCallbacks.\n\t\t\t\t// That might happen if a tool is defined in the options\n\t\t\t\t// both as a ToolCallback and as a tool name.\n\t\t\t\tif (regularTools.stream().anyMatch(tool -> tool.getToolDefinition().name().equals(toolName))) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (this.resolver == null) {\n\t\t\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\t\t\"ToolCallbackResolver is null; cannot resolve tool name: \" + toolName);\n\t\t\t\t}\n\t\t\t\tToolCallback toolCallback = this.resolver.resolve(toolName);\n\t\t\t\tif (toolCallback == null) {\n\t\t\t\t\tlogger.warn(POSSIBLE_LLM_TOOL_NAME_CHANGE_WARNING, toolName);\n\t\t\t\t\tthrow new IllegalStateException(\"No ToolCallback found for tool name: \" + toolName);\n\t\t\t\t}\n\t\t\t\tregularTools.add(toolCallback);\n\t\t\t}\n\t\t}\n\t\t\n\t\t// If regularTools is empty and resolver is provided, try to extract tools from resolver\n\t\tif (regularTools.isEmpty() && this.resolver != null) {\n\t\t\t// Check if resolver also implements ToolCallbackProvider\n\t\t\tif (this.resolver instanceof ToolCallbackProvider provider) {\n\t\t\t\tToolCallback[] resolverTools = provider.getToolCallbacks();\n\t\t\t\tif (resolverTools != null && resolverTools.length > 0) {\n\t\t\t\t\tregularTools.addAll(List.of(resolverTools));\n\t\t\t\t\tif (logger.isDebugEnabled()) {\n\t\t\t\t\t\tlogger.debug(\"Extracted {} tools from ToolCallbackResolver (ToolCallbackProvider)\",\n\t\t\t\t\t\t\t\tresolverTools.length);\n\t\t\t\t\t}\n\t\t\t\t}","sourceCodeStart":245,"sourceCodeEnd":281,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/DefaultBuilder.java#L245-L281","documentation":"During local tool gathering, DefaultBuilder resolves each requested tool name through the configured ToolCallbackResolver. When resolve() returns null for a name, it logs this warning (suspecting the LLM altered a truncated/prefixed MCP tool name) and then throws IllegalStateException.","triggerScenarios":"AllTools/gatherLocalTools is given a tool name that no registered ToolCallback matches — typically because the LLM emitted an LLM-mangled MCP tool name (prefix stripped/changed or truncated by name-length limits) instead of the exact registered name.","commonSituations":"Long MCP tool names exceeding model limits; custom McpToolNamePrefixGenerator mismatching what the model echoes back; tool registered in a different agent/registry than the one being queried.","solutions":["Verify the exact registered tool name is used (log available tool names and compare)","Shorten tool names or configure a McpToolNamePrefixGenerator whose output the model faithfully reproduces","Ensure the ToolCallbackResolver is wired with the registry containing the tool (resolver was non-null, but resolved nothing)","Check that MCP server tool naming config hasn't changed between runs"],"exampleFix":"// before\nbuilder.tools(\"spring_ai_alibaba_mcp_very_long_tool_name_that_gets_truncat\");\n// after\nbuilder.tools(\"mcp_long_tool_name\"); // short registered name, within model name-length limits","handlingStrategy":"validation","validationCode":"Set<String> registered = resolver.getClass() != null ? availableToolNames() : Set.of();\nif (!registered.contains(toolName)) { throw new IllegalArgumentException(\"Unknown tool: \" + toolName + \"; available: \" + registered); }","typeGuard":"static boolean toolExists(ToolCallbackResolver r, String name) { try { return r.resolve(name) != null; } catch (Exception e) { return false; } }","tryCatchPattern":"try { builder.tools(names); } catch (IllegalStateException e) { log.error(\"Tool resolution failed: {}\", e.getMessage()); /* retry with corrected names or re-register tools */ }","preventionTips":["Keep MCP tool names short and stable; configure McpToolNamePrefixGenerator consistently","Log the set of registered tool names at startup and compare with what the LLM requests","Pin MCP server tool naming config to avoid silent renames between versions"],"tags":["mcp","tool-resolution","llm-tool-naming"],"backgroundTag":"resource-not-found","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}