Draft: Share JSON-RPC request handling between MCP endpoints
What this does
This merge request extracts shared JSON-RPC handling logic from two GitLab MCP server endpoints. The CE endpoint in lib/api/mcp/base.rb and the EE Orbit endpoint in ee/lib/api/orbit/mcp.rb each had duplicate copies of the same JSON-RPC code. This refactor moves the shared parts into the module at lib/api/helpers/mcp/json_rpc.rb. There is no behaviour change, and no spec assertion needed a change.
This is merge request 1 of 5 planned merge requests for issue #627825. It targets branch 611372-mcp-error-response-request-id, which belongs to a separate merge request, !253329 (merged), that creates the shared module file.
The extracted code is:
- the JSON-RPC version constant
JSONRPC_VERSION - the error table
JSONRPC_ERRORS method_not_found!format_jsonrpc_response
Notable decisions
- The dead
version_mismatcherror entry with code-32001was removed. Nothing in the codebase called it. An unsupported protocol version raisesArgumentError, which the endpoints answer with-32602. The MCP spec from 2026-07-28 marks the-32000to-32019range as legacy and tells new implementations to stay out of it. - The
-32603internal error code stays only inee/lib/api/orbit/mcp.rb, because only that endpoint raises it. The file merges this one extra entry onto the shared error table. - The
-32700parse error is still absent on purpose. Workhorse answers with HTTP 400 before a parse error reaches this code. - The two endpoints answer JSON-RPC notifications differently. The CE endpoint returns HTTP 202 Accepted with an empty body. The EE Orbit endpoint returns HTTP 204. Specs pin both, so the difference is preserved through a small overridable method,
jsonrpc_notification_response, which the EE endpoint overrides. - Both endpoints use
includeto bring in the shared constants andhelpersto bring in the shared methods. Grapehelpersonly shares methods, not constants, and the class bodies need the constants in theirparamsandrescue_fromblocks.
How to test locally
bundle exec rspec spec/requests/api/mcp/ spec/lib/api/helpers/mcp/json_rpc_spec.rbresult: 174 examples, 0 failures, 4 pending
bundle exec rspec ee/spec/requests/api/orbit/mcp_spec.rbresult: 78 examples, 0 failures, 4 pending
bundle exec rubocop lib/api/helpers/mcp/json_rpc.rb lib/api/mcp/base.rb ee/lib/api/orbit/mcp.rbresult: 3 files inspected, no offenses detected
The 4 pending examples in each rspec run are pre-existing skips in a shared granular token example group. They are not related to this change.
Closes #628249 Related to #627825