MCP server returns 404 for ping and unhandled notifications such as notifications/cancelled
Summary
The main MCP endpoint, POST /api/v4/mcp, only routes four methods: initialize, notifications/initialized, tools/list and tools/call. Every other method falls through to method_not_found! in lib/api/mcp/base.rb, which answers HTTP 404 with JSON-RPC error -32601.
That includes two messages that compliant clients send during normal use:
ping, which the MCP spec defines as a request every server must answer with an empty result. See https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/pingnotifications/cancelled, and any other notification without a handler. The Streamable HTTP transport requires a server that accepts a notification to answer 202 Accepted with no body. See https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#sending-messages-to-the-server. The cancellation spec lets the receiver ignore it. See https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/cancellation
In the Streamable HTTP transport, a 404 means the session was terminated, so clients treat it as fatal.
Why this matters
The same fall-through on the Orbit endpoint made GitLab Duo CLI drop the server after its first tool approval, because the CLI sends notifications/cancelled. See #631580 (moved). That issue notes that lib/api/mcp/base.rb "probably behaves the same way" but could not verify it. This issue tracks the main endpoint. #628350 (closed) covers a related Orbit-only notification status bug.
Steps to reproduce
curl -s -w " -> HTTP %{http_code}\n" -X POST https://gitlab.com/api/v4/mcp \
-H "Authorization: Bearer $MCP_TOKEN" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}'
curl -s -w " -> HTTP %{http_code}\n" -X POST https://gitlab.com/api/v4/mcp \
-H "Authorization: Bearer $MCP_TOKEN" -H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"notifications/cancelled","params":{"requestId":1}}'Based on the code on master, both are expected to return -32601 Method not found with HTTP 404.
Proposed fix
- Add a
pinghandler that returns an empty result{}. - In
invoke_basic_handler, accept a message that has noid(a JSON-RPC notification) and no handler, returning 202 with an empty body through the existingformat_jsonrpc_responsepath, instead of callingmethod_not_found!. - Leave unknown requests (messages with an
id) unchanged in this fix. - Add request specs for
pingand for an unknown notification.
Acceptance criteria
-
pingreturns HTTP 200 withresult: {}and the requestid. -
notifications/cancelledand other unhandled notifications return HTTP 202 with an empty body. - Unknown requests with an
idstill return-32601.