Sunset SemanticCodeSearchService; serve MCP via REST ApiTool

Summary

Sunsets Mcp::Tools::SemanticCodeSearchService and replaces it with an auto-generated MCP tool backed by the REST API endpoint (added in !227817 (merged)).

Changes:

  • Adds route_setting :mcp to GET /projects/278964/search/semantic — auto-registers it as an MCP tool via ApiTool, the same mechanism used by get_issue, get_merge_request, gitlab_search_in_project, etc.
  • Deletes ee/app/services/mcp/tools/semantic_code_search_service.rb
  • Clears EE_CUSTOM_TOOLS in ee/app/services/ee/mcp/tools/manager.rb

Closes https://gitlab.com/gitlab-org/gitlab/-/work_items/593917 https://gitlab.com/gitlab-org/gitlab/-/work_items/593918

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) merged 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

MCP call and response: before and after

Both before and after, the MCP client calls POST /api/v4/mcp with an OAuth token (mcp scope):

curl -X POST https://gitlab.example.com/api/v4/mcp \
  -H "Authorization: Bearer <oauth_token_with_mcp_scope>" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "id": "1",
    "params": {
      "name": "semantic_code_search",
      "arguments": {
        "id": "mygroup/myproject",
        "q": "rate limiting middleware",
        "limit": 5
      }
    }
  }'

Before (SemanticCodeSearchService): Formatted text string for LLM in content[0].text.

After (ApiTool): Raw REST JSON body as string in content[0].text.

How to test

Verify MCP tool routes to ApiTool:

manager = Mcp::Tools::Manager.new
tool = manager.get_tool(name: 'semantic_code_search')
tool.class # => Mcp::Tools::ApiTool

Unit tests:

bundle exec rspec ee/spec/services/ee/mcp/tools/manager_spec.rb
bundle exec rspec ee/spec/requests/api/mcp/handlers/list_tools_spec.rb
Edited by Tian Gao

Merge request reports

Loading