gitlab-api 25.8.14__tar.gz
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.
- gitlab_api-25.8.14/LICENSE +20 -0
- gitlab_api-25.8.14/MANIFEST.in +1 -0
- gitlab_api-25.8.14/PKG-INFO +468 -0
- gitlab_api-25.8.14/README.md +445 -0
- gitlab_api-25.8.14/gitlab_api/__init__.py +367 -0
- gitlab_api-25.8.14/gitlab_api/__main__.py +7 -0
- gitlab_api-25.8.14/gitlab_api/decorators.py +24 -0
- gitlab_api-25.8.14/gitlab_api/exceptions.py +42 -0
- gitlab_api-25.8.14/gitlab_api/gitlab_api.py +4737 -0
- gitlab_api-25.8.14/gitlab_api/gitlab_api_mcp.py +5277 -0
- gitlab_api-25.8.14/gitlab_api/gitlab_db_models.py +3511 -0
- gitlab_api-25.8.14/gitlab_api/gitlab_input_models.py +3093 -0
- gitlab_api-25.8.14/gitlab_api/gitlab_response_models.py +4026 -0
- gitlab_api-25.8.14/gitlab_api/utils.py +341 -0
- gitlab_api-25.8.14/gitlab_api.egg-info/PKG-INFO +468 -0
- gitlab_api-25.8.14/gitlab_api.egg-info/SOURCES.txt +27 -0
- gitlab_api-25.8.14/gitlab_api.egg-info/dependency_links.txt +1 -0
- gitlab_api-25.8.14/gitlab_api.egg-info/entry_points.txt +2 -0
- gitlab_api-25.8.14/gitlab_api.egg-info/requires.txt +7 -0
- gitlab_api-25.8.14/gitlab_api.egg-info/top_level.txt +3 -0
- gitlab_api-25.8.14/pyproject.toml +38 -0
- gitlab_api-25.8.14/requirements.txt +7 -0
- gitlab_api-25.8.14/setup.cfg +4 -0
- gitlab_api-25.8.14/test/conftest.py +58 -0
- gitlab_api-25.8.14/test/test_gitlab_api.py +208 -0
- gitlab_api-25.8.14/test/test_gitlab_db_models.py +535 -0
- gitlab_api-25.8.14/test/test_gitlab_models.py +14046 -0
- gitlab_api-25.8.14/test/test_sqlalchemy.py +172 -0
- gitlab_api-25.8.14/test/test_utils.py +1277 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2012-2023 Audel Rouhi
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include README.md include requirements.txt recursive-include gitlab_api *.py
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gitlab-api
|
|
3
|
+
Version: 25.8.14
|
|
4
|
+
Summary: GitLab API Python Wrapper
|
|
5
|
+
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: License :: Public Domain
|
|
9
|
+
Classifier: Environment :: Console
|
|
10
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Requires-Python: >=3.8
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: requests>=2.8.1
|
|
16
|
+
Requires-Dist: urllib3>=2.2.2
|
|
17
|
+
Requires-Dist: pydantic[email]>=2.8.2
|
|
18
|
+
Requires-Dist: SQLAlchemy>=2.0.36
|
|
19
|
+
Requires-Dist: alembic>=1.14.1
|
|
20
|
+
Requires-Dist: tenacity>=9.0.0
|
|
21
|
+
Requires-Dist: fastmcp>=2.11.3
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
|
|
24
|
+
# GitLab API
|
|
25
|
+
|
|
26
|
+

|
|
27
|
+

|
|
28
|
+

|
|
29
|
+

|
|
30
|
+

|
|
31
|
+

|
|
32
|
+

|
|
33
|
+
|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+

|
|
38
|
+
|
|
39
|
+

|
|
40
|
+

|
|
41
|
+

|
|
42
|
+

|
|
43
|
+

|
|
44
|
+

|
|
45
|
+
|
|
46
|
+
*Version: 25.8.14*
|
|
47
|
+
|
|
48
|
+
Pythonic GitLab API Library
|
|
49
|
+
|
|
50
|
+
GitLab MCP Server for Agentic AI! Get started with Pip or Docker
|
|
51
|
+
|
|
52
|
+
Includes a large portion of useful API calls to GitLab and SQLAlchemy Models to handle loading API calls directly to a database!
|
|
53
|
+
|
|
54
|
+
This repository is actively maintained - Contributions are welcome!
|
|
55
|
+
|
|
56
|
+
Additional Features:
|
|
57
|
+
- All responses are returned as native Pydantic models
|
|
58
|
+
- Save Pydantic models to pickle files locally
|
|
59
|
+
- Easily convert Pydantic to SQLAlchemy models for quick database insertion
|
|
60
|
+
|
|
61
|
+
### API Calls:
|
|
62
|
+
- Branches
|
|
63
|
+
- Commits
|
|
64
|
+
- Deploy Tokens
|
|
65
|
+
- Groups
|
|
66
|
+
- Jobs
|
|
67
|
+
- Members
|
|
68
|
+
- Merge Request
|
|
69
|
+
- Merge Request Rules
|
|
70
|
+
- Merge Request Rule Settings
|
|
71
|
+
- Namespaces
|
|
72
|
+
- Packages
|
|
73
|
+
- Pipeline
|
|
74
|
+
- Pipeline Schedules
|
|
75
|
+
- Projects
|
|
76
|
+
- Protected Branches
|
|
77
|
+
- Releases
|
|
78
|
+
- Runners
|
|
79
|
+
- Users
|
|
80
|
+
- Wiki
|
|
81
|
+
- Environments
|
|
82
|
+
- Protected Environments
|
|
83
|
+
- Tags
|
|
84
|
+
- Protected Tags
|
|
85
|
+
- Custom Endpoint
|
|
86
|
+
|
|
87
|
+
If your API call isn't supported, you can always run the standard custom API endpoint function to get/post/put/delete and endpoint
|
|
88
|
+
|
|
89
|
+
#### Using an an MCP Server:
|
|
90
|
+
|
|
91
|
+
AI Prompt:
|
|
92
|
+
```text
|
|
93
|
+
Get me the details of my gitlab project with id 420.
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
AI Response:
|
|
97
|
+
```text
|
|
98
|
+
Here are the details for your GitLab project:
|
|
99
|
+
|
|
100
|
+
Project Name: Docker Registry
|
|
101
|
+
|
|
102
|
+
Project ID: 420
|
|
103
|
+
|
|
104
|
+
Namespace: Homelab
|
|
105
|
+
|
|
106
|
+
Visibility: Internal
|
|
107
|
+
|
|
108
|
+
Created: November 13, 1999
|
|
109
|
+
|
|
110
|
+
Default Branch: main
|
|
111
|
+
|
|
112
|
+
Last Activity: August 20, 2025
|
|
113
|
+
|
|
114
|
+
Web URL:
|
|
115
|
+
http://gitlab.arpa/homelab/docker-registry
|
|
116
|
+
|
|
117
|
+
This project is configured with container registry capabilities
|
|
118
|
+
and supports CI/CD pipelines, merge requests, and issue tracking.
|
|
119
|
+
It is currently active with no open issues and follows
|
|
120
|
+
the default branch strategy for its workflow.
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
AI Prompt:
|
|
125
|
+
```text
|
|
126
|
+
Run the gitlab pipeline for this project id 133 on the main branch
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
AI Response:
|
|
130
|
+
```text
|
|
131
|
+
The pipeline has been successfully created for the project ID 133 on the main reference. Here are the details:
|
|
132
|
+
|
|
133
|
+
Pipeline ID: 20601
|
|
134
|
+
Reference: main
|
|
135
|
+
SHA: asidfaskdjvalksdjv
|
|
136
|
+
Status: Created
|
|
137
|
+
Web URL:
|
|
138
|
+
|
|
139
|
+
Created At: 2025-08-27T02:49:20.068Z
|
|
140
|
+
The pipeline is now queued and will start executing soon. Let me know if you'd like further details or actions!
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
AI Prompt:
|
|
144
|
+
```text
|
|
145
|
+
Create a branch called "test" from the main branch in this gitlab project with id 133
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
AI Response:
|
|
149
|
+
```text
|
|
150
|
+
The branch test has been successfully created from the main branch in the project with ID 133.
|
|
151
|
+
|
|
152
|
+
Branch Details:
|
|
153
|
+
Name: test
|
|
154
|
+
URL:
|
|
155
|
+
|
|
156
|
+
Commit:
|
|
157
|
+
Short ID: 1c3775ac
|
|
158
|
+
Message: "Add adgurad."
|
|
159
|
+
Author: KnucklesSG1
|
|
160
|
+
Committed Date: August 25, 2025, at 05:03:01 (UTC-05:00)
|
|
161
|
+
This branch is not protected, and it is not set as the default branch.
|
|
162
|
+
The branch is currently unmerged and can be pushed to by authorized users.
|
|
163
|
+
|
|
164
|
+
Let me know if you'd like further actions (e.g., merging, pushing changes)!
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
AI Prompt:
|
|
168
|
+
```text
|
|
169
|
+
Create a merge request for project 133 from the test branch to the main branch with a title of
|
|
170
|
+
"This is a merge request by Qwen3" and a description of "This is a description populated by qwen3 LLM"
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
AI Response:
|
|
174
|
+
```text
|
|
175
|
+
The merge request has been successfully created with the following details:
|
|
176
|
+
|
|
177
|
+
Title: This is a merge request by Qwen3
|
|
178
|
+
Description: This is a description populated by qwen3 LLM
|
|
179
|
+
Source Branch: test
|
|
180
|
+
Target Branch: main
|
|
181
|
+
Project: homelab/containers/services/project
|
|
182
|
+
Merge Request URL:
|
|
183
|
+
|
|
184
|
+
Status: Opened
|
|
185
|
+
Created At: 2025-08-27T03:15:51.520000Z
|
|
186
|
+
The merge request is currently in the "preparing" state and is ready for review. Let me know if you'd like further actions, such as assigning reviewers or approving the merge! 😊
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
<details>
|
|
190
|
+
<summary><b>Usage:</b></summary>
|
|
191
|
+
|
|
192
|
+
### Use API directly
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
#!/usr/bin/python
|
|
196
|
+
|
|
197
|
+
import gitlab_api
|
|
198
|
+
from gitlab_api import pydantic_to_sqlalchemy, upsert, save_model, load_model
|
|
199
|
+
from gitlab_api.gitlab_db_models import (
|
|
200
|
+
BaseDBModel as Base,
|
|
201
|
+
)
|
|
202
|
+
import urllib3
|
|
203
|
+
import os
|
|
204
|
+
from urllib.parse import quote_plus
|
|
205
|
+
|
|
206
|
+
from sqlalchemy import create_engine
|
|
207
|
+
from sqlalchemy.orm import sessionmaker
|
|
208
|
+
|
|
209
|
+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
210
|
+
|
|
211
|
+
gitlab_token = os.environ["GITLAB_TOKEN"]
|
|
212
|
+
postgres_username = os.environ["POSTGRES_USERNAME"]
|
|
213
|
+
postgres_password = os.environ["POSTGRES_PASSWORD"]
|
|
214
|
+
postgres_db_host = os.environ["POSTGRES_DB_HOST"]
|
|
215
|
+
postgres_port = os.environ["POSTGRES_PORT"]
|
|
216
|
+
postgres_db_name = os.environ["POSTGRES_DB_NAME"]
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
print("Creating GitLab Client...")
|
|
221
|
+
client = gitlab_api.Api(
|
|
222
|
+
url="http://gitlab.arpa/api/v4/",
|
|
223
|
+
token=gitlab_token,
|
|
224
|
+
verify=False,
|
|
225
|
+
)
|
|
226
|
+
print("GitLab Client Created\n\n")
|
|
227
|
+
|
|
228
|
+
print("\nFetching User Data...")
|
|
229
|
+
user_response = client.get_users(active=True, humans=True)
|
|
230
|
+
print(
|
|
231
|
+
f"Users ({len(user_response.data)}) Fetched - "
|
|
232
|
+
f"Status: {user_response.status_code}\n"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
print("\nFetching Namespace Data...")
|
|
236
|
+
namespace_response = client.get_namespaces()
|
|
237
|
+
print(
|
|
238
|
+
f"Namespaces ({len(namespace_response.data)}) Fetched - "
|
|
239
|
+
f"Status: {namespace_response.status_code}\n"
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
print("\nFetching Project Data...")
|
|
243
|
+
project_response = client.get_nested_projects_by_group(group_id=2, per_page=100)
|
|
244
|
+
print(
|
|
245
|
+
f"Projects ({len(project_response.data)}) Fetched - "
|
|
246
|
+
f"Status: {project_response.status_code}\n"
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
print("\nFetching Merge Request Data...")
|
|
250
|
+
merge_request_response = client.get_group_merge_requests(
|
|
251
|
+
argument="state=all", group_id=2
|
|
252
|
+
)
|
|
253
|
+
|
|
254
|
+
print(
|
|
255
|
+
f"\nMerge Requests ({len(merge_request_response.data)}) Fetched - "
|
|
256
|
+
f"Status: {merge_request_response.status_code}\n"
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# Pipeline Jobs table
|
|
260
|
+
pipeline_job_response = None
|
|
261
|
+
for project in project_response.data:
|
|
262
|
+
job_response = client.get_project_jobs(project_id=project.id)
|
|
263
|
+
if (
|
|
264
|
+
not pipeline_job_response
|
|
265
|
+
and hasattr(job_response, "data")
|
|
266
|
+
and len(job_response.data) > 0
|
|
267
|
+
):
|
|
268
|
+
pipeline_job_response = job_response
|
|
269
|
+
elif (
|
|
270
|
+
pipeline_job_response
|
|
271
|
+
and hasattr(job_response, "data")
|
|
272
|
+
and len(job_response.data) > 0
|
|
273
|
+
):
|
|
274
|
+
pipeline_job_response.data.extend(job_response.data)
|
|
275
|
+
print(
|
|
276
|
+
f"Pipeline Jobs ({len(getattr(pipeline_job_response, 'data', []))}) "
|
|
277
|
+
f"Fetched for Project ({project.id}) - "
|
|
278
|
+
f"Status: {pipeline_job_response.status_code}\n"
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
print("Saving Pydantic Models...")
|
|
282
|
+
user_file = save_model(model=user_response, file_name="user_model", file_path=".")
|
|
283
|
+
namespace_file = save_model(
|
|
284
|
+
model=namespace_response, file_name="namespace_model", file_path="."
|
|
285
|
+
)
|
|
286
|
+
project_file = save_model(
|
|
287
|
+
model=project_response, file_name="project_model", file_path="."
|
|
288
|
+
)
|
|
289
|
+
merge_request_file = save_model(
|
|
290
|
+
model=merge_request_response, file_name="merge_request_model", file_path="."
|
|
291
|
+
)
|
|
292
|
+
pipeline_job_file = save_model(
|
|
293
|
+
model=pipeline_job_response, file_name="pipeline_job_model", file_path="."
|
|
294
|
+
)
|
|
295
|
+
print("Models Saved")
|
|
296
|
+
|
|
297
|
+
print("Loading Pydantic Models...")
|
|
298
|
+
user_response = load_model(file=user_file)
|
|
299
|
+
namespace_response = load_model(file=namespace_file)
|
|
300
|
+
project_response = load_model(file=project_file)
|
|
301
|
+
merge_request_response = load_model(file=merge_request_file)
|
|
302
|
+
pipeline_job_response = load_model(file=pipeline_job_file)
|
|
303
|
+
print("Models Loaded")
|
|
304
|
+
|
|
305
|
+
print("Converting Pydantic to SQLAlchemy model...")
|
|
306
|
+
user_db_model = pydantic_to_sqlalchemy(schema=user_response)
|
|
307
|
+
print(f"Database Models: {user_db_model}\n")
|
|
308
|
+
|
|
309
|
+
print("Converting Pydantic to SQLAlchemy model...")
|
|
310
|
+
namespace_db_model = pydantic_to_sqlalchemy(schema=namespace_response)
|
|
311
|
+
print(f"Database Models: {namespace_db_model}\n")
|
|
312
|
+
|
|
313
|
+
print("Converting Pydantic to SQLAlchemy model...")
|
|
314
|
+
project_db_model = pydantic_to_sqlalchemy(schema=project_response)
|
|
315
|
+
print(f"Database Models: {project_db_model}\n")
|
|
316
|
+
|
|
317
|
+
print("Converting Pydantic to SQLAlchemy model...")
|
|
318
|
+
merge_request_db_model = pydantic_to_sqlalchemy(schema=merge_request_response)
|
|
319
|
+
print(f"Database Models: {merge_request_db_model}\n")
|
|
320
|
+
|
|
321
|
+
print("Converting Pydantic to SQLAlchemy model...")
|
|
322
|
+
pipeline_db_model = pydantic_to_sqlalchemy(schema=pipeline_job_response)
|
|
323
|
+
print(f"Database Models: {pipeline_db_model}\n")
|
|
324
|
+
|
|
325
|
+
print("Creating Engine")
|
|
326
|
+
engine = create_engine(
|
|
327
|
+
f"postgresql://{postgres_username}:{quote_plus(postgres_password)}@"
|
|
328
|
+
f"{postgres_db_host}:{postgres_port}/{postgres_db_name}"
|
|
329
|
+
)
|
|
330
|
+
print("Engine Created\n\n")
|
|
331
|
+
|
|
332
|
+
print("Creating Tables...")
|
|
333
|
+
Base.metadata.create_all(engine)
|
|
334
|
+
print("Tables Created\n\n")
|
|
335
|
+
|
|
336
|
+
print("Creating Session...")
|
|
337
|
+
Session = sessionmaker(bind=engine)
|
|
338
|
+
session = Session()
|
|
339
|
+
print("Session Created\n\n")
|
|
340
|
+
|
|
341
|
+
print(f"Inserting ({len(user_response.data)}) Users Into Database...")
|
|
342
|
+
upsert(session=session, model=user_db_model)
|
|
343
|
+
print("Users Synchronization Complete!\n")
|
|
344
|
+
|
|
345
|
+
print(f"Inserting ({len(namespace_response.data)}) Namespaces Into Database...")
|
|
346
|
+
upsert(session=session, model=namespace_db_model)
|
|
347
|
+
print("Namespaces Synchronization Complete!\n")
|
|
348
|
+
|
|
349
|
+
print(f"Inserting ({len(project_response.data)}) Projects Into Database...\n")
|
|
350
|
+
upsert(session=session, model=project_db_model)
|
|
351
|
+
print("Projects Synchronization Complete!\n")
|
|
352
|
+
|
|
353
|
+
print(
|
|
354
|
+
f"Inserting ({len(merge_request_response.data)}) Merge Requests Into Database..."
|
|
355
|
+
)
|
|
356
|
+
upsert(session=session, model=merge_request_db_model)
|
|
357
|
+
print("Merge Request Synchronization Complete!\n")
|
|
358
|
+
|
|
359
|
+
print(
|
|
360
|
+
f"Inserting ({len(pipeline_job_response.data)}) Pipeline Jobs Into Database..."
|
|
361
|
+
)
|
|
362
|
+
upsert(session=session, model=pipeline_db_model)
|
|
363
|
+
print("Pipeline Jobs Synchronization Complete!\n")
|
|
364
|
+
|
|
365
|
+
session.close()
|
|
366
|
+
print("Session Closed")
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Use with AI
|
|
370
|
+
|
|
371
|
+
Deploy MCP Server as a Service
|
|
372
|
+
```bash
|
|
373
|
+
docker pull knucklessg1/gitlab:latest
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
Modify the `compose.yml`
|
|
377
|
+
|
|
378
|
+
```compose
|
|
379
|
+
services:
|
|
380
|
+
gitlab-mcp:
|
|
381
|
+
image: knucklessg1/gitlab:latest
|
|
382
|
+
environment:
|
|
383
|
+
- HOST=0.0.0.0
|
|
384
|
+
- PORT=8003
|
|
385
|
+
ports:
|
|
386
|
+
- 8003:8003
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Configure `mcp.json`
|
|
390
|
+
|
|
391
|
+
Recommended: Store secrets in environment variables with lookup in JSON file.
|
|
392
|
+
|
|
393
|
+
For Testing Only: Plain text storage will also work, although **not** recommended.
|
|
394
|
+
|
|
395
|
+
```json
|
|
396
|
+
{
|
|
397
|
+
"mcpServers": {
|
|
398
|
+
"gitlab": {
|
|
399
|
+
"command": "gitlab-mcp"
|
|
400
|
+
},
|
|
401
|
+
"env": {
|
|
402
|
+
"GITLAB_INSTANCE": "http://gitlab.com/api/v4/",
|
|
403
|
+
"ACCESS_TOKEN": "${env:ACCESS_TOKEN}"
|
|
404
|
+
// "ACCESS_TOKEN": "glpat-abc123youandme"
|
|
405
|
+
},
|
|
406
|
+
"timeout": 300000
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
</details>
|
|
414
|
+
|
|
415
|
+
<details>
|
|
416
|
+
<summary><b>Installation Instructions:</b></summary>
|
|
417
|
+
|
|
418
|
+
Install Python Package
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
python -m pip install gitlab-api
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
</details>
|
|
425
|
+
|
|
426
|
+
<details>
|
|
427
|
+
<summary><b>Tests:</b></summary>
|
|
428
|
+
|
|
429
|
+
pre-commit check
|
|
430
|
+
```bash
|
|
431
|
+
pre-commit run --all-files
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
pytest
|
|
435
|
+
```bash
|
|
436
|
+
python -m pip install -r test-requirements.txt
|
|
437
|
+
pytest ./test/test_gitlab_models.py
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
Full pytests
|
|
441
|
+
|
|
442
|
+
```bash
|
|
443
|
+
rm -rf ./dist/* \
|
|
444
|
+
&& python setup.py bdist_wheel --universal \
|
|
445
|
+
&& python -m pip uninstall gitlab-api -y \
|
|
446
|
+
&& python -m pip install ./dist/*.whl \
|
|
447
|
+
&& pytest -vv ./test/test_gitlab_models.py \
|
|
448
|
+
&& pytest -vv ./test/test_gitlab_db_models.py \
|
|
449
|
+
&& python ./test/test_sqlalchemy.py
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
Validate MCP Server
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
npx @modelcontextprotocol/inspector gitlab-mcp
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
</details>
|
|
459
|
+
|
|
460
|
+
<details>
|
|
461
|
+
<summary><b>Repository Owners:</b></summary>
|
|
462
|
+
|
|
463
|
+
<img width="100%" height="180em" src="https://github-readme-stats.vercel.app/api?username=Knucklessg1&show_icons=true&hide_border=true&&count_private=true&include_all_commits=true" />
|
|
464
|
+
|
|
465
|
+

|
|
466
|
+

|
|
467
|
+
|
|
468
|
+
</details>
|