Skip to content
Zereight Gitlab logo

Zereight Gitlab

By zereightยท1,845

GitLab MCP server for projects, merge requests, issues, pipelines, wiki, releases, and more.

GitLab MCP Server

English | ํ•œ๊ตญ์–ด | ็ฎ€ไฝ“ไธญๆ–‡

๐Ÿ“– ๋ฌธ์„œ โ†’ ์„ค์ • ๊ฐ€์ด๋“œ, ํ™˜๊ฒฝ ๋ณ€์ˆ˜, ์ „์ฒด ๋„๊ตฌ ๋ ˆํผ๋Ÿฐ์Šค๋Š” ํ˜ธ์ŠคํŒ…๋œ ๋ฌธ์„œ ์‚ฌ์ดํŠธ์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Star History Chart

@zereight/mcp-gitlab

AI ํด๋ผ์ด์–ธํŠธ๋ฅผ ์œ„ํ•œ ํฌ๊ด„์ ์ธ GitLab MCP ์„œ๋ฒ„์ž…๋‹ˆ๋‹ค. stdio, SSE, Streamable HTTP๋ฅผ ํ†ตํ•ด ํ”„๋กœ์ ํŠธ, ๋จธ์ง€ ๋ฆฌํ€˜์ŠคํŠธ, ์ด์Šˆ, ํŒŒ์ดํ”„๋ผ์ธ, ์œ„ํ‚ค, ๋ฆด๋ฆฌ์Šค, ๋งˆ์ผ์Šคํ†ค ๋“ฑ์„ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

PAT, OAuth, ์ฝ๊ธฐ ์ „์šฉ ๋ชจ๋“œ, ๋™์  API URL, ์›๊ฒฉ ์ธ์ฆ์„ ์ง€์›ํ•˜๋ฉฐ VS Code, Claude, Cursor, Copilot ๋ฐ ๊ธฐํƒ€ MCP ํด๋ผ์ด์–ธํŠธ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ ์ด GitLab MCP๋ฅผ ์‚ฌ์šฉํ•˜๋‚˜์š”?

  • ๋„“์€ GitLab ์ง€์› ๋ฒ”์œ„: ํ”„๋กœ์ ํŠธ, ์ €์žฅ์†Œ ํƒ์ƒ‰, ๋จธ์ง€ ๋ฆฌํ€˜์ŠคํŠธ, ์ด์Šˆ, ํŒŒ์ดํ”„๋ผ์ธ, ์œ„ํ‚ค, ๋ฆด๋ฆฌ์Šค, ๋ผ๋ฒจ, ๋งˆ์ผ์Šคํ†ค ๋“ฑ
  • ์œ ์—ฐํ•œ ์ธ์ฆ: Personal Access Token, ๋กœ์ปฌ OAuth2 ๋ธŒ๋ผ์šฐ์ € ํ”Œ๋กœ์šฐ, MCP OAuth ํ”„๋ก์‹œ, ์š”์ฒญ๋ณ„ ์›๊ฒฉ ์ธ์ฆ
  • ์—ฌ๋Ÿฌ ์ „์†ก ๋ฐฉ์‹: ๋กœ์ปฌ ํด๋ผ์ด์–ธํŠธ์šฉ stdio, ๋ ˆ๊ฑฐ์‹œ ํด๋ผ์ด์–ธํŠธ์šฉ SSE, ์ตœ์‹  ์›๊ฒฉ ๋ฐฐํฌ์šฉ Streamable HTTP
  • ํด๋ผ์ด์–ธํŠธ ์นœํ™”์  ์„ค์ •: Claude Code, Codex, Antigravity, OpenCode, Copilot, Cline, Roo Code, Cursor, Kilo Code, Amp Code ์˜ˆ์‹œ ์ œ๊ณต
  • ์…€ํ”„ ํ˜ธ์ŠคํŒ… ๋Œ€์‘: ์ปค์Šคํ…€ GitLab ์ธ์Šคํ„ด์Šค, ํ”„๋ก์‹œ ์„ค์ •, ๋™์  API URL ๋ผ์šฐํŒ… ์ง€์›

๋น ๋ฅธ ์‹œ์ž‘: ์•„๋ž˜์—์„œ Personal Access Token ๋˜๋Š” OAuth2 ์„ค์ • ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜๊ณ  @zereight/mcp-gitlab์„ ์„ค์น˜ํ•œ ๋’ค MCP ํด๋ผ์ด์–ธํŠธ ์„ค์ •์—์„œ zereight-mcp-gitlab์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

ํด๋ผ์ด์–ธํŠธ ์„ค์ • ๊ฐ€์ด๋“œ

์‚ฌ์šฉ๋ฒ•

์„ค์ • ๊ฐœ์š”

์ธ์ฆ ๋ฐฉ์‹

์ด ์„œ๋ฒ„๋Š” ๋„ค ๊ฐ€์ง€ ์ธ์ฆ ๋ฐฉ์‹์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค.

๋กœ์ปฌ/๋ฐ์Šคํฌํ†ฑ ์‚ฌ์šฉ(๊ฐ€์žฅ ์ผ๋ฐ˜์ ):

  1. Personal Access Token (GITLAB_PERSONAL_ACCESS_TOKEN) โ€” ๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ์„ค์ •
  2. OAuth2 โ€” ๋กœ์ปฌ ๋ธŒ๋ผ์šฐ์ € (GITLAB_USE_OAUTH) โ€” ๋” ๋‚˜์€ ๋ณด์•ˆ์„ ์œ„ํ•ด ๊ถŒ์žฅ

์„œ๋ฒ„/์›๊ฒฉ ๋ฐฐํฌ:

  1. OAuth2 โ€” MCP ํ”„๋ก์‹œ (GITLAB_MCP_OAUTH) โ€” Claude.ai ๊ฐ™์€ ์›๊ฒฉ MCP ํด๋ผ์ด์–ธํŠธ์šฉ
  2. ์›๊ฒฉ ์ธ์ฆ (REMOTE_AUTHORIZATION) โ€” ๊ฐ ํ˜ธ์ถœ์ž๊ฐ€ ์ž์‹ ์˜ ํ† ํฐ์„ ์ œ๊ณตํ•˜๋Š” ๋ฉ€ํ‹ฐ ์œ ์ € ๋ฐฐํฌ์šฉ

๋น ๋ฅธ ์„ค์ • ๊ฒฝ๋กœ

๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ๋กœ์ปฌ ์„ค์ •์€ Personal Access Token์œผ๋กœ ์‹œ์ž‘ํ•˜์„ธ์š”. ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ฐ˜ ๋กœ์ปฌ ์ธ์ฆ์€ OAuth2๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์›๊ฒฉ ๋˜๋Š” ๋ฉ€ํ‹ฐ ์œ ์ € ๋ฐฐํฌ๋Š” ์•„๋ž˜ MCP OAuth ๋ฐ ์›๊ฒฉ ์ธ์ฆ ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”.

์„œ๋ฒ„๋ฅผ ํ•œ ๋ฒˆ ์„ค์น˜ํ•˜์„ธ์š”.

brew tap zereight/gitlab-mcp https://github.com/zereight/gitlab-mcp
brew install zereight/gitlab-mcp/zereight-mcp-gitlab

npm์œผ๋กœ ์„ค์น˜ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค:

npm install -g @zereight/mcp-gitlab

์˜ˆ์‹œ๋Š” ๊ธฐ์กด mcp-gitlab๋ณด๋‹ค ์ถฉ๋Œ ๊ฐ€๋Šฅ์„ฑ์ด ๋‚ฎ์€ zereight-mcp-gitlab ๋ณ„์นญ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. MCP ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์ฐพ์ง€ ๋ชปํ•˜๋ฉด which zereight-mcp-gitlab์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

์ „์—ญ ์„ค์น˜๋ฅผ ์“ฐ์ง€ ์•Š์œผ๋ ค๋ฉด npx -y @zereight/mcp-gitlab@2.1.42์ฒ˜๋Ÿผ ์ง์ „ ์•ˆ์ • ๋ฒ„์ „(๋ฌธ์„œ๊ฐ€ ๊ถŒ์žฅํ•˜๋Š” ๋ฒ„์ „)์œผ๋กœ ๊ณ ์ •ํ•˜์„ธ์š”. ํ•ญ์ƒ ์ตœ์‹  ๋ฒ„์ „์„ ์›ํ•˜๋ฉด npx -y @zereight/mcp-gitlab@latest๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์ƒˆ ๋ฒ„์ „์ด ๋‚˜์˜ค๋ฉด ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘ ์‹œ stderr๋กœ ์•Œ๋ ค์ค๋‹ˆ๋‹ค(GITLAB_DISABLE_VERSION_CHECK=true๋กœ ๋น„ํ™œ์„ฑํ™” ๊ฐ€๋Šฅ).

CLI ์ธ์ž ์‚ฌ์šฉํ•˜๊ธฐ(ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ํด๋ผ์ด์–ธํŠธ์šฉ)

์ผ๋ถ€ MCP ํด๋ผ์ด์–ธํŠธ(์˜ˆ: GitHub Copilot CLI)๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ฒ˜๋ฆฌ์— ๋ฌธ์ œ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ CLI ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

{
  "mcpServers": {
    "gitlab": {
      "command": "zereight-mcp-gitlab",
      "args": ["--token=YOUR_GITLAB_TOKEN", "--api-url=https://gitlab.com/api/v4"],
      "tools": ["*"]
    }
  }
}

์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ CLI ์ธ์ž:

  • --token - GitLab Personal Access Token (GITLAB_PERSONAL_ACCESS_TOKEN ๋Œ€์ฒด)
  • --api-url - GitLab API URL (GITLAB_API_URL ๋Œ€์ฒด)
  • --read-only=true - ์ฝ๊ธฐ ์ „์šฉ ๋ชจ๋“œ ํ™œ์„ฑํ™” (GITLAB_READ_ONLY_MODE ๋Œ€์ฒด, deprecated โ€” --permission-mode=readonly ๊ถŒ์žฅ)
  • --permission-mode - ๊ถŒํ•œ ์ˆ˜์ค€: readonly, modify(์‚ญ์ œ ๋„๊ตฌ ๋น„ํ™œ์„ฑ), full (GITLAB_PERMISSION_MODE ๋Œ€์ฒด, ๊ธฐ๋ณธ๊ฐ’ full)
  • --use-wiki=true - ์œ„ํ‚ค API ํ™œ์„ฑํ™” (USE_GITLAB_WIKI ๋Œ€์ฒด, ๋ ˆ๊ฑฐ์‹œ โ€” GITLAB_TOOLSETS=wiki ๊ถŒ์žฅ)
  • --use-milestone=true - ๋งˆ์ผ์Šคํ†ค API ํ™œ์„ฑํ™” (USE_MILESTONE ๋Œ€์ฒด, ๋ ˆ๊ฑฐ์‹œ โ€” GITLAB_TOOLSETS=milestones ๊ถŒ์žฅ)
  • --use-pipeline=true - ํŒŒ์ดํ”„๋ผ์ธ API ํ™œ์„ฑํ™” (USE_PIPELINE ๋Œ€์ฒด, ๋ ˆ๊ฑฐ์‹œ โ€” GITLAB_TOOLSETS=pipelines ๊ถŒ์žฅ)
  • --disable-version-check=true - ์‹œ์ž‘ ์‹œ ์‹ ๊ทœ ๋ฒ„์ „ ์•Œ๋ฆผ ๋น„ํ™œ์„ฑํ™” (GITLAB_DISABLE_VERSION_CHECK ๋Œ€์ฒด)

CLI ์ธ์ž๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ณด๋‹ค ์šฐ์„ ํ•ฉ๋‹ˆ๋‹ค.

์„ธ๋ฐ€ํ•œ ๋„๊ตฌ ํ•„ํ„ฐ๋ง: GITLAB_PERMISSION_MODE=modify๋กœ ์ƒ์„ฑ/์ˆ˜์ •์€ ํ—ˆ์šฉํ•˜๊ณ  ๋ชจ๋“  ์‚ญ์ œ ๋„๊ตฌ๋ฅผ
์ฐจ๋‹จํ•˜๊ฑฐ๋‚˜, GITLAB_PERMISSION_MODE=readonly๋กœ ์ฝ๊ธฐ ์ „์šฉ์œผ๋กœ ์šด์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ
GITLAB_TOOLSETS=<group,โ€ฆ>๋กœ ๋„๊ตฌ ๊ทธ๋ฃน์„ ํ™œ์„ฑํ™”ํ•˜๊ณ , GITLAB_TOOLS=<tool,โ€ฆ>๋กœ ๊ฐœ๋ณ„ ๋„๊ตฌ๋งŒ
ํ—ˆ์šฉํ•˜๋ฉฐ(์˜ˆ: ์ฝ๊ธฐ ๋„๊ตฌ + ํŠน์ • ์“ฐ๊ธฐ ๋„๊ตฌ ๋ช‡ ๊ฐœ), GITLAB_DENIED_TOOLS_REGEX๋กœ ํŒจํ„ด ์ฐจ๋‹จํ•  ์ˆ˜
์žˆ์Šต๋‹ˆ๋‹ค. ๋ ˆ๊ฑฐ์‹œ USE_GITLAB_WIKI / USE_MILESTONE / USE_PIPELINE ํ”Œ๋ž˜๊ทธ๋Š” ํ•˜์œ„ ํ˜ธํ™˜์šฉ์œผ๋กœ๋งŒ
์œ ์ง€๋ฉ๋‹ˆ๋‹ค. Tools Reference์™€
Environment Variables๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

SSE

docker run -i --rm \
  -e HOST=0.0.0.0 \
  -e GITLAB_PERSONAL_ACCESS_TOKEN=your_gitlab_token \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_PERMISSION_MODE=readonly \
  -e GITLAB_TOOLSETS=wiki,milestones,pipelines \
  -e SSE=true \
  -e SSE_AUTH_TOKEN=your_mcp_sse_token \
  -p 3333:3002 \
  zereight050/gitlab-mcp
{
  "mcpServers": {
    "gitlab": {
      "type": "sse",
      "url": "http://localhost:3333/sse",
      "headers": {
        "Authorization": "Bearer your_mcp_sse_token"
      }
    }
  }
}

Streamable HTTP

docker run -i --rm \
  -e HOST=0.0.0.0 \
  -e REMOTE_AUTHORIZATION=true \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_PERMISSION_MODE=readonly \
  -e GITLAB_TOOLSETS=wiki,milestones,pipelines \
  -e STREAMABLE_HTTP=true \
  -p 3333:3002 \
  zereight050/gitlab-mcp
{
  "mcpServers": {
    "gitlab": {
      "type": "streamable-http",
      "url": "http://localhost:3333/mcp",
      "headers": {
        "Authorization": "Bearer glpat-..."
      }
    }
  }
}

MCP OAuth ํ”„๋ก์‹œ ์‚ฌ์šฉํ•˜๊ธฐ(GITLAB_MCP_OAUTH)

์„œ๋ฒ„/์›๊ฒฉ ๋ฐฐํฌ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ์ด ๋ชจ๋“œ๋Š” ๊ณต๊ฐœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ HTTPS URL๋กœ MCP ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋กœ์ปฌ/๋ฐ์Šคํฌํ†ฑ ์‚ฌ์šฉ์€ GITLAB_USE_OAUTH๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

MCP OAuth ์‚ฌ์–‘์„ ์ง€์›ํ•˜๋Š” ์›๊ฒฉ MCP ํด๋ผ์ด์–ธํŠธ(์˜ˆ: Claude.ai)์šฉ์ž…๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” ์™„์ „ํ•œ OAuth 2.0 ์ธ์ฆ ์„œ๋ฒ„๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ๋˜์ง€ ์•Š์€ ์š”์ฒญ์€ 401 + WWW-Authenticate ์‘๋‹ต์„ ๋ฐ›๊ณ , ํด๋ผ์ด์–ธํŠธ ์ธก OAuth ๋ธŒ๋ผ์šฐ์ € ํ”Œ๋กœ์šฐ๊ฐ€ ์ž๋™์œผ๋กœ ์‹œ์ž‘๋ฉ๋‹ˆ๋‹ค.

OpenCode, MCPJam, Claude.ai ๊ฐ™์€ ์›๊ฒฉ MCP ํด๋ผ์ด์–ธํŠธ๋Š” ์ธ์ฆ ์ค‘์— ์ž์ฒด callback URL์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํด๋ผ์ด์–ธํŠธ callback URL์„ GitLab์— ๋“ฑ๋กํ•  ์ˆ˜ ์—†๋‹ค๋ฉด GITLAB_OAUTH_CALLBACK_PROXY=true๋ฅผ ์ผœ์„ธ์š”. ์ฝœ๋ฐฑ ํ”„๋ก์‹œ ๋ชจ๋“œ์—์„œ๋Š” GitLab์— {MCP_SERVER_URL}/callback ํ•˜๋‚˜๋งŒ Redirect URI๋กœ ๋“ฑ๋กํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

GITLAB_OAUTH_REDIRECT_URI๋Š” ๋กœ์ปฌ OAuth(GITLAB_USE_OAUTH) ์ „์šฉ์ž…๋‹ˆ๋‹ค. ์›๊ฒฉ MCP OAuth ํด๋ผ์ด์–ธํŠธ callback URL์„ ๋ฎ์–ด์“ฐ์ง€ ์•Š์œผ๋ฉฐ, ์›๊ฒฉ Unregistered redirect_uri ์˜ค๋ฅ˜ ํ•ด๊ฒฐ์šฉ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

์ด ๋ณ€์ˆ˜๊ฐ€ ์กด์žฌํ•˜๋Š” ์ด์œ ๋Š” ๋กœ์ปฌ OAuth ํ”Œ๋กœ์šฐ๊ฐ€ MCP ์„œ๋ฒ„์™€ ๊ฐ™์€ ๋จธ์‹ ์—์„œ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์—ด๊ณ , http://127.0.0.1:8888/callback ๊ฐ™์€ ๋กœ์ปฌ HTTP ์„œ๋ฒ„๋กœ callback์„ ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์›๊ฒฉ MCP OAuth๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค. GITLAB_MCP_OAUTH=true ๋ชจ๋“œ์—์„œ๋Š” MCP ํด๋ผ์ด์–ธํŠธ๊ฐ€ /authorize ์š”์ฒญ ์ค‘์— ์ž์ฒด callback URL์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. GITLAB_OAUTH_REDIRECT_URI๋Š” ๊ทธ ํด๋ผ์ด์–ธํŠธ ์ œ๊ณต URL์„ ๋Œ€์ฒดํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ชจ๋“œ ํ™œ์„ฑํ™” ๋ณ€์ˆ˜ Callback ๋ณ€์ˆ˜ GitLab Redirect URI
๋กœ์ปฌ OAuth GITLAB_USE_OAUTH=true GITLAB_OAUTH_REDIRECT_URI http://127.0.0.1:8888/callback ๋˜๋Š” ๋กœ์ปฌ callback
์›๊ฒฉ MCP OAuth GITLAB_MCP_OAUTH=true GITLAB_OAUTH_CALLBACK_PROXY=true {MCP_SERVER_URL}/callback

MCP ์„œ๋ฒ„๊ฐ€ ์ง์ ‘ ๋กœ์ปฌ ๋ธŒ๋ผ์šฐ์ € callback์„ ๋ฐ›์„ ๋•Œ๋งŒ GITLAB_OAUTH_REDIRECT_URI๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”. ์›๊ฒฉ MCP ํด๋ผ์ด์–ธํŠธ๊ฐ€ callback URL์„ ์†Œ์œ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” GITLAB_OAUTH_CALLBACK_PROXY=true๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.

๋™์ž‘ ๋ฐฉ์‹: ๊ณต๊ฐœ HTTPS URL์„ ๊ฐ€์ง„ ์œ„์น˜์— ์ด MCP ์„œ๋ฒ„๋ฅผ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. MCP ํด๋ผ์ด์–ธํŠธ๋Š” {MCP_SERVER_URL}/mcp๋กœ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„๋Š” OAuth 2.0 ํ”Œ๋กœ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  GitLab๊ณผ ์ž๊ฒฉ ์ฆ๋ช…์„ ๊ตํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์‚ฌ์ „ ์ค€๋น„:

  1. ๊ณต๊ฐœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ HTTPS ์„œ๋ฒ„ URL (MCP_SERVER_URL) โ€” ๋กœ์ปฌ ํ…Œ์ŠคํŠธ์—๋Š” ngrok์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  2. api ๋˜๋Š” read_api scope๊ฐ€ ์žˆ๋Š” ์‚ฌ์ „ ๋“ฑ๋ก GitLab OAuth ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜
    โ€” Admin area โ†’ Applications์—์„œ Redirect URI๋ฅผ {MCP_SERVER_URL}/callback์œผ๋กœ ์„ค์ •ํ•˜์„ธ์š”.
ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํ•„์ˆ˜ ์„ค๋ช…
GITLAB_MCP_OAUTH ์˜ˆ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด true
GITLAB_API_URL ์˜ˆ GitLab API base URL
GITLAB_OAUTH_APP_ID ์˜ˆ GitLab OAuth Application ID
MCP_SERVER_URL ์˜ˆ ์ด MCP ์„œ๋ฒ„์˜ ๊ณต๊ฐœ HTTPS URL
STREAMABLE_HTTP ์˜ˆ ๋ฐ˜๋“œ์‹œ true
GITLAB_OAUTH_CALLBACK_PROXY ์„ ํƒ MCP ์„œ๋ฒ„์˜ ๊ณ ์ • /callback URL์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด true
GITLAB_OAUTH_SCOPES ์„ ํƒ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ scope ๋ชฉ๋ก(๊ธฐ๋ณธ๊ฐ’: api,read_api,read_user)
GITLAB_OAUTH_ALLOWED_GROUPS ์„ ํƒ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„๋œ GitLab ๊ทธ๋ฃน ์ „์ฒด ๊ฒฝ๋กœ โ€” ํ•ด๋‹น ๊ทธ๋ฃน ๋ฐ ํ•˜์œ„ ๊ทธ๋ฃน ๋ฉค๋ฒ„๋งŒ ํ† ํฐ์„ ๋ฐœ๊ธ‰๋ฐ›์„ ์ˆ˜ ์žˆ์Œ (๊ธฐ์กด GITLAB_ALLOWED_GROUPS ๋Œ€์ฒด)

STREAMABLE_HTTP=true์ผ ๋•Œ ์„œ๋ฒ„ ์ธก GitLab ์ž๊ฒฉ ์ฆ๋ช…(GITLAB_PERSONAL_ACCESS_TOKEN, GITLAB_JOB_TOKEN, GITLAB_AUTH_COOKIE_PATH, ๋˜๋Š” GITLAB_USE_OAUTH)์€ REMOTE_AUTHORIZATION=true, GITLAB_MCP_OAUTH=true, ๋˜๋Š” STREAMABLE_HTTP_AUTH_TOKEN์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

Unregistered redirect_uri ๋ฌธ์ œ ํ•ด๊ฒฐ

๋ธŒ๋ผ์šฐ์ € URL์˜ redirect_uri๋ฅผ ํ™•์ธํ•˜์„ธ์š”. ๊ฐ’์ด http://127.0.0.1:xxxxx/.../callback ๊ฐ™์€ ํด๋ผ์ด์–ธํŠธ callback์„ ๊ฐ€๋ฆฌํ‚ค๋ฉด ๋‹ค์Œ ์„ค์ •์„ ์ผœ์„ธ์š”.

GITLAB_OAUTH_CALLBACK_PROXY=true

์›๊ฒฉ MCP OAuth ๋ฌธ์ œ๋ฅผ GITLAB_OAUTH_REDIRECT_URI ๋ณ€๊ฒฝ์œผ๋กœ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ•˜์ง€ ๋งˆ์„ธ์š”. ์ด ๋ณ€์ˆ˜๋Š” ๋กœ์ปฌ OAuth(GITLAB_USE_OAUTH) ์ „์šฉ์ž…๋‹ˆ๋‹ค.

docker run -i --rm \
  -e HOST=0.0.0.0 \
  -e GITLAB_MCP_OAUTH=true \
  -e GITLAB_OAUTH_CALLBACK_PROXY=true \
  -e STREAMABLE_HTTP=true \
  -e MCP_SERVER_URL=https://your-server.example.com \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_OAUTH_APP_ID=your_app_id \
  -p 3000:3002 \
  zereight050/gitlab-mcp

MCP ํด๋ผ์ด์–ธํŠธ ์„ค์ •:

{
  "mcpServers": {
    "gitlab": {
      "type": "http",
      "url": "https://your-server.example.com/mcp"
    }
  }
}

์›๊ฒฉ ์ธ์ฆ ์‚ฌ์šฉํ•˜๊ธฐ(REMOTE_AUTHORIZATION)

์„œ๋ฒ„/์›๊ฒฉ ๋ฐฐํฌ ์ „์šฉ์ž…๋‹ˆ๋‹ค. ๊ฐ HTTP ํ˜ธ์ถœ์ž๊ฐ€ ์š”์ฒญ ํ—ค๋”์— ์ž์‹ ์˜ GitLab ํ† ํฐ์„ ์ง์ ‘ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. OAuth ํ”Œ๋กœ์šฐ๋Š” ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฐ ํ˜ธ์ถœ์ž๊ฐ€ HTTP ์š”์ฒญ ํ—ค๋”์— ์ž์‹ ์˜ GitLab ํ† ํฐ์„ ์ œ๊ณตํ•˜๋Š” ๋ฉ€ํ‹ฐ ์œ ์ € ๋˜๋Š” ๋ฉ€ํ‹ฐ ํ…Œ๋„ŒํŠธ ๋ฐฐํฌ์šฉ์ž…๋‹ˆ๋‹ค. MCP ์„œ๋ฒ„๋Š” ํ˜ธ์ถœ์ž๋ฅผ ๋Œ€์‹ ํ•ด ํ† ํฐ์„ GitLab์œผ๋กœ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

ํ—ค๋” ์šฐ์„ ์ˆœ์œ„: Private-Token > JOB-TOKEN > Authorization: Bearer

ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํ•„์ˆ˜ ์„ค๋ช…
REMOTE_AUTHORIZATION ์˜ˆ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด true
STREAMABLE_HTTP ์˜ˆ ๋ฐ˜๋“œ์‹œ true
ENABLE_DYNAMIC_API_URL ์„ ํƒ ์š”์ฒญ๋ณ„ X-GitLab-API-URL ํ—ค๋” ํ—ˆ์šฉ
GITLAB_ALLOWED_HOSTS ์„ ํƒ ํ—ˆ์šฉํ•  X-GitLab-API-URL ํ˜ธ์ŠคํŠธ์˜ ์‰ผํ‘œ ๊ตฌ๋ถ„ ๋ชฉ๋ก; GITLAB_API_URL ํ˜ธ์ŠคํŠธ๋Š” ํ•ญ์ƒ ํ—ˆ์šฉ
GITLAB_ALLOW_UNAUTHENTICATED_TOOL_DISCOVERY ์„ ํƒ ์ธ์ฆ ์—†์ด initialize, notifications/initialized, tools/list๋งŒ ํ—ˆ์šฉ(๋„๊ตฌ ํ˜ธ์ถœ์€ ์—ฌ์ „ํžˆ ์ธ์ฆ ํ•„์š”)
MCP_SERVER_URL / MCP_ALLOWED_HOSTS / MCP_ALLOWED_ORIGINS ์„ ํƒ DNS rebinding ๋ฐฉ์ง€๋ฅผ ์œ„ํ•œ ํ—ˆ์šฉ /mcp ํ˜ธ์ŠคํŠธ/์˜ค๋ฆฌ์ง„ ๊ฐ’
MCP_TRUST_PROXY ์„ ํƒ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ๋’ค์—์„œ Forwarded / X-Forwarded-* ํ—ค๋” ์‹ ๋ขฐ(๋‹ค์šด๋กœ๋“œ URL, Express req.ip, /mcp IP rate limit, OAuth rate limit)

GITLAB_ALLOW_UNAUTHENTICATED_TOOL_DISCOVERY=true๋Š” ์‚ฌ์šฉ์ž๊ฐ€ GitLab ํ† ํฐ์„ ์ œ๊ณตํ•˜๊ธฐ ์ „์— ๋„๊ตฌ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ์กฐํšŒํ•ด์•ผ ํ•˜๋Š” MCP ๊ฒŒ์ดํŠธ์›จ์ด๋‚˜ ๊ด€๋ฆฌ UI์šฉ์ž…๋‹ˆ๋‹ค. ๋ฐฐํฌ ํ™˜๊ฒฝ์—์„œ ๋„๊ตฌ ๋ชฉ๋ก ๊ณต๊ฐœ๊ฐ€ ์•ˆ์ „ํ•œ ๊ฒฝ์šฐ๊ฐ€ ์•„๋‹ˆ๋ฉด ๋น„ํ™œ์„ฑํ™”ํ•˜์„ธ์š”.

MCP_SERVER_URL์ด ์„ค์ •๋˜์ง€ ์•Š์œผ๋ฉด ์›๊ฒฉ ๋‹ค์šด๋กœ๋“œ URL์€ ๋กœ์ปฌ ์„œ๋ฒ„ ์ฃผ์†Œ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค. MCP_TRUST_PROXY=true๋Š” ์„œ๋ฒ„๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ๋ฅผ ํ†ตํ•ด์„œ๋งŒ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•˜๊ณ  MCP ์„œ๋ฒ„์— ๋Œ€ํ•œ ์ง์ ‘ ํด๋ผ์ด์–ธํŠธ ์ ‘๊ทผ์ด ์ฐจ๋‹จ๋œ ๊ฒฝ์šฐ์—๋งŒ ์„ค์ •ํ•˜์„ธ์š”. ์ด ์„ค์ •์€ Streamable HTTP ๋ฐ SSE์šฉ Express trust proxy๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ณ , Forwarded / X-Forwarded-Proto / X-Forwarded-Host / X-Forwarded-Prefix์—์„œ ๊ณต๊ฐœ ๋‹ค์šด๋กœ๋“œ URL์„ ํŒŒ์ƒํ•˜๋ฉฐ, ํ”„๋ก์‹œ๊ฐ€ X-Forwarded-For์— ํด๋ผ์ด์–ธํŠธ ํฌํŠธ๋ฅผ ํฌํ•จํ•ด ๋ณด๋‚ผ ๋•Œ(์˜ˆ: 1.2.3.4:5678) OAuth ์—”๋“œํฌ์ธํŠธ rate limiting์ด ๋™์ž‘ํ•˜๋„๋ก ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์ด ํ”Œ๋ž˜๊ทธ ๋„์ž… ์ดํ›„ ๊ธฐ์กด OAuth+ํ”„๋ก์‹œ ๋ฐฐํฌ๋Š” ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ์‹œ ์š”์ฒญ ํ—ค๋”:

Private-Token: glpat-xxxxxxxxxxxxxxxxxxxx

๋˜๋Š” Bearer ํ† ํฐ ์‚ฌ์šฉ:

Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx

โš ๏ธ REMOTE_AUTHORIZATION์€ SSE ์ „์†ก๊ณผ ํ˜ธํ™˜๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. STREAMABLE_HTTP=true๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜

์ „์ฒด ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ๋ชฉ๋ก์€ ์ „์šฉ ๋ฌธ์„œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

๋Œ€๋ถ€๋ถ„์˜ ์‚ฌ์šฉ์ž๋Š” ์•„๋ž˜ ์‹œ์ž‘ ์กฐํ•ฉ ์ค‘ ํ•˜๋‚˜๋งŒ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

  • ๋กœ์ปฌ PAT: GITLAB_PERSONAL_ACCESS_TOKEN, GITLAB_API_URL
  • ๋กœ์ปฌ OAuth: GITLAB_USE_OAUTH=true, GITLAB_OAUTH_CLIENT_ID, GITLAB_OAUTH_REDIRECT_URI, GITLAB_API_URL
  • ์›๊ฒฉ ๋ฉ€ํ‹ฐ ์œ ์ € HTTP: STREAMABLE_HTTP=true, REMOTE_AUTHORIZATION=true(๋˜๋Š” GITLAB_MCP_OAUTH=true), MCP_TRUST_PROXY=true(๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ ๋’ค), MAX_REQUESTS_PER_MINUTE=300, MCP_SERVER_URL ๋˜๋Š” MCP_ALLOWED_HOSTS, HOST, PORT
  • ์—ฌ๋Ÿฌ ๋ฐฐํฌ๋ฅผ ๋™์‹œ์— ์šด์˜: ๋ฐฐํฌ๋งˆ๋‹ค MCP_SERVER_NAME์„ ๋‹ค๋ฅด๊ฒŒ ์„ค์ •(์˜ˆ: gitlab-selfhosted-readonly)ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ, ๋กœ๊ทธ, ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ์—์„œ ์„œ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค
  • ๋ฉ€ํ‹ฐ Pod HPA (stateless): ์œ„ ์„ค์ • + OAUTH_STATELESS_MODE=true, OAUTH_STATELESS_SECRET(๋ชจ๋“  Pod์—์„œ ๋™์ผ). Stateless Mode ์ฐธ๊ณ .

์ž์ฃผ ์ฐธ์กฐํ•˜๋Š” ๋ณ€์ˆ˜:

  • GITLAB_API_URL
  • GITLAB_PERSONAL_ACCESS_TOKEN
  • GITLAB_USE_OAUTH
  • REMOTE_AUTHORIZATION
  • MCP_TRUST_PROXY
  • MAX_REQUESTS_PER_MINUTE
  • MAX_SESSIONS
  • MCP_ALLOWED_HOSTS
  • MCP_ALLOWED_ORIGINS
  • GITLAB_MCP_OAUTH
  • GITLAB_OAUTH_CALLBACK_PROXY
  • OAUTH_STATELESS_MODE
  • OAUTH_STATELESS_SECRET

๋ ˆํผ๋Ÿฐ์Šค ๋ฌธ์„œ๋Š” ๋‹ค์Œ ๋‚ด์šฉ๋„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

  • ์ธ์ฆ ๋ฐ OAuth ๋ณ€์ˆ˜
  • MCP OAuth ํ”„๋ก์‹œ ๋ณ€์ˆ˜
  • ํ”„๋กœ์ ํŠธ ๋ฐ ๋„๊ตฌ ํ•„ํ„ฐ๋ง ๋ณ€์ˆ˜
  • discover_tools๋ฅผ ํ†ตํ•œ ๋™์  ๋„๊ตฌ ํƒ์ƒ‰(์˜จ๋””๋งจ๋“œ ๋„๊ตฌ์…‹ ํ™œ์„ฑํ™”)
  • ์ „์†ก ๋ฐ ์„ธ์…˜ ๋ณ€์ˆ˜
  • ํ”„๋ก์‹œ ๋ฐ TLS ๋ณ€์ˆ˜

์ฝœ๋ฐฑ ํ”„๋ก์‹œ ๋ชจ๋“œ ์ƒ์„ธ๋Š” GitLab MCP OAuth Callback Proxy๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.

์›๊ฒฉ ์ธ์ฆ ์„ค์ •(๋ฉ€ํ‹ฐ ์œ ์ € ์ง€์›)

REMOTE_AUTHORIZATION=true๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด MCP ์„œ๋ฒ„๋Š” ์—ฌ๋Ÿฌ ์‚ฌ์šฉ์ž๋ฅผ ์ง€์›ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์‚ฌ์šฉ์ž๋Š” HTTP ํ—ค๋”๋กœ ์ž์‹ ์˜ GitLab ํ† ํฐ์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์Œ ๊ฒฝ์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ๊ฐ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ž์‹ ์˜ GitLab ์ ‘๊ทผ ๊ถŒํ•œ์ด ํ•„์š”ํ•œ ๊ณต์œ  MCP ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค
  • ์‚ฌ์šฉ์ž๋ณ„ ํ† ํฐ์„ MCP ์š”์ฒญ์— ์ฃผ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” IDE ํ†ตํ•ฉ

์„ค์ • ์˜ˆ์‹œ:

docker run -d \
  -e HOST=0.0.0.0 \
  -e STREAMABLE_HTTP=true \
  -e REMOTE_AUTHORIZATION=true \
  -e GITLAB_API_URL="https://gitlab.com/api/v4" \
  -e GITLAB_PERMISSION_MODE=readonly \
  -e SESSION_TIMEOUT_SECONDS=3600 \
  -p 3333:3002 \
  zereight050/gitlab-mcp

ํด๋ผ์ด์–ธํŠธ ์„ค์ •:

IDE ๋˜๋Š” MCP ํด๋ผ์ด์–ธํŠธ๋Š” ๊ฐ ์š”์ฒญ์— ์•„๋ž˜ ํ—ค๋” ์ค‘ ํ•˜๋‚˜๋ฅผ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Authorization: Bearer glpat-xxxxxxxxxxxxxxxxxxxx

๋˜๋Š”

Private-Token: glpat-xxxxxxxxxxxxxxxxxxxx

ํ† ํฐ์€ ์„ธ์…˜๋ณ„๋กœ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค(mcp-session-id ํ—ค๋”๋กœ ์‹๋ณ„). ๊ฐ™์€ ์„ธ์…˜์˜ ํ›„์† ์š”์ฒญ์—์„œ ์žฌ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

Cursor ์›๊ฒฉ ์ธ์ฆ ํด๋ผ์ด์–ธํŠธ ์„ค์ • ์˜ˆ์‹œ

{
  "mcpServers": {
    "GitLab": {
      "url": "http(s)://<your_mcp_gitlab_server>/mcp",
      "headers": {
        "Authorization": "Bearer glpat-..."
      }
    }
  }
}

์ค‘์š” ์‚ฌํ•ญ:

  • ์›๊ฒฉ ์ธ์ฆ์€ Streamable HTTP ์ „์†ก์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ ์„ธ์…˜์€ ๊ฒฉ๋ฆฌ๋ฉ๋‹ˆ๋‹ค. ํ•œ ์„ธ์…˜์˜ ํ† ํฐ์€ ๋‹ค๋ฅธ ์„ธ์…˜ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์„ธ์…˜์ด ์ข…๋ฃŒ๋˜๋ฉด ํ† ํฐ์€ ์ž๋™์œผ๋กœ ์ •๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ์„ธ์…˜ ํƒ€์ž„์•„์›ƒ: ์ธ์ฆ ํ† ํฐ์€ SESSION_TIMEOUT_SECONDS(๊ธฐ๋ณธ 1์‹œ๊ฐ„) ๋™์•ˆ ๋น„ํ™œ์„ฑ ์ƒํƒœ๊ฐ€ ์ง€์†๋˜๋ฉด ๋งŒ๋ฃŒ๋ฉ๋‹ˆ๋‹ค. ๋งŒ๋ฃŒ ํ›„ ํด๋ผ์ด์–ธํŠธ๋Š” ์ธ์ฆ ํ—ค๋”๋ฅผ ๋‹ค์‹œ ๋ณด๋‚ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ „์†ก ์„ธ์…˜์€ ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.
  • ๊ฐ ์š”์ฒญ์€ ํ•ด๋‹น ์„ธ์…˜์˜ ํƒ€์ž„์•„์›ƒ ํƒ€์ด๋จธ๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • Rate limiting: /mcp ์š”์ฒญ์€ ํด๋ผ์ด์–ธํŠธ IP๋‹น MAX_REQUESTS_PER_MINUTE๋กœ ์ œํ•œ๋˜๋ฉฐ, OAuth ๋˜๋Š” ์›๊ฒฉ ์ธ์ฆ ์‚ฌ์šฉ ์‹œ MCP ์„ธ์…˜๋‹น์œผ๋กœ๋„ ์ œํ•œ๋ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ 60). ์ž์„ธํ•œ ๋‚ด์šฉ์€ environment-variables.md๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”.
  • Capacity limit: ์„œ๋ฒ„๋Š” ์ตœ๋Œ€ MAX_SESSIONS ๋™์‹œ ์„ธ์…˜์„ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค(๊ธฐ๋ณธ 1000).

MCP OAuth ์„ค์ •(Claude.ai Native OAuth)

GITLAB_MCP_OAUTH=true๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„œ๋ฒ„๊ฐ€ GitLab ์ธ์Šคํ„ด์Šค์˜ OAuth ํ”„๋ก์‹œ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. Claude.ai ๋ฐ MCP ์‚ฌ์–‘์„ ์ค€์ˆ˜ํ•˜๋Š” ํด๋ผ์ด์–ธํŠธ๋Š” ๋ธŒ๋ผ์šฐ์ € ์ธ์ฆ ํ”Œ๋กœ์šฐ๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค. ์ˆ˜๋™ Personal Access Token ๊ด€๋ฆฌ๊ฐ€ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.

์‚ฌ์ „ ์ค€๋น„:

์‚ฌ์ „ ๋“ฑ๋ก๋œ GitLab OAuth ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. GitLab์€ ๋™์ ์œผ๋กœ ๋“ฑ๋ก๋œ ๋ฏธ๊ฒ€์ฆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ mcp scope๋กœ ์ œํ•œํ•˜๋ฉฐ, ์ด scope๋งŒ์œผ๋กœ๋Š” API ํ˜ธ์ถœ์— ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(api ๋˜๋Š” read_api ํ•„์š”).

  1. GitLab ์ธ์Šคํ„ด์Šค โ†’ Admin Area > Applications(์ธ์Šคํ„ด์Šค ์ „์ฒด) ๋˜๋Š” User Settings > Applications(๊ฐœ์ธ)๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
  2. ์ƒˆ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    • Confidential: ์ฒดํฌ ํ•ด์ œ
    • Scopes: api, read_api, read_user ๋˜๋Š” GITLAB_OAUTH_SCOPES๋กœ ์š”์ฒญํ•  scope
  3. ์ €์žฅ ํ›„ Application ID๋ฅผ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฐ’์ด GITLAB_OAUTH_APP_ID์ž…๋‹ˆ๋‹ค.

๋™์ž‘ ๋ฐฉ์‹:

  1. ์‚ฌ์šฉ์ž๊ฐ€ Claude.ai์— MCP ์„œ๋ฒ„ URL์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  2. Claude.ai๊ฐ€ /.well-known/oauth-authorization-server๋กœ OAuth ์—”๋“œํฌ์ธํŠธ๋ฅผ ๋ฐœ๊ฒฌํ•ฉ๋‹ˆ๋‹ค.
  3. Claude.ai๊ฐ€ Dynamic Client Registration(POST /register)์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. MCP ์„œ๋ฒ„๊ฐ€ ๋กœ์ปฌ์—์„œ ์ฒ˜๋ฆฌํ•˜๋ฉฐ ๊ฐ ํด๋ผ์ด์–ธํŠธ์— ๊ฐ€์ƒ client ID๋ฅผ ๋ถ€์—ฌํ•ฉ๋‹ˆ๋‹ค.
  4. Claude.ai๊ฐ€ ์‚ฌ์ „ ๋“ฑ๋ก OAuth ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์‚ฌ์šฉํ•ด ์‚ฌ์šฉ์ž์˜ ๋ธŒ๋ผ์šฐ์ €๋ฅผ GitLab ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.
  5. ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ฆํ•˜๋ฉด GitLab์ด https://claude.ai/api/mcp/auth_callback์œผ๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธํ•ฉ๋‹ˆ๋‹ค.
  6. Claude.ai๊ฐ€ ๋ชจ๋“  MCP ์š”์ฒญ์— Authorization: Bearer <token>์„ ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  7. ์„œ๋ฒ„๊ฐ€ GitLab์œผ๋กœ ํ† ํฐ์„ ๊ฒ€์ฆํ•˜๊ณ  ์„ธ์…˜๋ณ„๋กœ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

์„œ๋ฒ„ ์„ค์ •:

docker run -d \
  -e STREAMABLE_HTTP=true \
  -e GITLAB_MCP_OAUTH=true \
  -e GITLAB_OAUTH_APP_ID="your-gitlab-oauth-app-client-id" \
  -e GITLAB_API_URL="https://gitlab.example.com/api/v4" \
  -e MCP_SERVER_URL="https://your-mcp-server.example.com" \
  -p 3002:3002 \
  zereight050/gitlab-mcp

๋กœ์ปฌ ๊ฐœ๋ฐœ(HTTP ํ—ˆ์šฉ):

MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL=true \
STREAMABLE_HTTP=true \
GITLAB_MCP_OAUTH=true \
GITLAB_OAUTH_APP_ID=your-gitlab-oauth-app-client-id \
MCP_SERVER_URL=http://localhost:3002 \
GITLAB_API_URL=https://gitlab.com/api/v4 \
node build/index.js

Claude.ai ์„ค์ •:

{
  "mcpServers": {
    "GitLab": {
      "url": "https://your-mcp-server.example.com/mcp"
    }
  }
}

headers ํ•„๋“œ๋Š” ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค. Claude.ai๊ฐ€ OAuth๋กœ ํ† ํฐ์„ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ ๋ณ€์ˆ˜:

๋ณ€์ˆ˜ ํ•„์ˆ˜ ์„ค๋ช…
GITLAB_MCP_OAUTH ์˜ˆ ํ™œ์„ฑํ™”ํ•˜๋ ค๋ฉด true
GITLAB_OAUTH_APP_ID ์˜ˆ ์‚ฌ์ „ ๋“ฑ๋ก GitLab OAuth ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ client ID
MCP_SERVER_URL ์˜ˆ MCP ์„œ๋ฒ„์˜ ๊ณต๊ฐœ HTTPS URL
GITLAB_API_URL ์˜ˆ GitLab ์ธ์Šคํ„ด์Šค API URL(์˜ˆ: https://gitlab.com/api/v4)
STREAMABLE_HTTP ์˜ˆ ๋ฐ˜๋“œ์‹œ true(SSE ๋ฏธ์ง€์›)
GITLAB_OAUTH_SCOPES ์•„๋‹ˆ์˜ค ์š”์ฒญํ•  GitLab scope ๋ชฉ๋ก(์‰ผํ‘œ ๊ตฌ๋ถ„). ๊ธฐ๋ณธ๊ฐ’์€ api ๋˜๋Š” GITLAB_READ_ONLY_MODE=true์ผ ๋•Œ read_api์ž…๋‹ˆ๋‹ค. ์‚ฌ์ „ ๋“ฑ๋ก ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•ด๋‹น scope๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
MCP_DANGEROUSLY_ALLOW_INSECURE_ISSUER_URL ์•„๋‹ˆ์˜ค ๋กœ์ปฌ HTTP ๊ฐœ๋ฐœ์—์„œ๋งŒ true

์ค‘์š” ์‚ฌํ•ญ:

  • MCP OAuth๋Š” Streamable HTTP ์ „์†ก์—์„œ๋งŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค(SSE=true์™€ ํ˜ธํ™˜๋˜์ง€ ์•Š์Œ).
  • ๊ฐ ์‚ฌ์šฉ์ž ์„ธ์…˜์€ ์ž์ฒด OAuth ํ† ํฐ์„ ์ €์žฅํ•˜๋ฉฐ ์™„์ „ํžˆ ๊ฒฉ๋ฆฌ๋ฉ๋‹ˆ๋‹ค.
  • ์„ธ์…˜ ํƒ€์ž„์•„์›ƒ, rate limiting, capacity limit์€ REMOTE_AUTHORIZATION ๋ชจ๋“œ์™€ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค(SESSION_TIMEOUT_SECONDS, MAX_REQUESTS_PER_MINUTE, MAX_SESSIONS).
  • ํ—ค๋” ์ธ์ฆ fallback: Private-Token ๋˜๋Š” JOB-TOKEN ์š”์ฒญ ํ—ค๋”๊ฐ€ ์žˆ์œผ๋ฉด OAuth ๊ฒ€์ฆ์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  raw token์„ ํ•ด๋‹น ์„ธ์…˜์— ์ง์ ‘ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ฐ™์€ ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค์—์„œ OAuth ํ”Œ๋กœ์šฐ์™€ ํ•จ๊ป˜ PAT ๋ฐ CI job token์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Authorization: Bearer๋Š” ํ•ญ์ƒ OAuth token์œผ๋กœ ์ฒ˜๋ฆฌ๋ฉ๋‹ˆ๋‹ค. PAT ๊ธฐ๋ฐ˜ ํ—ค๋” ์ธ์ฆ์—๋Š” Private-Token์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

Agent Skill Files

AI ์—์ด์ „ํŠธ๊ฐ€ skill/instruction ๋กœ๋”ฉ์„ ์ง€์›ํ•˜๋Š” ๊ฒฝ์šฐ(Claude Code, GitHub Copilot, Cursor ๋“ฑ), skills/gitlab-mcp/์— ๋ฏธ๋ฆฌ ์ž‘์„ฑ๋œ skill ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • SKILL.md โ€” ๋„๊ตฌ์…‹ ๊ฐœ์š”, ํ•ต์‹ฌ ์›Œํฌํ”Œ๋กœ์šฐ, ํŒŒ๋ผ๋ฏธํ„ฐ ํžŒํŠธ๋ฅผ ๋‹ด์€ ํ•ต์‹ฌ ๊ฐ€์ด๋“œ
  • reference/ โ€” ์ฝ”๋“œ ๋ฆฌ๋ทฐ, ๋จธ์ง€ ๋ฆฌํ€˜์ŠคํŠธ, ์ด์Šˆ, ํŒŒ์ดํ”„๋ผ์ธ, ์ทจ์•ฝ์  ํŠธ๋ฆฌ์•„์ง€์šฉ ์ƒ์„ธ ์›Œํฌํ”Œ๋กœ์šฐ ๋ฌธ์„œ

skills CLI๋กœ ์„ค์น˜:

npx skills add zereight/gitlab-mcp --skill gitlab-mcp-skill

AI ํด๋ผ์ด์–ธํŠธ์— skill ๋””๋ ‰ํ„ฐ๋ฆฌ๋ฅผ ๋“ฑ๋กํ•˜๋ฉด ์ „์ฒด ListTools ์‘๋‹ต์—๋งŒ ์˜์กดํ•˜์ง€ ์•Š๊ณ  ๋” ์ข‹์€ ๋„๊ตฌ ์‚ฌ์šฉ ์ง€์นจ์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋„๊ตฌ ๐Ÿ› ๏ธ

์ „์ฒด ๋„๊ตฌ ๋ชฉ๋ก์€ ์˜์–ด README์˜ Tools ์„น์…˜์„ ์ฐธ๊ณ ํ•˜์„ธ์š”. ํ˜„์žฌ ์„œ๋ฒ„๋Š” ๋จธ์ง€ ๋ฆฌํ€˜์ŠคํŠธ, ์ด์Šˆ, ํŒŒ์ดํ”„๋ผ์ธ, ๋ฐฐํฌ, ํ™˜๊ฒฝ, ์•„ํ‹ฐํŒฉํŠธ, ๋งˆ์ผ์Šคํ†ค, ์œ„ํ‚ค, ์ €์žฅ์†Œ, ๋ฆด๋ฆฌ์Šค, ์‚ฌ์šฉ์ž, ์ด๋ฒคํŠธ, work item, ์›นํ›…, ์ฝ”๋“œ ๊ฒ€์ƒ‰, CI/CD ๋ณ€์ˆ˜, dependency proxy, ์ทจ์•ฝ์  ํŠธ๋ฆฌ์•„์ง€, GraphQL ์‹คํ–‰ ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

Wiki ํŽ˜์ด์ง€ ์ œ๋ชฉ๊ณผ slug

GitLab์€ wiki ํŽ˜์ด์ง€ ์ œ๋ชฉ์—์„œ slug(URL, /-/wikis/<slug>)๋ฅผ ๋„์ถœํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ update_wiki_page / update_group_wiki_page์— title์„ ์ „๋‹ฌํ•˜๋ฉด ํŽ˜์ด์ง€ ์ด๋ฆ„์ด ๋ฐ”๋€Œ๊ณ  URL์ด ๋ณ€๊ฒฝ๋˜์–ด(์ค‘์ฒฉ ํŽ˜์ด์ง€์˜ ๊ฒฝ์šฐ ํŽ˜์ด์ง€๊ฐ€ ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋กœ ์ด๋™ํ•  ์ˆ˜๋„ ์žˆ์Œ) ๊ธฐ์กด ๋งํฌ๊ฐ€ ๊นจ์ง‘๋‹ˆ๋‹ค.

URL์„ ์œ ์ง€ํ•œ ์ฑ„ ํ‘œ์‹œ ์ œ๋ชฉ๋งŒ ๋ณ€๊ฒฝํ•˜๋ ค๋ฉด title์„ ์ „๋‹ฌํ•˜์ง€ ๋ง๊ณ , ํ‘œ์‹œ ์ œ๋ชฉ์„ ํŽ˜์ด์ง€ ๋‚ด์šฉ์˜ YAML front matter์— ์ €์žฅํ•œ ๋’ค ๋‚ด์šฉ์„ ์—…๋ฐ์ดํŠธํ•˜์„ธ์š”:

---
title: ์‚ฌ์šฉ์ž ์ง€์ • ํ‘œ์‹œ ์ œ๋ชฉ
---

ํŽ˜์ด์ง€ ๋ณธ๋ฌธโ€ฆ

GitLab์€ slug/URL์„ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•˜๊ณ  UI์— front matter์˜ ์ œ๋ชฉ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ๋‹ค์‹œ ์ฝ์„ ๋•Œ๋Š” get_wiki_page์— render_html: true๋ฅผ ์ „๋‹ฌํ•˜๋ฉด front_matter ํ•„๋“œ๊ฐ€ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค โ€” ์ผ๋ฐ˜ title ํ•„๋“œ๋Š” ํ•ญ์ƒ slug์—์„œ ๋„์ถœ๋œ ๊ฐ’์„ ๋ฐ˜์˜ํ•ฉ๋‹ˆ๋‹ค.

ํ…Œ์ŠคํŠธ ๐Ÿงช

ํ”„๋กœ์ ํŠธ์—๋Š” ์›๊ฒฉ ์ธ์ฆ์„ ํฌํ•จํ•œ ํฌ๊ด„์ ์ธ ํ…Œ์ŠคํŠธ๊ฐ€ ํฌํ•จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

# ์ „์ฒด ํ…Œ์ŠคํŠธ ์‹คํ–‰(API ๊ฒ€์ฆ + ์›๊ฒฉ ์ธ์ฆ)
npm test

# ์›๊ฒฉ ์ธ์ฆ ํ…Œ์ŠคํŠธ๋งŒ ์‹คํ–‰
npm run test:remote-auth

# readonly MCP ํ…Œ์ŠคํŠธ๋ฅผ ํฌํ•จํ•œ ์ „์ฒด ํ…Œ์ŠคํŠธ ์‹คํ–‰
npm run test:all

# API ๊ฒ€์ฆ๋งŒ ์‹คํ–‰
npm run test:integration

๋ชจ๋“  ์›๊ฒฉ ์ธ์ฆ ํ…Œ์ŠคํŠธ๋Š” mock GitLab ์„œ๋ฒ„๋ฅผ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์‹ค์ œ GitLab ์ž๊ฒฉ ์ฆ๋ช…์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.