gitlab-mcp

gitlab-mcp

MCP server that acts as a thin proxy over GitLab REST API v4, enabling users to list merge requests, view diffs, and leave inline comments without leaving their MCP client.

Category
访问服务器

README

@vinihcrosa/gitlab-mcp

MCP server (stdio) que funciona como proxy fino sobre a REST API v4 de uma instância GitLab CE self-hosted.

MVP com um objetivo só: navegar merge requests e deixar review inline sem abrir o browser. Ler o estado da CI faz parte disso — pipeline vermelha é justamente o momento em que o review para. Escrever em CI não faz: nada dispara, cancela ou re-roda pipeline, e nada lê variável ou secret. Fora de escopo também: issues, criar/mergear MR, aprovações, recursos Premium/Ultimate.

Como funciona

  • 13 tools: 10 de leitura, 3 de escrita.
  • Toda resposta passa por whitelist explícita de campos — a API do GitLab devolve objetos com 40+ campos e nenhum deles chega cru no contexto do modelo.
  • Toda listagem tem per_page com default 20 (máximo 100) e informa se há mais páginas.
  • Read-only por default. As tools de escrita só funcionam com GITLAB_READ_ONLY=false.
  • O diff sai parseado, com os números de linha de cada lado impressos (old= / new=), porque é isso que torna o comentário em linha confiável.

Instalação

Não precisa instalar nada: o client MCP executa o pacote via npx e o npm cuida do download.

npx -y @vinihcrosa/gitlab-mcp

Rodar esse comando na mão só serve para conferir que sobe — ele fica esperando o protocolo em stdin. A configuração de verdade está em Configuração no client.

Requer Node >= 20 (usa fetch nativo e AbortSignal.timeout).

A partir do código-fonte

Para desenvolver ou rodar um fork:

git clone https://github.com/vinihcrosa/gitlab-mcp.git
cd gitlab-mcp
npm install     # o script `prepare` já compila

O client passa a apontar para dist/index.js com caminho absoluto, em vez de npx.

Configuração

Variável Obrigatória Default Descrição
GITLAB_URL sim — Base da instância, ex.: https://gitlab.empresa.com. Barra final e sufixo /api/v4 são removidos automaticamente.
GITLAB_TOKEN sim — Personal Access Token.
GITLAB_READ_ONLY não true Só o literal false habilita as tools de escrita.
GITLAB_CA_CERT não — Caminho para CA privada / cert self-signed em PEM.
GITLAB_TIMEOUT_MS não 20000 Timeout por request, em ms.

Falta GITLAB_URL ou GITLAB_TOKEN → o server escreve o erro em stderr e sai com código 1. Não sobe quebrado.

Veja .env.example.

Escopos do token — leia antes de gerar

Tools Escopo mínimo
1–7 (whoami, list_my_projects, list_my_authored_mrs, list_mrs_awaiting_my_review, get_mr, get_mr_diff, list_mr_discussions) read_api
11, 13 (get_mr_pipeline, list_pipelines) read_api
12 (get_job_log) api — ver nota abaixo
8–10 (comment_on_mr, comment_on_mr_line, reply_to_mr_discussion) api

get_job_log pede api por precaução, não por medida: não foi verificado se read_api alcança /jobs/:id/trace. Se você testar com um token read_api e funcionar, esta linha da tabela muda e nenhum código muda junto.

read_api não escreve. Se você gerar o token com read_api e tentar comentar, o GitLab devolve 403 — o server traduz isso para uma mensagem dizendo exatamente que provavelmente é esse o caso, mas o conserto é regerar o token com escopo api.

Configuração no client

MCP stdio não é daemon: você não sobe o servidor, você registra um comando. O client executa esse comando, conversa por stdin/stdout e mata o processo ao fim da sessão.

Claude Code

Instale global e aponte para o arquivo, com caminhos absolutos:

npm i -g @vinihcrosa/gitlab-mcp

claude mcp add gitlab -s user \
  -e GITLAB_URL=https://gitlab.empresa.com \
  -e GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx \
  -e GITLAB_READ_ONLY=true \
  -- "$(which node)" "$(npm root -g)/@vinihcrosa/gitlab-mcp/dist/index.js"

-s user vale em todos os projetos. Use -s project só se aceitar que o arquivo .mcp.json gerado é commitável — e aí não coloque o token nele.

Por que não npx aqui. Duas armadilhas, as duas silenciosas — o sintoma é sempre Connection closed:

  1. O bloco env substitui o ambiente do processo em vez de estender. Sem PATH, o npx não acha o node e morre com env: node: No such file or directory. Se insistir no npx, passe -e PATH=/opt/homebrew/bin:/usr/bin:/bin junto.
  2. O client roda o servidor com cwd no diretório do projeto. Se esse projeto for este repositório, o npx resolve o nome para o pacote local em vez do publicado e falha com command not found. Só afeta quem desenvolve o próprio pacote, mas custa meia hora para descobrir.

Caminho absoluto para o node e para o dist/index.js não depende de PATH nem de cwd, e ainda corta a resolução do npx a cada spawn.

Claude Desktop

claude_desktop_config.json:

{
  "mcpServers": {
    "gitlab": {
      "command": "/opt/homebrew/bin/node",
      "args": ["/opt/homebrew/lib/node_modules/@vinihcrosa/gitlab-mcp/dist/index.js"],
      "env": {
        "GITLAB_URL": "https://gitlab.empresa.com",
        "GITLAB_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
        "GITLAB_READ_ONLY": "true"
      }
    }
  }
}

Descubra os dois caminhos da sua máquina com which node e npm root -g — variam entre Homebrew, nvm e Linux. As mesmas duas armadilhas da seção do Claude Code valem aqui.

Rodando a partir do código-fonte, aponte args para o dist/index.js do seu clone.

Para habilitar review inline, troque para "GITLAB_READ_ONLY": "false" (e use um token com escopo api).

Com CA privada:

"env": {
  "GITLAB_URL": "https://gitlab.empresa.com",
  "GITLAB_TOKEN": "glpat-...",
  "GITLAB_CA_CERT": "/etc/ssl/certs/empresa-ca.pem"
}

Não existe opção de desabilitar verificação TLS. De propósito.

Testar antes de plugar no client

npm run build
GITLAB_URL=https://gitlab.empresa.com \
GITLAB_TOKEN=glpat-xxx \
npx @modelcontextprotocol/inspector node dist/index.js

O Inspector abre no browser, lista as 13 tools e deixa você chamar cada uma com os argumentos na mão. Se algo falhar aqui, falha no client também — e aqui você vê a mensagem de erro inteira.

Logs do server saem em stderr (aba de logs do Inspector). stdout é exclusivo do protocolo MCP.

Checklist de validação manual

Nesta ordem. Cada passo alimenta o seguinte.

  1. whoami — devolve seu username? Se der Token inválido ou expirado., pare aqui.

  2. list_my_projects — anote o path_with_namespace de um projeto com MR aberto.

  3. list_mrs_awaiting_my_review — deve listar MRs onde você é reviewer. Se vier vazio e você sabe que tem MR esperando: confira que você está como reviewer e não como assignee (são campos diferentes no GitLab).

  4. get_mr com project + iid (o número da URL, /-/merge_requests/123) — confira que diff_refs não é null.

  5. get_mr_diff com o mesmo project + iid — deve sair o diff com old= / new= em cada linha e os diff_refs no rodapé. Anote uma linha add e uma linha ctx.

    A partir daqui precisa de GITLAB_READ_ONLY=false e token com escopo api.

  6. comment_on_mr — comentário geral. Abra o web_url retornado e confirme que apareceu.

  7. comment_on_mr_line numa linha add: side="new", line = o número new= daquela linha.

  8. comment_on_mr_line numa linha ctx: side="context", line = o new=, context_old_line = o old= da mesma linha. Os dois são obrigatórios — é o erro mais comum.

  9. list_mr_discussions — as duas threads criadas devem aparecer com position e discussion_id.

  10. reply_to_mr_discussion com um dos discussion_id do passo 9.

Se o passo 7 ou 8 falhar, a mensagem de erro diz quais linhas de fato existem naquele lado do diff. Não é preciso adivinhar.

