forked from zereight/gitlab-mcp
-
Notifications
You must be signed in to change notification settings - Fork 1
refactor(files): CQRS consolidation - 5 tools → 2 tools #12
Copy link
Copy link
Labels
refactorCode restructuring without behavior changeCode restructuring without behavior change
Description
Summary
Consolidate 5 file tools into 2 CQRS-aligned tools for better MCP client compatibility and cleaner read/write separation.
Current State (5 tools)
| Tool | Type | Description |
|---|---|---|
get_repository_tree |
READ | List files/folders in repository |
get_file_contents |
READ | Get file content |
create_or_update_file |
WRITE | Single file commit |
push_files |
WRITE | Batch file commit |
upload_markdown |
WRITE | Upload attachment for markdown |
Target State (2 tools)
browse_files (Query)
Consolidates all READ operations:
{
action: "tree" | "content",
// Common
projectId: string,
ref?: string, // Branch, tag, or commit SHA
// For "tree" action
path?: string, // Directory path
recursive?: boolean,
per_page?: number,
page?: number,
// For "content" action
file_path: string // File path to read
}Read-only mode: Always allowed
manage_files (Command)
Consolidates all WRITE operations:
{
action: "single" | "batch" | "upload",
// Common
projectId: string,
// For "single" action (create_or_update_file)
file_path?: string,
content?: string, // Base64 encoded
commit_message?: string,
branch?: string,
start_branch?: string,
author_email?: string,
author_name?: string,
// For "batch" action (push_files)
files?: Array<{
file_path: string,
content?: string, // Base64 encoded (for create/update)
action: "create" | "update" | "delete" | "move",
previous_path?: string // For move action
}>,
// For "upload" action (upload_markdown)
file?: string, // Base64 encoded file
filename?: string
}Read-only mode: Blocked entirely
Implementation Tasks
- Create new
browse_fileshandler with action dispatch - Create new
manage_fileshandler with action dispatch - Update Zod schemas with discriminated union pattern
- Update registry to export new tool names
- Update read-only tools list (only
browse_files) - Remove old handlers after migration
- Update unit tests
- Update integration tests
Schema Pattern
const ManageFilesSchema = z.discriminatedUnion("action", [
z.object({
action: z.literal("single"),
projectId: z.string(),
file_path: z.string(),
content: z.string(), // Base64
commit_message: z.string(),
branch: z.string().optional(),
// ...
}),
z.object({
action: z.literal("batch"),
projectId: z.string(),
branch: z.string(),
commit_message: z.string(),
files: z.array(FileActionSchema),
}),
z.object({
action: z.literal("upload"),
projectId: z.string(),
file: z.string(), // Base64
filename: z.string(),
}),
]);Breaking Changes
| Old Tool | Migration Path |
|---|---|
get_repository_tree |
browse_files with action: "tree" |
get_file_contents |
browse_files with action: "content" |
create_or_update_file |
manage_files with action: "single" |
push_files |
manage_files with action: "batch" |
upload_markdown |
manage_files with action: "upload" |
Feature Flag
Existing USE_FILES flag continues to control entire files entity visibility.
Testing Requirements
- Unit tests for discriminated union schema validation
- Test tree listing with pagination
- Test file content retrieval
- Test single file create/update
- Test batch file operations
- Test markdown upload
- Test read-only mode blocks
manage_filesentirely - Integration tests for all operations
Acceptance Criteria
- Total tools reduced from 5 to 2
- All existing functionality preserved
- Base64 encoding/decoding works correctly
- Batch operations atomic (all-or-nothing)
- 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