gitlab-api 25.27.0__tar.gz → 25.32.0__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.27.0/gitlab_api.egg-info → gitlab_api-25.32.0}/PKG-INFO +58 -30
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/README.md +52 -25
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/agent_server.py +1 -1
- gitlab_api-25.32.0/gitlab_api/api/__init__.py +1 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_base.py +214 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_environments.py +725 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_issues.py +455 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_merge_requests.py +269 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_other.py +587 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_pipelines.py +783 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_projects.py +1213 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_repositories.py +984 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_system.py +69 -0
- gitlab_api-25.32.0/gitlab_api/api/api_client_users_groups.py +620 -0
- gitlab_api-25.32.0/gitlab_api/api_client.py +34 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/gitlab_gql.py +1 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/gitlab_input_models.py +190 -4
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/gitlab_response_models.py +23 -0
- gitlab_api-25.32.0/gitlab_api/mcp/__init__.py +61 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_branches.py +49 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_commits.py +65 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_custom_api.py +44 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_deploy_tokens.py +59 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_environments.py +67 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_epics.py +51 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_graphql.py +80 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_groups.py +55 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_issues.py +51 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_jobs.py +55 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_labels.py +51 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_members.py +45 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_merge_requests.py +49 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_merge_rules.py +65 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_milestones.py +51 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_misc.py +10 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_notes.py +51 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_packages.py +47 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_pipeline_schedules.py +61 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_pipelines.py +47 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_projects.py +57 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_protected_branches.py +49 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_releases.py +65 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_runners.py +71 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_snippets.py +51 -0
- gitlab_api-25.32.0/gitlab_api/mcp/mcp_tags.py +57 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/mcp_server.py +479 -168
- {gitlab_api-25.27.0 → gitlab_api-25.32.0/gitlab_api.egg-info}/PKG-INFO +58 -30
- gitlab_api-25.32.0/gitlab_api.egg-info/SOURCES.txt +78 -0
- gitlab_api-25.32.0/gitlab_api.egg-info/requires.txt +21 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/pyproject.toml +5 -5
- gitlab_api-25.32.0/tests/test_auth.py +105 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_gitlab_a2a_validation.py +1 -1
- gitlab_api-25.32.0/tests/test_gitlab_api_brute_force_coverage.py +411 -0
- gitlab_api-25.32.0/tests/test_gitlab_gql.py +317 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_gitlab_mcp_validation.py +1 -1
- gitlab_api-25.32.0/tests/test_init_dynamics.py +51 -0
- gitlab_api-25.32.0/tests/test_mock_coverage.py +372 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_verify_agent.py +1 -1
- gitlab_api-25.27.0/gitlab_api/api_client.py +0 -5109
- gitlab_api-25.27.0/gitlab_api.egg-info/SOURCES.txt +0 -36
- gitlab_api-25.27.0/gitlab_api.egg-info/requires.txt +0 -20
- gitlab_api-25.27.0/tests/test_gitlab_api_brute_force_coverage.py +0 -164
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/LICENSE +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/MANIFEST.in +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/__init__.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/__main__.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/auth.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api/mcp_config.json +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api.egg-info/dependency_links.txt +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api.egg-info/entry_points.txt +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/gitlab_api.egg-info/top_level.txt +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/requirements.txt +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/scripts/validate_a2a_agent.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/scripts/validate_agent.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/scripts/verify_api_integration.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/setup.cfg +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/test_setup.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/__init__.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/conftest.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_api_wrapper.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_concept_parity.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_gitlab_models.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/test_startup.py +0 -0
- {gitlab_api-25.27.0 → gitlab_api-25.32.0}/tests/verify_a2a_queries.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-api
|
|
3
|
-
Version: 25.
|
|
3
|
+
Version: 25.32.0
|
|
4
4
|
Summary: GitLab API + MCP Server + A2A Server
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,16 +12,17 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: <3.14,>=3.11
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-utilities>=0.
|
|
15
|
+
Requires-Dist: agent-utilities>=0.26.0
|
|
16
16
|
Requires-Dist: python-dotenv>=1.0.0
|
|
17
|
+
Requires-Dist: gql>=4.0.0
|
|
17
18
|
Provides-Extra: mcp
|
|
18
|
-
Requires-Dist: agent-utilities[mcp]>=0.
|
|
19
|
+
Requires-Dist: agent-utilities[mcp]>=0.26.0; extra == "mcp"
|
|
19
20
|
Provides-Extra: agent
|
|
20
|
-
Requires-Dist: agent-utilities[agent,logfire]>=0.
|
|
21
|
+
Requires-Dist: agent-utilities[agent,logfire]>=0.26.0; extra == "agent"
|
|
21
22
|
Provides-Extra: gql
|
|
22
23
|
Requires-Dist: gql>=4.0.0; extra == "gql"
|
|
23
24
|
Provides-Extra: all
|
|
24
|
-
Requires-Dist: gitlab-api[agent,gql,logfire,mcp]>=25.
|
|
25
|
+
Requires-Dist: gitlab-api[agent,gql,logfire,mcp]>=25.32.0; extra == "all"
|
|
25
26
|
Provides-Extra: test
|
|
26
27
|
Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
|
|
27
28
|
Requires-Dist: pytest; extra == "test"
|
|
@@ -51,7 +52,7 @@ Dynamic: license-file
|
|
|
51
52
|

