Add save_merge_request MCP tool folding create and update

What does this MR do and why?

Adds save_merge_request, an aggregated REST-backed MCP server tool that combines the existing create and update merge request API endpoints into one tool. The presence of merge_request_iid selects the operation — absent creates, present updates. It follows the same aggregated-tool pattern as search and manage_pipeline. The previous create_merge_request tool name and new update_merge_request are kept as aliases, so existing MCP clients continue to resolve.

Closes #605880 (closed)

Design notes
  • The create route (POST /projects/:id/merge_requests) now joins the aggregator; a new route_setting :mcp is added to the update route (PUT /projects/:id/merge_requests/:merge_request_iid). Both carry aggregators: [SaveMergeRequestService].
  • REST was chosen over GraphQL because each REST endpoint is coarse-grained and accepts the full field set (labels, assignees, reviewers, milestone, squash, state transitions) in a single call. The GraphQL path would need multiple mutations and cannot set fields on a merge request it just created in one operation.
  • SaveMergeRequestService subclasses Base::AggregatedService and exposes its own tool_aliases, so no dependency on other in-flight alias work.
  • Argument-shape change under the aliases: the project argument is now project_id (ID or full path), not the old create_merge_request id. A cached or hardcoded caller still sending {id: ...} under the alias must switch to project_id; clients that re-fetch tools/list per session pick this up automatically.
  • A scoped spec asserts the tool's mcp param lists stay a subset of the params its two routes actually declare, guarding against silent schema drift. It is intentionally scoped to this tool's routes rather than all MCP tools, because a codebase-wide sweep surfaces pre-existing drift in the search and pipeline tools that is tracked separately in #607880 and #607881 (closed).

References

Screenshots or screen recordings

No UI changes.

How to set up and validate locally

  1. Restart Rails so the new tool registers: gdk restart rails-web (the tool registry is memoized at boot).
  2. Add GDK mcp server to your tool of choice
  3. Pick a project you have access to work in
  4. Ask the tool to update an existing merge request
  5. Have it create a new merge request

I ended up writing a script to test this out and here's the output from it:

script: $6034623

GDK_DIR=~/Developer/gdk/gitlab MODEL=sonnet PROJECT=top-level-public/top-project-public ANTHROPIC_API_KEY="$(op read 'op://Employee/ANTHROPIC_API_KEY/password')" bash /tmp/test-save-merge-request.sh
>> Minting a local-GDK PAT (api+mcp) — boots Rails, ~30-60s...
   minted PAT from GITLAB_DIR=/Users/terrichu/Developer/gdk/gitlab (length 57; a real PAT is ~26 chars)
>> Preflight OK. Project: top-level-public/top-project-public   target branch: main
>> Seeding ephemeral branches...

==================================================================
A. save_merge_request CREATE (username assignee + array labels)
   PASS A create returns success
   PASS A created MR !4
   PASS A state opened
   PASS A assignee root resolved from username

B. save_merge_request UPDATE (add_labels + state_event close/reopen)
   PASS B update+close returns success
   PASS B state closed
   PASS B reopened

C. create_merge_request ALIAS create (assignee_ids integer spelling)
   PASS C alias create returns success
   PASS C created MR !5 via create_merge_request alias

D. update_merge_request ALIAS update (title change)
   PASS D alias update returns success
   PASS D title updated

E. guard: state_event without merge_request_iid must NOT create
   PASS E refuses update-only fields on create

F. guard: assignees + assignee_ids together is rejected
   PASS F rejects both spellings

==================================================================
G. agentic smoke: does an agent pick save_merge_request for 'create an MR'?
   agent called: Skill,mcp__gdk__save_merge_request
   PASS G agent used save_merge_request

==================================================================
>> Cleanup...
   closed MR !4
   closed MR !5
   closed MR !6
   deleted branch mcp-mrtest-a-1787074293
   deleted branch mcp-mrtest-b-1787074293
   deleted branch mcp-mrtest-c-1787074293
   revoked test PAT

==================================================================
RESULT: 14 passed, 0 failed

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.

Edited by Terri Chu

Merge request reports

Loading
Loading