nostoslabs/gitlab-mcp
If you are the rightful owner of gitlab-mcp and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
A Python-based MCP (Model Context Protocol) server for GitLab integration.
GitLab MCP Server
A Python-based MCP (Model Context Protocol) server for GitLab integration
Features ⢠Quick Start ⢠Documentation ⢠Development ⢠Architecture
Overview
GitLab MCP Server is a comprehensive Python implementation of the Model Context Protocol for GitLab, providing 88 tools to interact with GitLab's API. Built with Clean Architecture principles and the FastMCP framework, it offers type-safe, tested, and maintainable access to GitLab's full feature set.
Key Highlights
- 88 GitLab Tools - Full feature parity with TypeScript implementation
- Clean Architecture - 4-layer architecture for maintainability and testability
- Type-Safe - Full type hints with mypy strict mode enforcement
- Well-Tested - 240+ tests with 72% coverage
- Production-Ready - Docker support, CI/CD pipelines, security scanning
- Multiple Transports - stdio, SSE, and Streamable HTTP support
Features
GitLab Operations (88 Tools)
The server provides comprehensive GitLab API access across 19 categories:
Category | Tools | Description |
---|---|---|
Issues | 6 | Create, read, update, delete, and list issues |
Merge Requests | 9 | Full MR lifecycle management including diffs |
Projects | 5 | Project management and search |
Pipelines | 7 | CI/CD pipeline operations and job management |
Repository | 4 | File operations and repository tree navigation |
Branches | 3 | Branch creation, deletion, and listing |
Wikis | 7 | Wiki page management and attachments |
Milestones | 10 | Milestone tracking and burndown charts |
Labels | 3 | Label management and organization |
Commits | 2 | Commit details and diffs |
Discussions | 2 | Issue and MR discussions/threads |
Users | 1 | User information retrieval |
Members | 1 | Project member management |
Namespaces | 3 | Namespace operations and verification |
Groups | 1 | Group project listing |
Jobs | 2 | Pipeline job control (play, cancel) |
Issue Links | 2 | Issue relationship tracking |
Draft Notes | 0 | (Planned - see roadmap) |
Events | 0 | (Planned - see roadmap) |
Architecture Features
- Clean Architecture - Separation of concerns across 4 distinct layers
- FastMCP Framework - Modern async-first MCP implementation
- python-gitlab - Official GitLab Python client for API access
- Pydantic - Data validation and settings management
- Structured Logging - Production-ready logging with structlog
- Retry Logic - Automatic retries with exponential backoff (tenacity)
Security & Quality
- Read-Only Mode - Optional safety mode for production environments
- Access Control - Project allowlist/denylist support
- Tool Filtering - Regex-based tool access control
- Type Safety - 100% mypy strict mode compliance
- Security Scanning - Bandit static analysis and pip-audit
- Pre-commit Hooks - Automatic code quality enforcement
Quick Start
Prerequisites
- Python 3.11+ - Required for modern type hints and async features
- uv - Fast Python package manager (recommended)
- GitLab Personal Access Token - With appropriate API scopes
Installation
# Install uv package manager (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone the repository
git clone https://github.com/nostoslabs/gitlab-mcp.git
cd gitlab-mcp
# Install all dependencies
uv sync
# Copy and configure environment variables
cp .env.example .env
# Edit .env and set your GITLAB_PERSONAL_ACCESS_TOKEN
Configuration
Create a .env
file with your GitLab credentials:
# ============================================
# Required Configuration
# ============================================
GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx
GITLAB_API_URL=https://gitlab.com # or your self-hosted GitLab URL
# ============================================
# Optional Configuration
# ============================================
# Project Access Control
GITLAB_PROJECT_ID=123456 # Default project
GITLAB_ALLOWED_PROJECT_IDS=123456,789012 # Comma-separated list
# Security Features
GITLAB_READ_ONLY_MODE=false # Enable read-only mode
GITLAB_DENIED_TOOLS_REGEX= # Regex to block tools
# Feature Toggles
USE_GITLAB_WIKI=true # Enable wiki tools
USE_MILESTONE=true # Enable milestone tools
USE_PIPELINE=true # Enable pipeline tools
# Transport Configuration
SSE=false # Server-Sent Events mode
STREAMABLE_HTTP=false # Streamable HTTP mode
HOST=127.0.0.1 # Server host
PORT=8080 # Server port
# Network Proxy (optional)
HTTP_PROXY=
HTTPS_PROXY=
NO_PROXY=localhost,127.0.0.1
# Advanced Options
GITLAB_AUTH_COOKIE_PATH= # Cookie auth path
GITLAB_COMMIT_FILES_PER_PAGE=20 # Pagination size
LOG_LEVEL=INFO # Logging level
Running the Server
# Run with stdio transport (default)
uv run python -m gitlab_mcp
# Run with Server-Sent Events transport
SSE=true uv run python -m gitlab_mcp
# Run with Streamable HTTP transport
STREAMABLE_HTTP=true HOST=0.0.0.0 PORT=8080 uv run python -m gitlab_mcp
Testing the Installation
# Run all tests
make test
# Run tests with coverage report
make test-cov
# Run quality checks
make all
Architecture
GitLab MCP Server follows Clean Architecture principles with 4 distinct layers:
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Presentation Layer ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā FastMCP Server (server.py) ā ā
ā ā ⢠88 Tool Handlers ā ā
ā ā ⢠Pydantic Schemas ā ā
ā ā ⢠Transport: stdio/SSE/HTTP ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Application Layer ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā Use Cases ā ā
ā ā ⢠CreateIssue, UpdateMergeRequest, etc. ā ā
ā ā ⢠Business Logic Orchestration ā ā
ā ā ⢠DTOs (Data Transfer Objects) ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Domain Layer ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā Entities ā ā
ā ā ⢠Issue, MergeRequest, Project, Pipeline ā ā
ā ā ⢠Pure business logic (no dependencies) ā ā
ā ā ⢠Value Objects: ProjectId, Pagination ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Infrastructure Layer ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā GitLab API Client (python-gitlab + httpx) ā ā
ā ā ⢠Repository Implementations ā ā
ā ā ⢠Configuration (Pydantic Settings) ā ā
ā ā ⢠Logging (structlog) ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Directory Structure
src/gitlab_mcp/
āāā domain/ # Pure business logic (no external deps)
ā āāā entities/ # Issue, MergeRequest, Project, Pipeline
ā āāā value_objects/ # ProjectId, Pagination, IssueIid
ā
āāā application/ # Use cases and orchestration
ā āāā interfaces/ # Repository ports (abstract)
ā āāā dtos/ # Data transfer objects
ā āāā use_cases/ # Business logic (CreateIssue, etc.)
ā
āāā infrastructure/ # External services integration
ā āāā config/ # Pydantic Settings (environment vars)
ā āāā gitlab/ # python-gitlab client & repositories
ā āāā logging/ # Structured logging setup
ā
āāā presentation/ # MCP interface (FastMCP)
ā āāā server.py # Main FastMCP server setup
ā āāā schemas/ # Pydantic validation schemas
ā āāā tools/ # 88 MCP tool handlers (19 categories)
ā āāā issues/
ā āāā merge_requests/
ā āāā projects/
ā āāā pipelines/
ā āāā repository/
ā āāā branches/
ā āāā wikis/
ā āāā milestones/
ā āāā labels/
ā āāā commits/
ā āāā discussions/
ā āāā users/
ā āāā members/
ā āāā namespaces/
ā āāā groups/
ā āāā jobs/
ā āāā issue_links/
ā āāā draft_notes/
ā āāā events/
ā
āāā services/ # Shared services
ā āāā gitlab_client_factory.py
ā
āāā __main__.py # Entry point
āāā server.py # FastMCP server (main file)
Development
Development Setup
# Install development dependencies
uv sync --dev
# Install pre-commit hooks
uv run pre-commit install
# Verify installation
make help
Available Commands
The project includes a comprehensive Makefile for all development tasks:
# Code Quality
make format # Format code with black and ruff
make lint # Lint code with ruff (must pass with 0 errors)
make type-check # Type check with mypy (must pass with 0 errors)
# Testing
make test # Run all tests
make test-cov # Run tests with coverage report
# Complete Validation
make all # Run all quality checks (format + lint + type-check + test)
# Cleanup
make clean # Remove cache and generated files
# Help
make help # Show all available commands
Quality Standards
All code must meet these standards before merging:
- Linting: Zero ruff errors
- Type Checking: Zero mypy errors
- Formatting: Black-formatted code
- Testing: All tests passing
- Coverage: Maintain 70%+ overall coverage
Testing Strategy
The project follows Test-Driven Development (TDD) with three test layers:
# Unit Tests - Fast, isolated tests
uv run pytest tests/unit/
# Integration Tests - API interaction tests
uv run pytest tests/integration/
# End-to-End Tests - Full workflow tests
uv run pytest tests/e2e/
# Run specific test file
uv run pytest tests/unit/presentation/tools/issues/test_create_issue.py -v
# Run with coverage
uv run pytest --cov=src --cov-report=html --cov-report=term-missing
Coverage Targets by Layer:
- Domain Layer: 100% (pure business logic)
- Application Layer: 90%+ (use cases)
- Infrastructure Layer: 80%+ (external integrations)
- Presentation Layer: 85%+ (MCP tools)
Adding New Tools
To add a new GitLab tool, follow the :
- Domain: Create entity if needed (e.g.,
Issue
,MergeRequest
) - Application: Create use case with tests (e.g.,
CreateIssueUseCase
) - Infrastructure: Implement repository method for API calls
- Presentation: Create Pydantic schema and MCP tool handler
- Testing: Write unit, integration, and e2e tests
- Documentation: Update tool catalog and API docs
Pre-commit Hooks
The project uses pre-commit hooks to enforce quality:
- Trailing whitespace removal
- End-of-file fixer
- YAML validation
- Large file check
- Black formatting
- Ruff linting
- Mypy type checking
- Bandit security scanning
# Run manually
uv run pre-commit run --all-files
Docker Deployment
Building the Image
# Build the Docker image
docker build -t gitlab-mcp .
# Build with specific Python version
docker build --build-arg PYTHON_VERSION=3.12 -t gitlab-mcp:py312 .
Running with Docker
# Run with environment file
docker run -it --env-file .env gitlab-mcp
# Run with SSE transport
docker run -it --env-file .env -p 8080:8080 -e SSE=true gitlab-mcp
# Run in detached mode
docker run -d --name gitlab-mcp-server --env-file .env gitlab-mcp
Docker Compose
# Start the server
docker-compose up -d
# View logs
docker-compose logs -f
# Stop the server
docker-compose down
# Rebuild and restart
docker-compose up -d --build
The Docker image uses:
- Multi-stage build for minimal size
- Chainguard Python base for security
- Health checks for container monitoring
- Non-root user for security (planned)
CI/CD
GitHub Actions Workflows
The project includes 5 automated workflows:
-
CI (
.github/workflows/ci.yml
)- Code quality checks (black, ruff, mypy)
- Test execution with coverage
- Security scanning (bandit, pip-audit)
- Codecov integration
-
CodeQL (
.github/workflows/codeql.yml
)- Security vulnerability scanning
- Code quality analysis
-
Docker Publish (
.github/workflows/docker-publish.yml
)- Automated Docker image builds
- Push to container registry
-
Release (
.github/workflows/release.yml
)- Automated version tagging
- Release notes generation
-
SonarCloud (
.github/workflows/sonarcloud.yml
)- Code quality metrics
- Technical debt tracking
Running CI Locally
# Run the same checks as CI
make all
# Individual checks
make format
make lint
make type-check
make test-cov
Documentation
Comprehensive documentation is available in the docs/
directory:
Document | Description |
---|---|
Clean Architecture principles and layer details | |
Step-by-step guide for implementing tools | |
TDD approach and testing patterns | |
Code templates and quick snippets | |
Future tool implementation plan |
Additional Resources
- TypeScript Reference: The original TypeScript implementation is preserved in
old/
for reference - API Documentation: See GitLab API Docs
- python-gitlab: Official Documentation
- FastMCP: Framework Documentation
Configuration Reference
Environment Variables
Variable | Required | Default | Description |
---|---|---|---|
GITLAB_PERSONAL_ACCESS_TOKEN | Yes | - | GitLab API token |
GITLAB_API_URL | No | https://gitlab.com | GitLab instance URL |
GITLAB_PROJECT_ID | No | - | Default project ID |
GITLAB_ALLOWED_PROJECT_IDS | No | - | Allowed project IDs (comma-separated) |
GITLAB_READ_ONLY_MODE | No | false | Enable read-only mode |
GITLAB_DENIED_TOOLS_REGEX | No | - | Regex to block specific tools |
USE_GITLAB_WIKI | No | true | Enable wiki tools |
USE_MILESTONE | No | true | Enable milestone tools |
USE_PIPELINE | No | true | Enable pipeline tools |
SSE | No | false | Use Server-Sent Events transport |
STREAMABLE_HTTP | No | false | Use Streamable HTTP transport |
HOST | No | 127.0.0.1 | Server host (SSE/HTTP modes) |
PORT | No | 8080 | Server port (SSE/HTTP modes) |
HTTP_PROXY | No | - | HTTP proxy URL |
HTTPS_PROXY | No | - | HTTPS proxy URL |
NO_PROXY | No | - | Proxy bypass list |
GITLAB_AUTH_COOKIE_PATH | No | - | Cookie authentication file |
GITLAB_COMMIT_FILES_PER_PAGE | No | 20 | Commit pagination size |
LOG_LEVEL | No | INFO | Logging level |
Transport Modes
The server supports three transport modes with the following priority:
- Streamable HTTP (if
STREAMABLE_HTTP=true
) - Highest priority - SSE (if
SSE=true
andSTREAMABLE_HTTP!=true
) - Medium priority - stdio (default) - Standard input/output
Troubleshooting
Common Issues
Issue: GITLAB_PERSONAL_ACCESS_TOKEN not set
# Solution: Set your token in .env file
echo "GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxxxxxxxxxx" >> .env
Issue: Tests failing with authentication errors
# Solution: Use test token for unit tests
env GITLAB_PERSONAL_ACCESS_TOKEN=test_token uv run pytest tests/unit/
Issue: Import errors when running the server
# Solution: Reinstall dependencies
uv sync --reinstall
Issue: Type checking errors
# Solution: Run mypy with verbose output
uv run mypy src/ --verbose
Debug Mode
Enable debug logging for troubleshooting:
LOG_LEVEL=DEBUG uv run python -m gitlab_mcp
Contributing
We welcome contributions! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature
) - Write tests for your changes
- Ensure all quality checks pass (
make all
) - Commit your changes
- Push to your branch
- Open a Pull Request
Code Style
- Follow PEP 8 (enforced by Black and Ruff)
- Use type hints for all functions
- Write docstrings for public APIs
- Keep functions focused and testable
- Maintain Clean Architecture boundaries
Project Status
Current Implementation
- ā Core Infrastructure: Complete
- ā 88 GitLab Tools: Fully implemented
- ā Clean Architecture: 4 layers implemented
- ā Testing Framework: 240+ tests, 72% coverage
- ā CI/CD: GitHub Actions workflows
- ā Docker: Production-ready containers
- ā Documentation: Comprehensive guides
Roadmap
See for future enhancements.
License
This project is licensed under the MIT License - see the file for details.
Acknowledgments
- FastMCP - Modern MCP framework by @jlowin
- python-gitlab - Official GitLab Python client
- TypeScript Version - Original implementation (preserved in
old/
directory) - Clean Architecture - Inspired by Uncle Bob's architecture principles
Made with ā¤ļø using Python and Clean Architecture
Report Bug ⢠Request Feature ā¢