Let API tools declare aliases via route settings
What does this MR do and why?
API-backed MCP tools could not declare aliases, so renaming one had no backward-compatible path. ApiTool is a single class shared by every API route, so a class-level tool_aliases would leak across all of them. This adds a per-instance ApiTool#tool_aliases sourced from the route's mcp settings, a matching instance-level reader on BaseService, and switches Manager#build_alias_map to read the instance method so all tool types resolve through one path.
Part of #606029 (closed) (MR B). Behavior-only for API tools; the existing class-based aliases (gitlab_search, gitlab_merge_request_search) are unchanged and keep resolving through the new delegator.
Update dev docs + tool builder skill
Implementation details
ApiTool#tool_aliasesreadssettings[:tool_aliases]and maps to strings, matching howtool_nameis.to_s'd indiscover_api_tools. Without this, a symbol alias would never match the string tool name passed toget_tool.BaseService#tool_aliasesdelegates to the existingself.tool_aliases, so custom, GraphQL, and aggregated tools are unaffected.Manager#build_alias_mapnow callstool.tool_aliasesinstead oftool.class.tool_aliases.list_toolsstays canonical-only — aliases are not added to it.tool_aliases:on a route that also setsaggregators:is dead config: that route's standaloneApiToolis never registered under its own name (discover_api_toolsskips aggregated routes), so its aliases are never read. Aggregated tools alias through the aggregator class'sself.tool_aliases. Documented in_index.md.
References
- Closes #606029 (closed) (MR B)
- Parent epic: &22414
Screenshots or screen recordings
No UI changes.
How to set up and validate locally
- In the Rails console, confirm the refactor preserves the existing class-based aliases:
mgr = Mcp::Tools::Manager.new mgr.alias_map # => includes "gitlab_search" => "search" mgr.get_tool(name: "gitlab_search").name # => "search" - Validate the new API-tool path. Add
tool_aliases: [:old_name]to anyroute_setting :mcpblock (for example onget_issue), reload, then:Revert the temporary route change afterward.mgr = Mcp::Tools::Manager.new mgr.alias_map # => includes "old_name" => "get_issue" mgr.get_tool(name: "old_name").name # => "get_issue"
MR acceptance checklist
Evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.