Add accept_merge_request MCP server tool
What does this MR do and why?
Adds the accept_merge_request MCP server tool, closing the second Red Hat gap-analysis blocker: agents could not merge a merge request or arm auto-merge.
This is a standalone GraphQL tool wrapping the mergeRequestAccept mutation. Without a strategy argument the merge starts immediately (asynchronously); with a strategy argument, auto-merge is armed and the MR merges once its checks pass.
The standalone name is a deliberate exception to the get_/list_/save_/delete_ taxonomy used elsewhere in the MCP server: merging is a state transition backed by its own mutation with its own argument surface, not a resource CRUD operation. This naming rationale is pre-ratified in the tracking issue.
Closes #617968 (closed)
Design decisions
destructiveHint: true— merging is irreversible;save_pipelinealready carries the destructive hint for a lower-stakes operation. This tool is therefore never pre-approved.- Idempotency before guards — an already-merged MR returns success with status
already_merged(checked before the mutation even runs), and astrategycall against an already-scheduled MR returnsalready_scheduled. Retries by unattended agents never see misleading errors. An immediate-merge call against an MR with auto-merge already armed still errors, because that is a genuine conflict, not a retry. - Honest async statuses — a successful immediate merge reports
merging(the mutation completes the merge asynchronously, so the payload's MR state is stillopenedat return time); arming auto-merge reportsauto_merge_scheduled. - Enriched failure messaging —
AutoMergeServicereports strategy unavailability as a bare "The merge failed". When astrategywas requested, the tool appends the likely cause and the recovery path (omitstrategyto merge immediately instead). shais required and the tool refuses stale merges, surfacing the mutation's own "merge-head is not at the anticipated SHA" message. The tool description tells agents to source this fromdiff_head_shaonget_merge_request.strategyenum is derived, not hardcoded — it's built fromAutoMergeService.all_strategies_ordered_by_preference, so CE advertises onlymerge_when_checks_passwhile EE automatically adds the merge-train strategies. No list to keep in sync.
Verification
- New service + tool specs: 20 examples, 0 failures — covering immediate merge,
already_merged/already_scheduledidempotency, stale-sha refusal, draftNOT_MERGEABLEpassthrough, strategy-unavailable message enrichment, authorization, and input/schema validation. spec/requests/api/mcp/handlers/call_tool_spec.rbadds a:sidekiq_inlinerequest-level example that drives the full HTTP → tool → mutation →MergeWorkerpath and asserts the merge request actually reaches the merged state, plus a stale-sha refusal example at the same layer.- Both
list_toolsspec locks (destructive bucket) andspec/graphql/all_queries_spec.rb(validates the new.graphqlfile againstGitlabSchema) are green. RuboCop clean. - Verified end-to-end on GDK through MCP Inspector (OAuth, real nginx path), all eight scenarios:
GDK Inspector walkthrough (8/8)
| # | Scenario | Result |
|---|---|---|
| 1 | tools/list |
tool advertised with DESTRUCTIVE badge, sha required, strategy enum derived (3 EE values) |
| 2 | stale sha |
error The merge-head is not at the anticipated SHA |
| 3 | correct sha |
success status: "merging"; DB confirmed state=merged seconds later |
| 4 | accept again (any sha) | success status: "already_merged" — idempotency short-circuits before the sha guard |
| 5 | draft MR | error This branch cannot be merged |
| 6 | strategy when auto-merge unavailable |
enriched error The merge failed. The requested auto-merge strategy may not be available… Omit strategy to merge immediately. |
| 7 | strategy when already armed |
success status: "already_scheduled" with auto_merge_strategy echoed |
| 8 | immediate merge when already armed | error The merge request is already scheduled to be merged |
Immediate merge and DB confirmation:
Idempotent retry on a merged MR:
Enriched strategy-unavailable error:
Idempotent re-arm echoing the armed strategy:
The strategy-armed happy path (auto_merge_scheduled) was additionally exercised in a JSON-RPC round trip against a project with an in-progress pipeline (see comment thread). Along the way the authorization gate was validated for real: a user with only planner-level project access receives the uniform authorization error.



