Negotiate a handshake version in MCP initialize
What does this MR do and why?
The initialize handshake accepted 2026-07-28 and echoed it back. That revision removes the initialize handshake and replaces it with per-request metadata, a server/discover method, and new headers that GitLab does not implement. So the server claimed a protocol it does not speak.
This MR keeps 2026-07-28 in the accepted list, so clients like Cursor still connect, but answers with 2025-11-25, the newest revision the server implements. Other handshake versions still get their own value back. The MCP Go SDK made the same fix for the same reason.
| Requested version | Before | After |
|---|---|---|
2026-07-28 |
2026-07-28 |
2025-11-25 |
2025-11-25 |
2025-11-25 |
2025-11-25 |
2025-06-18 |
2025-06-18 |
2025-06-18 |
These are the protocolVersion field of the initialize result. I measured them on master and on this branch, against both /api/v4/mcp and /api/v4/orbit/mcp.
References
- Related issue: #611372 (closed)
- Commit that added
2026-07-28: 79115f79 - Version negotiation rules: https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle
- Backward compatibility in 2026-07-28: https://modelcontextprotocol.io/specification/2026-07-28/basic/versioning
- Changelog for 2026-07-28: https://modelcontextprotocol.io/specification/2026-07-28/changelog
- Same change in the MCP Go SDK: https://github.com/modelcontextprotocol/go-sdk/pull/1051
Screenshots or screen recordings
Not applicable. This changes a JSON-RPC API response.
How to set up and validate locally
-
Enable the MCP server. In the Rails console run
ApplicationSetting.current.update!(mcp_server_enabled: true). -
Send an
initializerequest that asks for2026-07-28and confirm the answer is2025-11-25.curl --request POST --header "Authorization: Bearer $TOKEN" \ --header "Content-Type: application/json" \ --data '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2026-07-28"}}' \ http://gdk.test:3000/api/v4/mcp -
Repeat with
"protocolVersion":"2025-06-18"and confirm the answer is2025-06-18. -
Run the specs.
bundle exec rspec spec/requests/api/mcp/handlers/initialize_request_spec.rb \ ee/spec/lib/api/orbit/mcp_handlers/initialize_request_spec.rb \ ee/spec/requests/api/orbit/mcp_spec.rb \ ee/spec/requests/api/mcp/base_spec.rb
I ran these specs locally: 85 examples, 0 failures. Steps 2 and 3 ran against both endpoints through the full request stack.
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.