efficient-gitlab について
efficient-gitlabは、GitLabプロジェクトを扱うエージェント向けにコンテキスト消費を抑えるMCPサーバーです。ツールのオンデマンド有効化、フィールド投影、ページネーションで定義や応答を絞ります。リポジトリはアーカイブ済みで、READMEは上流版の利用を推奨しています。
主な機能
- 013つのメタツールから167ツールを有効化
- 02一覧応答のフィールド投影
- 03行数やバイト数によるファイル内容の制限
- 04リポジトリツリーのキーセットページネーション
- 05読み取り専用モードとプロジェクト制限
活用シーン
- 01必要なGitLab操作カテゴリを有効化
- 02一覧結果から指定フィールドのみ取得
- 03大きなファイルやリポジトリツリーを分割して読む
MCP 対応
3つのメタツールを通じてGitLab操作を提供し、カテゴリ単位でツールを動的に有効化します。GitLabのアクセストークンとAPI URLを設定して、GitLab.comまたはセルフホスト型インスタンスに接続できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y efficient-gitlab-mcp-serverGITLAB_PERSONAL_ACCESS_TOKENシークレットGitLab personal access token with API scopeGITLAB_API_URLGitLab API base URL (default: https://gitlab.com)ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
3掲載時のツール一覧 · 2 週間前に更新
このツールにパラメーターはありません。
詳細
効率的な GitLab MCP
注意
このリポジトリはアーカイブされています(2026-05-22)。
上流の
zereight/gitlab-mcpv2.1+ は、プログレッシブディスクロージャーとスキーマのスリム化を独自に実装済みです(コミット44983ec)。このフォークを作成する理由となった差別化要素は、もはや当てはまりません。代わりに上流版をご利用ください。
トークン効率に優れた GitLab MCP サーバーです。 zereight/gitlab-mcp のフォークを、エージェントのコンテキスト予算に合わせて再設計しました。167 個のツールを 3 つのメタツール経由で提供し、すべての一覧エンドポイントでフィールドを投影するほか、サーバー側でファイルをトリミングし、大きなディレクトリではキーセットページネーションを使用します。
MCP サーバーに対する最初のやり取りで、何かを尋ねる前にツール定義だけで約 20K トークンを消費するエージェントをお使いなら、このフォークが役立ちます。
クイックスタート
前提条件
MCP クライアントの設定(ほとんどのユーザーにおすすめ)
MCP クライアントの設定に以下を追加します。対象は Claude Desktop、Cursor、Claude Code、IDE 拡張機能などです。
{
"mcpServers": {
"gitlab": {
"command": "npx",
"args": ["efficient-gitlab-mcp-server@latest"],
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
"GITLAB_API_URL": "https://gitlab.com"
}
}
}
}
クライアントを再起動します。3 つのメタツール(list_categories、activate_tools、deactivate_tools)を備えたサーバーが起動します。エージェントは必要に応じてカテゴリーを有効化し、GitLab ツールを検出します。実際の使用例については、仕組みをご覧ください。
bunをお使いですか?"command": "npx"を"command": "bunx"に置き換えてください。
バリエーション
セルフホスト版 GitLab — インスタンスのベース URL を指定します(サーバーが /api/v4 を追加します)。
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
"GITLAB_API_URL": "https://gitlab.your-company.com"
}
単一プロジェクトに固定 — エージェントが project_id を繰り返し指定する必要はありません。デフォルトとして使用されます。
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
"GITLAB_API_URL": "https://gitlab.com",
"GITLAB_PROJECT_ID": "12345"
}
複数のプロジェクトに制限 — すべての呼び出しで許可リスト内の project_id を指定する必要があります。
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
"GITLAB_API_URL": "https://gitlab.com",
"GITLAB_ALLOWED_PROJECT_IDS": "12345,67890,123"
}
読み取り専用(自動検出) — read_api スコープのみを持つ PAT を使用します。サーバーは起動時に制限されたスコープを検出し、93 個の読み取りツールのみを公開します。追加の設定は不要です。
読み取り専用(強制) — api スコープの PAT をそのまま使用しつつ、サーバーレベルで読み取り専用モードを強制します。
"env": {
"GITLAB_PERSONAL_ACCESS_TOKEN": "glpat-xxxxxxxxxxxxxxxxxxxx",
"GITLAB_API_URL": "https://gitlab.com",
"GITLAB_READ_ONLY_MODE": "true"
}
その他のエントリーポイント
Claude Code CLI(1 行で追加):
claude mcp add -s user gitlab \
-e GITLAB_PERSONAL_ACCESS_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxx \
-e GITLAB_API_URL=https://gitlab.com \
-- npx efficient-gitlab-mcp-server@latest
GitLab CI runner — PAT が設定されていない場合、CI_JOB_TOKEN が自動検出されます。実行中のプロジェクトに対象を限定するには、GITLAB_PROJECT_ID: $CI_PROJECT_ID を使用します。追加の設定は不要です。
ソースから(開発):
git clone https://github.com/detailobsessed/efficient-gitlab-mcp.git
cd efficient-gitlab-mcp
bun install
bun run build
bun start
問題が発生した場合は、トラブルシューティングをご覧ください。環境変数をさらに調整する必要がある場合は、設定の全リファレンスをご覧ください。
目次
- クイックスタート
- このフォークの理由
- トークン効率
- アップストリームとの違い
- 利用可能なカテゴリ
- 仕組み
- 設定
- 機能
- トラブルシューティング
- 開発
- アップストリームの追跡
- セキュリティ
- 謝辞
- ライセンス
このフォークの理由
GitLab の API の範囲は非常に広く、アップストリームの MCP サーバーにもそれが反映されています。つまり、すべてのツールが起動時に常に公開されます。コンテキストの上限があるエージェントにとって、これは次の 3 点で非効率です。
- 起動時のツール定義。 数百ものツールスキーマが、最初のユーザーターンの前にプロンプトへ強制的に含められます。
- リストエンドポイントの応答。 GitLab のリストエンドポイントは、デフォルトで 1 行あたり 100 個以上のフィールドを持つオブジェクトを返しますが、関連する情報は通常 10 個未満のフィールドです。
- ファイルの内容と大規模なディレクトリ。 単一ファイルの読み取りで、無関係な行が数千行も取り込まれることがあります。また、大規模なリポジトリツリーを一覧表示すると、すべてが一度に返されます。
このフォークは、ツール定義の段階的な開示、リスト応答のフィールド投影、コンテンツのトリミングとキーセットページネーションによって、この 3 点すべてに対処します。
トークン効率
段階的な開示
167 個のツールを個別に公開する代わりに、サーバーは 3 個のメタツールを公開します。
| メタツール | 目的 |
|---|---|
list_categories | 利用可能なツールカテゴリとその有効状態を確認します |
activate_tools | 1 つ以上のカテゴリのすべてのツールを有効にします |
deactivate_tools | 作業が終わったカテゴリを無効にし、トークンを解放します |
| 方法 | 公開されるツール | おおよそのトークンコスト |
|---|---|---|
| 従来型 | 167 個のツール | 約 20,000 トークン以上 |
| 段階的な開示 | 3 個のメタツール | 約 1,500 トークン |
起動時のツール定義トークンを約 90% 削減します。 ツールは MCP SDK に登録されますが、LLM がカテゴリを有効にするまでは無効(tool.disable())のままです。有効化すると tools/list_changed 通知が送られ、クライアントに即座に反映されます。
フィールド投影
一覧エンドポイントと、増加中の単一リソース向け get_* エンドポイントでは、リソースごとに厳選された許可リスト形式のデフォルトフィールドを返します。呼び出し側は fields: "all" で完全なペイロードを取得するか、fields: ["id", "name"] のように独自のリストを指定できます。
現在、以下に適用されています。
list_projects、list_group_projects、get_projectlist_issues、my_issues、get_issuelist_merge_requests、get_merge_requestlist_pipelines、get_pipelinelist_releaseslist_commits、get_commitget_current_user、get_user、get_users、search_users
所有するプロジェクトが5件の状態で list_projects を試験的に測定したところ、コンパクトなデフォルトに切り替えることで 約32 KB → 約3 KB になりました。許可リスト方式のため、GitLab 側で新しいフィールドが追加されても、コンパクトな出力を維持できます。
例 — コンパクトなデフォルトと完全な GitLab ペイロードでマージリクエストを取得する場合:
// Default: ~17 fields (iid, title, state, draft, labels, branches, author, …)
{ "name": "get_merge_request", "arguments": { "merge_request_iid": 42 } }
// Opt out: the raw GitLab response
{ "name": "get_merge_request", "arguments": { "merge_request_iid": 42, "fields": "all" } }
// Custom pick
{ "name": "get_merge_request", "arguments": { "merge_request_iid": 42, "fields": ["iid", "title", "state"] } }
簡潔なデフォルトは、GitLab API レスポンスの検証に使用するものと同じ Zod レスポンススキーマ(src/schemas/ を参照)から導出されるため、型レベルの形状と同期が保たれ、リソースごとの信頼できる情報源が一元化されます。
サーバーサイドでのファイルトリミング
get_file_contents はトリミング用パラメーターを受け付けるため、エージェントは関数を読むためだけにファイル全体をコンテキストに取り込む必要がありません。
| パラメーター | 目的 |
|---|---|
head: N | 最初の N 行だけを返します |
tail: N | 最後の N 行だけを返します |
range: "start-end" | 指定した行範囲を返します |
max_bytes: N | バイト数の上限を設定します(行ベースのトリミングと併用できます) |
切り詰められたレスポンスには Showing lines 100-200 of 5234 のような注記が含まれるため、行数を数えるために再取得することなく、次の呼び出しで別の範囲を指定できます。
キーセットページネーション
get_repository_tree はキーセットページネーション(pagination=keyset)をサポートし、エンベロープ形式で返します。
{
"items": [...],
"pagination_note": "Next page available — call again with pagination=keyset&page_token=..."
}
大規模なモノレポでも、1回のレスポンスに1万件のエントリーが出力されることはなくなりました。サーバーは X-Next-Page-Token からカーソルを読み取り(古い GitLab インスタンスでは X-Next-Page にフォールバック)、レスポンス内にその値を提示します。
Upstream との違い
このフォークは、トークン効率と保守性に重点を置いてアーキテクチャを再設計した zereight/gitlab-mcp を基盤としています。Upstream のコミットを定期的に確認し、新機能やバグ修正を選択的に移植しています。コードベースの構造が大きく異なるため、無条件のリベースは行いません。
アーキテクチャの概要
| 領域 | Upstream | このフォーク |
|---|---|---|
| アーキテクチャ | 単一の index.ts(約1万行) | 16個のツールモジュールを備えたモジュール構成の src/ |
| ツールの検出 | 140以上のツールをすべて一度に公開 | SDK ネイティブの段階的開示(3つのメタツール) |
| 一覧レスポンス | GitLab の完全なペイロード(1行あたり100以上のフィールド) | フィールド投影:コンパクトなデフォルトと、任意指定の fields |
| ファイル内容 | ファイル全体を取得 | サーバーサイドで head / tail / range / max_bytes によるトリミング |
| ツリー一覧 | オフセットページネーションのみ | カーソルエンベロープ付きのオフセット+キーセット(pagination=keyset) |
| ツールのアノテーション | 部分的 | 完全:すべてのツールに readOnlyHint / destructiveHint / idempotentHint / openWorldHint を設定 |
| 設定 | 個別のエクスポートをフラットに配置 | loadConfig() を備えた型付き ServerConfig インターフェース |
| ロギング | console.log | エージェントの可観測性を高める、構造化された MCP プロトコルロガー |
| ランタイム | Node.js + npm | Bun(ビルドの高速化、TypeScript ネイティブ対応) |
| リンティング | ESLint + Prettier | 厳格な Biome ルール(noExplicitAny、noNonNullAssertion、認知的複雑度の上限) |
| CI/CD | 基本的な構成 | GitHub Actions(lint、build、test、semantic-release) |
| コミット前処理 | なし | prek フック(typos、フォーマット、ビルド検証) |
| 機能フラグ | USE_PIPELINE、USE_MILESTONE、USE_GITLAB_WIKI が必要 | なし — すべてのカテゴリを登録し、有効化されるまで休止状態 |
その他の改善点
- 読み取り専用モードとPATの安全性 — PATスコープを自動検出し、明示的な読み取り専用モードと、対処方法を示す403エラーメッセージを提供します。
- シークレットのマスキング —
runners_tokenはデフォルトでプロジェクトのレスポンスからマスキングされます。include_secrets: trueを指定すると、再び含めることができます。 - 堅牢なスキーマ強制変換 — ブール値、数値ID、文字列化された配列をすべて防御的に強制変換します(LLMによるシリアライズには一貫性がありません)。
- HTTPトランスポートのセキュリティ — DNSリバインディング保護と、許可するホスト/オリジンの設定が可能です。
- 包括的なテストスイート — レジストリ、設定、ロガー、MCP統合、読み取り専用モード、射影、メタツールをカバーする280件以上のテストがあります。
- 厳格なコード品質 —
any型はゼロ、非nullアサーションは不使用、認知的複雑度の上限を適用します。 - リリースの自動化 — Conventional Commitsを使用したセマンティックバージョニングを採用しています。
利用可能なカテゴリ
GitLabのすべての操作は、合計167個のツールを含む16カテゴリに整理されています。すべてのカテゴリは起動時に登録されますが、初期状態では無効です。必要なカテゴリを有効にしてください。
| カテゴリ | ツール数 | 説明 |
|---|---|---|
repositories | 11 | リポジトリの検索、作成、フォーク。ファイルの取得/プッシュ、ブランチの管理、ツリーの一覧表示 |
merge-requests | 33 | MRの作成、更新、マージ。ディスカッション、スレッド、差分 |
issues | 14 | イシューの作成、更新、削除。リンク、ディスカッション |
pipelines | 19 | パイプラインの一覧表示、作成、再試行、キャンセル。ジョブの出力 |
projects | 10 | プロジェクトの詳細、一覧、メンバー、ラベル |
commits | 3 | コミットの一覧表示、取得、差分の取得 |
namespaces | 3 | ネームスペースの一覧表示、取得、検証 |
users | 8 | ユーザーの詳細、検索、監査/プロジェクトイベント、ファイルのアップロード、現在のユーザー(whoami) |
search | 6 | コード、イシュー、MR、コミットを対象とした、グローバル、プロジェクト、グループ横断の検索 |
wiki | 10 | プロジェクトおよびグループのWikiページ管理 |
milestones | 9 | マイルストーンの作成、編集、削除。バーンダウンイベント |
releases | 7 | リリースの一覧表示、作成、更新、削除。アセットのダウンロード |
webhooks | 3 | プロジェクトのWebhookと最近のイベントの一覧表示 |
work-items | 12 | GraphQLワークアイテム:作成、更新、階層、ノート、インシデント |
graphql | 1 | 任意のGraphQLクエリを実行 |
emoji-reactions | 18 | MR/イシュー/ワークアイテム/ノートへの絵文字リアクションの追加、削除、一覧表示(REST + GraphQL) |
動作の仕組み
一般的なエージェントのセッションは、検出、有効化、作業の3つのフェーズで進みます。カテゴリが不要になったら、必要に応じて無効化してクリーンアップします。
1. 検出(約1.5Kトークン)
MCPクライアントが接続すると、サーバーは3つのメタツールのみを公開します。エージェントはlist_categoriesを呼び出して、利用可能なものを確認します。
> list_categories()
{
"categories": [
{ "name": "repositories", "tools": 11, "active": false, "description": "Search, create, fork repos. Get/push files, manage branches, list tree" },
{ "name": "merge-requests", "tools": 33, "active": false, "description": "Create, update, merge MRs. Discussions, threads, diffs" },
{ "name": "issues", "tools": 14, "active": false, "description": "Create, update, delete issues. Links, discussions" },
// ... 13 more, 167 tools total
]
}
2. 有効化
エージェントは必要なものを判断し、カテゴリを有効にします。
> activate_tools({ categories: ["merge-requests"] })
"Activated 33 tools in category 'merge-requests'."
サーバーはtools/list_changed通知を送信し、クライアントは新たに追加された33個のツール定義をその場で取得します。
Claude Codeのレイテンシに関する注意:ターン中に有効化されたツールは、次のターンから呼び出せるようになります(Claude Codeはターン間で遅延ツールのインデックスを再構築します)。他のクライアントでは、すぐに利用できる場合があります。
3. 作業
> create_merge_request({
project_id: "123",
title: "Fix bug",
source_branch: "fix",
target_branch: "main"
})
{ "id": 7891, "iid": 42, "title": "Fix bug", "state": "opened", ... }
4. 無効化(任意)
このカテゴリでの作業が終わったら、エージェントはトークンを解放できます。
> deactivate_tools({ categories: ["merge-requests"] })
"Deactivated 33 tools in category 'merge-requests'."
これは、コンテキストに余裕がない長時間のエージェントセッションで特に役立ちます。必要なものだけを取得し、使い終わったら解放してから、別のカテゴリを取得できます。
設定
コア設定
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
GITLAB_PERSONAL_ACCESS_TOKEN | はい* | - | GitLab パーソナルアクセストークン(CI_JOB_TOKEN より優先されます) |
CI_JOB_TOKEN | いいえ | - | GitLab CI ジョブトークン(CI パイプラインで自動検出されます) |
GITLAB_API_URL | いいえ | https://gitlab.com | GitLab インスタンスの URL |
GITLAB_PROJECT_ID | いいえ | - | ツールで project_id が省略された場合のデフォルトのプロジェクト ID |
GITLAB_ALLOWED_PROJECT_IDS | いいえ | - | ツールの対象をこれらのプロジェクトに制限します(カンマ区切り)。プロジェクトが1つの場合はデフォルトとして機能します。複数の場合は、呼び出しごとに project_id が必要です |
GITLAB_READ_ONLY_MODE | いいえ | false | 読み取り専用ツールのみを公開します。設定されていない場合は、PAT のスコープから自動検出されます |
GITLAB_IS_OLD | いいえ | false | 古い GitLab インスタンス向け |
*PAT を推奨します。PAT が設定されていない場合、GitLab CI パイプラインで CI_JOB_TOKEN が自動検出されます。OAuth のサポートは計画中です(OAuth セットアップガイドを参照)。
トランスポート設定
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
STREAMABLE_HTTP | いいえ | false | HTTP トランスポートを有効にします |
SSE | いいえ | false | SSE トランスポートを有効にします |
PORT | いいえ | 3002 | HTTP サーバーのポート |
HOST | いいえ | 127.0.0.1 | HTTP サーバーのホスト |
ログとセキュリティ
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
LOG_LEVEL | いいえ | info | debug、info、warn、error |
LOG_FORMAT | いいえ | pretty | json、pretty |
HTTP_ALLOWED_HOSTS | いいえ | localhost,127.0.0.1 | 許可する Host ヘッダー |
HTTP_ALLOWED_ORIGINS | いいえ | (すべて) | 許可する Origin ヘッダー |
HTTP_ENABLE_DNS_REBINDING_PROTECTION | いいえ | true | DNS リバインディング攻撃への保護を有効にします |
リモート認証(マルチテナント)
| 変数 | 必須 | デフォルト | 説明 |
|---|---|---|---|
REMOTE_AUTHORIZATION | いいえ | false | リモート認証を有効にします |
ENABLE_DYNAMIC_API_URL | いいえ | false | 動的な GitLab URL を許可します |
SESSION_TIMEOUT_SECONDS | いいえ | 3600 | セッションのタイムアウト |
MAX_SESSIONS | いいえ | 1000 | 同時セッションの最大数 |
MAX_REQUESTS_PER_MINUTE | いいえ | 60 | セッションごとのレート制限 |
機能
読み取り専用モードと PAT の安全性
このサーバーは、スコープが限定されたパーソナルアクセストークンを使用するユーザー向けに、3段階の保護を提供します。
1. 明示的な読み取り専用モード — GITLAB_READ_ONLY_MODE=true を設定すると、サーバーを読み取り専用ツールに制限できます。書き込みツールは list_categories の件数に表示されず、有効化もできません。これは、すべてのツールに付与された readOnlyHint アノテーションによって制御されます。
2. PAT スコープの自動検出 — 起動時に、サーバーは GitLab の GET /personal_access_tokens/self を呼び出し、トークンのスコープを確認します。トークンに api スコープがない場合(たとえば、read_api しかない場合)、読み取り専用モードが自動的に有効になります。設定は不要で、そのまま機能します。
3. 対処方法を示す 403 エラーメッセージ — ツール呼び出しで 403 Forbidden エラーが発生した場合、必要な PAT スコープについての具体的な案内がエラーメッセージに含まれるため、LLM は手当たり次第に再試行するのではなく、ユーザーに伝えることができます。
# Explicit read-only mode
GITLAB_READ_ONLY_MODE=true
# Or just use a read_api token — auto-detected!
GITLAB_PERSONAL_ACCESS_TOKEN=glpat-your-read-only-token
シークレットのマスキング
GitLab プロジェクトのレスポンスには、デフォルトで runners_token フィールドが含まれます。このトークンを持つ人は誰でも、そのプロジェクトに対して CI ランナーを登録できます。サーバーは get_project と list_projects のレスポンスで、デフォルトで runners_token をマスキングします。再び含める場合(たとえば、エージェントがランナー登録を管理する必要がある場合)は、include_secrets: true を渡してください。
ツールの注釈
すべてのツールは、完全なMCP ツール注釈セットを宣言しているため、MCP 対応クライアントは操作ごとの確認を提示したり、破壊的な操作と冪等な更新を区別したり、副作用のプロファイルでフィルタリングしたりできます。
| ツールの種類 | readOnlyHint | destructiveHint | idempotentHint | openWorldHint |
|---|---|---|---|---|
| 読み取り専用(list/get) | true | (省略) | (省略) | true |
| 作成 | false | false | false | true |
| 更新 | false | true | true | true |
| 削除 | false | true | true | true |
すべてのツールが GitLab の API と通信するため、openWorldHint は常に true です。この注釈マトリックスは不変条件テストによって検証されます。
MCP プロトコルのログ記録
サーバーは、エージェントの可観測性を高めるために MCP プロトコルのログ記録をサポートしています。接続すると、LLM クライアントはサーバーの動作を示す構造化ログメッセージを受け取ることができます。
- ツール実行ログ
- GitLab API 呼び出しの詳細
- コンテキスト付きのエラー情報
これにより、開発者にしか見えない不透明な console.log 出力とは異なり、エージェントがサーバーの動作を理解し、問題をデバッグしやすくなります。
HTTP トランスポートのセキュリティ
HTTP トランスポート(STREAMABLE_HTTP=true)を使用する場合、サーバーには次のセキュリティ機能が含まれます。
| 環境変数 | デフォルト | 説明 |
|---|---|---|
HTTP_ALLOWED_HOSTS | localhost,127.0.0.1 | 許可する Host ヘッダーをカンマ区切りで指定したリスト |
HTTP_ALLOWED_ORIGINS | (任意) | 許可する Origin ヘッダーをカンマ区切りで指定したリスト |
HTTP_ENABLE_DNS_REBINDING_PROTECTION | true | DNS リバインディング攻撃対策を有効にします |
本番環境での例:
HTTP_ALLOWED_HOSTS=api.example.com,localhost \
HTTP_ALLOWED_ORIGINS=https://app.example.com \
STREAMABLE_HTTP=true \
bun start
トラブルシューティング
エージェントがカテゴリーを有効にしたのに、新しいツールが表示されません
実行時に有効化したツールを反映するには、MCP クライアントがtools/list_changed 通知に対応している必要があります。最新のクライアントの多くは対応しています。
特に Claude Code では、有効化したツールは次のターンから呼び出せるようになります。クライアントはターンの間に遅延ツールのインデックスを再構築するため、同じターン内で同期的には更新されません。そのため、activate_tools({ categories: ["issues"] }) を呼び出してから同じターンで list_issues() を呼び出しても動作しません。次のターンであれば動作します。ほかのクライアント(Claude Desktop、Cursor)は比較的すぐに反映されます。
動作するはずのツールで「403 Forbidden」が発生します
サーバーは対処方法がわかる 403 エラーを返します。エラーメッセージには不足している PAT スコープが示されます。よくある原因は、PAT に read_api スコープ(読み取り専用)しかなく、呼び出したツールには api が必要なことです。api スコープを持つ PAT を再生成するか、読み取り専用モードのまま読み取りツールを使用してください。
project_id が繰り返し拒否されます
GITLAB_ALLOWED_PROJECT_IDS に複数の ID をカンマ区切りで設定している場合、すべてのツール呼び出しで、それらのいずれかと一致する project_id を明示的に指定する必要があります。デフォルト値はありません。1つの ID の場合、project_id が渡されなければ、その ID がデフォルトとして使われます。空または未設定の場合、制限はなく、任意のプロジェクト ID が許可されます。
セルフホスト版 GitLab に接続できません
GITLAB_API_URL には、API パスではなくインスタンスのベース URL(https://gitlab.your-company.com)を指定してください。サーバーが自動的に /api/v4 を追加します。ベース URL にすでに /api/v4 が含まれていると、呼び出し先が /api/v4/api/v4/... となり、404 が返されます。
GitLab CI で CI ツールが動作しません
GITLAB_PERSONAL_ACCESS_TOKEN が設定されていない場合、サーバーは自動的に CI_JOB_TOKEN にフォールバックします(GitLab CI 環境から自動検出されます)。実行中のパイプラインのプロジェクトがデフォルトのスコープとして使われるように、.gitlab-ci.yml で GITLAB_PROJECT_ID: $CI_PROJECT_ID を設定してください。
プロジェクトのレスポンスに runners_token がありません
安全のため、デフォルトで秘匿されています。取得するには、呼び出し時に include_secrets: true を渡してください。
List エンドポイントで想定より少ない結果が返される
list_issues、list_merge_requests などの場合:project_id が指定されていないとき、GitLab のグローバルエンドポイントは従来、デフォルトで scope: created_by_me を使用していました。すべての項目を表示するには、明示的に scope: "all" を渡してください。project_id を指定すると、呼び出しはプロジェクトスコープのエンドポイントにルーティングされ、このデフォルトは適用されません。
MCP サーバーのログに GitLab response failed schema validation と表示される
サーバーのスキーマ検証対象の読み取りエンドポイント(ユーザー、プロジェクト、マージリクエスト、コミット、課題、パイプライン、リポジトリツリー)からの GitLab レスポンスは、Zod スキーマを通じて処理されます。不一致があると、サーバーはフィールドのパスと Zod のエラーコードを含む WARN GitLab response failed schema validation; passing through unchanged をログに記録し、その後レスポンスを変更せずに LLM に渡します。そのため呼び出しは成功しますが、GitLab が既知の形式と異なるレスポンスを返したことを示すシグナルが得られます。原因として多いのは、GitLab API の変更(新しいフィールド、型の変更、削除)や、EE 専用フィールドを返すセルフホスト可能な EE インスタンスです。こうした警告が表示された場合は、path、code、および警告を発生させたツールを記載して、issue を作成してください。それをもとにスキーマを更新します。
開発
# Install dependencies
bun install
# Run tests (280+ tests, <1s)
bun test
# Run tests with coverage
bun test --coverage
# Lint and format
bun run check
# Build
bun run build
スキーマドリフトの CI
実行時に parseGitLabResponse を通る処理は、想定外の GitLab フィールドによって MCP ツールの呼び出しが妨げられないよう、意図的に寛容にしています(.safeParse() +警告のログ記録+そのまま通過)。ドリフトゲートはその厳格な対になるものです。すべてのレスポンススキーマ対応 GitLab REST エンドポイントを呼び出し、各レスポンスを宣言済みの Zod スキーマに対して .parse() する Bun スクリプトで、不一致があると失敗します。
ローカルで実行するには:
export GITLAB_API_URL=https://gitlab.com
export GITLAB_PERSONAL_ACCESS_TOKEN=glpat-... # read_api scope only
export GITLAB_PROJECT_ID=12345 # must have ≥1 MR/commit/issue/pipeline
bun run drift
手動で実行するタイミング:
src/schemas/に関わる PR をマージする前 — 実際のインスタンスを使ってスキーマの問題を検出し、フィクスチャーベースのユニットテストを補完します。- セルフホストの GitLab をアップグレードした後 — レスポンスの形式に変更がないことをすばやく確認できます。
- 疑わしい LLM の挙動を調査するとき — レスポンスがおかしく見えるのにツールが OK を返す場合、スキーマの不一致が気付かれないまま通過している可能性があります。ドリフトチェックで確認するか、その可能性を除外できます。
同じスクリプトは .github/workflows/schema-drift.yml を通じて CI でも実行されます。schedule は月曜日の 06:00 UTC、workflow_dispatch は任意のタイミングで実行します。同じ 3 つの環境変数がリポジトリシークレットとして設定されています。
上流の追跡
main は上流の読み取り専用ミラーとして維持しています。上流からの新機能やバグ修正はレビューし、必要に応じて私たちのアーキテクチャに移植します。コードベースの構造が大きく異なるため、無条件にリベースすることはありません。特定の上流機能をお探しの場合は、リリースを確認するか、issue を作成してください。
セキュリティ
- トークンをコミットしない —
.envファイルを使用してください(gitignore 対象です) - トークンをローテーションする — 定期的に再生成してください
- 最小権限 — 必要な API スコープのみを付与してください
- 監査ログ — API アクセスを監視してください
- シークレットの秘匿化 —
runners_tokenはデフォルトで秘匿化されます。詳しくはシークレットの秘匿化をご覧ください
謝辞
このプロジェクトは zereight/gitlab-mcp のフォークです。包括的な GitLab API 実装を公開してくださった原作者に感謝します。
リソース
- MCP プロトコル:modelcontextprotocol.io
- GitLab API:docs.gitlab.com/ee/api
- Bun:bun.sh
ライセンス
MIT License — 詳細は LICENSE をご覧ください。
Efficient GitLab MCP
トークン効率に優れた AI による GitLab 管理
Bun と Model Context Protocol を使用して構築
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。