forked from zereight/gitlab-mcp
-
Notifications
You must be signed in to change notification settings - Fork 1
refactor(workitems): CQRS consolidation - 5 tools → 2 tools #11
Copy link
Copy link
Closed
Labels
refactorCode restructuring without behavior changeCode restructuring without behavior change
Description
Summary
Consolidate 5 work items tools into 2 CQRS-aligned tools for better MCP client compatibility and cleaner read/write separation.
Current State (5 tools)
| Tool | Type | Description |
|---|---|---|
list_work_items |
READ | List work items with filtering |
get_work_item |
READ | Get single work item with all widgets |
create_work_item |
WRITE | Create new work item |
update_work_item |
WRITE | Modify work item properties/widgets |
delete_work_item |
WRITE | Remove work item |
Target State (2 tools)
browse_work_items (Query)
Consolidates all READ operations:
{
action: "list" | "get",
// Common
namespacePath: string, // Group or project path
// For "list" action
types?: WorkItemTypeEnum[], // EPIC, ISSUE, TASK, etc.
state?: "opened" | "closed" | "all",
search?: string,
authorUsername?: string,
assigneeUsernames?: string[],
labelNames?: string[],
milestoneTitle?: string,
iids?: string[],
sort?: string,
first?: number,
after?: string,
// For "get" action
id: string, // Work item global ID or IID
iid?: string // Alternative: use IID with namespacePath
}Read-only mode: Always allowed
manage_work_item (Command)
Consolidates all WRITE operations:
{
action: "create" | "update" | "delete",
// Common
namespacePath: string,
// For "update" and "delete"
id?: string, // Work item ID
// For "create"
workItemType?: WorkItemTypeEnum,
// For "create" and "update" - core fields
title?: string,
confidential?: boolean,
// Widget updates
descriptionWidget?: { description: string },
assigneesWidget?: { assigneeIds: string[] },
labelsWidget?: {
addLabelIds?: string[],
removeLabelIds?: string[]
},
milestoneWidget?: { milestoneId: string | null },
startAndDueDateWidget?: {
startDate?: string,
dueDate?: string
},
hierarchyWidget?: {
parentId?: string | null,
childrenIds?: string[]
},
// State change
stateEvent?: "CLOSE" | "REOPEN"
}Read-only mode: Blocked entirely
Implementation Tasks
- Create new
browse_work_itemshandler with action dispatch - Create new
manage_work_itemhandler with action dispatch - Update Zod schemas with discriminated union pattern
- Preserve GraphQL-based implementation for work items
- Handle dynamic work item type discovery
- Update registry to export new tool names
- Update read-only tools list (only
browse_work_items) - Remove old handlers after migration
- Update unit tests
- Update integration tests
Schema Pattern
const BrowseWorkItemsSchema = z.discriminatedUnion("action", [
z.object({
action: z.literal("list"),
namespacePath: z.string(),
types: z.array(WorkItemTypeEnumSchema).optional(),
state: z.enum(["opened", "closed", "all"]).optional(),
// ... list-specific params
}),
z.object({
action: z.literal("get"),
namespacePath: z.string(),
id: z.string().optional(),
iid: z.string().optional(),
}).refine(
(data) => data.id || data.iid,
{ message: "Either id or iid is required" }
),
]);Breaking Changes
| Old Tool | Migration Path |
|---|---|
list_work_items |
browse_work_items with action: "list" |
get_work_item |
browse_work_items with action: "get" |
create_work_item |
manage_work_item with action: "create" |
update_work_item |
manage_work_item with action: "update" |
delete_work_item |
manage_work_item with action: "delete" |
GraphQL Considerations
Work Items use GraphQL API exclusively. The refactored tools must:
- Preserve dynamic widget inclusion based on tier
- Maintain work item type discovery
- Handle GROUP vs PROJECT level restrictions (Epics vs Issues)
- Support all 26 widget types
Feature Flag
Existing USE_WORKITEMS flag continues to control entire work items entity visibility.
Testing Requirements
- Unit tests for discriminated union schema validation
- Test all work item types (Epic, Issue, Task, etc.)
- Test widget operations (assignees, labels, milestones)
- Test hierarchy operations (parent/child)
- Test read-only mode blocks
manage_work_itementirely - Integration tests against real GitLab instance
Acceptance Criteria
- Total tools reduced from 5 to 2
- All existing functionality preserved
- All work item types supported
- All widgets properly handled
- GROUP/PROJECT level restrictions respected
- Read-only mode correctly gates write operations
- Clear error messages for invalid action/parameter combinations
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
refactorCode restructuring without behavior changeCode restructuring without behavior change