create_merge_request
Create a new merge request in a GitLab project to propose code changes from one branch to another, requiring user authentication with write permissions.
Instructions
Create a new merge request in a GitLab project (requires user authentication with write permissions)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectPath | Yes | Full path of the project (e.g., "group/project-name") | |
| title | Yes | Title of the merge request | |
| sourceBranch | Yes | Source branch name | |
| targetBranch | Yes | Target branch name | |
| description | No | Description of the merge request | |
| userCredentials | No | Your GitLab credentials (optional - uses shared token if not provided) |
Implementation Reference
- src/tools.ts:200-237 (registration)Tool registration and schema definition for create_merge_request. Defines the tool interface with name, title, description, authentication requirements, input schema (projectPath, title, sourceBranch, targetBranch, description), and the handler function.
const createMergeRequestTool: Tool = { name: 'create_merge_request', title: 'Create Merge Request', description: 'Create a new merge request in a GitLab project (requires user authentication with write permissions)', requiresAuth: true, requiresWrite: true, annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, }, inputSchema: withUserAuth(z.object({ projectPath: z.string().describe('Full path of the project (e.g., "group/project-name")'), title: z.string().min(1).describe('Title of the merge request'), sourceBranch: z.string().min(1).describe('Source branch name'), targetBranch: z.string().min(1).describe('Target branch name'), description: z.string().optional().describe('Description of the merge request'), })), handler: async (input, client, userConfig) => { const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig; if (!credentials) { throw new Error('User authentication is required for creating merge requests. Please provide your GitLab credentials.'); } const result = await client.createMergeRequest( input.projectPath, input.title, input.sourceBranch, input.targetBranch, input.description, credentials ); const payload = result.createMergeRequest; if (payload.errors && payload.errors.length > 0) { throw new Error(`Failed to create merge request: ${payload.errors.join(', ')}`); } return payload.mergeRequest; }, }; - src/tools.ts:218-236 (handler)Tool handler that validates user credentials and delegates to the GitLab client's createMergeRequest method. Extracts user credentials, checks for authentication requirement, calls the client method, handles errors, and returns the created merge request.
handler: async (input, client, userConfig) => { const credentials = input.userCredentials ? validateUserConfig(input.userCredentials) : userConfig; if (!credentials) { throw new Error('User authentication is required for creating merge requests. Please provide your GitLab credentials.'); } const result = await client.createMergeRequest( input.projectPath, input.title, input.sourceBranch, input.targetBranch, input.description, credentials ); const payload = result.createMergeRequest; if (payload.errors && payload.errors.length > 0) { throw new Error(`Failed to create merge request: ${payload.errors.join(', ')}`); } return payload.mergeRequest; }, - src/gitlab-client.ts:471-526 (handler)Core implementation of createMergeRequest in GitLabGraphQLClient. Introspects GitLab schema to determine available mutation types (createMergeRequest or mergeRequestCreate), builds appropriate GraphQL mutation with schema-aware input types, executes the mutation, and returns the created merge request with error handling.
async createMergeRequest( projectPath: string, title: string, sourceBranch: string, targetBranch: string, description?: string, userConfig?: UserConfig ): Promise<any> { await this.introspectSchema(userConfig); const mutationType = this.schema?.getMutationType(); const fields = mutationType ? mutationType.getFields() : {}; const fieldName = fields['createMergeRequest'] ? 'createMergeRequest' : (fields['mergeRequestCreate'] ? 'mergeRequestCreate' : null); if (!fieldName) { throw new Error('Neither createMergeRequest nor mergeRequestCreate mutation is available on this GitLab instance'); } const hasCreateInput = !!this.schema.getType('CreateMergeRequestInput'); const hasLegacyInput = !!this.schema.getType('MergeRequestCreateInput'); const inputType = hasCreateInput ? 'CreateMergeRequestInput' : (hasLegacyInput ? 'MergeRequestCreateInput' : null); if (!inputType) { throw new Error('Neither CreateMergeRequestInput nor MergeRequestCreateInput input type is available on this GitLab instance'); } const mutation = gql` mutation createMergeRequest($input: ${inputType}!) { ${fieldName}(input: $input) { mergeRequest { id iid title description webUrl state sourceBranch targetBranch createdAt } errors } } `; const input = { projectPath, title, sourceBranch, targetBranch, description, }; const result = await this.query(mutation, { input }, userConfig, true); // Normalize payload to { createMergeRequest: ... } const payload = (result as any)[fieldName]; return { createMergeRequest: payload }; } - src/gitlab-client.ts:479-493 (schema)Schema introspection logic for createMergeRequest. Dynamically checks GitLab instance for available mutation names (createMergeRequest vs mergeRequestCreate) and input types (CreateMergeRequestInput vs MergeRequestCreateInput) to support different GitLab versions.
await this.introspectSchema(userConfig); const mutationType = this.schema?.getMutationType(); const fields = mutationType ? mutationType.getFields() : {}; const fieldName = fields['createMergeRequest'] ? 'createMergeRequest' : (fields['mergeRequestCreate'] ? 'mergeRequestCreate' : null); if (!fieldName) { throw new Error('Neither createMergeRequest nor mergeRequestCreate mutation is available on this GitLab instance'); } const hasCreateInput = !!this.schema.getType('CreateMergeRequestInput'); const hasLegacyInput = !!this.schema.getType('MergeRequestCreateInput'); const inputType = hasCreateInput ? 'CreateMergeRequestInput' : (hasLegacyInput ? 'MergeRequestCreateInput' : null); if (!inputType) { throw new Error('Neither CreateMergeRequestInput nor MergeRequestCreateInput input type is available on this GitLab instance'); }