As 13 tools

# Tool Escrita Resumo
1 whoami Identidade do token. Cacheada no processo.
2 list_my_projects Projetos onde você é membro, por atividade recente.
3 list_my_authored_mrs MRs que você criou, em todos os projetos.
4 list_mrs_awaiting_my_review MRs abertos onde você é reviewer.
5 get_mr Detalhe do MR, incluindo diff_refs.
6 get_mr_diff Diff parseado com numeração de linha explícita.
7 list_mr_discussions Threads de comentário, com discussion_id e posição.
8 comment_on_mr sim Comentário geral no MR.
9 comment_on_mr_line sim Thread ancorada numa linha do diff.
10 reply_to_mr_discussion sim Resposta numa thread existente.
11 get_mr_pipeline Pipeline mais recente do MR e seus jobs. Nomeia o que falhou.
12 get_job_log Log do job, limpo e cortado pelo fim.
13 list_pipelines Pipelines do projeto, com filtro de branch e status.

Notas de implementação que importam

  • iid, não id. Todas as tools de MR usam o iid — o número que aparece na URL. O id global existe e a API aceita em outros contextos; usar o errado pega o MR de outro projeto ou dá 404.
  • Resolução de projeto. O path (grupo/subgrupo/projeto) é URL-encoded (%2F) e resolvido para id numérico, com cache em memória.
  • comment_on_mr_line busca diff_refs fresco com um GET do MR imediatamente antes do POST, e nunca aceita os shas como parâmetro: se alguém deu push, os shas velhos invalidam a posição.
  • Validação local antes do POST. A tool confere que o arquivo está no MR e que a linha existe no lado pedido. Se não existir, falha localmente listando as linhas válidas, em vez de mandar pro GitLab e devolver um 400 opaco. Se mesmo assim vier 400, a mensagem do GitLab volta na íntegra junto com o payload enviado.
  • Linha de contexto exige os dois números. side="context" sem context_old_line é rejeitado localmente, com o valor correto na mensagem.
  • Prompt injection. description de MR e body de comentário são conteúdo escrito por qualquer pessoa com acesso ao GitLab. Vêm envelopados em <untrusted source="gitlab:..."> e a resposta carrega uma nota dizendo que aquilo é dado, não instrução. Não é blindagem; é o mínimo defensável.
  • Comentário multi-linha está fora de escopo. Só linha única.

Testes

npm test

Todos offline. Cobrem a lógica pura — onde saída errada parece plausível:

  • src/diff.ts — hunk misto, múltiplos hunks, arquivo novo/deletado/renomeado, \ No newline at end of file, truncamento em 400 linhas, binário. É o que quebra comment_on_mr_line quando erra.
  • src/trace.ts — ANSI (CSI e OSC), marcador de seção, prefixo de timestamp e de stream, colapso de barra de progresso, corte pela cauda em limite de linha.
  • src/pipelines.ts — whitelist de campos, escolha da pipeline mais recente, precedência entre "nunca começou" e "log apagado", envelope <untrusted>.
  • src/tools/index.ts — a superfície registrada é exatamente 13 tools, o que pega tanto tool nova que não registrou quanto tool existente derrubada por engano.

Sem testes de integração e sem mock de HTTP: a camada de I/O não tem cobertura, e o que isso deixa de fora está declarado em docs/features/001-ci-pipelines/tests.md em vez de subentendido.

Estrutura

src/
├── index.ts       # entrypoint stdio. NUNCA escreve em stdout.
├── config.ts      # env, validação no boot, normalização da URL
├── gitlab.ts      # único ponto de saída HTTP: token, timeout, CA, paginação, 429, erros
├── errors.ts      # GitLabError / ToolError
├── projects.ts    # resolveProject + cache path <-> id
├── diff.ts        # parser de diff unificado (puro, testado)
├── trace.ts       # limpeza e corte pela cauda de log de job (puro, testado)
├── pipelines.ts   # projeção, decisão e renderização de CI (puro, testado)
├── format.ts      # whitelist, truncamento, blocos <untrusted>
└── tools/         # as 13 tools, agrupadas por domínio

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选