Back to Developer Tools

GitLabLinker

GitLabLinker is a GitLab-compatible MCP server for private GitLab instances. It allows per-project configuration of external Git providers without modifying GitLab's source. Using a pluggable architecture, it routes GitLab API calls to the correct backend, making it easy to integrate third-party Git services into GitLab via the MCP plugin.

Last updated: 1/27/2026

README

# GitLab MR MCP

[![CI](https://github.com/amirsina-mandegari/gitlab-mr-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/amirsina-mandegari/gitlab-mr-mcp/actions/workflows/ci.yml)
[![PyPI version](https://badge.fury.io/py/gitlab-mr-mcp.svg)](https://pypi.org/project/gitlab-mr-mcp/)
[![Python Versions](https://img.shields.io/pypi/pyversions/gitlab-mr-mcp.svg)](https://pypi.org/project/gitlab-mr-mcp/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)

Connect your AI assistant to GitLab. Ask questions like _"List open merge requests"_, _"Show me reviews for MR #123"_, _"Get commit discussions for MR #456"_, or _"Find merge requests for the feature branch"_ directly in your chat.

## Table of Contents

- [Quick Setup](#quick-setup)
- [What You Can Do](#what-you-can-do)
- [Configuration Options](#configuration-options)
- [Troubleshooting](#troubleshooting)
- [Tool Reference](#tool-reference)
- [Roadmap](#roadmap)
- [Development](#development)
- [Security Notes](#security-notes)
- [Support](#support)

## Quick Setup

### Installation

```bash
# Using pipx (recommended)
pipx install gitlab-mr-mcp

# Or using uv
uv tool install gitlab-mr-mcp

# Or using pip
pip install gitlab-mr-mcp
```

> **Note:** Using `pipx` or `uv tool` is recommended as they automatically add the `gitlab-mcp` command to your PATH. If using `pip install`, ensure your Python scripts directory is in PATH, or use the full path to the command.

### Get your GitLab token

1. Go to GitLab → Settings → Access Tokens
2. Create token with **`read_api`** scope (add `api` scope if you want write access)
3. Copy the token

### Configure your MCP client

Add to your MCP config (e.g., `.cursor/mcp.json` for Cursor):

```json
{
  "mcpServers": {
    "gitlab-mcp": {
      "command": "gitlab-mcp",
      "env": {
        "GITLAB_URL": "https://gitlab.com",
        "GITLAB_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
        "GITLAB_PROJECT_ID": "12345"
      }
    }
  }
}
```

Restart your MCP client and start asking GitLab questions!

## What You Can Do

Once connected, try these commands in your chat:

- _"List open merge requests"_
- _"Show me details for merge request 456"_
- _"Get reviews and discussions for MR #123"_
- _"Show me the test summary for MR #456"_
- _"What tests failed in merge request #789?"_
- _"Show me the pipeline for MR #456"_
- _"Get the failed job logs for merge request #789"_
- _"Show me commit discussions for MR #456"_
- _"Get all comments on commits in merge request #789"_
- _"Find merge requests for the feature/auth-improvements branch"_
- _"Show me closed merge requests targeting main"_
- _"Reply to discussion abc123 in MR #456 with 'Thanks for the feedback!'"_
- _"Create a new review comment in MR #789 asking about the error handling"_
- _"Resolve discussion def456 in MR #123"_
- _"Approve merge request #456"_
- _"Merge MR #123 with squash"_
- _"Merge MR #789 when pipeline succeeds"_

## Working with Review Comments

The enhanced review tools allow you to interact with merge request discussions:

1. **First, get the reviews** to see discussion IDs:

   ```
   "Show me reviews for MR #123"
   ```

2. **Reply to specific discussions** using the discussion ID:

   ```
   "Reply to discussion abc123 in MR #456 with 'I'll fix this in the next commit'"
   ```

3. **Create new discussion threads** to start conversations:

   ```
   "Create a review comment in MR #789 asking 'Could you add error handling here?'"
   ```

4. **Resolve discussions** when issues are addressed:
   ```
   "Resolve discussion def456 in MR #123"
   ```

**Note**: The `get_merge_request_reviews` tool now displays discussion IDs and note IDs in the output, making it easy to reference specific discussions when replying or resolving.

## Approving and Merging

Complete the MR lifecycle with approval and merge tools:

1. **Approve a merge request**:

   ```
   "Approve MR #123"
   ```

2. **Merge with options**:

   ```
   "Merge MR #456 with squash"
   "Merge MR #789 and remove source branch"
   "Merge MR #123 when pipeline succeeds"
   ```

3. **Revoke approval** (if needed):
   ```
   "Unapprove MR #456"
   ```

**Merge Options:**

- `squash` - Squash commits into a single commit
- `should_remove_source_branch` - Delete source branch after merge
- `merge_when_pipeline_succeeds` - Auto-merge when pipeline passes
- `sha` - Ensure HEAD hasn't changed (safety check)

**Note**: You cannot approve your own MRs. The merge will fail if the MR has conflicts, is in draft status, or doesn't meet approval requirements.

## Working with Test Reports (Recommended for Test Failures)

GitLab provides two tools for checking test results - use the summary for quick checks, and the full report for detailed debugging:

### Option 1: Test Summary (Fast & Lightweight) ⚔

Use `get_pipeline_test_summary` for a quick overview:

```
"Show me the test summary for MR #123"
"How many tests passed in MR #456?"
```

**What You Get:**

- šŸ“Š Pass/fail counts per test suite
- ā±ļø Total execution time
- šŸŽÆ Pass rate percentage
- ⚔ **Fast** - doesn't include detailed error messages

### Option 2: Full Test Report (Detailed) šŸ”

Use `get_merge_request_test_report` for detailed debugging:

```
"Show me the test report for MR #123"
"What tests failed in merge request #456?"
```

**What You Get:**

- āœ… **Specific test names** that passed/failed
- āŒ **Error messages** and stack traces
- šŸ“¦ **Test suites** organized by class/file
- ā±ļø **Execution time** for each test
- šŸ“Š **Pass rate** and summary statistics
- šŸ“„ **File paths** and line numbers

**How Both Work:**

- Automatically fetch the latest pipeline for the merge request
- Retrieve test data from that pipeline (uses GitLab's `/pipelines/:pipeline_id/test_report` or `/test_report_summary` API)

**Example Output:**

```
## Summary

**Total**: 45 | **Passed**: 42 | **Failed**: 3 | **Errors**: 0
**Pass Rate**: 93.3%

## Failed Tests

### [FAIL] test_login_with_invalid_password

**Duration**: 0.300s
**Class**: `tests.auth_test.TestAuth`

**Error Output**:
AssertionError: Expected 401, got 200
```

**Why Use This Instead of Job Logs?**

- šŸŽÆ **No noise**: Only test results, no build/setup output
- šŸ“Š **Structured data**: Easy for AI to understand and suggest fixes
- šŸš€ **Fast**: Much smaller than full job logs
- šŸ” **Precise**: Shows exact test names and error locations

**Requirements:**

Your CI must upload test results using `artifacts:reports:junit` in `.gitlab-ci.yml`:

```yaml
test:
  script:
    - pytest --junitxml=report.xml
  artifacts:
    reports:
      junit: report.xml
```

## Working with Pipeline Jobs and Logs

The pipeline tools provide a two-step workflow for debugging test failures:

### Step 1: Get Pipeline Overview

Use `get_merge_request_pipeline` to see all jobs and their statuses:

```
"Show me the pipeline for MR #456"
```

**What You Get:**

- Pipeline overview (status, duration, coverage)
- All jobs grouped by status (failed, running, success)
- **Job IDs** for each job (use these to fetch logs)
- Direct links to view jobs in GitLab
- Job-level timing and stage information

### Step 2: Get Specific Job Logs

Use `get_job_log` with a job ID to fetch the actual output:

```
"Get the log for job 12345"
"Show me the output of job 67890"
```

**What You Get:**

- Complete job output/trace
- Log size and line count
- Automatically truncated to last 15,000 characters for very long logs

### Typical Workflow:

```
You: "Show me the pipeline for MR #123"
AI: "Pipeline failed. 2 jobs failed:
     - test-unit (Job ID: 12345)
     - test-integration (Job ID: 67890)"

You: "Get the log for job 12345"
AI: [Shows full test output with error details]

You: "Fix the failing test"
AI: [Analyzes the log and suggests fixes]
```

**Why Two Tools?**

- **Performance**: Only fetch logs when needed (not all at once)
- **Flexibility**: Check any job's log (failed, successful, or running)
- **Context Efficient**: Avoid dumping huge logs unnecessarily

## Working with Commit Discussions

The `get_commit_discussions` tool provides comprehensive insights into discussions and comments on individual commits within a merge request:

1. **View all commit discussions** for a merge request:

   ```
   "Show me commit discussions for MR #123"
   ```

2. **Get detailed commit conversation history**:

   ```
   "Get all comments on commits in merge request #456"
   ```

This tool is particularly useful for:

- **Code Review Tracking**: See all feedback on specific commits
- **Discussion History**: Understand the evolution of code discussions
- **Commit-Level Context**: View comments tied to specific code changes
- **Review Progress**: Monitor which commits have been discussed

**Technical Implementation:**

- Uses `/projects/:project_id/merge_requests/:merge_request_iid/commits` to get all commits with proper pagination
- Fetches ALL merge request discussions using `/projects/:project_id/merge_requests/:merge_request_iid/discussions` with pagination support
- Filters discussions by commit SHA using position data to show commit-specific conversations
- Handles both individual comments and discussion threads correctly

The output includes:

- Summary of total commits and discussion counts
- Individual commit details (SHA, title, author, date)
- All discussions and comments for each commit with file positions
- Complete conversation threads with replies
- File positions for diff-related comments
- Thread conversations with replies

## Configuration Options

### MCP Config (Recommended)

Configure environment variables directly in your MCP client config as shown in [Quick Setup](#quick-setup). This keeps project-specific settings with the project.

### Environment Variables

Alternatively, set environment variables in your shell:

```bash
export GITLAB_PROJECT_ID=12345
export GITLAB_ACCESS_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
export GITLAB_URL=https://gitlab.com
```

### SOCKS Proxy Support

Route all GitLab API requests through a SOCKS5 proxy by setting `SOCKS_PROXY`:

```json
{
  "mcpServers": {
    "gitlab-mcp": {
      "command": "gitlab-mcp",
      "env": {
        "GITLAB_URL": "https://gitlab.com",
        "GITLAB_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
        "GITLAB_PROJECT_ID": "12345",
        "SOCKS_PROXY": "socks5://127.0.0.1:1080"
      }
    }
  }
}
```

Or via environment variable:

```bash
export SOCKS_PROXY=socks5://127.0.0.1:1080
```

When `SOCKS_PROXY` is not set, connections are made directly (no proxy).

### Find Your Project ID

- Go to your GitLab project → Settings → General → Project ID
- Or check the URL: `https://gitlab.com/username/project` (use the numeric ID)

## Troubleshooting

**Authentication Error**: Verify your token has `read_api` permissions and is not expired.

**Project Not Found**: Double-check your project ID is correct (it's a number, not the project name).

**Connection Issues**: Make sure your GitLab URL is accessible and correct.

**Script Not Found**: Ensure the path in your MCP config points to the actual server location and the script is executable.

## Tool Reference

| Tool                            | Description                       | Parameters                                       |
| ------------------------------- | --------------------------------- | ------------------------------------------------ |
| `list_merge_requests`           | List merge requests               | `state`, `target_branch`, `limit`                |
| `get_merge_request_details`     | Get MR details                    | `merge_request_iid`                              |
| `create_merge_request`          | Create a new merge request        | `source_branch`, `target_branch`, `title`, etc.  |
| `update_merge_request`          | Update an existing merge request  | `merge_request_iid`, `title`, `assignees`, etc.  |
| `merge_merge_request`           | Merge an MR                       | `merge_request_iid`, `squash`, `sha`, etc.       |
| `approve_merge_request`         | Approve an MR                     | `merge_request_iid`, `sha`                       |
| `unapprove_merge_request`       | Revoke approval from an MR        | `merge_request_iid`                              |
| `get_pipeline_test_summary`     | Get test summary (fast overview)  | `merge_request_iid`                              |
| `get_merge_request_test_report` | Get detailed test failure reports | `merge_request_iid`                              |
| `get_merge_request_pipeline`    | Get pipeline with all jobs        | `merge_request_iid`                              |
| `get_job_log`                   | Get trace/output for specific job | `job_id`                                         |
| `get_merge_request_reviews`     | Get reviews/discussions           | `merge_request_iid`                              |
| `get_commit_discussions`        | Get discussions on commits        | `merge_request_iid`                              |
| `get_branch_merge_requests`     | Find MRs for branch               | `branch_name`                                    |
| `reply_to_review_comment`       | Reply to existing discussion      | `merge_request_iid`, `discussion_id`, `body`     |
| `create_review_comment`         | Create new discussion thread      | `merge_request_iid`, `body`                      |
| `resolve_review_discussion`     | Resolve/unresolve discussion      | `merge_request_iid`, `discussion_id`, `resolved` |
| `list_project_members`          | List project members              | (none)                                           |
| `list_project_labels`           | List project labels               | (none)                                           |

## Roadmap

### Recently Added

- **v1.3.0**: SOCKS5 proxy support for routing GitLab API requests
- **v1.2.0**: Merge, approve, and unapprove MR tools - complete MR lifecycle
- **v1.1.0**: Create and update MR tools, cleaner output formatting

### Coming Next

- [ ] **Issue Management** - List, create, update issues and add comments
- [ ] **Inline Comments** - Add code review comments on specific lines

### Considering

- [ ] Lightweight file list for MRs (changed files without full diff)
- [ ] Rebase MR via API

### Out of Scope

Branch operations, file content fetching, and full diffs are intentionally not included - use `git` locally for these tasks, it's faster and more capable.

Have a feature request? [Open an issue](https://github.com/amirsina-mandegari/gitlab-mr-mcp/issues)!

## Development

### Project Structure

```
gitlab_mr_mcp/
ā”œā”€ā”€ __init__.py          # Package version
ā”œā”€ā”€ __main__.py          # Entry point for python -m
ā”œā”€ā”€ server.py            # MCP server implementation
ā”œā”€ā”€ config.py            # Configuration management
ā”œā”€ā”€ gitlab_api.py        # GitLab API client
ā”œā”€ā”€ utils.py             # Utility functions
ā”œā”€ā”€ logging_config.py    # Logging configuration
└── tools/               # Tool implementations
    ā”œā”€ā”€ __init__.py
    ā”œā”€ā”€ list_merge_requests.py
    ā”œā”€ā”€ get_merge_request_details.py
    ā”œā”€ā”€ create_merge_request.py
    ā”œā”€ā”€ update_merge_request.py
    └── ... (more tools)
```

### Adding Tools

1. Create new file in `gitlab_mr_mcp/tools/` directory
2. Add import and export to `gitlab_mr_mcp/tools/__init__.py`
3. Add to `list_tools()` in `gitlab_mr_mcp/server.py`
4. Add handler to `call_tool()` in `gitlab_mr_mcp/server.py`

### Development Setup

1. **Install development dependencies:**

```bash
make install
# or: uv pip install -e ".[dev]"
```

2. **Available make commands:**

```bash
make install   # Install in editable mode with dev deps
make dev       # Build and install wheel locally
make test      # Run tests
make lint      # Run linters
make format    # Format code
make check     # Lint + test
make clean     # Remove build artifacts
```

3. **Set up pre-commit hooks:**

```bash
pre-commit install
```

This will automatically check and format your code for:

- ✨ **Trailing whitespace** - auto-removed
- šŸ“„ **End-of-file issues** - auto-fixed
- šŸŽØ **Code formatting (black)** - auto-formatted
- šŸ“¦ **Import sorting (isort)** - auto-organized
- šŸ **Python style (flake8)** - linted with bugbear & print detection
- šŸ”’ **Security issues (bandit)** - security checks
- šŸ“‹ **YAML/JSON formatting** - validated

4. **Format all existing code (first time only):**

```bash
make format
# or: black --line-length=120 . && isort --profile black --line-length=120 .
```

5. **Run pre-commit manually on all files:**

```bash
pre-commit run --all-files
```

### Running Tests

```bash
make test
# or: uv run pytest tests/ -v
```

## Security Notes

- Never commit access tokens to version control
- Use project-specific tokens with minimal permissions (`read_api` scope)
- Rotate tokens regularly
- Store tokens in your MCP config (which should not be committed)

## Support

- Check [GitLab API documentation](https://docs.gitlab.com/ee/api/)
- Open issues at [github.com/amirsina-mandegari/gitlab-mr-mcp](https://github.com/amirsina-mandegari/gitlab-mr-mcp)

## License

MIT License - see LICENSE file for details.

Installation

Add this MCP to your configuration:

{
  "mcpServers": {
    "gitlablinker-1": {
      // See GitHub repository for configuration
    }
  }
}

See the GitHub repository for full installation instructions.