npm package: @alexsarrell/gitlab-mcp-server
Description: GitLab MCP server for self-hosted GitLab instances
Latest version: 0.2.0

# gitlab-mcp

MCP (Model Context Protocol) сервер для self-hosted GitLab. Позволяет AI-ассистентам (Claude Code, Cursor, Windsurf и др.) работать с GitLab через стандартный MCP-протокол.

Разработан для [gitlab.just-ai.com](https://gitlab.just-ai.com), но работает с любым GitLab инстансом (self-hosted или gitlab.com).

## Возможности

- **30 MCP tools** — проекты, файлы, MR, issues, пайплайны, поиск, ветки, метки, CI lint
- **Настраиваемые политики доступа** — RBAC + ABAC через Casbin, YAML-профили с наследованием
- **Безопасность** — hardcoded deny list опасных операций, secret detection в output, deny-list файлов
- **Rate limiting** — per-session, burst allowance, лимиты на тяжёлые операции
- **Audit logging** — structured JSON в stderr, неотключаемый
- **Zero-config режим** — работает только с env vars, без YAML файла

## Быстрый старт

### Claude Code / Claude Desktop

Добавьте в настройки MCP:

```json
{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": ["-y", "@alexsarrell/gitlab-mcp-server"],
      "env": {
        "GITLAB_URL": "https://gitlab.just-ai.com",
        "GITLAB_MCP_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}
```

Готово. Сервер стартует с дефолтным профилем — все read/write операции разрешены, secret detection включён.

### С YAML-конфигом (гранулярные политики)

```json
{
  "mcpServers": {
    "gitlab": {
      "command": "npx",
      "args": ["-y", "@alexsarrell/gitlab-mcp-server"],
      "env": {
        "GITLAB_MCP_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
        "GITLAB_MCP_CONFIG": "/path/to/gitlab-mcp.config.yaml"
      }
    }
  }
}
```

## Переменные окружения

| Переменная | Обязательная | Описание |
|-----------|-------------|----------|
| `GITLAB_MCP_TOKEN` | Да | GitLab Personal/Project/Group Access Token |
| `GITLAB_URL` | Нет* | URL GitLab инстанса (e.g. `https://gitlab.just-ai.com`) |
| `GITLAB_MCP_CONFIG` | Нет | Путь к YAML конфигу |

\* Обязательна в zero-config режиме (без YAML файла). В YAML конфиге задаётся через `gitlab.url`.

## Токены

Рекомендуемые scopes для токена:

| Scope | Для чего |
|-------|----------|
| `read_api` | Чтение проектов, MR, issues, пайплайнов |
| `read_repository` | Чтение файлов из репозиториев |
| `write_repository` | Создание веток |
| `api` | Полный доступ (write-операции: MR, issues, comments, pipelines) |

Минимальный набор для read-only: `read_api` + `read_repository`.

## MCP Tools

### Read-операции

| Tool | Описание |
|------|----------|
| `project:list` | Список проектов (поиск, пагинация) |
| `project:info` | Детали проекта |
| `file:read` | Чтение файла из репо |
| `file:list` | Содержимое директории |
| `file:tree` | Рекурсивное дерево файлов |
| `mr:list` | Список MR (фильтр по state, labels) |
| `mr:get` | Детали MR |
| `mr:diff` | Diff MR |
| `issue:list` | Список issues |
| `issue:get` | Детали issue |
| `search:code` | Поиск по коду |
| `search:issues` | Поиск по issues |
| `search:mrs` | Поиск по MR |
| `pipeline:status` | Статус пайплайна + джобы |
| `pipeline:logs` | Логи CI-джобы |
| `comment:list` | Комментарии к MR/issue |
| `branch:list` | Список веток |
| `label:list` | Список меток проекта |

### Write-операции

| Tool | Описание |
|------|----------|
| `mr:create` | Создание MR |
| `mr:update` | Обновление MR (title, description, labels, assignees) |
| `mr:merge` | Merge MR (squash, remove source branch) |
| `mr:approve` | Approve MR |
| `issue:create` | Создание issue |
| `issue:update` | Обновление issue (title, labels, state, assignees) |
| `comment:create` | Комментарий к MR или issue |
| `comment:reply` | Ответ на discussion thread в MR |
| `pipeline:trigger` | Запуск пайплайна (с переменными) |
| `pipeline:retry` | Перезапуск упавшего пайплайна |
| `pipeline:cancel` | Отмена пайплайна |
| `branch:create` | Создание ветки |
| `branch:delete` | Удаление ветки |
| `label:create` | Создание метки |
| `ci:lint` | Валидация `.gitlab-ci.yml` |

## Конфигурация (YAML)

Пример конфига с политиками доступа:

```yaml
version: "1"

gitlab:
  url: "https://gitlab.just-ai.com"

defaults:
  role: reader

profiles:
  reader:
    tools:
      allow: ["project:*", "file:*", "mr:list", "mr:get", "mr:diff",
              "issue:*", "search:*", "pipeline:status", "pipeline:logs",
              "comment:list", "branch:list", "label:list"]

  contributor:
    extends: reader
    tools:
      allow: ["mr:create", "mr:update", "issue:create", "issue:update",
              "comment:create", "comment:reply", "pipeline:trigger",
              "branch:create", "label:create", "ci:lint"]

  maintainer:
    extends: contributor
    tools:
      allow: ["mr:merge", "mr:approve", "branch:delete",
              "pipeline:retry", "pipeline:cancel"]

policies:
  # Все проекты just-ai — contributor
  - match: "group:just-ai/**"
    profile: contributor

  # Инфра-проекты — только чтение
  - match: "group:just-ai/infra/**"
    profile: reader

  # Core-проект — полный доступ
  - match: "project:just-ai/platform/core"
    profile: maintainer

  # Секретный проект — запрет на чтение файлов
  - match: "project:just-ai/infra/secrets"
    profile: reader
    tools:
      deny: ["file:read"]

rate_limits:
  per_session: 60        # запросов в минуту
  per_token: 120         # агрегированно по всем сессиям
  burst_multiplier: 2    # допустимый burst
  burst_window_sec: 10
  heavy_ops:
    "pipeline:trigger": 10   # в час
    "mr:create": 20          # в час

security:
  secret_detection: true
  denied_file_patterns:
    - ".env*"
    - "*.pem"
    - "*.key"
    - "*secret*"
    - "*credential*"
    - "id_rsa*"
```

### Наследование политик

- Профили поддерживают `extends` — `contributor` наследует все права `reader`
- Приоритет: project policy > group policy > defaults
- `deny` всегда побеждает `allow` на любом уровне
- MCP политики могут только **сужать** права GitLab-токена, не расширять

## Безопасность

### Запрещённые операции (hardcoded, не настраивается)

Эти операции заблокированы всегда, независимо от конфигурации:

- Удаление проектов и групп
- Transfer проекта между группами
- Экспорт проекта
- Форк в чужой namespace
- Управление пользователями
- Системные admin-настройки
- SSH-ключи и deploy keys с write-доступом

### Secret Detection

Автоматическая маскировка секретов в output:

- GitLab PAT (`glpat-*`)
- GitLab Deploy Tokens (`gldt-*`)
- Private keys (PEM)
- AWS Access Keys (`AKIA*`)
- Пароли в URL
- GitHub tokens

Секреты заменяются на `[REDACTED:тип]`, а не блокируются — AI видит, что секрет был, но не видит значение.

### Запрещённые файлы

По умолчанию блокируется чтение: `.env*`, `*.pem`, `*.key`, `*secret*`, `*credential*`, `id_rsa*`, `kubeconfig`.

## Audit Logging

Каждое действие логируется в stderr как structured JSON:

```json
{
  "timestamp": "2026-04-08T19:30:00.000Z",
  "level": "warn",
  "session_id": "sess_abc123",
  "tool": "mr:create",
  "project": "just-ai/platform/core",
  "params": {"source_branch": "feature/x", "target_branch": "main"},
  "result": "success",
  "duration_ms": 342
}
```

Уровни: `info` (read), `warn` (write), `error` (ошибки), `critical` (denied).

## Разработка

```bash
git clone git@gitlab.just-ai.com:secretary/ai-generated/gitlab-mcp-server.git
cd gitlab-mcp-server
npm install
npm test          # 142 теста
npm run lint      # TypeScript type check
npm run build     # Сборка в dist/
npm run dev       # Запуск в dev-режиме (tsx)
```

## Стек

- TypeScript 5.x + Node.js 20+
- [@modelcontextprotocol/sdk](https://github.com/modelcontextprotocol/typescript-sdk) — MCP протокол
- [@gitbeaker/rest](https://github.com/jdalrymple/gitbeaker) — GitLab API клиент
- [casbin](https://casbin.org/) — Policy engine (RBAC + ABAC)
- [vitest](https://vitest.dev/) — Тесты
- [tsup](https://tsup.egoist.dev/) — Сборка

## Лицензия

MIT