|
|
52
53
|

|
|
53
54
|
|
|
54
|
-
*Version: 25.
|
|
55
|
+
*Version: 25.32.0*
|
|
55
56
|
|
|
56
57
|
---
|
|
57
58
|
|
|
@@ -74,7 +75,7 @@ Dynamic: license-file
|
|
|
74
75
|
|
|
75
76
|
This agent wraps the GitLab API + MCP Server + A2A Server API. You can interact with it programmatically or via its integrated execution entrypoints.
|
|
76
77
|
|
|
77
|
-
Detailed instructions on how to use the underlying API wrappers, extended schema bindings, and developer SDK references are maintained in [docs/index.md](
|
|
78
|
+
Detailed instructions on how to use the underlying API wrappers, extended schema bindings, and developer SDK references are maintained in [docs/index.md](docs/index.md).
|
|
78
79
|
|
|
79
80
|
---
|
|
80
81
|
|
|
@@ -85,28 +86,55 @@ This server utilizes dynamic Action-Routed tools to optimize token overhead and
|
|
|
85
86
|
### Available MCP Tools
|
|
86
87
|
| Tool Module | Toggle Env Var | Enabled by Default | Description & Nested Methods |
|
|
87
88
|
|-------------|----------------|--------------------|------------------------------|
|
|
88
|
-
| **Misc** | `
|
|
89
|
-
| **Branches** | `
|
|
90
|
-
| **Protected Branches** | `
|
|
91
|
-
| **Commits** | `
|
|
92
|
-
| **Deploy Tokens** | `
|
|
93
|
-
| **Environments** | `
|
|
94
|
-
| **Groups** | `
|
|
95
|
-
| **Jobs** | `
|
|
96
|
-
| **Members** | `
|
|
97
|
-
| **Merge Requests** | `
|
|
98
|
-
| **Merge Rules** | `
|
|
99
|
-
| **Packages** | `
|
|
100
|
-
| **Pipelines** | `
|
|
101
|
-
| **Pipeline Schedules** | `
|
|
102
|
-
| **Projects** | `
|
|
103
|
-
| **Releases** | `
|
|
104
|
-
| **Runners** | `
|
|
105
|
-
| **Tags** | `
|
|
106
|
-
| **
|
|
107
|
-
| **
|
|
108
|
-
|
|
109
|
-
|
|
89
|
+
| **Misc** | `MISC_TOOL` | `True` | Manage gitlab api misc operations. |
|
|
90
|
+
| **Branches** | `BRANCHES_TOOL` | `True` | Manage gitlab branches operations. Action-routed methods: `create`, `delete`, `get`. |
|
|
91
|
+
| **Protected Branches** | `PROTECTED_BRANCHES_TOOL` | `True` | Manage gitlab protected branches operations. Action-routed methods: `get`, `protect`, `unprotect`. |
|
|
92
|
+
| **Commits** | `COMMITS_TOOL` | `True` | Manage gitlab commits operations. Action-routed methods: `create`, `create_comment`, `diff`, `get`, `get_comments`, `get_discussions`, `get_gpg_signature`, `get_merge_requests`, `get_statuses`, `post_status`, `revert`. |
|
|
93
|
+
| **Deploy Tokens** | `DEPLOY_TOKENS_TOOL` | `True` | Manage gitlab deploy tokens operations. Action-routed methods: `create_group`, `create_project`, `delete_group`, `delete_project`, `get`, `get_group`, `get_project`. |
|
|
94
|
+
| **Environments** | `ENVIRONMENTS_TOOL` | `True` | Manage gitlab environments operations. Action-routed methods: `create`, `delete`, `delete_stopped`, `get`, `get_protected`, `protect`, `stop`, `stop_stale`, `unprotect`, `update`, `update_protected`. |
|
|
95
|
+
| **Groups** | `GROUPS_TOOL` | `True` | Manage gitlab groups operations. Action-routed methods: `edit`, `get`, `get_descendants`, `get_merge_requests`, `get_projects`, `get_subgroups`. |
|
|
96
|
+
| **Jobs** | `JOBS_TOOL` | `True` | Manage gitlab jobs operations. Action-routed methods: `cancel`, `erase`, `get_log`, `get_pipeline_jobs`, `get_project_jobs`, `retry`, `run`. |
|
|
97
|
+
| **Members** | `MEMBERS_TOOL` | `True` | Manage gitlab members operations. Action-routed methods: `get_group`, `get_project`. |
|
|
98
|
+
| **Merge Requests** | `MERGE_REQUESTS_TOOL` | `True` | Manage gitlab merge requests operations. Action-routed methods: `create`, `get`, `get_project`. |
|
|
99
|
+
| **Merge Rules** | `MERGE_RULES_TOOL` | `True` | Manage gitlab merge rules operations. Action-routed methods: `approve_mr`, `create_project_level`, `delete_project_level`, `edit_group_level`, `edit_project_level`, `get_group_level`, `get_mr_approval_state`, `get_mr_approvals`, `get_mr_level`, `get_project_level`, `unapprove_mr`, `update_project_level`. |
|
|
100
|
+
| **Packages** | `PACKAGES_TOOL` | `True` | Manage gitlab packages operations. Action-routed methods: `download`, `get`, `publish`. |
|
|
101
|
+
| **Pipelines** | `PIPELINES_TOOL` | `True` | Manage gitlab pipelines operations. Action-routed methods: `get`, `run`. |
|
|
102
|
+
| **Pipeline Schedules** | `PIPELINE_SCHEDULES_TOOL` | `True` | Manage gitlab pipeline schedules operations. Action-routed methods: `create`, `create_variable`, `delete`, `delete_variable`, `edit`, `get`, `get_all`, `get_triggered`, `run`, `take_ownership`. |
|
|
103
|
+
| **Projects** | `PROJECTS_TOOL` | `True` | Manage gitlab projects operations. Action-routed methods: `edit`, `get`, `get_contributors`, `get_nested_by_group`, `get_statistics`, `share_with_group`, `unshare_with_group`. |
|
|
104
|
+
| **Releases** | `RELEASES_TOOL` | `True` | Manage gitlab releases operations. Action-routed methods: `create`, `create_evidence`, `delete`, `download_asset`, `get`, `get_by_tag`, `get_group_releases`, `get_latest`, `get_latest_asset`, `get_latest_evidence`, `update`. |
|
|
105
|
+
| **Runners** | `RUNNERS_TOOL` | `True` | Manage gitlab runners operations. Action-routed methods: `delete`, `delete_project`, `enable_project`, `get_all`, `get_group`, `get_jobs`, `get_project`, `pause`, `register`, `reset_gitlab_token`, `reset_group_token`, `reset_project_token`, `reset_token`, `update_details`, `verify_auth`. |
|
|
106
|
+
| **Tags** | `TAGS_TOOL` | `True` | Manage gitlab tags operations. Action-routed methods: `create`, `delete`, `get`, `get_protected`, `get_protected_tag`, `protect`, `unprotect`. |
|
|
107
|
+
| **Labels** | `LABELS_TOOL` | `True` | Manage GitLab labels. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
108
|
+
| **Milestones** | `MILESTONES_TOOL` | `True` | Manage GitLab milestones. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
109
|
+
| **Snippets** | `SNIPPETS_TOOL` | `True` | Manage GitLab snippets. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
110
|
+
| **Notes** | `NOTES_TOOL` | `True` | Manage GitLab notes/comments on issues, merge requests, commits, and epics. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
111
|
+
| **Epics** | `EPICS_TOOL` | `True` | Manage GitLab epics. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
112
|
+
| **Issues** | `ISSUES_TOOL` | `True` | Manage GitLab issues. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
113
|
+
| **Custom Api** | `CUSTOM_API_TOOL` | `True` | Execute arbitrary GitLab REST API requests directly. |
|
|
114
|
+
| **Graphql** | `GRAPHQL_TOOL` | `True` | Execute raw GraphQL queries and mutations natively on GitLab. |
|
|
115
|
+
|
|
116
|
+
Detailed tool schemas, parameter shapes, and validation constraints are preserved in [docs/mcp.md](docs/mcp.md).
|
|
117
|
+
|
|
118
|
+
### Dynamic Tool Selection & Visibility
|
|
119
|
+
|
|
120
|
+
This MCP server supports dynamic toolset selection and visibility filtering at runtime. This allows you to restrict the set of exposed tools in order to prevent blowing up the LLM's context window.
|
|
121
|
+
|
|
122
|
+
You can configure tool filtering via multiple input channels:
|
|
123
|
+
|
|
124
|
+
- **CLI Arguments:** Pass `--tools` or `--toolsets` (or their disabled counterparts `--disabled-tools` and `--disabled-toolsets`) during startup.
|
|
125
|
+
- **Environment Variables:** Define standard environment variables:
|
|
126
|
+
- `MCP_ENABLED_TOOLS` / `MCP_DISABLED_TOOLS`
|
|
127
|
+
- `MCP_ENABLED_TAGS` / `MCP_DISABLED_TAGS`
|
|
128
|
+
- **HTTP SSE Request Headers:** Pass custom headers during transport initialization:
|
|
129
|
+
- `x-mcp-enabled-tools` / `x-mcp-disabled-tools`
|
|
130
|
+
- `x-mcp-enabled-tags` / `x-mcp-disabled-tags`
|
|
131
|
+
- **HTTP SSE Request Query Parameters:** Append query parameters directly to your transport connection URL:
|
|
132
|
+
- `?tools=tool1,tool2`
|
|
133
|
+
- `?tags=tag1`
|
|
134
|
+
|
|
135
|
+
When query strings or parameters are supplied, an LLM-free **Knowledge Graph resolution layer** (using `DynamicToolOrchestrator`) matches query intents against known tool tags, names, or descriptions, with safe fallback and automated 24-hour background cache refreshing.
|
|
136
|
+
|
|
137
|
+
---
|
|
110
138
|
|
|
111
139
|
### MCP Configuration Examples
|
|
112
140
|
|
|
@@ -268,7 +296,7 @@ services:
|
|
|
268
296
|
|
|
269
297
|
```
|
|
270
298
|
|
|
271
|
-
Detailed graph node architecture explanations, custom skill configurations, and agentic trace guides are available in [docs/agent.md](
|
|
299
|
+
Detailed graph node architecture explanations, custom skill configurations, and agentic trace guides are available in [docs/agent.md](docs/agent.md).
|
|
272
300
|
|
|
273
301
|
---
|
|
274
302
|
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|

|
|
21
21
|

|
|
22
22
|
|
|
23
|
-
*Version: 25.
|
|
23
|
+
*Version: 25.32.0*
|
|
24
24
|
|
|
25
25
|
---
|
|
26
26
|
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
This agent wraps the GitLab API + MCP Server + A2A Server API. You can interact with it programmatically or via its integrated execution entrypoints.
|
|
45
45
|
|
|
46
|
-
Detailed instructions on how to use the underlying API wrappers, extended schema bindings, and developer SDK references are maintained in [docs/index.md](
|
|
46
|
+
Detailed instructions on how to use the underlying API wrappers, extended schema bindings, and developer SDK references are maintained in [docs/index.md](docs/index.md).
|
|
47
47
|
|
|
48
48
|
---
|
|
49
49
|
|
|
@@ -54,28 +54,55 @@ This server utilizes dynamic Action-Routed tools to optimize token overhead and
|
|
|
54
54
|
### Available MCP Tools
|
|
55
55
|
| Tool Module | Toggle Env Var | Enabled by Default | Description & Nested Methods |
|
|
56
56
|
|-------------|----------------|--------------------|------------------------------|
|
|
57
|
-
| **Misc** | `
|
|
58
|
-
| **Branches** | `
|
|
59
|
-
| **Protected Branches** | `
|
|
60
|
-
| **Commits** | `
|
|
61
|
-
| **Deploy Tokens** | `
|
|
62
|
-
| **Environments** | `
|
|
63
|
-
| **Groups** | `
|
|
64
|
-
| **Jobs** | `
|
|
65
|
-
| **Members** | `
|
|
66
|
-
| **Merge Requests** | `
|
|
67
|
-
| **Merge Rules** | `
|
|
68
|
-
| **Packages** | `
|
|
69
|
-
| **Pipelines** | `
|
|
70
|
-
| **Pipeline Schedules** | `
|
|
71
|
-
| **Projects** | `
|
|
72
|
-
| **Releases** | `
|
|
73
|
-
| **Runners** | `
|
|
74
|
-
| **Tags** | `
|
|
75
|
-
| **
|
|
76
|
-
| **
|
|
77
|
-
|
|
78
|
-
|
|
57
|
+
| **Misc** | `MISC_TOOL` | `True` | Manage gitlab api misc operations. |
|
|
58
|
+
| **Branches** | `BRANCHES_TOOL` | `True` | Manage gitlab branches operations. Action-routed methods: `create`, `delete`, `get`. |
|
|
59
|
+
| **Protected Branches** | `PROTECTED_BRANCHES_TOOL` | `True` | Manage gitlab protected branches operations. Action-routed methods: `get`, `protect`, `unprotect`. |
|
|
60
|
+
| **Commits** | `COMMITS_TOOL` | `True` | Manage gitlab commits operations. Action-routed methods: `create`, `create_comment`, `diff`, `get`, `get_comments`, `get_discussions`, `get_gpg_signature`, `get_merge_requests`, `get_statuses`, `post_status`, `revert`. |
|
|
61
|
+
| **Deploy Tokens** | `DEPLOY_TOKENS_TOOL` | `True` | Manage gitlab deploy tokens operations. Action-routed methods: `create_group`, `create_project`, `delete_group`, `delete_project`, `get`, `get_group`, `get_project`. |
|
|
62
|
+
| **Environments** | `ENVIRONMENTS_TOOL` | `True` | Manage gitlab environments operations. Action-routed methods: `create`, `delete`, `delete_stopped`, `get`, `get_protected`, `protect`, `stop`, `stop_stale`, `unprotect`, `update`, `update_protected`. |
|
|
63
|
+
| **Groups** | `GROUPS_TOOL` | `True` | Manage gitlab groups operations. Action-routed methods: `edit`, `get`, `get_descendants`, `get_merge_requests`, `get_projects`, `get_subgroups`. |
|
|
64
|
+
| **Jobs** | `JOBS_TOOL` | `True` | Manage gitlab jobs operations. Action-routed methods: `cancel`, `erase`, `get_log`, `get_pipeline_jobs`, `get_project_jobs`, `retry`, `run`. |
|
|
65
|
+
| **Members** | `MEMBERS_TOOL` | `True` | Manage gitlab members operations. Action-routed methods: `get_group`, `get_project`. |
|
|
66
|
+
| **Merge Requests** | `MERGE_REQUESTS_TOOL` | `True` | Manage gitlab merge requests operations. Action-routed methods: `create`, `get`, `get_project`. |
|
|
67
|
+
| **Merge Rules** | `MERGE_RULES_TOOL` | `True` | Manage gitlab merge rules operations. Action-routed methods: `approve_mr`, `create_project_level`, `delete_project_level`, `edit_group_level`, `edit_project_level`, `get_group_level`, `get_mr_approval_state`, `get_mr_approvals`, `get_mr_level`, `get_project_level`, `unapprove_mr`, `update_project_level`. |
|
|
68
|
+
| **Packages** | `PACKAGES_TOOL` | `True` | Manage gitlab packages operations. Action-routed methods: `download`, `get`, `publish`. |
|
|
69
|
+
| **Pipelines** | `PIPELINES_TOOL` | `True` | Manage gitlab pipelines operations. Action-routed methods: `get`, `run`. |
|
|
70
|
+
| **Pipeline Schedules** | `PIPELINE_SCHEDULES_TOOL` | `True` | Manage gitlab pipeline schedules operations. Action-routed methods: `create`, `create_variable`, `delete`, `delete_variable`, `edit`, `get`, `get_all`, `get_triggered`, `run`, `take_ownership`. |
|
|
71
|
+
| **Projects** | `PROJECTS_TOOL` | `True` | Manage gitlab projects operations. Action-routed methods: `edit`, `get`, `get_contributors`, `get_nested_by_group`, `get_statistics`, `share_with_group`, `unshare_with_group`. |
|
|
72
|
+
| **Releases** | `RELEASES_TOOL` | `True` | Manage gitlab releases operations. Action-routed methods: `create`, `create_evidence`, `delete`, `download_asset`, `get`, `get_by_tag`, `get_group_releases`, `get_latest`, `get_latest_asset`, `get_latest_evidence`, `update`. |
|
|
73
|
+
| **Runners** | `RUNNERS_TOOL` | `True` | Manage gitlab runners operations. Action-routed methods: `delete`, `delete_project`, `enable_project`, `get_all`, `get_group`, `get_jobs`, `get_project`, `pause`, `register`, `reset_gitlab_token`, `reset_group_token`, `reset_project_token`, `reset_token`, `update_details`, `verify_auth`. |
|
|
74
|
+
| **Tags** | `TAGS_TOOL` | `True` | Manage gitlab tags operations. Action-routed methods: `create`, `delete`, `get`, `get_protected`, `get_protected_tag`, `protect`, `unprotect`. |
|
|
75
|
+
| **Labels** | `LABELS_TOOL` | `True` | Manage GitLab labels. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
76
|
+
| **Milestones** | `MILESTONES_TOOL` | `True` | Manage GitLab milestones. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
77
|
+
| **Snippets** | `SNIPPETS_TOOL` | `True` | Manage GitLab snippets. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
78
|
+
| **Notes** | `NOTES_TOOL` | `True` | Manage GitLab notes/comments on issues, merge requests, commits, and epics. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
79
|
+
| **Epics** | `EPICS_TOOL` | `True` | Manage GitLab epics. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
80
|
+
| **Issues** | `ISSUES_TOOL` | `True` | Manage GitLab issues. Action-routed methods: `create`, `delete`, `get`, `update`. |
|
|
81
|
+
| **Custom Api** | `CUSTOM_API_TOOL` | `True` | Execute arbitrary GitLab REST API requests directly. |
|
|
82
|
+
| **Graphql** | `GRAPHQL_TOOL` | `True` | Execute raw GraphQL queries and mutations natively on GitLab. |
|
|
83
|
+
|
|
84
|
+
Detailed tool schemas, parameter shapes, and validation constraints are preserved in [docs/mcp.md](docs/mcp.md).
|
|
85
|
+
|
|
86
|
+
### Dynamic Tool Selection & Visibility
|
|
87
|
+
|
|
88
|
+
This MCP server supports dynamic toolset selection and visibility filtering at runtime. This allows you to restrict the set of exposed tools in order to prevent blowing up the LLM's context window.
|
|
89
|
+
|
|
90
|
+
You can configure tool filtering via multiple input channels:
|
|
91
|
+
|
|
92
|
+
- **CLI Arguments:** Pass `--tools` or `--toolsets` (or their disabled counterparts `--disabled-tools` and `--disabled-toolsets`) during startup.
|
|
93
|
+
- **Environment Variables:** Define standard environment variables:
|
|
94
|
+
- `MCP_ENABLED_TOOLS` / `MCP_DISABLED_TOOLS`
|
|
95
|
+
- `MCP_ENABLED_TAGS` / `MCP_DISABLED_TAGS`
|
|
96
|
+
- **HTTP SSE Request Headers:** Pass custom headers during transport initialization:
|
|
97
|
+
- `x-mcp-enabled-tools` / `x-mcp-disabled-tools`
|
|
98
|
+
- `x-mcp-enabled-tags` / `x-mcp-disabled-tags`
|
|
99
|
+
- **HTTP SSE Request Query Parameters:** Append query parameters directly to your transport connection URL:
|
|
100
|
+
- `?tools=tool1,tool2`
|
|
101
|
+
- `?tags=tag1`
|
|
102
|
+
|
|
103
|
+
When query strings or parameters are supplied, an LLM-free **Knowledge Graph resolution layer** (using `DynamicToolOrchestrator`) matches query intents against known tool tags, names, or descriptions, with safe fallback and automated 24-hour background cache refreshing.
|
|
104
|
+
|
|
105
|
+
---
|
|
79
106
|
|
|
80
107
|
### MCP Configuration Examples
|
|
81
108
|
|
|
@@ -237,7 +264,7 @@ services:
|
|
|
237
264
|
|
|
238
265
|
```
|
|
239
266
|
|
|
240
|
-
Detailed graph node architecture explanations, custom skill configurations, and agentic trace guides are available in [docs/agent.md](
|
|
267
|
+
Detailed graph node architecture explanations, custom skill configurations, and agentic trace guides are available in [docs/agent.md](docs/agent.md).
|
|
241
268
|
|
|
242
269
|
---
|
|
243
270
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# GitLab Agent API Package
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
#!/usr/bin/python
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from base64 import b64encode
|
|
5
|
+
from typing import Any, TypeVar
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
import urllib3
|
|
9
|
+
from agent_utilities.base_utilities import get_logger
|
|
10
|
+
|
|
11
|
+
logger = get_logger(__name__)
|
|
12
|
+
|
|
13
|
+
from agent_utilities.core.exceptions import (
|
|
14
|
+
AuthError,
|
|
15
|
+
MissingParameterError,
|
|
16
|
+
ParameterError,
|
|
17
|
+
UnauthorizedError,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
T = TypeVar("T")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class GitLabApiBase:
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
url: str | None = None,
|
|
27
|
+
username: str | None = None,
|
|
28
|
+
password: str | None = None,
|
|
29
|
+
token: str | None = None,
|
|
30
|
+
tokens: list | None = None,
|
|
31
|
+
proxies: dict | None = None,
|
|
32
|
+
verify: bool = True,
|
|
33
|
+
debug: bool = False,
|
|
34
|
+
):
|
|
35
|
+
if debug:
|
|
36
|
+
logger.setLevel(logging.DEBUG)
|
|
37
|
+
logger.debug("Debug mode enabled")
|
|
38
|
+
else:
|
|
39
|
+
logger.setLevel(logging.ERROR)
|
|
40
|
+
if url is None:
|
|
41
|
+
raise MissingParameterError
|
|
42
|
+
|
|
43
|
+
self._session = requests.Session()
|
|
44
|
+
self.url = url.rstrip("/")
|
|
45
|
+
forbidden = ["/api/v4", "/api/v4/"]
|
|
46
|
+
for end in forbidden:
|
|
47
|
+
if url.endswith(end):
|
|
48
|
+
self.url = url[: -len(end)]
|
|
49
|
+
self.url = self.url + "/api/v4"
|
|
50
|
+
self.headers = None
|
|
51
|
+
self.headers_parallel = None
|
|
52
|
+
self.verify = verify
|
|
53
|
+
self.proxies = proxies
|
|
54
|
+
self.debug = debug
|
|
55
|
+
self._current_header_index = 0
|
|
56
|
+
|
|
57
|
+
if self.verify is False:
|
|
58
|
+
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
|
|
59
|
+
|
|
60
|
+
if token:
|
|
61
|
+
self.headers = {
|
|
62
|
+
"Authorization": f"Bearer {token}",
|
|
63
|
+
"Content-Type": "application/json",
|
|
64
|
+
}
|
|
65
|
+
elif tokens:
|
|
66
|
+
self.headers_parallel = []
|
|
67
|
+
for token in tokens:
|
|
68
|
+
self.headers_parallel.append(
|
|
69
|
+
{
|
|
70
|
+
"Authorization": f"Bearer {token}",
|
|
71
|
+
"Content-Type": "application/json",
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
self.headers = self.headers_parallel[self._current_header_index]
|
|
75
|
+
elif username and password:
|
|
76
|
+
user_pass = f"{username}:{password}".encode()
|
|
77
|
+
user_pass_encoded = b64encode(user_pass).decode()
|
|
78
|
+
self.headers = {
|
|
79
|
+
"Authorization": f"Basic {user_pass_encoded}",
|
|
80
|
+
"Content-Type": "application/json",
|
|
81
|
+
}
|
|
82
|
+
else:
|
|
83
|
+
raise MissingParameterError
|
|
84
|
+
|
|
85
|
+
headers_to_check = (
|
|
86
|
+
self.headers_parallel if self.headers_parallel else [self.headers]
|
|
87
|
+
)
|
|
88
|
+
for header in headers_to_check:
|
|
89
|
+
response = self._session.get(
|
|
90
|
+
url=f"{self.url}/projects",
|
|
91
|
+
headers=header,
|
|
92
|
+
verify=self.verify,
|
|
93
|
+
proxies=self.proxies,
|
|
94
|
+
timeout=10,
|
|
95
|
+
)
|
|
96
|
+
if response.status_code in (401, 403):
|
|
97
|
+
logger.error(f"Authentication Error with header: {response.content}") # type: ignore
|
|
98
|
+
raise AuthError if response.status_code == 401 else UnauthorizedError
|
|
99
|
+
elif response.status_code == 404:
|
|
100
|
+
logger.error(f"Parameter Error: {response.content}") # type: ignore
|
|
101
|
+
raise ParameterError
|
|
102
|
+
|
|
103
|
+
def switch_to_next_headers(self) -> bool:
|
|
104
|
+
"""
|
|
105
|
+
Switches self.headers to the next set of headers in self.headers_parallel.
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
- bool: True if headers were switched, False if no switch occurred (e.g., no parallel headers).
|
|
109
|
+
"""
|
|
110
|
+
if not self.headers_parallel or len(self.headers_parallel) <= 1:
|
|
111
|
+
logging.debug("No parallel headers available to switch to.")
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
self._current_header_index = (self._current_header_index + 1) % len(
|
|
115
|
+
self.headers_parallel
|
|
116
|
+
)
|
|
117
|
+
self.headers = self.headers_parallel[self._current_header_index]
|
|
118
|
+
logging.debug(f"Switched to headers at index {self._current_header_index}")
|
|
119
|
+
return True
|
|
120
|
+
|
|
121
|
+
def _fetch_next_page(
|
|
122
|
+
self, endpoint: str, model: T, header: dict, page: int
|
|
123
|
+
) -> list[dict]:
|
|
124
|
+
"""Fetch a single page of data from the specified endpoint"""
|
|
125
|
+
import copy
|
|
126
|
+
|
|
127
|
+
local_model = copy.copy(model)
|
|
128
|
+
local_model.page = page # type: ignore
|
|
129
|
+
local_model.model_post_init(local_model) # type: ignore
|
|
130
|
+
response = self._session.get(
|
|
131
|
+
url=f"{self.url}{endpoint}",
|
|
132
|
+
params=local_model.api_parameters, # type: ignore
|
|
133
|
+
headers=header,
|
|
134
|
+
verify=self.verify,
|
|
135
|
+
proxies=self.proxies,
|
|
136
|
+
)
|
|
137
|
+
page_data = response.json()
|
|
138
|
+
return page_data if isinstance(page_data, list) else []
|
|
139
|
+
|
|
140
|
+
def _fetch_all_pages(
|
|
141
|
+
self,
|
|
142
|
+
endpoint: str,
|
|
143
|
+
model: T,
|
|
144
|
+
id_field: str | None = None,
|
|
145
|
+
id_value: Any | None = None,
|
|
146
|
+
) -> tuple[requests.Response, list[dict]]:
|
|
147
|
+
"""Generic method to fetch all pages with parallelization"""
|
|
148
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
|
149
|
+
|
|
150
|
+
if id_field and getattr(model, id_field) is None:
|
|
151
|
+
raise MissingParameterError
|
|
152
|
+
all_data = []
|
|
153
|
+
headers_to_use = (
|
|
154
|
+
self.headers_parallel if self.headers_parallel else [self.headers]
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
initial_endpoint = (
|
|
158
|
+
endpoint.format(id=id_value) if "{id}" in endpoint else endpoint
|
|
159
|
+
)
|
|
160
|
+
total_pages_response = self._session.get(
|
|
161
|
+
url=f"{self.url}{initial_endpoint}",
|
|
162
|
+
params=model.api_parameters, # type: ignore
|
|
163
|
+
headers=headers_to_use[0],
|
|
164
|
+
verify=self.verify,
|
|
165
|
+
proxies=self.proxies,
|
|
166
|
+
)
|
|
167
|
+
total_pages = int(total_pages_response.headers.get("X-Total-Pages", 1))
|
|
168
|
+
try:
|
|
169
|
+
initial_data = total_pages_response.json()
|
|
170
|
+
except Exception:
|
|
171
|
+
logging.error(f"Failed to decode JSON from {self.url}{initial_endpoint}")
|
|
172
|
+
logging.error(f"Status Code: {total_pages_response.status_code}")
|
|
173
|
+
logging.error(f"Response Content: {total_pages_response.text}")
|
|
174
|
+
raise
|
|
175
|
+
if isinstance(initial_data, list):
|
|
176
|
+
all_data.extend(initial_data)
|
|
177
|
+
|
|
178
|
+
# Fetch all pages by default (max up to 10 pages) if max_pages is None, 0, or not set
|
|
179
|
+
if (
|
|
180
|
+
not hasattr(model, "max_pages")
|
|
181
|
+
or model.max_pages is None
|
|
182
|
+
or model.max_pages == 0
|
|
183
|
+
): # type: ignore
|
|
184
|
+
model.max_pages = min(total_pages, 10) # type: ignore
|
|
185
|
+
elif model.max_pages > total_pages: # type: ignore
|
|
186
|
+
model.max_pages = total_pages # type: ignore
|
|
187
|
+
|
|
188
|
+
if model.max_pages > 1: # type: ignore
|
|
189
|
+
with ThreadPoolExecutor(max_workers=len(headers_to_use)) as executor:
|
|
190
|
+
future_to_page = {}
|
|
191
|
+
header_idx = 0
|
|
192
|
+
|
|
193
|
+
for page in range(2, model.max_pages + 1): # type: ignore
|
|
194
|
+
header = headers_to_use[header_idx % len(headers_to_use)]
|
|
195
|
+
future = executor.submit(
|
|
196
|
+
self._fetch_next_page, # type: ignore[arg-type]
|
|
197
|
+
initial_endpoint,
|
|
198
|
+
model,
|
|
199
|
+
header,
|
|
200
|
+
page,
|
|
201
|
+
)
|
|
202
|
+
future_to_page[future] = page
|
|
203
|
+
header_idx += 1
|
|
204
|
+
|
|
205
|
+
for future in as_completed(future_to_page):
|
|
206
|
+
try:
|
|
207
|
+
page_data = future.result()
|
|
208
|
+
all_data.extend(page_data)
|
|
209
|
+
except Exception as e:
|
|
210
|
+
logging.error(
|
|
211
|
+
f"Error fetching page {future_to_page[future]}: {str(e)}"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
return total_pages_response, all_data
|