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):
SemanticCodeSearchServicehandles tool calls, preserving existing MCP-specific behaviour including versioned responses and structured metadata. - Flag on: the REST endpoint's
ApiTool(auto-discovered viaroute_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) | Extract post-processing concern | |
| gitlab-org/gitlab | !227817 (merged) | Add REST endpoint | |
| gitlab-org/gitlab | !229665 (merged) | Add gPAT support (read_code permission) | |
| gitlab-org/gitlab | !228569 (merged) | FF mcp_semantic_code_search_use_rest_api | |
| gitlab-org/gitlab | !227818 | Sunset SemanticCodeSearchService | |
| gitlab-org/cli | cli!3084 | Add glab search semantic CLI command | |
| gitlab-org/editor-extensions/gitlab-lsp | gitlab-org/editor-extensions/gitlab-lsp!3157 | Add gitlab_semantic_code_search to tool catalog | |
| ai-assist | gitlab-org/modelops/applied-ml/code-suggestions/ai-assist!5174 | Add SemanticCodeSearch tool implementation |
Epic: https://gitlab.com/groups/gitlab-org/-/epics/21285
How to test
Unit tests:
bundle exec rspec ee/spec/services/ee/mcp/tools/manager_spec.rbLocal 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