@asapo/gitlab-mcp-server
v1.2.1
Published
MCP server for GitLab with intelligent response system, thread resolution, and smart question detection
Maintainers
Readme
GitLab MCP Server
A Model Context Protocol (MCP) server that provides comprehensive access to GitLab repositories, including merge requests, issues, comments, and project management features.
Features
- Merge Request Management: Full CRUD operations for merge requests and discussions
- Issue Management: Create, read, update, and delete issues with comments
- Intelligent Response System: Automatically implement feedback and resolve discussions
- Comment & Discussion Management: Add, edit, and manage comments on both merge requests and issues
- Project Search: Find and explore GitLab projects
- Smart Question Detection: Automatically identify questions and feedback in comments
- Comprehensive Pagination: Handle large datasets efficiently
- Type Safety: Full TypeScript support with comprehensive types
Installation
From npm (Recommended)
# Install globally for system-wide use
npm install -g @asapo/gitlab-mcp-server
# Or install locally in your project
npm install @asapo/gitlab-mcp-serverFrom Source
git clone https://github.com/your-username/gitlab-mcp-server.git
cd gitlab-mcp-server
npm install
npm run buildConfiguration
Create a .env file based on .env.example:
cp .env.example .envConfigure your GitLab settings:
# GitLab instance base URL (without trailing slash)
GITLAB_BASE_URL=https://gitlab.com
# GitLab Personal Access Token
GITLAB_TOKEN=your_gitlab_token_hereCreating a GitLab Personal Access Token
- Go to your GitLab instance (e.g., https://gitlab.com)
- Navigate to Settings > Access Tokens
- Create a new token with the required scopes:
Token Scopes:
For Full Functionality (Read + Write):
- ☑️
api- Complete read/write API access
This single scope provides access to all MCP server features including:
- Reading merge requests, comments, and discussions
- Adding comments and replies
- Resolving/unresolving discussion threads
- Using the intelligent response system
For Read-Only Mode:
- ☑️
read_api- Read-only API access - ☑️
read_repository- Read-only repository access
This combination provides access to analysis features only:
- Reading and analyzing discussions
- Detecting questions and thread status
- Getting summaries and insights
- Cannot use write operations
Recommended: Use api scope
For the complete "fix, respond, resolve" workflow, select only the api scope. It includes all read permissions plus write capabilities.
Usage
Running the Server
npm startThe server will start and listen for MCP requests on stdio.
Integration with Claude Code
To use this MCP server with Claude Code, you have several options for configuration.
1. Quick Setup with claude mcp add
The easiest way to install this MCP server is using the claude mcp add command:
# Clone and install the GitLab MCP server
git clone https://github.com/your-username/gitlab-mcp-server.git
cd gitlab-mcp-server
npm install
npm run build
# Add to Claude Code using the mcp add command
claude mcp add gitlab @asapo/gitlab-mcp-server \
--env GITLAB_BASE_URL=https://gitlab.com \
--env GITLAB_TOKEN=your_gitlab_token_hereThis will automatically:
- Add the server to your Claude Code configuration
- Set up the environment variables
- Make the GitLab tools available in your Claude Code sessions
Managing the MCP Server
Once added, you can manage the GitLab MCP server using Claude Code commands:
# List all installed MCP servers
claude mcp list
# Check status of the GitLab server
claude mcp status gitlab
# Remove the GitLab server
claude mcp remove gitlab
# Update environment variables
claude mcp update gitlab --env GITLAB_TOKEN=new_token_here
# Restart the server
claude mcp restart gitlabAlternative: Local Development Setup
For local development or if installing from source:
# Clone and build locally
git clone https://github.com/your-username/gitlab-mcp-server.git
cd gitlab-mcp-server
npm install
npm run build
# Add to Claude Code with local path
claude mcp add gitlab ./dist/index.js \
--env GITLAB_BASE_URL=https://gitlab.com \
--env GITLAB_TOKEN=your_gitlab_token_here2. Manual Configuration
If you prefer manual setup, create or edit your Claude Code configuration file (typically ~/.config/claude-code/config.json or in your project's .claude/ directory):
{
"mcpServers": {
"gitlab": {
"command": "node",
"args": ["/path/to/gitlab-mcp/dist/index.js"],
"env": {
"GITLAB_BASE_URL": "https://gitlab.com",
"GITLAB_TOKEN": "your_gitlab_token_here"
}
}
}
}3. Alternative: Using npm script
If you want to use the npm start script:
{
"mcpServers": {
"gitlab": {
"command": "npm",
"args": ["start"],
"cwd": "/path/to/gitlab-mcp",
"env": {
"GITLAB_BASE_URL": "https://gitlab.com",
"GITLAB_TOKEN": "your_gitlab_token_here"
}
}
}
}4. Project-specific Configuration
For project-specific GitLab access, create a .claude/config.json in your project root:
{
"mcpServers": {
"gitlab": {
"command": "node",
"args": ["/path/to/gitlab-mcp/dist/index.js"],
"env": {
"GITLAB_BASE_URL": "https://your-gitlab-instance.com",
"GITLAB_TOKEN": "project_specific_token"
}
}
}
}5. Using with Environment Files
If you prefer to use .env files, you can set up the MCP server to load from a specific location:
{
"mcpServers": {
"gitlab": {
"command": "node",
"args": ["/path/to/gitlab-mcp/dist/index.js"],
"cwd": "/path/to/gitlab-mcp"
}
}
}Then ensure your .env file is in the gitlab-mcp directory.
6. Example Claude Code Usage
Once configured, you can use the GitLab MCP tools in Claude Code:
# Analyze merge request comments and questions
Can you analyze the discussions on merge request !123 in project "myorg/myproject" and tell me if there are any unresolved questions?
# Check thread resolution status
Get a summary of unresolved threads for merge request !456 in "myorg/frontend" - are there any blocking discussions?
# Review recent merge requests
Show me the last 10 open merge requests for project "myorg/myproject" and their current status.
# Search for projects
Find all projects with "backend" in the name and show their details.
# Smart question detection
Analyze merge request !789 in "myorg/api" and extract all the questions that reviewers are asking.
# 🚀 THE MAGIC COMMAND - Your desired workflow!
Read the comments on MR !123, fix where possible, resolve threads if fixed, and answer if you need further information.
# Preview what would happen (dry run)
Show me what actions would be taken for MR !456 without actually executing them.
# Use friendly response style
Respond to MR !789 discussions using a friendly, casual tone.
# Issue Management Examples
Create a new bug report issue for "User login fails on mobile" in project "myorg/webapp" with labels "bug" and "mobile".
# Find all open issues assigned to me
Show me all open issues assigned to me in project "myorg/backend".
# Update issue status and add comment
Close issue #42 in "myorg/frontend" and add a comment explaining the fix.
# Track specific issue types
List all incidents and test cases in project "myorg/platform" that are still open.
# Comment management on issues
Add a comment to issue #156 in "myorg/api" with the current investigation status.7. Troubleshooting Integration
Server Not Starting:
- Check that the path to the compiled JavaScript is correct
- Verify Node.js is available in the PATH where Claude Code runs
- Check the Claude Code logs for error messages
- Permission Error (EACCES): Run
chmod +x /path/to/gitlab-mcp/dist/index.jsto add execute permissions
Authentication Issues:
- Ensure environment variables are properly set in the MCP configuration
- Verify the GitLab token has the required scopes
- Test the connection manually by running the server standalone
Permission Errors:
- Make sure the GitLab token has access to the projects you're querying
- Check that the projects exist and are accessible with your token
Debug Mode: Add debug environment variables to your MCP configuration:
{
"mcpServers": {
"gitlab": {
"command": "node",
"args": ["/path/to/gitlab-mcp/dist/index.js"],
"env": {
"DEBUG": "1",
"GITLAB_BASE_URL": "https://gitlab.com",
"GITLAB_TOKEN": "your_gitlab_token_here"
}
}
}
}Available Tools
1. get_merge_request_notes
Get all notes (comments) for a specific merge request.
Parameters:
project(string): Project ID or path (e.g., "group/project" or "123")mergeRequestIid(number): Merge request internal IDsort(optional): Sort order ("asc" or "desc")orderBy(optional): Field to order by ("created_at" or "updated_at")perPage(optional): Number of notes per page (max 100)page(optional): Page number for pagination
2. get_merge_request_note
Get a specific note by ID from a merge request.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDnoteId(number): Note ID
3. get_merge_request_discussions
Get discussions (threaded comments) for a merge request.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDperPage(optional): Number of discussions per page (max 100)page(optional): Page number for pagination
4. get_merge_request
Get detailed information about a specific merge request.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal ID
5. get_project_merge_requests
List merge requests for a project with optional filtering.
Parameters:
project(string): Project ID or pathstate(optional): Filter by state ("opened", "closed", "locked", "merged")orderBy(optional): Field to order bysort(optional): Sort order ("asc" or "desc")search(optional): Search in title and descriptionperPage(optional): Number of merge requests per page (max 100)page(optional): Page number for pagination
6. search_projects
Search for GitLab projects by name.
Parameters:
search(string): Search term for project namesvisibility(optional): Filter by visibility ("private", "internal", "public")orderBy(optional): Field to order bysort(optional): Sort order ("asc" or "desc")perPage(optional): Number of projects per page (max 100)page(optional): Page number for pagination
7. analyze_merge_request_discussions
Analyze merge request discussions for thread resolution status and open questions.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal ID
Returns comprehensive analysis including:
- Total, resolved, and unresolved discussion counts
- Detected questions in comments using smart pattern matching
- Thread-by-thread analysis with resolution status
- Summary with attention flags and blocking indicators
8. get_merge_request_thread_summary
Get a concise summary of unresolved threads and open questions.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal ID
Returns concise summary with:
- Number of unresolved threads
- List of open questions detected in comments
- Attention flags for blocking issues
- Human-readable details and recommendations
9. add_merge_request_note
Add a comment to a merge request or reply to a discussion thread.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDbody(string): The comment content to adddiscussionId(optional): Discussion ID to reply to (for threaded replies)
10. resolve_discussion
Resolve or unresolve a discussion thread.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDdiscussionId(string): Discussion ID to resolveresolved(optional): Whether to resolve (true) or unresolve (false), default: true
11. intelligent_mr_response 🚀
The main tool for your "fix and respond" workflow!
Intelligently analyze discussions and automatically:
- Reply to feedback indicating fixes are made
- Ask clarifying questions when more information is needed
- Resolve threads when issues are addressed
- Use appropriate response styles
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDdryRun(optional): Preview actions without executing (default: false)autoResolve(optional): Auto-resolve threads when providing fixes (default: true)responseStyle(optional): Response style - "professional", "friendly", or "concise" (default: "concise")
12. mark_discussions_as_fixed
Mark specific discussions as fixed/done with a response and resolve them.
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDdiscussionIds(array): Array of discussion IDs to mark as fixedresponseStyle(optional): Style of "fixed" response - "professional", "friendly", or "concise" (default: "concise")customMessage(optional): Custom message instead of auto-generated "fixed" response
13. remove_resolved_threads ⚠️ Manual Use Only
Remove resolved status from all resolved threads in a merge request (unresolves them).
⚠️ WARNING: This is a manual cleanup operation only. Never call automatically.
Use Cases:
- Clean up after testing the intelligent response system
- Reset MR state when you want to re-run feedback implementation
- Remove resolved status when threads were resolved prematurely
Parameters:
project(string): Project ID or pathmergeRequestIid(number): Merge request internal IDdryRun(optional): Preview what threads would be removed without actually removing them (default: false)
Issue Management Tools 🆕
14. create_issue
Create a new issue in a GitLab project.
Parameters:
project(string): Project ID or path (e.g., "group/project" or "123")title(string): Issue titledescription(optional): Issue description/contentassigneeIds(optional): Array of user IDs to assignassigneeId(optional): Single user ID to assign (legacy)milestoneId(optional): Milestone IDlabels(optional): Labels as string or arraydueDate(optional): Due date in YYYY-MM-DD formatweight(optional): Issue weightissueType(optional): Issue type ("issue", "incident", "test_case")confidential(optional): Make issue confidential
15. get_issue
Get detailed information about a specific issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal ID (iid)
16. get_project_issues
List issues for a project with optional filtering.
Parameters:
project(string): Project ID or pathstate(optional): Filter by state ("opened", "closed", "all")labels(optional): Filter by labels (string or array)milestone(optional): Filter by milestonescope(optional): Filter by scope ("created_by_me", "assigned_to_me", "all")authorId(optional): Filter by author IDassigneeId(optional): Filter by assignee (number, "None", or "Any")search(optional): Search in title and descriptionorderBy(optional): Field to order bysort(optional): Sort order ("asc" or "desc")perPage(optional): Number of issues per page (max 100)page(optional): Page number for pagination
17. update_issue
Update an existing issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal IDtitle(optional): New issue titledescription(optional): New issue descriptionassigneeIds(optional): Array of user IDs to assignassigneeId(optional): Single user ID to assignmilestoneId(optional): Milestone IDlabels(optional): Labels to setaddLabels(optional): Labels to addremoveLabels(optional): Labels to removestateEvent(optional): State transition ("close" or "reopen")dueDate(optional): Due date in YYYY-MM-DD formatweight(optional): Issue weightissueType(optional): Issue typeconfidential(optional): Make issue confidential
18. get_issue_notes
Get all notes (comments) for a specific issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal IDsort(optional): Sort order ("asc" or "desc")orderBy(optional): Field to order by ("created_at" or "updated_at")perPage(optional): Number of notes per page (max 100)page(optional): Page number for pagination
19. get_issue_note
Get a specific note (comment) by ID from an issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal IDnoteId(number): Note ID
20. add_issue_note
Add a note (comment) to an issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal IDbody(string): The comment/note content to addconfidential(optional): Make note confidentialinternal(optional): Make note internal
21. update_issue_note
Update an existing note (comment) on an issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal IDnoteId(number): Note ID to updatebody(string): New note contentconfidential(optional): Make note confidential
22. delete_issue_note
Delete a note (comment) from an issue.
Parameters:
project(string): Project ID or pathissueIid(number): Issue internal IDnoteId(number): Note ID to delete
New Features
Smart Question Detection
The server now automatically detects questions in merge request comments using advanced pattern matching:
- Direct questions: Text ending with "?"
- Implicit questions: "Can you...", "Could we...", "What about..."
- Feedback requests: "thoughts?", "WDYT", "let me know"
- Clarification requests: "make sense?", "agree?", "any concerns?"
Thread Resolution Analysis
Automatically analyzes discussion threads to identify:
- Resolution status: Which threads are resolved vs. unresolved
- Blocking discussions: Threads that may prevent merge
- Open questions: Questions awaiting responses
- Attention needed: Threads requiring reviewer action
Intelligent Response System 🚀
The breakthrough feature that enables your desired workflow:
- Smart Reply Generation: Automatically craft appropriate responses to reviewer feedback
- Contextual Thread Resolution: Resolve threads when fixes are confirmed
- Clarification Requests: Ask targeted questions when more information is needed
- Response Style Adaptation: Professional, friendly, or concise communication styles
- Dry-Run Mode: Preview all actions before execution
- Batch Processing: Handle all discussions in a single operation
Slash Command Integration
You can create a /gitlab slash command for Claude Code to make GitLab operations even easier!
Setup Instructions:
Option 1: NPX Installation (Easiest)
Install the slash commands directly from npm:
# One-command installation from anywhere
npx asapo-gitlab-mcp-installThis will automatically:
- ✅ Download the latest GitLab slash command
- ✅ Install it to
~/.claude/commands/gitlab.md - ✅ Create backups of existing files
- ✅ Show you all available commands
Option 2: Local Project Installation
Run the provided install script from the local project:
# From the GitLab MCP project directory
cd claude-integration
./install.sh
# Or using npm script
npm run install-claudeBoth installation methods will:
- ✅ Create
~/.claude/commands/directory if needed - ✅ Backup any existing GitLab command files
- ✅ Install the new slash command with colored output
- ✅ Show you all available commands and examples
Option 3: Manual Installation
# Create the commands directory
mkdir -p ~/.claude/commands
# Copy the slash command file from your local GitLab MCP project
cp /path/to/gitlab-mcp/claude-integration/gitlab-slash-command.md ~/.claude/commands/gitlab.mdOption 4: Download and Install
If you don't have the project locally:
# Create directory
mkdir -p ~/.claude/commands
# Download the slash command file (replace with actual URL when published)
curl -o ~/.claude/commands/gitlab.md https://raw.githubusercontent.com/your-username/gitlab-mcp-server/main/claude-integration/gitlab-slash-command.mdUsage Examples:
Once installed, you can use these slash commands in Claude Code:
# Quick resolve
/gitlab resolve myorg/project 123 abc456def
# Analyze discussions
/gitlab analyze myorg/project 123
# Mark multiple as fixed
/gitlab fix myorg/project 123 ["abc123", "def456"]
# Intelligent implementation of all feedback (your main workflow!)
/gitlab implement myorg/project 123
# Custom reply
/gitlab reply myorg/project 123 abc456def "Thanks for the feedback!"
# Get thread summary
/gitlab summary myorg/project 123Available Commands:
/gitlab analyze <project> <mr_id>- Analyze discussions and detect questions/gitlab summary <project> <mr_id>- Get concise thread summary/gitlab resolve <project> <mr_id> <discussion_id>- Resolve specific discussion/gitlab fix <project> <mr_id> <discussion_ids>- Mark discussions as fixed/gitlab implement <project> <mr_id>- Intelligent implementation of all feedback/gitlab reply <project> <mr_id> <discussion_id> "message"- Custom reply
This gives you rapid GitLab management directly in Claude Code! 🚀
Quick Start Workflow:
Install the slash commands:
npx asapo-gitlab-mcp-installUse your main workflow:
/gitlab implement myorg/project 123
Instead of typing "Read the comments on MR !123, fix where possible, resolve threads if fixed and answer if you need further information", just use the slash command! 🎯
Your Workflow: "Implement, Don't Just Talk"
You can now tell Claude exactly what you wanted:
"Read the comments on the MR, fix where possible, resolve threads if fixed and answer if you need further information"
Claude will use the intelligent_mr_response tool to:
- 📖 Read all discussions in the merge request
- 🔍 Analyze each piece of feedback to understand what needs to be done
- 📋 Generate specific file modification instructions for Claude Code to execute
- 🛠️ Claude Code implements the changes using its file tools (Edit, MultiEdit, Write)
- ✅ Resolve threads after changes are implemented
- ❓ Only comment when clarification is needed - no fake responses!
The Correct Architecture:
# Your desired command:
"Analyze MR !123, implement the requested changes, resolve threads when fixed,
ask questions only when feedback is unclear."
# What happens:
1. MCP server analyzes feedback and generates file instructions
2. Claude Code receives actionable modification steps
3. Claude Code uses Edit/Write tools to implement changes
4. Threads resolved after actual implementationWhat Actually Happens Now:
For simple feedback:
Reviewer: "remove this line"
→ MCP: "INSTRUCTION: Remove code in file 'Invoice.php' at line 42. Use Edit tool to delete the specified line."
→ Claude Code: *uses Edit tool to remove the line*
→ Thread resolved after implementation ✅For architectural feedback:
Reviewer: "Invoice should be readonly, no setters, use builder pattern"
→ MCP: "ARCHITECTURAL INSTRUCTIONS:
1. Modify Invoice.php: Remove all setter methods (setAmount, setDate, etc.)
2. Create InvoiceBuilder.php: Implement builder pattern with fluent interface
3. Update calling code: Replace direct instantiation with builder usage
Files to modify: [Invoice.php, InvoiceBuilder.php, InvoiceService.php]"
→ Claude Code: *implements multi-step architectural changes across files*
→ Thread resolved after complete implementation ✅For questions/unclear feedback:
Reviewer: "what about the validation logic?"
→ MCP: *adds clarifying question comment*
→ Thread kept open for responseFor general comments:
Reviewer: "The whole invoice system needs to be immutable"
→ MCP: "GENERAL FEEDBACK ANALYSIS:
Scope: System-wide immutability implementation
Files likely affected: Invoice*.php, *Invoice*.php
Instructions: Search codebase for Invoice classes, analyze mutability patterns,
implement immutable design with builder/factory patterns"
→ Claude Code: *analyzes codebase and implements comprehensive changes*Key Improvements:
- ✅ Generates actionable file modification instructions instead of fake responses
- ✅ Claude Code actually implements changes using its file tools
- ✅ Resolves threads only when work is done
- ✅ No more fake "thanks, resolved!" messages
- ✅ Comments only when genuine questions exist
- ✅ Dry-run shows specific file changes that will be made
Safety Features:
- Dry-run mode: Preview specific file modifications before executing
- Smart analysis: Detects complexity levels and provides appropriate instructions
- Clarification requests: Asks specific questions when feedback is unclear
- Clear separation: MCP provides instructions, Claude Code executes them
Comment Attribution
All comments generated by the GitLab MCP server include a clear attribution footer:
---
🤖 Generated via Claude Code + GitLab MCPAvoiding Personal Attribution
Since the MCP server uses your GitLab token, comments appear to come from your account. To avoid this:
Option 1: Dedicated Bot Account (Recommended)
Create a GitLab bot account:
Email: [email protected] Username: yourname-bot Display name: GitLab AssistantAdd bot to projects as Developer/Maintainer
Generate bot token and update Claude Code:
claude mcp update gitlab --env GITLAB_TOKEN=bot_token_here
Option 2: Team Account
Use a shared team account token instead of your personal token.
Development
Scripts
npm run build- Build the TypeScript projectnpm run dev- Build in watch modenpm start- Start the servernpm run lint- Run ESLintnpm run format- Format code with Prettier
Project Structure
src/
├── index.ts # MCP server implementation
├── gitlab-client.ts # GitLab API client
└── types.ts # TypeScript type definitionsSecurity
This server is designed with security in mind:
- Controlled Write Access: Write operations only for comments and thread resolution
- Token-Based Auth: Uses GitLab Personal Access Tokens with appropriate scopes
- Input Validation: All inputs are validated using Zod schemas
- Error Handling: Comprehensive error handling prevents information leakage
- Clear Attribution: All generated comments include AI attribution footer
License
MIT
Publishing to npm
If you want to publish your own version of this package:
1. Update Package Details
Edit package.json:
- Change the
nameto your package name - Update the
repositoryURLs to your GitHub repository - Update the
authorfield - Bump the
versionif needed
2. Build and Test
npm run build
npm pack --dry-run # Test what will be published3. Publish
# Login to npm (one time)
npm login
# Publish the package
npm publish
# Or publish with specific tag
npm publish --tag beta4. Update Claude Code Instructions
After publishing, users can install with:
npm install -g @asapo/gitlab-mcp-server
claude mcp add gitlab @asapo/gitlab-mcp-server \
--env GITLAB_BASE_URL=https://gitlab.com \
--env GITLAB_TOKEN=your_gitlab_token_hereContributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Troubleshooting
Common Issues
Authentication Errors:
- Verify your
GITLAB_TOKENis correct and has the required scopes - Check that your GitLab instance URL is correct in
GITLAB_BASE_URL
Network Errors:
- Ensure you can reach your GitLab instance from your network
- Check firewall settings if using a self-hosted GitLab instance
Permission Errors:
- Verify your token has access to the projects you're trying to query
- Ensure the projects exist and you have at least read access
Debug Mode
Set the environment variable DEBUG=1 for verbose logging:
DEBUG=1 npm start