GitLab MCP Server
by lxnewayfarer
README.md
# GitLab MCP Server (OAuth)
A production-ready **MCP (Model Context Protocol) server** that lets AI agents
interact with GitLab through a **curated set of 20 tools**. Every user
authenticates with **their own GitLab account via OAuth 2.0** — no Personal
Access Tokens. The server calls the GitLab REST API directly (no `glab` CLI).
```
User → GitLab OAuth Login → MCP Server → GitLab REST API
```
## Features
- **Per-user OAuth 2.0** login (PKCE + `state`), token auto-refresh, logout.
- **MCP-client OAuth (zero token paste)** — the server is its own OAuth 2.0
Authorization Server: Dynamic Client Registration + authorization-code/PKCE,
with opaque, rotating refresh tokens (reuse detection revokes the whole
rotation family). GitLab is the upstream identity provider. Manual bearer-token
paste remains as a fallback.
- **Server-issued bearer tokens** — the client sends one bearer token; the
server maps it to that user's GitLab session.
- **Secure token storage** — GitLab tokens encrypted at rest (AES-256-GCM);
session tokens stored only as sha-256 hashes.
- **Strict tool allowlist** — only the 20 tools below; no raw API proxy, no
admin/destructive operations.
- **Real GitLab authorization** — every action runs as the authenticated user
with their own token; project access is checked before each call.
- **Audit logging** — every tool call recorded in PostgreSQL (secrets stripped).
- **Streamable HTTP MCP transport**, PostgreSQL + Prisma.
- **Docker Compose** one-command deploy. Vitest unit + integration tests.
## The 20 tools
**Merge requests:** `create_merge_request`, `update_merge_request`,
`get_merge_request`, `list_merge_requests`, `get_merge_request_diff`,
`get_merge_request_versions`.
**Comments & discussions:** `add_comment`, `list_merge_request_discussions`,
`reply_to_discussion`.
**Review actions:** `assign_reviewer`, `set_labels`, `approve_merge_request`,
`unapprove_merge_request`.
**Pipelines & jobs:** `get_pipeline_status`, `list_pipelines`,
`get_pipeline_jobs`, `get_job_log`.
**Repository:** `get_file_content` (read a file at a given ref; read-only).
**User lookup:** `get_current_user`, `find_user`.
## Quick start (Docker)
1. **Create a GitLab OAuth application** (User Settings → Applications, or an
instance/group app). See [`docs/oauth.md`](docs/oauth.md) for details.
- Scopes: `read_user`, `api`
- Redirect URI: `http://localhost:3000/auth/callback`
- Copy the **Application ID** and **Secret**.
2. **Configure environment:**
```bash
cp .env.example .env
# edit .env: set GITLAB_CLIENT_ID, GITLAB_CLIENT_SECRET, GITLAB_REDIRECT_URI
# and generate an encryption key:
openssl rand -hex 32 # paste into ENCRYPTION_KEY
```
For self-hosted GitLab, also set `GITLAB_BASE_URL`.
3. **Run the stack** (Postgres + app, migrations run automatically):
```bash
docker compose up --build
```
4. **Log in & get your token:** open <http://localhost:3000/auth/login> in a
browser, authorize with GitLab, and copy the **bearer token** shown.
5. **Configure your MCP client** to use the Streamable HTTP endpoint:
- URL: `http://localhost:3000/mcp`
- Header: `Authorization: Bearer <your-token>`
Example (clients supporting remote HTTP MCP servers with headers):
```json
{
"mcpServers": {
"gitlab": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": { "Authorization": "Bearer <your-token>" }
}
}
}
```
To disconnect: `curl -X POST http://localhost:3000/auth/logout -H "Authorization: Bearer <token>"`.
## Local development (without Docker for the app)
```bash
# Start datastores only:
docker compose up -d postgres
cp .env.example .env # set GitLab creds + ENCRYPTION_KEY
# point DATABASE_URL at localhost (the defaults already do)
npm install
npm run db:generate
npm run db:migrate # creates/apply migrations locally
npm run dev # http://localhost:3000
```
## Tests
```bash
npm test
```
GitLab is always mocked — no live calls and no credentials required.
## Documentation
- [Setup guide](docs/setup.md)
- [OAuth configuration guide](docs/oauth.md)
- [Deployment guide](docs/deployment.md)
- [Security review](docs/security.md)
- [Architecture](docs/architecture.md)
- [`CLAUDE.md`](CLAUDE.md) — repo conventions / hard rules for contributors.
## License
MIT
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues