@jswk1/gitlab-mcp 1.3.4 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,334 +1,369 @@
1
- # GitLab read-only MCP server
2
-
3
- Give your AI assistant GitLab issues, merge requests, discussions and attachments from a self-managed instance. The server reads GitLab; your assistant uses its own tools to inspect and edit your local repository.
4
-
5
- ## TL;DR — what can I use it for?
6
-
7
- Give your assistant an issue or merge request link and ask it to:
8
-
9
- - **Implement an issue:** investigate requirements, comments and attachments, then implement the requested fix locally.
10
- - **Review a merge request:** find bugs, regressions and improvements in changed code.
11
- - **Address review comments:** evaluate unresolved feedback, implement justified fixes and draft replies for disagreements or better alternatives.
12
- - **Investigate failed CI:** explain pipeline and unit-test failures, attempt requested unit-test fixes when checked out on the MR branch, and report linked ATF job status and failure reasons where accessible.
13
- - **Prepare manual testing:** produce prioritized test cases or a business-focused briefing covering the actual implementation, changes missing from the ticket, regression risks and documentation checks.
14
- - **Update documentation:** draft or update local Markdown to reflect verified implementation changes.
1
+ # GitLab MCP server
2
+
3
+ Give your AI assistant GitLab issues, merge requests, discussions and attachments from a self-managed instance. The server reads GitLab; your assistant uses its own tools to inspect and edit your local repository.
4
+
5
+ ## TL;DR — what can I use it for?
6
+
7
+ Give your assistant an issue or merge request link and ask it to:
8
+
9
+ - **Implement an issue:** investigate requirements, comments and attachments, then implement the requested fix locally.
10
+ - **Review a merge request:** find bugs, regressions and improvements in changed code.
11
+ - **Address review comments:** evaluate unresolved feedback, implement justified fixes and draft replies for disagreements or better alternatives.
12
+ - **Investigate failed CI:** explain pipeline and unit-test failures, attempt requested unit-test fixes when checked out on the MR branch, and report linked ATF job status and failure reasons where accessible.
13
+ - **Prepare manual testing:** produce prioritized test cases or a business-focused briefing covering the actual implementation, changes missing from the ticket, regression risks and documentation checks.
14
+ - **Update documentation:** draft or update local Markdown to reflect verified implementation changes.
15
15
  - **Report on client work:** summarize requirements and issue status, export filtered CSV reports by client, milestone or period, and reconcile them with a supplied sheet.
16
-
17
- The server provides read-only GitLab context; your assistant performs local edits, checks and file exports using its own tools. Review replies stay drafts. See [Setup](#setup) for Codex/OpenCode examples and [Workflows](#workflows) for details and sample requests.
18
-
19
- ## Setup
20
-
21
- - **GitLab 17.4+** for attachment downloads. Older versions are untested.
22
- - **A personal access token with `read_api` scope**, belonging to the developer using the assistant. The token owner's GitLab permissions determine access, including confidential issues.
23
- - **Node.js 20.20+** for npm/local setup, or **Docker** for container setup.
24
-
25
- Choose one launch option below and use the example for your client. All options use **stdio**: the client starts the server and communicates over stdin/stdout. Run one server process per developer/client; there is no HTTP endpoint.
26
-
27
- Client configuration formats differ:
28
-
29
- | Client | User configuration file | Server entry |
30
- | --- | --- | --- |
31
- | Codex | `~/.codex/config.toml` | `[mcp_servers.gitlab]`, string `command`, separate `args` and `env` |
32
- | OpenCode | `~/.config/opencode/opencode.json` | `mcp.gitlab`, `type: "local"`, command array and `environment` |
33
-
34
- Codex also supports `.codex/config.toml` in trusted projects; OpenCode supports a project-level `opencode.json`. Merge the chosen example into your existing configuration, replacing any previous `gitlab` entry. The `mcpServers` JSON wrapper used by some other MCP clients is not the direct configuration format for either client. See the official [Codex MCP documentation](https://developers.openai.com/codex/mcp/) and [OpenCode MCP documentation](https://opencode.ai/docs/mcp-servers/), plus [OpenCode configuration locations and variable substitution](https://opencode.ai/docs/config/).
35
-
36
- For npm and local builds, make `GITLAB_TOKEN` available in the client process environment before starting the client. Codex forwards it through `env_vars`; OpenCode substitutes `{env:GITLAB_TOKEN}`. A desktop app must receive the variable in its own launch environment; an export in a separate terminal does not update an already-running app. Keep real tokens out of shared project configuration. Docker examples instead read credentials from the specified private `.env` file.
37
-
38
- ### Option 1: npm package
39
-
40
- **Codex** — add to `~/.codex/config.toml`:
41
-
42
- ```toml
43
- [mcp_servers.gitlab]
44
- command = "npx"
45
- args = ["--yes", "--package=@jswk1/gitlab-mcp@1.3.4", "gitlab-mcp"]
46
- env_vars = ["GITLAB_TOKEN"]
47
- startup_timeout_sec = 60
48
-
49
- [mcp_servers.gitlab.env]
50
- GITLAB_URL = "https://gitlab.example.internal"
51
- ```
52
-
53
- **OpenCode** — add to `~/.config/opencode/opencode.json`:
54
-
55
- ```json
56
- {
57
- "$schema": "https://opencode.ai/config.json",
58
- "mcp": {
59
- "gitlab": {
60
- "type": "local",
61
- "command": ["npx", "--yes", "--package=@jswk1/gitlab-mcp@1.3.4", "gitlab-mcp"],
62
- "enabled": true,
63
- "timeout": 60000,
64
- "environment": {
65
- "GITLAB_URL": "https://gitlab.example.internal",
66
- "GITLAB_TOKEN": "{env:GITLAB_TOKEN}"
67
- }
68
- }
69
- }
70
- }
71
- ```
72
-
73
- The first run downloads the package; these examples allow extra startup time. Keep a pinned version for reproducible installs. If the package is unavailable, build locally or use Docker.
74
-
75
- ### Option 2: local build over stdio
76
-
77
- From the repository root:
78
-
79
- ```sh
80
- npm ci
81
- npm run build
82
- ```
83
-
84
- Point your client at the compiled entry point using an absolute path.
85
-
86
- **Codex**:
87
-
88
- ```toml
89
- [mcp_servers.gitlab]
90
- command = "node"
91
- args = ["/absolute/path/to/gitlab-mcp/dist/index.js"]
92
- env_vars = ["GITLAB_TOKEN"]
93
-
94
- [mcp_servers.gitlab.env]
95
- GITLAB_URL = "https://gitlab.example.internal"
96
- ```
97
-
98
- **OpenCode**:
99
-
100
- ```json
101
- {
102
- "$schema": "https://opencode.ai/config.json",
103
- "mcp": {
104
- "gitlab": {
105
- "type": "local",
106
- "command": ["node", "/absolute/path/to/gitlab-mcp/dist/index.js"],
107
- "enabled": true,
108
- "environment": {
109
- "GITLAB_URL": "https://gitlab.example.internal",
110
- "GITLAB_TOKEN": "{env:GITLAB_TOKEN}"
111
- }
112
- }
113
- }
114
- }
115
- ```
116
-
117
- These configurations use the client environment and do not automatically load the repository's `.env`. To launch manually with a file, copy `.env.example` to `.env`, fill in your credentials, then run `node --env-file=.env dist/index.js`. The process waits for MCP messages; it is not an interactive terminal application.
118
-
119
- ### Option 3: Docker
120
-
121
- From the repository root:
122
-
123
- ```sh
124
- npm run docker:build
125
- cp .env.example .env
126
- ```
127
-
128
- Fill in `GITLAB_URL` and `GITLAB_TOKEN` in `.env`, then configure your client with the file's absolute path.
129
-
130
- **Codex**:
131
-
132
- ```toml
133
- [mcp_servers.gitlab]
134
- command = "docker"
135
- args = [
136
- "run", "--rm", "-i",
137
- "--env-file", "/absolute/path/to/gitlab-mcp/.env",
138
- "gitlab-readonly-mcp"
139
- ]
140
- ```
141
-
142
- **OpenCode**:
143
-
144
- ```json
145
- {
146
- "$schema": "https://opencode.ai/config.json",
147
- "mcp": {
148
- "gitlab": {
149
- "type": "local",
150
- "command": [
151
- "docker", "run", "--rm", "-i",
152
- "--env-file", "/absolute/path/to/gitlab-mcp/.env",
153
- "gitlab-readonly-mcp"
154
- ],
155
- "enabled": true
156
- }
157
- }
158
- }
159
- ```
160
-
161
- Keep `-i`; do not add `-t` or `-d`. No ports or repository mounts are needed. The image runs as a non-root user and receives credentials at runtime.
162
-
163
- GitLab must be reachable from inside the container. On Docker Desktop, use `host.docker.internal` to reach GitLab on your host. On Linux Docker Engine, also add `--add-host=host.docker.internal:host-gateway` to the Docker arguments when using that hostname.
164
-
165
- After configuration changes, restart the client's MCP connection. After source updates, rebuild the local output or Docker image before reconnecting.
166
-
167
- ## Workflows
168
-
169
- Ask your assistant to work on an issue or MR in your local repository. It can start with `gitlab_get_workflow`, passing `project`, `iid`, `target` (`issue` or `merge_request`), optional `profile`, optional `goal` to specify scope.
170
-
16
+ - **Prepare a time report:** use your GitLab activity for a date to suggest projects in a supplied timesheet’s format, without editing the workbook.
17
+
18
+ The server provides GitLab context and write capabilities; your assistant performs local edits, checks and file exports using its own tools. Replies stay drafts unless posting is requested. See [Setup](#setup) for Codex/OpenCode examples and [Workflows](#workflows) for details and sample requests.
19
+
20
+ ## Setup
21
+
22
+ - **GitLab 17.4+** for attachment downloads. Older versions are untested.
23
+ - **A personal access token with `read_api` scope**, belonging to the developer using the assistant. The token owner's GitLab permissions determine access, including confidential issues.
24
+ - **Node.js 20.20+** for npm/local setup, or **Docker** for container setup.
25
+
26
+ Choose one launch option below and use the example for your client. All options use **stdio**: the client starts the server and communicates over stdin/stdout. Run one server process per developer/client; there is no HTTP endpoint.
27
+
28
+ Client configuration formats differ:
29
+
30
+ | Client | User configuration file | Server entry |
31
+ | --- | --- | --- |
32
+ | Codex | `~/.codex/config.toml` | `[mcp_servers.gitlab]`, string `command`, separate `args` and `env` |
33
+ | OpenCode | `~/.config/opencode/opencode.json` | `mcp.gitlab`, `type: "local"`, command array and `environment` |
34
+
35
+ Codex also supports `.codex/config.toml` in trusted projects; OpenCode supports a project-level `opencode.json`. Merge the chosen example into your existing configuration, replacing any previous `gitlab` entry. The `mcpServers` JSON wrapper used by some other MCP clients is not the direct configuration format for either client. See the official [Codex MCP documentation](https://developers.openai.com/codex/mcp/) and [OpenCode MCP documentation](https://opencode.ai/docs/mcp-servers/), plus [OpenCode configuration locations and variable substitution](https://opencode.ai/docs/config/).
36
+
37
+ For npm and local builds, make `GITLAB_TOKEN` available in the client process environment before starting the client. Codex forwards it through `env_vars`; OpenCode substitutes `{env:GITLAB_TOKEN}`. A desktop app must receive the variable in its own launch environment; an export in a separate terminal does not update an already-running app. Keep real tokens out of shared project configuration. Docker examples instead read credentials from the specified private `.env` file.
38
+
39
+ ### Option 1: npm package
40
+
41
+ **Codex** — add to `~/.codex/config.toml`:
42
+
43
+ ```toml
44
+ [mcp_servers.gitlab]
45
+ command = "npx"
46
+ args = ["--yes", "--package=@jswk1/gitlab-mcp@1.3.8", "gitlab-mcp"]
47
+ env_vars = ["GITLAB_TOKEN"]
48
+ startup_timeout_sec = 60
49
+
50
+ [mcp_servers.gitlab.env]
51
+ GITLAB_URL = "https://gitlab.example.internal"
52
+ ```
53
+
54
+ **OpenCode** — add to `~/.config/opencode/opencode.json`:
55
+
56
+ ```json
57
+ {
58
+ "$schema": "https://opencode.ai/config.json",
59
+ "mcp": {
60
+ "gitlab": {
61
+ "type": "local",
62
+ "command": ["npx", "--yes", "--package=@jswk1/gitlab-mcp@1.3.8", "gitlab-mcp"],
63
+ "enabled": true,
64
+ "timeout": 60000,
65
+ "environment": {
66
+ "GITLAB_URL": "https://gitlab.example.internal",
67
+ "GITLAB_TOKEN": "{env:GITLAB_TOKEN}"
68
+ }
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ The first run downloads the package; these examples allow extra startup time. Keep a pinned version for reproducible installs. If the package is unavailable, build locally or use Docker.
75
+
76
+ ### Option 2: local build over stdio
77
+
78
+ From the repository root:
79
+
80
+ ```sh
81
+ npm ci
82
+ npm run build
83
+ ```
84
+
85
+ Point your client at the compiled entry point using an absolute path.
86
+
87
+ **Codex**:
88
+
89
+ ```toml
90
+ [mcp_servers.gitlab]
91
+ command = "node"
92
+ args = ["/absolute/path/to/gitlab-mcp/dist/index.js"]
93
+ env_vars = ["GITLAB_TOKEN"]
94
+
95
+ [mcp_servers.gitlab.env]
96
+ GITLAB_URL = "https://gitlab.example.internal"
97
+ ```
98
+
99
+ **OpenCode**:
100
+
101
+ ```json
102
+ {
103
+ "$schema": "https://opencode.ai/config.json",
104
+ "mcp": {
105
+ "gitlab": {
106
+ "type": "local",
107
+ "command": ["node", "/absolute/path/to/gitlab-mcp/dist/index.js"],
108
+ "enabled": true,
109
+ "environment": {
110
+ "GITLAB_URL": "https://gitlab.example.internal",
111
+ "GITLAB_TOKEN": "{env:GITLAB_TOKEN}"
112
+ }
113
+ }
114
+ }
115
+ }
116
+ ```
117
+
118
+ These configurations use the client environment and do not automatically load the repository's `.env`. To launch manually with a file, copy `.env.example` to `.env`, fill in your credentials, then run `node --env-file=.env dist/index.js`. The process waits for MCP messages; it is not an interactive terminal application.
119
+
120
+ ### Option 3: Docker
121
+
122
+ From the repository root:
123
+
124
+ ```sh
125
+ npm run docker:build
126
+ cp .env.example .env
127
+ ```
128
+
129
+ Fill in `GITLAB_URL` and `GITLAB_TOKEN` in `.env`, then configure your client with the file's absolute path.
130
+
131
+ **Codex**:
132
+
133
+ ```toml
134
+ [mcp_servers.gitlab]
135
+ command = "docker"
136
+ args = [
137
+ "run", "--rm", "-i",
138
+ "--env-file", "/absolute/path/to/gitlab-mcp/.env",
139
+ "gitlab-readonly-mcp"
140
+ ]
141
+ ```
142
+
143
+ **OpenCode**:
144
+
145
+ ```json
146
+ {
147
+ "$schema": "https://opencode.ai/config.json",
148
+ "mcp": {
149
+ "gitlab": {
150
+ "type": "local",
151
+ "command": [
152
+ "docker", "run", "--rm", "-i",
153
+ "--env-file", "/absolute/path/to/gitlab-mcp/.env",
154
+ "gitlab-readonly-mcp"
155
+ ],
156
+ "enabled": true
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ Keep `-i`; do not add `-t` or `-d`. No ports or repository mounts are needed. The image runs as a non-root user and receives credentials at runtime.
163
+
164
+ GitLab must be reachable from inside the container. On Docker Desktop, use `host.docker.internal` to reach GitLab on your host. On Linux Docker Engine, also add `--add-host=host.docker.internal:host-gateway` to the Docker arguments when using that hostname.
165
+
166
+ After configuration changes, restart the client's MCP connection. After source updates, rebuild the local output or Docker image before reconnecting.
167
+
168
+ ## Workflows
169
+
170
+ Ask your assistant to work on an issue or MR in your local repository. It can start with `gitlab_get_workflow`, passing `project`, `iid`, `target` (`issue` or `merge_request`), optional `profile`, optional `goal` to specify scope.
171
+
171
172
  | Profile | Issue | Merge request |
172
- | --- | --- | --- |
173
- | `developer` (default) | Investigate and implement requested fixes/features directly | Review changed code; address unresolved review comments; diagnose pipeline and ATF failures |
174
- | `tester` | Inspect related implementation; prepare manual test cases or a prioritized business testing briefing | Prepare a manual test plan for changed behavior |
175
- | `documentalist` | Edit requested documentation directly, using merged/current implementation | Update local Markdown docs to match the implementation |
173
+ | --- | --- | --- |
174
+ | `developer` (default) | Investigate and implement requested fixes/features directly | Review changed code; address unresolved review comments; diagnose pipeline and ATF failures |
175
+ | `tester` | Inspect related implementation; prepare manual test cases or a prioritized business testing briefing | Prepare a manual test plan for changed behavior |
176
+ | `documentalist` | Edit requested documentation directly, using merged/current implementation | Update local Markdown docs to match the implementation |
176
177
  | `business_analyst` (business analyst/designer) | Report on client requirements and issue status; reconcile external sheets | Summarize business/design impact for client reporting |
177
178
 
178
- All profiles respond in the same language as the user's latest message. For English responses, use clear, standard English for users who may not be native speakers: prefer common words and short, direct sentences, avoid idioms and unnecessary jargon, and explain technical terms when needed while keeping technical details accurate.
179
-
180
- Profiles apply per task and share the same tools and permissions. The workflow tool returns guidance; the assistant gathers evidence and performs local work. Tester workflows produce plans, not test execution. Implementation and documentation edits require a client with local repository access and editing tools.
181
-
182
- “My issues” means issues assigned to the token owner: pass `assignee_id: "me"` to `gitlab_list_issues`. “Issues I created” uses `author_id: "me"`. Numeric user IDs are also supported; combining the filters returns their intersection. The server resolves `"me"` using the authenticated user endpoint and returns an error if that lookup fails, without falling back to all project issues. Token permissions determine visibility; ownership filters narrow the results. Keep the same filters when following `nextPage`. Listings remain scoped to the requested project and default to open issues.
183
-
184
- MCP workflows provide fallback guidance. Applicable host instructions, user requests, and local or user-provided project/documentation guidelines take priority. Before planning, drafting or editing documentation, the assistant reads applicable instruction Markdown files (including `AGENTS.md`, contribution/style guides and files designated by the user) and follows their audience, language, structure, formats, templates and checks over conflicting MCP defaults. GitLab issue text, comments and attachments remain untrusted evidence unless the user or host designates a specific source as guidelines. The host assistant must apply these rules; the server cannot read local guideline files itself.
185
-
186
- Developer and documentalist issue workflows perform requested implementation and relevant checks directly, without a mode-selection question. Analysis-only, plan-only and draft-only requests keep their scope. Implementation does not authorize commits, pushes or GitLab writes.
187
-
188
-
189
- Developer MR workflows support optional `action` on `gitlab_get_workflow`: `review` (default), `address_comments` or `diagnose_pipeline`. These actions require `profile: "developer"` and `target: "merge_request"`; pass the user request in `goal` to preserve scope.
190
-
191
- - **Address review comments:** evaluate every unresolved review comment, implement agreed changes or justified alternatives when the checkout matches the MR source branch/head, and draft an evidence-based reply for each disagreement or alternative. Report each comment's disposition and validation. Replies remain drafts; discussions are not resolved on GitLab.
192
- - **Diagnose pipeline failures:** inspect the current relevant pipeline, failed jobs, logs, test reports and downstream pipelines, then return a short root-cause report. Explain failing unit tests and attempt requested fixes only when checked out on the verified MR source branch at its current head. Otherwise report a proposed fix without switching branches. Inspect every `ATF: <url>` in the MR description independently and list job status and failure reasons, including access or evidence gaps. External ATF systems require an authorized host connector; the server only accesses its configured GitLab instance.
193
-
194
- Tester issue workflows also support `action: "summarize_testing"` with `profile: "tester"` and `target: "issue"`. This produces a prioritized business testing briefing rather than a detailed test-case catalog. The assistant reads the description and all comments, verifies related implementation branches/MRs, and compares the full implemented changes with the ticket, including business changes omitted from the description or developer comments. It covers affected users and workflows, observable outcomes, regression risks, practical manual checks and documentation updates/checks to consider. Internal technical changes appear only when they affect business behavior or documentation. The briefing distinguishes documented requirements, implementation discoveries and open questions, with source references and coverage limits. If implementation is unavailable, it reports that gap and limits the briefing to requirement-based checks. It does not edit files or execute tests.
195
-
196
- For aggregate reporting, select `profile: "business_analyst"`, `target: "report"`, `project` and a `goal`; omit `iid`. This mode does not require a source checkout. The assistant uses host file tools to generate actual CSV files with the requested columns (or returns CSV text if file tools are unavailable). External sheets require a user-provided file or an authorized host connector; this server does not connect to or update sheets itself.
197
-
198
- Client attribution must use an explicit label or supplied mapping. Reports follow all issue pages and filter `closed_at` locally with inclusive start and exclusive end dates in the agreed timezone. Current closed issues do not describe historical closure events for reopened issues. Milestone membership and closure dates are separate filters. Reports include source links, exact filters, retrieval time, totals and coverage limits. Client-facing exports omit confidential/internal content unless authorized, and CSV text cells are protected against spreadsheet formulas. Reconciliation preserves stable issue and external row identifiers and reports duplicates, missing rows and conflicts.
199
-
200
- Example requests:
201
-
202
- - “Guide me through fixing issue #123. I want to make the changes myself.”
203
- - “Automatically implement issue #123, including the relevant tests.”
204
- - “Read issue #123 in `group/project`, including comments and attachments, and fix the validation bug in this repository.”
205
- - “Review MR !456 in `group/project`. Return findings limited to changed code, ordered by severity.”
206
- - “<merge request link> Analyze unresolved code review comments and implement fixes you agree with. Draft a reply for each disagreement or better alternative.”
207
- - “<merge request link> If the MR pipeline failed, find the root cause and prepare a short report. Explain failed unit tests and try to fix them if checked out on the MR branch. Check every ATF: <url> in the description and list job status and failure reasons.”
208
- - “Use the tester profile for issue #123 in `group/project` and prepare the critical manual test cases for the latest related branch.”
209
- - “<issue link> Use the tester profile to analyze the description, comments and implemented branch. Summarize business changes to pay attention to during manual tests, ordered by priority, including changes missing from the ticket and anything requiring a documentation check or update.”
210
- - “Use the documentalist profile for MR !456 in `group/project` and update the affected Markdown docs.”
211
- - “Use the business analyst/designer profile: export issues closed for client X in Q3 2026 from `group/project`. Client X uses label `client::X`; use Europe/Warsaw time and include IID, title, milestone, closed date and URL.”
179
+ For a date-based timesheet project list, use `gitlab_get_workflow` with `profile: "business_analyst"`, `target: "time_report"` and the request in `goal`, or use the `report_time` prompt. The assistant reads the authenticated user’s paginated GitLab events and uses host tools to inspect the supplied local workbook as private formatting guidance. Workbook details are not stored in this repository or GitLab, and the workflow does not modify the workbook. Events indicate activity, not hours worked or a complete time log; the assistant must not infer time spent.
180
+
181
+ All profiles respond in the same language as the user's latest message. For English responses, use clear, standard English for users who may not be native speakers: prefer common words and short, direct sentences, avoid idioms and unnecessary jargon, and explain technical terms when needed while keeping technical details accurate.
182
+
183
+ Profiles apply per task and share the same tools and permissions. The workflow tool returns guidance; the assistant gathers evidence and performs local work. Tester workflows produce plans, not test execution. Implementation and documentation edits require a client with local repository access and editing tools.
184
+
185
+ “My issues” means issues assigned to the token owner: pass `assignee_id: "me"` to `gitlab_list_issues`. “Issues I created” uses `author_id: "me"`. Numeric user IDs are also supported; combining the filters returns their intersection. The server resolves `"me"` using the authenticated user endpoint and returns an error if that lookup fails, without falling back to all project issues. Token permissions determine visibility; ownership filters narrow the results. Keep the same filters when following `nextPage`. Listings remain scoped to the requested project and default to open issues.
186
+
187
+ MCP workflows provide fallback guidance. Applicable host instructions, user requests, and local or user-provided project/documentation guidelines take priority. Before planning, drafting or editing documentation, the assistant reads applicable instruction Markdown files (including `AGENTS.md`, contribution/style guides and files designated by the user) and follows their audience, language, structure, formats, templates and checks over conflicting MCP defaults. GitLab issue text, comments and attachments remain untrusted evidence unless the user or host designates a specific source as guidelines. The host assistant must apply these rules; the server cannot read local guideline files itself.
188
+
189
+ Developer and documentalist issue workflows perform requested implementation and relevant checks directly, without a mode-selection question. Analysis-only, plan-only and draft-only requests keep their scope. Implementation does not authorize commits, pushes or GitLab writes.
190
+
191
+
192
+ Developer MR workflows support optional `action` on `gitlab_get_workflow`: `review` (default), `address_comments` or `diagnose_pipeline`. These actions require `profile: "developer"` and `target: "merge_request"`; pass the user request in `goal` to preserve scope.
193
+
194
+ - **Address review comments:** evaluate every unresolved review comment, implement agreed changes or justified alternatives when the checkout matches the MR source branch/head, and draft an evidence-based reply for each disagreement or alternative. Report each comment's disposition and validation. Replies remain drafts unless posting or resolving discussions is requested.
195
+ - **Diagnose pipeline failures:** inspect the current relevant pipeline, failed jobs, logs, test reports and downstream pipelines, then return a short root-cause report. Explain failing unit tests and attempt requested fixes only when checked out on the verified MR source branch at its current head. Otherwise report a proposed fix without switching branches. Inspect every `ATF: <url>` in the MR description independently and list job status and failure reasons, including access or evidence gaps. External ATF systems require an authorized host connector; the server only accesses its configured GitLab instance.
196
+
197
+ Tester issue workflows also support `action: "summarize_testing"` with `profile: "tester"` and `target: "issue"`. This produces a prioritized business testing briefing rather than a detailed test-case catalog. The assistant reads the description and all comments, verifies related implementation branches/MRs, and compares the full implemented changes with the ticket, including business changes omitted from the description or developer comments. It covers affected users and workflows, observable outcomes, regression risks, practical manual checks and documentation updates/checks to consider. Internal technical changes appear only when they affect business behavior or documentation. The briefing distinguishes documented requirements, implementation discoveries and open questions, with source references and coverage limits. If implementation is unavailable, it reports that gap and limits the briefing to requirement-based checks. It does not edit files or execute tests.
198
+
199
+ For aggregate reporting, select `profile: "business_analyst"`, `target: "report"`, `project` and a `goal`; omit `iid`. This mode does not require a source checkout. The assistant uses host file tools to generate actual CSV files with the requested columns (or returns CSV text if file tools are unavailable). External sheets require a user-provided file or an authorized host connector; this server does not connect to or update sheets itself.
200
+
201
+ Client attribution must use an explicit label or supplied mapping. Reports follow all issue pages and filter `closed_at` locally with inclusive start and exclusive end dates in the agreed timezone. Current closed issues do not describe historical closure events for reopened issues. Milestone membership and closure dates are separate filters. Reports include source links, exact filters, retrieval time, totals and coverage limits. Client-facing exports omit confidential/internal content unless authorized, and CSV text cells are protected against spreadsheet formulas. Reconciliation preserves stable issue and external row identifiers and reports duplicates, missing rows and conflicts.
202
+
203
+ Example requests:
204
+
205
+ - “Guide me through fixing issue #123. I want to make the changes myself.”
206
+ - “Automatically implement issue #123, including the relevant tests.”
207
+ - “Read issue #123 in `group/project`, including comments and attachments, and fix the validation bug in this repository.”
208
+ - “Review MR !456 in `group/project`. Return findings limited to changed code, ordered by severity.”
209
+ - “<merge request link> Analyze unresolved code review comments and implement fixes you agree with. Draft a reply for each disagreement or better alternative.”
210
+ - “<merge request link> If the MR pipeline failed, find the root cause and prepare a short report. Explain failed unit tests and try to fix them if checked out on the MR branch. Check every ATF: <url> in the description and list job status and failure reasons.”
211
+ - “Use the tester profile for issue #123 in `group/project` and prepare the critical manual test cases for the latest related branch.”
212
+ - “<issue link> Use the tester profile to analyze the description, comments and implemented branch. Summarize business changes to pay attention to during manual tests, ordered by priority, including changes missing from the ticket and anything requiring a documentation check or update.”
213
+ - “Use the documentalist profile for MR !456 in `group/project` and update the affected Markdown docs.”
214
+ - “Use the business analyst/designer profile: export issues closed for client X in Q3 2026 from `group/project`. Client X uses label `client::X`; use Europe/Warsaw time and include IID, title, milestone, closed date and URL.”
212
215
  - “Generate a CSV of closed client X issues in milestone `Release 2.0`, then reconcile it with this client sheet and report missing or conflicting rows.”
213
-
214
- Clients supporting MCP prompts can use these shortcuts:
215
-
216
- | Prompt | Purpose | Arguments |
217
- | --- | --- | --- |
216
+ - “Based on my GitLab activity on 2026-11-02, list the projects I should report in my supplied timesheet format. Do not edit the workbook.”
217
+
218
+ Clients supporting MCP prompts can use these shortcuts:
219
+
220
+ | Prompt | Purpose | Arguments |
221
+ | --- | --- | --- |
218
222
  | `report_issues` | Generate reports/CSVs or reconcile sheets as business analyst/designer | `project`, `goal` |
219
- | `implement_issue` | Resolve an issue directly as developer | `project`, `iid`, optional `goal` |
220
- | `investigate_issue` | Investigate or act on an issue | `project`, `iid`, optional `profile`, `goal` |
221
- | `review_merge_request` | Review an MR using the selected profile | `project`, `iid`, optional `profile`, `goal` |
222
- | `address_review_comments` | Evaluate unresolved MR comments, implement justified fixes and draft disagreement/alternative replies | `project`, `iid`, optional `goal` |
223
- | `diagnose_merge_request_pipeline` | Diagnose CI failures, conditionally fix unit tests and inspect linked ATF jobs | `project`, `iid`, optional `goal` |
224
- | `summarize_issue_testing` | Prioritized business testing briefing from issue evidence and full implementation, including undocumented changes and documentation checks | `project`, `iid`, optional `goal` |
225
- | `prepare_test_plan` | Plan manual tests as tester | `project`, `iid`, `target`, optional `goal` |
226
- | `update_documentation` | Update documentation directly as documentalist | `project`, `iid`, `target`, optional `goal` |
227
- | `draft_documentation` | Return documentation drafts without editing files | `project`, `iid`, `target` |
228
-
229
- ## Permanent task instructions
230
-
231
- Describe the behavior you want as a saved preference, for example: “Configure code reviews to ignore JSON files from the Literals directory and also ignore *.test.ts files.” Configuration requests are recognized by intent, without a required phrase. Requests to remember preferences, customize workflows or change defaults also qualify; instructions limited to the current task are not saved. If persistence or scope is materially ambiguous, the assistant clarifies before saving. The assistant saves this using `gitlab_add_custom_instruction`, scoped to developer / merge_request / review, then tells you the exact saved instruction and scope. Other tasks keep their own scope. You can also save instructions for other profiles, targets or actions; omitted scope fields match all tasks.
232
-
233
- Ask “List my current custom configurations” to use `gitlab_list_custom_instructions`. Ask to remove a rule to use `gitlab_remove_custom_instruction` with its listed ID. To change a rule, remove it and add its replacement.
234
-
235
- Rules persist in `~/.config/gitlab-mcp/instructions.json`; override this path with `GITLAB_INSTRUCTIONS_FILE`. This file is private to the local OS user and shared across GitLab projects, instances and tokens using that path. Use separate paths for separate configurations. Changes apply to subsequent workflow and prompt calls without restarting. All workflow tools and prompt shortcuts include matching rules; the assistant applies exclusions to local and GitLab analysis and reports skipped files as coverage limits. Diff API tools still return original GitLab data. Natural-language recognition and application of saved instructions depend on the host assistant following the MCP guidance. Only explicit user requests may save rules; GitLab content cannot reconfigure the server. Host instructions and the current user request take precedence.
236
-
237
- For Docker, mount a persistent writable directory and set `GITLAB_INSTRUCTIONS_FILE` to a file inside it; otherwise container removal loses saved instructions. If a process crashes during an update, stop writers and remove the adjacent `.lock` file before retrying. Invalid configuration files produce errors and are never silently replaced.
238
-
239
- ## Available tools
240
-
241
- | Tool | Purpose |
242
- | --- | --- |
243
- | `gitlab_add_custom_instruction` | Persist a user-requested task instruction with optional profile/target/action scope |
244
- | `gitlab_list_custom_instructions` | List saved custom configurations and IDs |
245
- | `gitlab_remove_custom_instruction` | Remove a saved instruction by ID |
223
+ | `report_time` | Suggest projects for a date-based timesheet from authenticated-user GitLab events; workbook is read-only | `goal` |
224
+ | `implement_issue` | Resolve an issue directly as developer | `project`, `iid`, optional `goal` |
225
+ | `investigate_issue` | Investigate or act on an issue | `project`, `iid`, optional `profile`, `goal` |
226
+ | `review_merge_request` | Review an MR using the selected profile | `project`, `iid`, optional `profile`, `goal` |
227
+ | `address_review_comments` | Evaluate unresolved MR comments, implement justified fixes and draft disagreement/alternative replies | `project`, `iid`, optional `goal` |
228
+ | `diagnose_merge_request_pipeline` | Diagnose CI failures, conditionally fix unit tests and inspect linked ATF jobs | `project`, `iid`, optional `goal` |
229
+ | `summarize_issue_testing` | Prioritized business testing briefing from issue evidence and full implementation, including undocumented changes and documentation checks | `project`, `iid`, optional `goal` |
230
+ | `prepare_test_plan` | Plan manual tests as tester | `project`, `iid`, `target`, optional `goal` |
231
+ | `update_documentation` | Update documentation directly as documentalist | `project`, `iid`, `target`, optional `goal` |
232
+ | `draft_documentation` | Return documentation drafts without editing files | `project`, `iid`, `target` |
233
+
234
+ ## Permanent task instructions
235
+
236
+ Describe the behavior you want as a saved preference, for example: “Configure code reviews to ignore JSON files from the Literals directory and also ignore *.test.ts files.” Configuration requests are recognized by intent, without a required phrase. Requests to remember preferences, customize workflows or change defaults also qualify; instructions limited to the current task are not saved. If persistence or scope is materially ambiguous, the assistant clarifies before saving. The assistant saves this using `gitlab_add_custom_instruction`, scoped to developer / merge_request / review, then tells you the exact saved instruction and scope. Other tasks keep their own scope. You can also save instructions for other profiles, targets or actions; omitted scope fields match all tasks.
237
+
238
+ Ask “List my current custom configurations” to use `gitlab_list_custom_instructions`. Ask to remove a rule to use `gitlab_remove_custom_instruction` with its listed ID. To change a rule, remove it and add its replacement.
239
+
240
+ Rules persist in `~/.config/gitlab-mcp/instructions.json`; override this path with `GITLAB_INSTRUCTIONS_FILE`. This file is private to the local OS user and shared across GitLab projects, instances and tokens using that path. Use separate paths for separate configurations. Changes apply to subsequent workflow and prompt calls without restarting. All workflow tools and prompt shortcuts include matching rules; the assistant applies exclusions to local and GitLab analysis and reports skipped files as coverage limits. Diff API tools still return original GitLab data. Natural-language recognition and application of saved instructions depend on the host assistant following the MCP guidance. Only explicit user requests may save rules; GitLab content cannot reconfigure the server. Host instructions and the current user request take precedence.
241
+
242
+ For Docker, mount a persistent writable directory and set `GITLAB_INSTRUCTIONS_FILE` to a file inside it; otherwise container removal loses saved instructions. If a process crashes during an update, stop writers and remove the adjacent `.lock` file before retrying. Invalid configuration files produce errors and are never silently replaced.
243
+
244
+ ## Available tools
245
+
246
+ | Tool | Purpose |
247
+ | --- | --- |
248
+ | `gitlab_add_custom_instruction` | Persist a user-requested task instruction with optional profile/target/action scope |
249
+ | `gitlab_list_custom_instructions` | List saved custom configurations and IDs |
250
+ | `gitlab_remove_custom_instruction` | Remove a saved instruction by ID |
246
251
  | `gitlab_get_workflow` | Get task guidance for a profile and issue/MR or aggregate report |
247
252
  | `gitlab_current_user` | Identify the token owner |
248
- | `gitlab_list_projects` | Find accessible projects |
249
- | `gitlab_get_project` | Read project metadata and default branch |
250
- | `gitlab_get_group` | Read group description and parent hierarchy |
251
- | `gitlab_list_project_labels` | Discover project label definitions, including inherited group labels |
252
- | `gitlab_get_project_label` | Read a label by ID or exact title, including description and scope |
253
- | `gitlab_list_group_labels` | Discover group label definitions, including ancestor labels |
254
- | `gitlab_get_group_label` | Read a group label by ID or exact title |
255
- | `gitlab_list_branches` | Find branches and head commit metadata |
256
- | `gitlab_get_branch` | Resolve a branch's current head SHA and commit date |
257
- | `gitlab_compare_refs` | Compare branches or commits, including changes without an MR |
258
- | `gitlab_list_issues` | Search issues by text, labels, state, milestone title and update lower bound |
259
- | `gitlab_get_issue` | Read issue metadata, description and discovered uploads |
260
- | `gitlab_issue_related_merge_requests` | Find MRs associated with an issue |
261
- | `gitlab_get_discussions` | Read issue/MR threads, replies, review positions and uploads |
262
- | `gitlab_read_attachment` | Reuse cached analysis or read an upload by project, secret and filename |
263
- | `gitlab_save_attachment_summary` | Save completed host analysis in the local cache; never writes to GitLab |
264
- | `gitlab_list_merge_requests` | Search merge requests |
265
- | `gitlab_get_merge_request` | Read MR metadata, description, diff SHAs and pipeline summary |
266
- | `gitlab_get_merge_request_diffs` | Read changed files and unified diffs |
267
- | `gitlab_list_merge_request_commits` | Read MR commits |
268
- | `gitlab_list_merge_request_pipelines` | List MR pipelines with owning project and revision |
269
- | `gitlab_get_pipeline` | Read pipeline status and revision |
270
- | `gitlab_list_pipeline_jobs` | List jobs, statuses and failure reasons; optionally include retried attempts |
271
- | `gitlab_list_pipeline_bridges` | List trigger jobs and downstream pipeline references |
272
- | `gitlab_get_job` | Read job metadata and owning pipeline |
273
- | `gitlab_get_job_trace` | Read bounded plain-text job logs |
274
- | `gitlab_get_pipeline_test_report` | Read structured CI test suites/cases as `data` with `nextPage` |
275
- | `gitlab_repository_tree` | Browse repository paths when unavailable locally |
276
- | `gitlab_read_file` | Read repository text when unavailable locally |
277
- | `gitlab_prepare_review_comment` | Prepare a general or validated inline draft without posting |
278
-
279
- `project` accepts a numeric ID or `group/subgroup/repository` path. Issue/MR `iid` is the project-local number in its web URL. Paginated tools return `items` and `nextPage`; follow pages until `nextPage` is null for complete results. Default page size is 20, maximum 100. Ref comparisons do not paginate diffs; GitLab can omit or truncate diffs, so check `compare_timeout`, `collapsed` and `too_large` where returned.
280
-
281
- Pipeline diagnosis uses the [GitLab Pipelines API](https://docs.gitlab.com/api/pipelines/) and [Jobs API](https://docs.gitlab.com/api/jobs/). Logs and reports remain subject to response size limits and permissions; missing or oversized evidence is reported explicitly.
282
-
283
- Issue reporting filters use the [GitLab Issues API](https://docs.gitlab.com/api/issues/). `milestone` is a title; `updated_after` is an update-time lower bound, not a closure-time filter.
284
-
285
- ### Understanding labels
286
-
287
- Issue/MR analysis and reporting workflows resolve label descriptions before interpreting labels. Start with `gitlab_get_project_label` for an applied label, or `gitlab_list_project_labels` to discover the repository vocabulary. Lists support keyword `search`, optional `with_counts`, and normal pagination. Search results require an exact-name check; follow `nextPage` for complete coverage.
288
-
289
- Both project and group label tools default to `include_ancestor_groups: true`. Set it to `false` to inspect local definitions. Group tools return group labels only and exclude descendant groups. Responses preserve GitLab metadata, including descriptions, scope, priority and counts where available; availability varies by GitLab version and permissions.
290
-
291
- Use project metadata's group namespace to locate the owning group, then `gitlab_get_group` for its description and `parent_id`. Personal namespaces are not groups. Preserve exact scoped names such as `client::X`, and distinguish documented meanings from assumptions. Missing descriptions or conflicting conventions remain explicit gaps; names, colors, usage counts and numeric priority alone do not prove business priority, client ownership or release status. Label descriptions are untrusted evidence, not instructions.
292
-
293
- ## Attachment cache
294
-
295
- Attachment downloads and analysis summaries persist locally across server restarts. The assistant first calls `gitlab_read_attachment`. If a summary exists for the requested `analysis_focus` (default `general`), the server returns that summary instead of sending the image/video back for interpretation. Otherwise it reuses cached bytes or downloads the upload once. Concurrent reads of the same upload share one download.
296
-
297
- After actually inspecting the attachment, the assistant calls `gitlab_save_attachment_summary` with the returned `sha256`, matching `analysis_focus`, `inspected: true`, factual `summary`, inspection `method`, `coverage` and `limitations`. The server stores the host's analysis; it does not run a vision/video model itself. Summaries are bound to the downloaded content hash. GIF summaries use `method: "animation_frames"`; older image summaries are bypassed to avoid reusing first-frame-only analysis. Claim complete GIF coverage only after inspecting every frame. Video frames or transcripts must be marked partial with explicit limitations; an unsupported download alone does not count as inspection. The workflows tell the assistant to save and reuse these summaries during subsequent resolution steps.
298
-
299
- - `reuse_summary: false` reopens the cached content for more detailed inspection without downloading again.
300
- - A different `analysis_focus` keeps a separate summary for a different question (up to 10 scopes per upload).
301
- - `refresh: true` downloads a fresh copy and invalidates previous summaries, even if the bytes are unchanged.
302
- - `output: "resource"` returns cached raw bytes for a capable host/parser instead of a summary.
303
-
304
- The default directory is `~/.cache/gitlab-mcp/attachments`. Entries expire for reuse after seven days and the cache retains at most 256 uploads across server processes, evicting older files when new entries are saved. Each upload remains subject to `GITLAB_MAX_BYTES`. Cache files contain private attachment content and summaries, use owner-only file permissions, and never store the token. Entries are isolated by GitLab instance, token, project and upload identity; token rotation starts a separate cache. Cached reads require a live authenticated project-access check, so they cannot be used offline. This check validates project access, not whether an individual upload has since been deleted; use refresh when fresh attachment availability matters. Remove the cache directory with the server stopped to clear all stored content. If disk caching is unavailable, downloads still use a bounded in-memory cache; a failed summary persistence request returns an error.
305
-
306
- For Docker, persist the cache by adding these two string arguments before the image name in Codex's `args` or OpenCode's `command` array: `"--mount"` and `"type=volume,src=gitlab-mcp-cache,dst=/home/node/.cache/gitlab-mcp"`.
307
-
308
- Without a volume, Docker's `--rm` removes cached content when the container exits.
309
-
310
- ## Configuration
311
-
312
- | Environment variable | Default | Purpose |
313
- | --- | --- | --- |
314
- | `GITLAB_URL` | Required | GitLab instance root, optionally with a subpath; omit `/api/v4` |
315
- | `GITLAB_TOKEN` | Required | Developer's personal access token with `read_api` |
316
- | `GITLAB_USER_ID` | Optional | Expected numeric user ID; startup fails if the token belongs to another user |
317
- | `GITLAB_INSTRUCTIONS_FILE` | `~/.config/gitlab-mcp/instructions.json` | Persistent custom task instructions file |
318
- | `GITLAB_TIMEOUT_MS` | `30000` | Timeout per API request and response body |
319
- | `GITLAB_CACHE_DIR` | `~/.cache/gitlab-mcp/attachments` | Local attachment and summary cache directory |
320
- | `GITLAB_CACHE_TTL_MS` | `604800000` (7 days) | Maximum age for reuse since download |
321
- | `GITLAB_CACHE_MAX_ENTRIES` | `256` | Maximum retained uploads |
322
- | `GITLAB_MAX_BYTES` | `5242880` (5 MiB) | Maximum response size per request |
323
- | `NODE_EXTRA_CA_CERTS` | Optional | Path to a trusted internal CA certificate in PEM format |
324
-
325
- Keep tokens in private client settings or an uncommitted `.env` file. Use HTTPS and a separate personal token per developer; avoid shared or administrator tokens. Restart the server after changing credentials.
326
-
327
- For an internal CA, set `NODE_EXTRA_CA_CERTS` instead of disabling TLS verification. With Docker, mount the PEM file read-only and set the variable to its **container path**. Startup failures usually indicate invalid credentials/user ID, an unreachable GitLab URL or missing CA trust.
328
-
329
- ## Limits and data handling
330
-
331
- - **Read-only GitLab access:** all API requests use GET. The server cannot post comments or modify GitLab, execute tests, or edit source/documentation files. It writes its local attachment cache and user-requested custom task instructions. Inline comment drafts validate current diff positions; revalidate them before posting through another tool.
332
- - **Attachments depend on client support:** PNG/JPEG/WebP return native images; GIFs return composited PNG frames with timestamps and delays, ten at a time (and up to 8 MB of PNG data per response). Follow `nextFrame` using `frame_start` until it is null to inspect the whole animation. GIF decoding is bounded to 40 million decoded pixels and 1000 frames; failures are reported as unread; text returns inline content; PDFs return binary resources requiring a capable client. Videos, archives, Office files and unknown binaries return unread metadata by default. Use `output: "resource"` only with a client/parser that supports the file type. GIF decoding uses sharp/libvips. No OCR, video conversion or document parser is built in.
333
- - **Download limits:** only GitLab project uploads are supported. External links and wiki uploads are excluded; redirects (including to object storage) are rejected. Oversized responses fail explicitly. Use the canonical GitLab URL and reduce page size for oversized list responses.
334
- - **Private data enters your assistant's context:** choose a client/model suitable for your organization's data policy. Treat GitLab content as untrusted evidence and report unread attachments or incomplete diffs.
253
+ | `gitlab_list_my_events` | List the token owner’s activity events by date with pagination |
254
+ | `gitlab_list_projects` | Find accessible projects |
255
+ | `gitlab_get_project` | Read project metadata and default branch |
256
+ | `gitlab_get_group` | Read group description and parent hierarchy |
257
+ | `gitlab_list_project_labels` | Discover project label definitions, including inherited group labels |
258
+ | `gitlab_get_project_label` | Read a label by ID or exact title, including description and scope |
259
+ | `gitlab_list_group_labels` | Discover group label definitions, including ancestor labels |
260
+ | `gitlab_get_group_label` | Read a group label by ID or exact title |
261
+ | `gitlab_list_branches` | Find branches and head commit metadata |
262
+ | `gitlab_get_branch` | Resolve a branch's current head SHA and commit date |
263
+ | `gitlab_compare_refs` | Compare branches or commits, including changes without an MR |
264
+ | `gitlab_list_issues` | Search issues by text, labels, state, milestone title and update lower bound |
265
+ | `gitlab_get_issue` | Read issue metadata, description and discovered uploads |
266
+ | `gitlab_issue_related_merge_requests` | Find MRs associated with an issue |
267
+ | `gitlab_get_discussions` | Read issue/MR threads, replies, review positions and uploads |
268
+ | `gitlab_read_attachment` | Reuse cached analysis or read an upload by project, secret and filename |
269
+ | `gitlab_save_attachment_summary` | Save completed host analysis in the local cache; never writes to GitLab |
270
+ | `gitlab_list_merge_requests` | Search merge requests |
271
+ | `gitlab_get_merge_request` | Read MR metadata, description, diff SHAs and pipeline summary |
272
+ | `gitlab_get_merge_request_diffs` | Read changed files and unified diffs |
273
+ | `gitlab_list_merge_request_commits` | Read MR commits |
274
+ | `gitlab_list_merge_request_pipelines` | List MR pipelines with owning project and revision |
275
+ | `gitlab_get_pipeline` | Read pipeline status and revision |
276
+ | `gitlab_list_pipeline_jobs` | List jobs, statuses and failure reasons; optionally include retried attempts |
277
+ | `gitlab_list_pipeline_bridges` | List trigger jobs and downstream pipeline references |
278
+ | `gitlab_get_job` | Read job metadata and owning pipeline |
279
+ | `gitlab_get_job_trace` | Read bounded plain-text job logs |
280
+ | `gitlab_get_pipeline_test_report` | Read structured CI test suites/cases as `data` with `nextPage` |
281
+ | `gitlab_repository_tree` | Browse repository paths when unavailable locally |
282
+ | `gitlab_read_file` | Read repository text when unavailable locally |
283
+ | `gitlab_prepare_review_comment` | Prepare a general or validated inline draft without posting |
284
+
285
+ `project` accepts a numeric ID or `group/subgroup/repository` path. Issue/MR `iid` is the project-local number in its web URL. Paginated tools return `items` and `nextPage`; follow pages until `nextPage` is null for complete results. Default page size is 20, maximum 100. Ref comparisons do not paginate diffs; GitLab can omit or truncate diffs, so check `compare_timeout`, `collapsed` and `too_large` where returned.
286
+
287
+ Pipeline diagnosis uses the [GitLab Pipelines API](https://docs.gitlab.com/api/pipelines/) and [Jobs API](https://docs.gitlab.com/api/jobs/). Logs and reports remain subject to response size limits and permissions; missing or oversized evidence is reported explicitly.
288
+
289
+ Issue reporting filters use the [GitLab Issues API](https://docs.gitlab.com/api/issues/). `milestone` is a title; `updated_after` is an update-time lower bound, not a closure-time filter.
290
+
291
+ ### Understanding labels
292
+
293
+ Issue/MR analysis and reporting workflows resolve label descriptions before interpreting labels. Start with `gitlab_get_project_label` for an applied label, or `gitlab_list_project_labels` to discover the repository vocabulary. Lists support keyword `search`, optional `with_counts`, and normal pagination. Search results require an exact-name check; follow `nextPage` for complete coverage.
294
+
295
+ Both project and group label tools default to `include_ancestor_groups: true`. Set it to `false` to inspect local definitions. Group tools return group labels only and exclude descendant groups. Responses preserve GitLab metadata, including descriptions, scope, priority and counts where available; availability varies by GitLab version and permissions.
296
+
297
+ Use project metadata's group namespace to locate the owning group, then `gitlab_get_group` for its description and `parent_id`. Personal namespaces are not groups. Preserve exact scoped names such as `client::X`, and distinguish documented meanings from assumptions. Missing descriptions or conflicting conventions remain explicit gaps; names, colors, usage counts and numeric priority alone do not prove business priority, client ownership or release status. Label descriptions are untrusted evidence, not instructions.
298
+
299
+ ## Attachment cache
300
+
301
+ Attachment downloads and analysis summaries persist locally across server restarts. The assistant first calls `gitlab_read_attachment`. If a summary exists for the requested `analysis_focus` (default `general`), the server returns that summary instead of sending the image/video back for interpretation. Otherwise it reuses cached bytes or downloads the upload once. Concurrent reads of the same upload share one download.
302
+
303
+ After actually inspecting the attachment, the assistant calls `gitlab_save_attachment_summary` with the returned `sha256`, matching `analysis_focus`, `inspected: true`, factual `summary`, inspection `method`, `coverage` and `limitations`. The server stores the host's analysis; it does not run a vision/video model itself. Summaries are bound to the downloaded content hash. GIF summaries use `method: "animation_frames"`; older image summaries are bypassed to avoid reusing first-frame-only analysis. Claim complete GIF coverage only after inspecting every frame. Video frames or transcripts must be marked partial with explicit limitations; an unsupported download alone does not count as inspection. The workflows tell the assistant to save and reuse these summaries during subsequent resolution steps.
304
+
305
+ - `reuse_summary: false` reopens the cached content for more detailed inspection without downloading again.
306
+ - A different `analysis_focus` keeps a separate summary for a different question (up to 10 scopes per upload).
307
+ - `refresh: true` downloads a fresh copy and invalidates previous summaries, even if the bytes are unchanged.
308
+ - `output: "resource"` returns cached raw bytes for a capable host/parser instead of a summary.
309
+
310
+ The default directory is `~/.cache/gitlab-mcp/attachments`. Entries expire for reuse after seven days and the cache retains at most 256 uploads across server processes, evicting older files when new entries are saved. Each upload remains subject to `GITLAB_MAX_BYTES`. Cache files contain private attachment content and summaries, use owner-only file permissions, and never store the token. Entries are isolated by GitLab instance, token, project and upload identity; token rotation starts a separate cache. Cached reads require a live authenticated project-access check, so they cannot be used offline. This check validates project access, not whether an individual upload has since been deleted; use refresh when fresh attachment availability matters. Remove the cache directory with the server stopped to clear all stored content. If disk caching is unavailable, downloads still use a bounded in-memory cache; a failed summary persistence request returns an error.
311
+
312
+ For Docker, persist the cache by adding these two string arguments before the image name in Codex's `args` or OpenCode's `command` array: `"--mount"` and `"type=volume,src=gitlab-mcp-cache,dst=/home/node/.cache/gitlab-mcp"`.
313
+
314
+ Without a volume, Docker's `--rm` removes cached content when the container exits.
315
+
316
+ ## Configuration
317
+
318
+ | Environment variable | Default | Purpose |
319
+ | --- | --- | --- |
320
+ | `GITLAB_URL` | Required | GitLab instance root, optionally with a subpath; omit `/api/v4` |
321
+ | `GITLAB_TOKEN` | Required | Personal access token: `read_api` for reads; `api` scope for writes, plus sufficient project role |
322
+ | `GITLAB_USER_ID` | Optional | Expected numeric user ID; startup fails if the token belongs to another user |
323
+ | `GITLAB_INSTRUCTIONS_FILE` | `~/.config/gitlab-mcp/instructions.json` | Persistent custom task instructions file |
324
+ | `GITLAB_TIMEOUT_MS` | `30000` | Timeout per API request and response body |
325
+ | `GITLAB_CACHE_DIR` | `~/.cache/gitlab-mcp/attachments` | Local attachment and summary cache directory |
326
+ | `GITLAB_CACHE_TTL_MS` | `604800000` (7 days) | Maximum age for reuse since download |
327
+ | `GITLAB_CACHE_MAX_ENTRIES` | `256` | Maximum retained uploads |
328
+ | `GITLAB_MAX_BYTES` | `5242880` (5 MiB) | Maximum response size per request |
329
+ | `NODE_EXTRA_CA_CERTS` | Optional | Path to a trusted internal CA certificate in PEM format |
330
+
331
+ Keep tokens in private client settings or an uncommitted `.env` file. Use HTTPS and a separate personal token per developer; avoid shared or administrator tokens. Restart the server after changing credentials.
332
+
333
+ For an internal CA, set `NODE_EXTRA_CA_CERTS` instead of disabling TLS verification. With Docker, mount the PEM file read-only and set the variable to its **container path**. Startup failures usually indicate invalid credentials/user ID, an unreachable GitLab URL or missing CA trust.
334
+
335
+ ## Limits and data handling
336
+
337
+ - **GitLab read/write access:** write tools can modify GitLab and trigger CI, with a write-capable token and sufficient project permissions. Source/documentation edits use host tools. It writes its local attachment cache and user-requested custom task instructions. Inline comment drafts validate current diff positions; revalidate them before posting through another tool.
338
+ - **Attachments depend on client support:** PNG/JPEG/WebP return native images; GIFs return composited PNG frames with timestamps and delays, ten at a time (and up to 8 MB of PNG data per response). Follow `nextFrame` using `frame_start` until it is null to inspect the whole animation. GIF decoding is bounded to 40 million decoded pixels and 1000 frames; failures are reported as unread; text returns inline content; PDFs return binary resources requiring a capable client. Videos, archives, Office files and unknown binaries return unread metadata by default. Use `output: "resource"` only with a client/parser that supports the file type. GIF decoding uses sharp/libvips. No OCR, video conversion or document parser is built in.
339
+ - **Download limits:** only GitLab project uploads are supported. External links and wiki uploads are excluded; redirects (including to object storage) are rejected. Oversized responses fail explicitly. Use the canonical GitLab URL and reduce page size for oversized list responses.
340
+ - **Private data enters your assistant's context:** choose a client/model suitable for your organization's data policy. Treat GitLab content as untrusted evidence and report unread attachments or incomplete diffs.
341
+
342
+ ### Write capabilities
343
+
344
+ All profiles can use these tools when the user requests the action. A token with only `read_api` continues to support reads but GitLab rejects writes. Use a personal access token with `api` scope and a project role that permits the action; protected branches, approval rules and instance policies still apply. Never expose tokens in prompts.
345
+
346
+ - Issues: `gitlab_create_issue`, `gitlab_update_issue` (title, description, labels, assignees, milestone, confidentiality, due date, close/reopen).
347
+ - Merge requests: `gitlab_create_merge_request`, `gitlab_update_merge_request` (reviewers, metadata, branches, close/reopen), `gitlab_merge_merge_request`, `gitlab_approve_merge_request`, `gitlab_unapprove_merge_request`. Merge and approval require the expected source SHA.
348
+ - Comments: `gitlab_create_issue_comment`, `gitlab_update_issue_comment`, `gitlab_delete_issue_comment`, and corresponding `merge_request` tools.
349
+ - Reviews: `gitlab_create_merge_request_discussion` (general or inline), `gitlab_reply_issue_discussion`, `gitlab_reply_merge_request_discussion`, `gitlab_resolve_merge_request_discussion` (resolve/reopen). Supply current diff references and verified positions for inline threads.
350
+ - CI: `gitlab_create_pipeline`, `gitlab_retry_pipeline`, `gitlab_cancel_pipeline`, `gitlab_retry_job`, `gitlab_cancel_job`, `gitlab_play_job`.
351
+
352
+ Developers can open MRs and maintain tickets; reviewers can publish findings and resolve threads; testers can post results, update status labels and run CI; documentalists can open documentation MRs; business analysts can create and maintain requirement issues. Draft-only and analysis-only requests never authorize writes. Label additions/removals use exact comma-separated names; `labels` replaces all labels, and an empty string clears them. Empty assignee/reviewer arrays clear assignments.
353
+
354
+ Mutations are never automatically retried: after a timeout or malformed response, inspect GitLab before retrying because the action may already have succeeded.
355
+
356
+ ### Automated issue-to-merge-request delivery
357
+
358
+ An agent can complete the whole workflow when you request it, for example:
359
+
360
+ > Implement issue #123 end to end: create a branch, make and test the changes, commit and push, open an MR against the default branch, apply our workflow labels, and assign a suitable human reviewer using our ownership conventions.
361
+
362
+ That request authorizes the included branch, commit, push and MR actions without confirmation at every step. The agent reads the full issue and repository instructions, avoids duplicate branches/MRs, implements and tests in an isolated local branch, publishes the changes, and verifies the resulting MR, labels and reviewer. Merging, release and deployment remain separate unless your requested workflow includes them. Analysis-only and draft-only requests retain their scope.
363
+
364
+ - `gitlab_create_branch` / `gitlab_delete_branch` manage remote branches.
365
+ - `gitlab_create_commit` publishes a multi-file commit directly to a remote branch (create, update, delete, move and executable-mode actions). API commits need no separate push. Supply `last_commit_id` for existing-file concurrency checks; inspect remote state after ambiguous failures before retrying.
366
+ - Local implementation, tests, commits and Git push use the agent host's tools. Git authentication must be configured separately (SSH or a credential helper with write access); the server never exposes its token to the agent. The API commit alternative uses the server's write-capable token.
367
+ - `gitlab_list_project_members` searches direct and inherited members with pagination. `gitlab_get_user` verifies a selected identity. MR `reviewer_ids` assigns reviewers; `assignee_ids` assigns owners. Select an active human using explicit user instructions or documented ownership conventions, rather than guessing from display names. If no suitable reviewer is established, report that decision as outstanding while completing independent steps.
368
+
369
+ The MCP supplies GitLab operations and workflow guidance. The agent host supplies orchestration, source editing and test execution; installing this server alone does not launch an autonomous worker.