Skip to content

refactor(mrs): CQRS consolidation - 20 tools → 5 tools #15

@polaz

Description

@polaz

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_requests handler
  • Create new browse_mr_discussions handler
  • Create new manage_merge_request handler
  • Create new manage_mr_discussion handler
  • Create new manage_draft_notes handler
  • 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorCode restructuring without behavior change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions