Derive MCP pre-approved tools from readOnlyHint annotations
What does this MR do and why?
McpConfigService kept a hand-maintained GITLAB_PREAPPROVED_TOOLS constant, so a read-only MCP tool was only pre-approved if someone remembered to add it there. It had drifted: get_merge_request_conflicts and get_work_item_types are both readOnlyHint: true and both still prompted for approval.
This derives the list from each tool's own readOnlyHint annotation instead, and takes alias names from Mcp::Tools::Manager#alias_map rather than a second hardcoded constant. GITLAB_TOOL_ALIASES had drifted too — it listed gitlab_search but not gitlab_merge_request_search. The tool_access_policies claim now derives from the same list, minus alias-only names.
Why the claim had to be reworked, and how aliases are handled
Master built GITLAB_CLAIM_PREAPPROVED_TOOLS on top of GITLAB_PREAPPROVED_TOOLS, which this MR deletes. Git auto-merges that combination with no conflict marker into a class that raises NameError at load, so the claim had to be re-expressed rather than simply dropped. If it were dropped, no GitLab name would reach tool_access_policies and every tool would prompt again — the regression from #607151.
Aliases are deliberately handled differently on each side:
PreApprovedToolsincludes aliases. Workhorse matches on the name the client actually calls, and a client may call either name.- The claim excludes alias-only names. The MCP server serves canonical names only, so a
gitlab_-prefixed alias would match nothing.gitlab_searchstill appears in the claim, but from prefixing the canonicalsearchtool — not from the alias.
Deriving alias names from alias_map rather than a constant is what keeps those two consistent. With the stale constant, gitlab_merge_request_search would have leaked into the claim as gitlab_gitlab_merge_request_search.
The tool manager is memoized per request, not per process. Its tool list comes from sweeping API::API.routes, so a process-wide cache risks pinning a list built before Grape finished compiling — which would silently drop read-only tools back into prompting for the life of the process. That is observable in specs: without ::API::API.reset_routes!, semantic_code_search falls out of the derived list.
References
- Closes #596687 (closed)
- Related to #606029 — stored agent definitions still lose a tool referenced by an alias. That is the
& all_mcp_toolsintersection, which this MR does not change - Builds on !247872 (merged), which removed the duplicate list on the claim side but left
GITLAB_PREAPPROVED_TOOLShand-maintained
Screenshots or screen recordings
No UI changes.
How to set up and validate locally
-
In the Rails console, enable the feature flag and force a fresh EE-inclusive route compile. Without the reset, EE-only tools such as
semantic_code_searchare not yet registered and drop out of the derived list.Feature.enable(:mcp_client) ::API::API.reset_routes! service = Ai::DuoWorkflows::McpConfigService.new( User.first, 'fake-token', workflow_definition: 'chat' ) -
Confirm nothing that used to be pre-approved was lost. This should return
[]:previously_hardcoded = %w[ gitlab_search search semantic_code_search get_merge_request get_merge_request_commits get_merge_request_diffs get_merge_request_pipelines get_pipeline_jobs get_job_log get_issue get_workitem_notes get_merge_request_notes get_saved_view_work_items search_labels list_wiki_pages get_mcp_server_version ] previously_hardcoded - service.gitlab_enabled_tools -
Confirm the tools the old constant was missing are now pre-approved. Both should be
true:service.gitlab_enabled_tools.include?('get_merge_request_conflicts') service.gitlab_enabled_tools.include?('get_work_item_types') -
Confirm the claim still receives
gitlab_-prefixed names, and that no alias was double-prefixed. The first should be non-empty, the second[]:service.preapproved_tool_names service.preapproved_tool_names.grep(/gitlab_gitlab/) -
Confirm write tools stay out of pre-approval. Should be
false:service.gitlab_enabled_tools.include?('create_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.