Use REST API for Semantic Code Search MCP tool (behind feature flag)

What does this MR do and why?

Introduces the mcp_semantic_code_search_use_rest_api feature flag (default: off) to control which implementation backs the semantic_code_search MCP tool:

  • Flag off (default): SemanticCodeSearchService handles tool calls, preserving existing MCP-specific behaviour including versioned responses and structured metadata.
  • Flag on: the REST endpoint's ApiTool (auto-discovered via route_setting :mcp) is used instead, enabling parity evaluation before the custom service is formally removed (!227818).

This allows a safe, incremental rollout with the ability to roll back instantly if parity issues are found.

Root cause fix: EE_CUSTOM_TOOLS previously used symbol keys while ApiTool discovery used string keys, causing both entries to coexist in the merged hash — the ApiTool always winning regardless of the flag state. Keys are now strings throughout.

Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/work_items/594555

MR chain

Repo MR Status Description
gitlab-org/gitlab !227816 (merged) merged Extract post-processing concern
gitlab-org/gitlab !227817 (merged) merged Add REST endpoint
gitlab-org/gitlab !229665 (merged) merged Add gPAT support (read_code permission)
gitlab-org/gitlab !228569 (merged) 🔄 open FF mcp_semantic_code_search_use_rest_api
gitlab-org/gitlab !227818 🔄 open Sunset SemanticCodeSearchService
gitlab-org/cli cli!3084 🔄 open Add glab search semantic CLI command
gitlab-org/editor-extensions/gitlab-lsp gitlab-org/editor-extensions/gitlab-lsp!3157 🔄 open Add gitlab_semantic_code_search to tool catalog
ai-assist gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!5174 🔄 open Add SemanticCodeSearch tool implementation

Epic: https://gitlab.com/groups/gitlab-org/-/epics/21285

How to test

!228569 (comment 3188441233)

Unit tests:

bundle exec rspec ee/spec/services/ee/mcp/tools/manager_spec.rb

Local GDK verification (both flag states):

# Flag OFF (default) — SemanticCodeSearchService
bin/rails runner "Feature.disable(:mcp_semantic_code_search_use_rest_api)"
curl -sk -o /dev/null -w "%{http_code}\n" \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gdk.test:3443/api/v4/projects/7/search/semantic?q=test"
curl -sk -D - \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gdk.test:3443/api/v4/projects/1000000/search/semantic?q=authentication"

# Flag ON — ApiTool
bin/rails runner "Feature.enable(:mcp_semantic_code_search_use_rest_api)"
curl -sk -o /dev/null -w "%{http_code}\n" \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gdk.test:3443/api/v4/projects/7/search/semantic?q=test"
curl -sk -D - \
  --header "PRIVATE-TOKEN: $TOKEN" \
  "https://gdk.test:3443/api/v4/projects/1000000/search/semantic?q=authentication"
Edited by Tian Gao

Merge request reports

Loading