GitLab MCP 서버
✨ 특징
- 포괄적인 GitLab API 통합 - 저장소, 이슈, 병합 요청, 위키 등에 액세스
- 두 전송 모두 지원됨 - stdio 또는 SSE(Server-Sent Events)와 함께 사용
- 일관된 응답 형식 - 표준화된 페이지 매김 및 응답 구조
- 강력한 TypeScript 타이핑 - 유형 안전을 위해 MCP SDK로 구축됨
- 전체 문서 - 사용 가능한 모든 도구에 대한 예
🔍 지원되는 작업
- 저장소 관리 - 저장소 검색, 생성, 포크
- 파일 처리 - 파일 읽기, 생성, 업데이트
- 지점 운영 - 지점 생성 및 관리
- 이슈 추적 - 이슈 생성, 목록, 필터링
- 병합 요청 - 병합 요청 생성, 나열, 검토
- 그룹 관리 - 그룹 프로젝트 및 멤버 목록
- 프로젝트 활동 - 이벤트 추적 및 커밋 기록
- Wiki 관리 - 첨부 파일이 있는 프로젝트 및 그룹 Wiki에 대한 완벽한 지원
- 멤버 관리 - 프로젝트/그룹 멤버를 나열하고 관리합니다.
🚀 시작하기
설치
npm에서 (권장)
지엑스피1
출처에서
# Clone the repository
git clone https://github.com/yoda-digital/mcp-gitlab-server.git
cd mcp-gitlab-server
# Install dependencies
npm install
# Build the project
npm run build
구성
환경 변수
서버에는 다음과 같은 환경 변수가 필요합니다.
변하기 쉬운 | 필수의 | 기본 | 설명 |
---|
GITLAB_PERSONAL_ACCESS_TOKEN | 예 | - | 귀하의 GitLab 개인 액세스 토큰 |
GITLAB_API_URL | 아니요 | https://gitlab.com/api/v4 | GitLab API URL |
PORT | 아니요 | 3000 | SSE 운송 항구 |
USE_SSE | 아니요 | false | SSE 전송을 사용하려면 'true'로 설정하세요. |
GITLAB_READ_ONLY_MODE | 아니요 | false | 읽기 전용 모드를 활성화하려면 'true'로 설정하세요(아래 참조) |
읽기 전용 모드
GITLAB_READ_ONLY_MODE
true
로 설정하면 서버는 읽기 작업만 허용합니다. 이는 GitLab 리소스에 대한 쓰기 권한이 없는 클라이언트 애플리케이션에 유용합니다. 읽기 전용 모드에서는 다음 도구를 사용할 수 있습니다.
search_repositories
get_file_contents
list_group_projects
get_project_events
list_commits
list_issues
list_merge_requests
list_project_wiki_pages
get_project_wiki_page
list_group_wiki_pages
get_group_wiki_page
list_project_members
list_group_members
읽기 전용 모드에서 쓰기 작업(생성, 업데이트, 삭제)을 사용하려고 하면 오류가 발생합니다.
MCP 설정 구성
MCP 설정 파일에 GitLab MCP 서버를 추가합니다.
{
"mcpServers": {
"gitlab": {
"command": "npx",
"args": ["-y", "@yoda.digital/gitlab-mcp-server"],
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "your_token_here",
"GITLAB_API_URL": "https://gitlab.com/api/v4"
},
"alwaysAllow": [],
"disabled": false
}
}
}
읽기 전용 모드의 경우 GITLAB_READ_ONLY_MODE
환경 변수를 추가합니다.
{
"mcpServers": {
"gitlab-readonly": {
"command": "npx",
"args": ["-y", "@yoda.digital/gitlab-mcp-server"],
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "your_token_here",
"GITLAB_API_URL": "https://gitlab.com/api/v4",
"GITLAB_READ_ONLY_MODE": "true"
},
"alwaysAllow": [],
"disabled": false
}
}
}
용법
stdio 전송(기본값)
# Set your GitLab personal access token
export GITLAB_PERSONAL_ACCESS_TOKEN=your_token_here
# Run the server
npm start
SSE 운송으로
# Set your GitLab personal access token and enable SSE
export GITLAB_PERSONAL_ACCESS_TOKEN=your_token_here
export GITLAB_READ_ONLY_MODE=false
export USE_SSE=true
export PORT=3000 # Optional, defaults to 3000
# Run the server
npm start
npx로
# Run directly with npx
GITLAB_PERSONAL_ACCESS_TOKEN=your_token_here npx @yoda.digital/gitlab-mcp-server
🛠️ 사용 가능한 도구
저장소 작업
{
"search": "project-name",
"page": 1,
"per_page": 20
}
{
"name": "new-project",
"description": "A new project",
"visibility": "private",
"initialize_with_readme": true
}
{
"project_id": "username/project",
"namespace": "target-namespace"
}
{
"group_id": "group-name",
"archived": false,
"visibility": "public",
"include_subgroups": true,
"page": 1,
"per_page": 20
}
파일 작업
{
"project_id": "username/project",
"file_path": "path/to/file.txt",
"ref": "main"
}
{
"project_id": "username/project",
"file_path": "path/to/file.txt",
"content": "File content here",
"commit_message": "Add/update file",
"branch": "main",
"previous_path": "old/path/to/file.txt"
}
{
"project_id": "username/project",
"files": [
{
"path": "file1.txt",
"content": "Content for file 1"
},
{
"path": "file2.txt",
"content": "Content for file 2"
}
],
"commit_message": "Add multiple files",
"branch": "main"
}
지점 운영
{
"project_id": "username/project",
"branch": "new-branch",
"ref": "main"
}
이슈 운영
{
"project_id": "username/project",
"title": "Issue title",
"description": "Issue description",
"assignee_ids": [1, 2],
"milestone_id": 1,
"labels": ["bug", "critical"]
}
{
"project_id": "username/project",
"state": "opened",
"labels": "bug,critical",
"milestone": "v1.0",
"author_id": 1,
"assignee_id": 2,
"search": "keyword",
"created_after": "2023-01-01T00:00:00Z",
"created_before": "2023-12-31T23:59:59Z",
"updated_after": "2023-06-01T00:00:00Z",
"updated_before": "2023-06-30T23:59:59Z",
"page": 1,
"per_page": 20
}
{
"project_id": "username/project",
"issue_iid": 42,
"sort": "desc",
"order_by": "created_at",
"page": 1,
"per_page": 20
}
응답 형식:
{
"count": 15,
"notes": [
{
"id": 123456,
"body": "This is a comment on the issue",
"author": {
"id": 1,
"username": "username",
"name": "User Name"
},
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T00:00:00Z",
"system": false,
"type": "comment"
},
{
"id": 123457,
"body": "added label ~bug",
"author": {
"id": 1,
"username": "username",
"name": "User Name"
},
"created_at": "2023-01-02T00:00:00Z",
"updated_at": "2023-01-02T00:00:00Z",
"system": true,
"type": "system"
}
// ... other notes
]
}
{
"project_id": "username/project",
"issue_iid": 42,
"page": 1,
"per_page": 20
}
응답 형식:
{
"count": 5,
"discussions": [
{
"id": "discussion-123",
"individual_note": true,
"notes": [
{
"id": 123456,
"body": "This is a comment on the issue",
"author": {
"id": 1,
"username": "username",
"name": "User Name"
},
"created_at": "2023-01-01T00:00:00Z",
"updated_at": "2023-01-01T00:00:00Z",
"system": false,
"type": "comment"
}
]
},
{
"id": "discussion-124",
"individual_note": false,
"notes": [
{
"id": 123457,
"body": "This is a thread starter",
"author": {
"id": 1,
"username": "username",
"name": "User Name"
},
"created_at": "2023-01-02T00:00:00Z",
"updated_at": "2023-01-02T00:00:00Z",
"system": false,
"type": "comment"
},
{
"id": 123458,
"body": "This is a reply in the thread",
"author": {
"id": 2,
"username": "username2",
"name": "User Name 2"
},
"created_at": "2023-01-03T00:00:00Z",
"updated_at": "2023-01-03T00:00:00Z",
"system": false,
"type": "comment"
}
]
}
// ... other discussions
]
}
병합 요청 작업
{
"project_id": "username/project",
"title": "Merge request title",
"description": "Merge request description",
"source_branch": "feature-branch",
"target_branch": "main",
"allow_collaboration": true,
"draft": false
}
{
"project_id": "username/project",
"state": "opened",
"order_by": "created_at",
"sort": "desc",
"milestone": "v1.0",
"labels": "feature,enhancement",
"created_after": "2023-01-01T00:00:00Z",
"created_before": "2023-12-31T23:59:59Z",
"updated_after": "2023-06-01T00:00:00Z",
"updated_before": "2023-06-30T23:59:59Z",
"author_id": 1,
"assignee_id": 2,
"search": "keyword",
"source_branch": "feature-branch",
"target_branch": "main",
"page": 1,
"per_page": 20
}
프로젝트 활동
{
"project_id": "username/project",
"action": "pushed",
"target_type": "issue",
"before": "2023-12-31T23:59:59Z",
"after": "2023-01-01T00:00:00Z",
"sort": "desc",
"page": 1,
"per_page": 20
}
{
"project_id": "username/project",
"sha": "branch-or-commit-sha",
"path": "path/to/file",
"since": "2023-01-01T00:00:00Z",
"until": "2023-12-31T23:59:59Z",
"all": true,
"with_stats": true,
"first_parent": true,
"page": 1,
"per_page": 20
}
회원 운영
{
"project_id": "username/project",
"query": "search term",
"page": 1,
"per_page": 20
}
응답 형식:
{
"count": 3,
"items": [
{
"id": 123,
"username": "username",
"name": "User Name",
"state": "active",
"avatar_url": "https://gitlab.com/avatar.png",
"web_url": "https://gitlab.com/username",
"access_level": 50,
"access_level_description": "Owner"
}
// ... other members
]
}
{
"group_id": "group-name",
"query": "search term",
"page": 1,
"per_page": 20
}
응답 형식:
{
"count": 5,
"items": [
{
"id": 456,
"username": "username",
"name": "User Name",
"state": "active",
"avatar_url": "https://gitlab.com/avatar.png",
"web_url": "https://gitlab.com/username",
"access_level": 30,
"access_level_description": "Developer"
}
// ... other members
]
}
프로젝트 위키 운영
{
"project_id": "username/project",
"with_content": false
}
{
"project_id": "username/project",
"slug": "page-slug",
"render_html": false,
"version": "commit-sha"
}
{
"project_id": "username/project",
"title": "Page Title",
"content": "Wiki page content",
"format": "markdown"
}
{
"project_id": "username/project",
"slug": "page-slug",
"title": "New Page Title",
"content": "Updated wiki page content",
"format": "markdown"
}
{
"project_id": "username/project",
"slug": "page-slug"
}
{
"project_id": "username/project",
"file_path": "path/to/attachment.png",
"content": "base64-encoded-content",
"branch": "main"
}
그룹 위키 작업
{
"group_id": "group-name",
"with_content": false
}
{
"group_id": "group-name",
"slug": "page-slug",
"render_html": false,
"version": "commit-sha"
}
{
"group_id": "group-name",
"title": "Page Title",
"content": "Wiki page content",
"format": "markdown"
}
{
"group_id": "group-name",
"slug": "page-slug",
"title": "New Page Title",
"content": "Updated wiki page content",
"format": "markdown"
}
{
"group_id": "group-name",
"slug": "page-slug"
}
{
"group_id": "group-name",
"file_path": "path/to/attachment.png",
"content": "base64-encoded-content",
"branch": "main"
}
🔧 개발
요구 사항
- 노드.js 16+
- npm 7+
- 개인 액세스 토큰이 있는 GitLab 계정
프로젝트 구축
테스트 실행
코드 스타일 및 린팅
릴리스 프로세스
package.json
의 버전 업데이트- CHANGELOG.md 업데이트
- GitHub에 새 릴리스 만들기
npm publish
로 npm에 게시
📖 문서
더 자세한 내용을 보려면 설명서 사이트를 방문하거나 소스 코드에서 TypeScript 정의를 확인하세요.
💼 사용 사례
- AI 기반 개발 워크플로 - AI 어시스턴트가 GitLab 저장소와 상호 작용할 수 있도록 합니다.
- 자동화된 이슈 및 홍보 관리 - AI 지원을 통해 개발 프로세스 간소화
- Wiki 관리 - 문서 업데이트 및 지식 기반 관리 자동화
- 팀 협업 - AI 어시스턴트를 팀의 GitLab 워크플로에 통합
📊 로드맵
- [ ] GitLab CI/CD 통합
- [ ] 고급 프로젝트 분석
- [ ] 종합 테스트 모음
- [ ] GitLab GraphQL API 지원
- [ ] 확장된 웹훅 지원
🤝 기여하기
여러분의 참여를 환영합니다! 참여 방법은 다음과 같습니다.
- 저장소를 포크하세요
- 기능 브랜치를 생성합니다(
git checkout -b feature/amazing-feature
) - 변경 사항을 커밋하세요(
git commit -m 'Add some amazing feature'
) - 브랜치에 푸시(
git push origin feature/amazing-feature
) - 풀 리퀘스트 열기
적절하게 테스트를 업데이트하고 프로젝트의 코드 스타일을 따르세요.
📝 라이센스
이 프로젝트는 MIT 라이선스에 따라 라이선스가 부여되었습니다. 자세한 내용은 라이선스 파일을 참조하세요.
👥 기여자
이 프로젝트를 개선하는 데 도움을 주신 모든 기여자분들께 감사드립니다.
특별히 감사드립니다:
- thomasleveil - 일관된 응답 형식을 사용하여 프로젝트 및 그룹에 대한 GitLab 멤버 목록 기능을 구현했습니다.
📦 NPM 패키지
이 패키지는 npm에서 사용 가능합니다.
https://www.npmjs.com/package/@yoda.digital/gitlab-mcp-server