Skip to main content
Glama
ttpears

GitLab MCP Server

by ttpears

Create Merge Request

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
NameRequiredDescriptionDefault
projectPathYesFull path of the project (e.g., "group/project-name")
titleYesTitle of the merge request
sourceBranchYesSource branch name
targetBranchYesTarget branch name
descriptionNoDescription of the merge request
userCredentialsNoYour 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;
      },
    };
  • 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;
    },
  • 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 };
    }
  • 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');
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate this is a non-readOnly, non-idempotent, non-destructive operation. The description adds valuable context about authentication requirements ('requires user authentication with write permissions'), which isn't covered by annotations. However, it doesn't disclose other behavioral traits like rate limits, error conditions, or what happens on duplicate requests, leaving some gaps.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that efficiently communicates the core purpose and key requirement. Every word earns its place—there's no redundancy or unnecessary elaboration, making it perfectly concise and front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (creating a merge request with 6 parameters) and lack of an output schema, the description is reasonably complete. It covers the action, resource, and authentication needs. However, it doesn't explain what the tool returns (e.g., merge request ID or object), which would be helpful since there's no output schema, preventing a perfect score.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the input schema fully documents all 6 parameters. The description doesn't add any parameter-specific information beyond what's in the schema, so it meets the baseline of 3. No extra value is provided for parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Create a new merge request') and resource ('in a GitLab project'), distinguishing it from sibling tools like 'update_merge_request' (which modifies existing requests) and 'get_merge_requests' (which only reads). The verb+resource combination is precise and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool ('Create a new merge request') and includes a prerequisite ('requires user authentication with write permissions'), which provides clear context. However, it doesn't specify when NOT to use it or mention alternatives like 'update_merge_request' for modifying existing requests, preventing a perfect score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ttpears/gitlab-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server