forked from zereight/gitlab-mcp
-
Notifications
You must be signed in to change notification settings - Fork 1
refactor(mrs): CQRS consolidation - 20 tools → 5 tools #15
Copy link
Copy link
Closed
Labels
refactorCode restructuring without behavior changeCode restructuring without behavior change
Description
Summary
Consolidate 20 merge request tools into 5 CQRS-aligned tools for better MCP client compatibility and cleaner read/write separation. This is the largest refactoring effort.
Current State (20 tools)
READ Operations (8 tools)
| Tool | Description |
|---|---|
list_merge_requests |
List MRs with filtering |
get_merge_request |
Get MR details |
get_merge_request_diffs |
Get MR file changes |
list_merge_request_diffs |
Paginated diff list |
get_branch_diffs |
Compare branches |
mr_discussions |
List discussions |
list_draft_notes |
List draft comments |
get_draft_note |
Get single draft |
WRITE Operations (12 tools)
| Tool | Description |
|---|---|
create_merge_request |
Create new MR |
update_merge_request |
Modify MR properties |
merge_merge_request |
Merge MR |
create_note |
Add comment |
create_merge_request_thread |
Start discussion |
create_merge_request_note |
Reply to thread |
update_merge_request_note |
Edit comment |
create_draft_note |
Create draft comment |
update_draft_note |
Edit draft |
publish_draft_note |
Publish single draft |
bulk_publish_draft_notes |
Publish all drafts |
delete_draft_note |
Delete draft |
Target State (5 tools)
browse_merge_requests (Query)
Consolidates MR reading and diff operations:
{
action: "list" | "get" | "diffs" | "compare",
projectId: string,
// For "list" action
state?: "opened" | "closed" | "merged" | "all",
scope?: "created_by_me" | "assigned_to_me" | "all",
author_id?: number,
assignee_id?: number,
reviewer_id?: number,
labels?: string,
milestone?: string,
search?: string,
source_branch?: string,
target_branch?: string,
wip?: "yes" | "no",
order_by?: "created_at" | "updated_at",
sort?: "asc" | "desc",
// For "get", "diffs"
mergeRequestIid?: number,
sourceBranch?: string, // Alternative to IID
// For "compare"
from?: string, // Base ref
to?: string, // Head ref
straight?: boolean,
// Pagination
per_page?: number,
page?: number
}browse_mr_discussions (Query)
Consolidates discussion and draft reading:
{
action: "discussions" | "drafts" | "draft",
projectId: string,
mergeRequestIid: number,
// For "draft" action
draftNoteId?: number,
// Pagination
per_page?: number,
page?: number
}manage_merge_request (Command)
Core MR lifecycle operations:
{
action: "create" | "update" | "merge",
projectId: string,
// For "update" and "merge"
mergeRequestIid?: number,
sourceBranch?: string, // Alternative to IID
// For "create"
source_branch?: string,
target_branch?: string,
// For "create" and "update"
title?: string,
description?: string,
assignee_ids?: number[],
reviewer_ids?: number[],
labels?: string,
milestone_id?: number,
remove_source_branch?: boolean,
squash?: boolean,
draft?: boolean,
// For "merge"
merge_commit_message?: string,
squash_commit_message?: string,
should_remove_source_branch?: boolean,
merge_when_pipeline_succeeds?: boolean,
sha?: string
}manage_mr_discussion (Command)
Discussion/comment operations:
{
action: "comment" | "thread" | "reply" | "update",
projectId: string,
mergeRequestIid: number,
// For "comment" - simple comment
body?: string,
// For "thread" - start new discussion
position?: {
base_sha: string,
start_sha: string,
head_sha: string,
position_type: "text" | "image",
old_path?: string,
new_path?: string,
old_line?: number,
new_line?: number
},
// For "reply"
discussionId?: string,
// For "update"
noteId?: number
}manage_draft_notes (Command)
Draft note operations:
{
action: "create" | "update" | "publish" | "publish_all" | "delete",
projectId: string,
mergeRequestIid: number,
// For "update", "publish", "delete"
draftNoteId?: number,
// For "create" and "update"
note?: string,
position?: {
base_sha: string,
start_sha: string,
head_sha: string,
position_type: "text",
old_path?: string,
new_path?: string,
old_line?: number,
new_line?: number
},
// For "create"
in_reply_to_discussion_id?: string,
resolve_discussion?: boolean
}Tool Breakdown
| Category | Tools | Operations |
|---|---|---|
| Query | 2 | list, get, diffs, compare, discussions, drafts |
| Command | 3 | create, update, merge, comment, reply, draft mgmt |
| Total | 5 | All 20 original operations preserved |
Implementation Tasks
- Create new
browse_merge_requestshandler - Create new
browse_mr_discussionshandler - Create new
manage_merge_requesthandler - Create new
manage_mr_discussionhandler - Create new
manage_draft_noteshandler - Update Zod schemas with discriminated unions
- Update registry to export new tool names
- Update read-only tools list (browse_* tools only)
- Remove old handlers after migration
- Update unit tests
- Update integration tests
Breaking Changes
| Old Tool | Migration Path |
|---|---|
list_merge_requests |
browse_merge_requests action: "list" |
get_merge_request |
browse_merge_requests action: "get" |
get_merge_request_diffs |
browse_merge_requests action: "diffs" |
list_merge_request_diffs |
browse_merge_requests action: "diffs" |
get_branch_diffs |
browse_merge_requests action: "compare" |
mr_discussions |
browse_mr_discussions action: "discussions" |
list_draft_notes |
browse_mr_discussions action: "drafts" |
get_draft_note |
browse_mr_discussions action: "draft" |
create_merge_request |
manage_merge_request action: "create" |
update_merge_request |
manage_merge_request action: "update" |
merge_merge_request |
manage_merge_request action: "merge" |
create_note |
manage_mr_discussion action: "comment" |
create_merge_request_thread |
manage_mr_discussion action: "thread" |
create_merge_request_note |
manage_mr_discussion action: "reply" |
update_merge_request_note |
manage_mr_discussion action: "update" |
create_draft_note |
manage_draft_notes action: "create" |
update_draft_note |
manage_draft_notes action: "update" |
publish_draft_note |
manage_draft_notes action: "publish" |
bulk_publish_draft_notes |
manage_draft_notes action: "publish_all" |
delete_draft_note |
manage_draft_notes action: "delete" |
Read-Only Mode
| Tool | Read-Only |
|---|---|
browse_merge_requests |
Allowed |
browse_mr_discussions |
Allowed |
manage_merge_request |
Blocked |
manage_mr_discussion |
Blocked |
manage_draft_notes |
Blocked |
Feature Flag
Existing USE_MRS flag continues to control entire MRs entity visibility.
Testing Requirements
- Unit tests for all discriminated union schemas
- Test MR listing with various filters
- Test diff retrieval (by IID and by branch)
- Test branch comparison
- Test discussion listing
- Test MR create/update/merge lifecycle
- Test comment/thread/reply operations
- Test draft note lifecycle
- Test read-only mode blocks all command tools
- Integration tests for all operations
Acceptance Criteria
- Total tools reduced from 20 to 5
- All existing functionality preserved
- MR identification by IID or source branch
- Draft note workflow fully supported
- Position-based comments work for code review
- Read-only mode correctly gates write operations
- Clear error messages for invalid combinations
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
refactorCode restructuring without behavior changeCode restructuring without behavior change