gitlab-api 26.2.0__tar.gz → 26.4.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-26.2.0/gitlab_api.egg-info → gitlab_api-26.4.0}/PKG-INFO +5 -4
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/README.md +3 -2
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/agent_server.py +1 -1
- gitlab_api-26.4.0/gitlab_api/kg_ingest.py +269 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp_server.py +65 -1
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/ontology/gitlab.ttl +59 -1
- {gitlab_api-26.2.0 → gitlab_api-26.4.0/gitlab_api.egg-info}/PKG-INFO +5 -4
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api.egg-info/requires.txt +1 -1
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/pyproject.toml +2 -2
- gitlab_api-26.4.0/tests/test_kg_ingest.py +182 -0
- gitlab_api-26.2.0/gitlab_api/kg_ingest.py +0 -144
- gitlab_api-26.2.0/tests/test_kg_ingest.py +0 -93
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/LICENSE +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/MANIFEST.in +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/__main__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_base.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_environments.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_issues.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_merge_requests.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_other.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_pipelines.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_projects.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_repositories.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_system.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_users_groups.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api/api_client_vulnerabilities.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/api_client.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/auth.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/connectors/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/connectors/mcp_source_presets.json +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/gitlab_gql.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/gitlab_input_models.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/gitlab_response_models.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/instances.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/main_agent.json +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_branches.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_commits.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_custom_api.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_deploy_tokens.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_environments.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_epics.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_graphql.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_graphql_ops.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_groups.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_issues.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_jobs.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_labels.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_members.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_merge_requests.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_merge_rules.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_milestones.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_misc.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_namespaces.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_notes.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_packages.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_pipeline_schedules.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_pipelines.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_projects.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_protected_branches.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_releases.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_runners.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_snippets.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_tags.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_users.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_vulnerabilities.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp/mcp_wiki.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/mcp_config.json +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/ontology/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/prompts/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/prompts/devops_specialist.json +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/prompts/main_agent.json +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/skills/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/skills/gitlab-issues/SKILL.md +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/skills/gitlab-merge-request-create/SKILL.md +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/skills/gitlab-merge-request-review/SKILL.md +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/skills/gitlab-pipelines/SKILL.md +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api/skills/gitlab-vulnerabilities/SKILL.md +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api.egg-info/SOURCES.txt +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api.egg-info/dependency_links.txt +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api.egg-info/entry_points.txt +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/gitlab_api.egg-info/top_level.txt +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/requirements.txt +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/scripts/security_sanitizer.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/scripts/validate_a2a_agent.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/scripts/validate_agent.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/scripts/verify_api_integration.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/setup.cfg +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/__init__.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/conftest.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_action_discovery.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_api_wrapper.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_auth.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_concept_parity.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_gitlab_a2a_validation.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_gitlab_api_brute_force_coverage.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_gitlab_gql.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_gitlab_mcp_validation.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_gitlab_models.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_init_dynamics.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_instances.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_mock_coverage.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_startup.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_tool_modes.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.0}/tests/test_verify_agent.py +0 -0
- {gitlab_api-26.2.0 → gitlab_api-26.4.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: 26.
|
|
3
|
+
Version: 26.4.0
|
|
4
4
|
Summary: GitLab API + MCP Server + A2A Server
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -22,7 +22,7 @@ Requires-Dist: agent-utilities[agent,logfire]>=1.0.0; extra == "agent"
|
|
|
22
22
|
Provides-Extra: gql
|
|
23
23
|
Requires-Dist: gql[requests]>=4.0.0; extra == "gql"
|
|
24
24
|
Provides-Extra: all
|
|
25
|
-
Requires-Dist: gitlab-api[agent,gql,logfire,mcp]>=26.
|
|
25
|
+
Requires-Dist: gitlab-api[agent,gql,logfire,mcp]>=26.4.0; extra == "all"
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
|
|
28
28
|
Requires-Dist: pytest; extra == "test"
|
|
@@ -52,7 +52,7 @@ Dynamic: license-file
|
|
|
52
52
|

|
|
53
53
|

|
|
54
54
|
|
|
55
|
-
*Version: 26.
|
|
55
|
+
*Version: 26.4.0*
|
|
56
56
|
|
|
57
57
|
> **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
|
|
58
58
|
> interfaces, the integrated A2A agent server, and guidance for provisioning the
|
|
@@ -116,6 +116,7 @@ _Auto-generated from the live MCP server — do not edit by hand._
|
|
|
116
116
|
| `gitlab_graphql` | `GRAPHQLTOOL` | Execute raw GraphQL queries and mutations natively on GitLab. |
|
|
117
117
|
| `gitlab_graphql_ops` | `GRAPHQL_OPSTOOL` | Run a typed GitLab GraphQL operation by name. |
|
|
118
118
|
| `gitlab_groups` | `GROUPSTOOL` | Manage gitlab groups operations. |
|
|
119
|
+
| `gitlab_ingest_pipelines` | `MISCTOOL` | Natively ingest GitLab CI pipeline runs (+ jobs) into epistemic-graph. |
|
|
119
120
|
| `gitlab_ingest_projects` | `MISCTOOL` | Natively ingest GitLab projects into epistemic-graph as typed :Project nodes. |
|
|
120
121
|
| `gitlab_instances` | `MISCTOOL` | List the configured GitLab tenants (CONCEPT:AU-KG.backend.declared-columns-so-schema). |
|
|
121
122
|
| `gitlab_issues` | `ISSUESTOOL` | Manage GitLab issues. |
|
|
@@ -346,7 +347,7 @@ _Auto-generated from the live MCP server — do not edit by hand._
|
|
|
346
347
|
|
|
347
348
|
</details>
|
|
348
349
|
|
|
349
|
-
|
|
350
|
+
_34 action-routed tool(s) (default) · 196 verbose 1:1 tool(s). Each is enabled unless its `<DOMAIN>TOOL` toggle is set false; `MCP_TOOL_MODE` selects the surface (`condensed` default · `verbose` 1:1 · `both`). Auto-generated — do not edit._
|
|
350
351
|
<!-- MCP-TOOLS-TABLE:END -->
|
|
351
352
|
|
|
352
353
|
Detailed tool schemas, parameter shapes, and validation constraints are preserved in [docs/mcp.md](docs/mcp.md).
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|

|
|
21
21
|

|
|
22
22
|
|
|
23
|
-
*Version: 26.
|
|
23
|
+
*Version: 26.4.0*
|
|
24
24
|
|
|
25
25
|
> **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
|
|
26
26
|
> interfaces, the integrated A2A agent server, and guidance for provisioning the
|
|
@@ -84,6 +84,7 @@ _Auto-generated from the live MCP server — do not edit by hand._
|
|
|
84
84
|
| `gitlab_graphql` | `GRAPHQLTOOL` | Execute raw GraphQL queries and mutations natively on GitLab. |
|
|
85
85
|
| `gitlab_graphql_ops` | `GRAPHQL_OPSTOOL` | Run a typed GitLab GraphQL operation by name. |
|
|
86
86
|
| `gitlab_groups` | `GROUPSTOOL` | Manage gitlab groups operations. |
|
|
87
|
+
| `gitlab_ingest_pipelines` | `MISCTOOL` | Natively ingest GitLab CI pipeline runs (+ jobs) into epistemic-graph. |
|
|
87
88
|
| `gitlab_ingest_projects` | `MISCTOOL` | Natively ingest GitLab projects into epistemic-graph as typed :Project nodes. |
|
|
88
89
|
| `gitlab_instances` | `MISCTOOL` | List the configured GitLab tenants (CONCEPT:AU-KG.backend.declared-columns-so-schema). |
|
|
89
90
|
| `gitlab_issues` | `ISSUESTOOL` | Manage GitLab issues. |
|
|
@@ -314,7 +315,7 @@ _Auto-generated from the live MCP server — do not edit by hand._
|
|
|
314
315
|
|
|
315
316
|
</details>
|
|
316
317
|
|
|
317
|
-
|
|
318
|
+
_34 action-routed tool(s) (default) · 196 verbose 1:1 tool(s). Each is enabled unless its `<DOMAIN>TOOL` toggle is set false; `MCP_TOOL_MODE` selects the surface (`condensed` default · `verbose` 1:1 · `both`). Auto-generated — do not edit._
|
|
318
319
|
<!-- MCP-TOOLS-TABLE:END -->
|
|
319
320
|
|
|
320
321
|
Detailed tool schemas, parameter shapes, and validation constraints are preserved in [docs/mcp.md](docs/mcp.md).
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
"""Native epistemic-graph ingestion for GitLab records (typed graph nodes).
|
|
2
|
+
|
|
3
|
+
CONCEPT:AU-KG.ingest.enterprise-source-extractor. This is the record-source twin of
|
|
4
|
+
media-downloader's blob ingestion: the package natively pushes its data into the
|
|
5
|
+
epistemic-graph knowledge graph as **typed OWL nodes** (`:Project`, `:GitLabGroup`,
|
|
6
|
+
`:MergeRequest`, `:Issue`, …) + links, using the lightweight engine client
|
|
7
|
+
(``GraphComputeEngine()._client`` + ``txn``) — the same fast client the blob
|
|
8
|
+
``MediaStore`` uses, NOT the heavy in-process ingestion engine.
|
|
9
|
+
|
|
10
|
+
Entirely best-effort and dependency-/engine-guarded: with no agent-utilities KG stack
|
|
11
|
+
or no reachable engine, every entry point **no-ops** (returns ``None``), so the
|
|
12
|
+
connector keeps working with zero KG infrastructure. Nodes carry the shared provenance
|
|
13
|
+
(``domain``/``source``) and match the classes federated by ``gitlab_api.ontology``.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import logging
|
|
19
|
+
from typing import Any
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger("gitlab_api.kg")
|
|
22
|
+
|
|
23
|
+
_SOURCE = "gitlab-api"
|
|
24
|
+
_DOMAIN = "gitlab"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _client() -> tuple[Any | None, str]:
|
|
28
|
+
"""Return ``(engine_client, graph_name)`` or ``(None, "")`` when unavailable."""
|
|
29
|
+
try:
|
|
30
|
+
from agent_utilities.knowledge_graph.core.graph_compute import (
|
|
31
|
+
GraphComputeEngine,
|
|
32
|
+
)
|
|
33
|
+
except Exception as e: # noqa: BLE001 — KG stack absent
|
|
34
|
+
logger.debug("KG ingest unavailable (import): %s", e)
|
|
35
|
+
return None, ""
|
|
36
|
+
try:
|
|
37
|
+
engine = GraphComputeEngine()
|
|
38
|
+
client = getattr(engine, "_client", None)
|
|
39
|
+
if client is None:
|
|
40
|
+
return None, ""
|
|
41
|
+
graph = getattr(engine, "graph_name", None) or "__commons__"
|
|
42
|
+
return client, graph
|
|
43
|
+
except Exception as e: # noqa: BLE001 — engine unreachable
|
|
44
|
+
logger.debug("KG ingest: engine unreachable: %s", e)
|
|
45
|
+
return None, ""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def ingest_entities(
|
|
49
|
+
entities: list[dict[str, Any]],
|
|
50
|
+
relationships: list[dict[str, Any]] | None = None,
|
|
51
|
+
*,
|
|
52
|
+
client: Any | None = None,
|
|
53
|
+
graph: str | None = None,
|
|
54
|
+
) -> dict[str, int] | None:
|
|
55
|
+
"""Write typed nodes (+ edges) into epistemic-graph via the fast engine client.
|
|
56
|
+
|
|
57
|
+
``entities``: ``[{"id":..., "type":..., ...props}]``.
|
|
58
|
+
``relationships``: ``[{"source":id, "target":id, "type":rel}]``.
|
|
59
|
+
Returns ``{"nodes":n, "edges":m}`` or ``None`` (no engine / failure; never raises).
|
|
60
|
+
``client``/``graph`` may be injected (tests); otherwise resolved on demand.
|
|
61
|
+
"""
|
|
62
|
+
entities = [e for e in (entities or []) if e.get("id")]
|
|
63
|
+
if not entities:
|
|
64
|
+
return None
|
|
65
|
+
if client is None:
|
|
66
|
+
client, graph = _client()
|
|
67
|
+
if client is None:
|
|
68
|
+
return None
|
|
69
|
+
graph = graph or "__commons__"
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
txn = client.txn.begin(graph=graph)
|
|
73
|
+
for ent in entities:
|
|
74
|
+
props = {k: v for k, v in ent.items() if k != "id" and v is not None}
|
|
75
|
+
props.setdefault("source", _SOURCE)
|
|
76
|
+
props.setdefault("domain", _DOMAIN)
|
|
77
|
+
client.txn.add_node(txn, ent["id"], props)
|
|
78
|
+
committed = client.txn.commit(txn)
|
|
79
|
+
except Exception as e: # noqa: BLE001 — engine/txn failure is non-fatal
|
|
80
|
+
logger.warning("KG ingest: txn failed: %s", e)
|
|
81
|
+
return None
|
|
82
|
+
if not committed:
|
|
83
|
+
logger.warning("KG ingest: txn not committed (conflict)")
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
edges = 0
|
|
87
|
+
for rel in relationships or []:
|
|
88
|
+
try:
|
|
89
|
+
client.edges.add(
|
|
90
|
+
rel["source"], rel["target"], {"type": rel.get("type", "RELATED")}
|
|
91
|
+
)
|
|
92
|
+
edges += 1
|
|
93
|
+
except Exception as e: # noqa: BLE001 — pure edge link, best-effort
|
|
94
|
+
logger.debug("KG ingest: edge skipped: %s", e)
|
|
95
|
+
|
|
96
|
+
logger.info("KG ingest: wrote %d nodes, %d edges", len(entities), edges)
|
|
97
|
+
return {"nodes": len(entities), "edges": edges}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def ingest_projects(
|
|
101
|
+
projects: list[dict[str, Any]],
|
|
102
|
+
*,
|
|
103
|
+
client: Any | None = None,
|
|
104
|
+
graph: str | None = None,
|
|
105
|
+
) -> dict[str, int] | None:
|
|
106
|
+
"""Map GitLab project records → ``:Project`` (+ ``:GitLabGroup``) nodes and ingest."""
|
|
107
|
+
entities: list[dict[str, Any]] = []
|
|
108
|
+
relationships: list[dict[str, Any]] = []
|
|
109
|
+
for proj in projects or []:
|
|
110
|
+
pid = proj.get("id")
|
|
111
|
+
if pid is None:
|
|
112
|
+
continue
|
|
113
|
+
entities.append(
|
|
114
|
+
{
|
|
115
|
+
"id": f"gitlab:project:{pid}",
|
|
116
|
+
"type": "Project",
|
|
117
|
+
"name": proj.get("name"),
|
|
118
|
+
"path_with_namespace": proj.get("path_with_namespace"),
|
|
119
|
+
"web_url": proj.get("web_url"),
|
|
120
|
+
"state": proj.get("state"),
|
|
121
|
+
"last_activity_at": proj.get("last_activity_at"),
|
|
122
|
+
"externalToolId": str(pid),
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
namespace = proj.get("namespace") or {}
|
|
126
|
+
gid = namespace.get("id") or namespace.get("full_path")
|
|
127
|
+
if gid is not None:
|
|
128
|
+
entities.append(
|
|
129
|
+
{
|
|
130
|
+
"id": f"gitlab:group:{gid}",
|
|
131
|
+
"type": "GitLabGroup",
|
|
132
|
+
"name": namespace.get("name") or namespace.get("full_path"),
|
|
133
|
+
}
|
|
134
|
+
)
|
|
135
|
+
relationships.append(
|
|
136
|
+
{
|
|
137
|
+
"source": f"gitlab:project:{pid}",
|
|
138
|
+
"target": f"gitlab:group:{gid}",
|
|
139
|
+
"type": "partOfGroup",
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
return ingest_entities(entities, relationships, client=client, graph=graph)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
def ingest_pipeline_runs(
|
|
146
|
+
project_id: str | int,
|
|
147
|
+
pipelines: list[dict[str, Any]],
|
|
148
|
+
*,
|
|
149
|
+
jobs_by_pipeline: dict[Any, list[dict[str, Any]]] | None = None,
|
|
150
|
+
client: Any | None = None,
|
|
151
|
+
graph: str | None = None,
|
|
152
|
+
) -> dict[str, int] | None:
|
|
153
|
+
"""Map GitLab pipeline runs (+ their jobs) → ``:PipelineRun``/``:CheckRun`` nodes.
|
|
154
|
+
|
|
155
|
+
This is the substrate the autonomous-SDLC loop needs to observe CI (closes gap #2,
|
|
156
|
+
"CI has no graph representation", of ``reports/autonomous-sdlc-loop-design.md``).
|
|
157
|
+
|
|
158
|
+
Uses the SAME ``:PipelineRun``/``:CheckRun`` classes and ``ranFor``/``hasJob`` edge
|
|
159
|
+
names as github-agent's ingestion so GitLab CI/CD and GitHub Actions unify under one
|
|
160
|
+
CI node shape in the knowledge graph. ``ranFor`` is emitted once per known target —
|
|
161
|
+
the ``:Project``, the head ``:Commit``, and (if resolved) the triggering
|
|
162
|
+
``:MergeRequest``. Stable ids: ``gitlab:pipelinerun:<project>:<id>`` /
|
|
163
|
+
``gitlab:checkrun:<project>:<pipeline>:<job>``.
|
|
164
|
+
|
|
165
|
+
``pipelines``: raw GitLab pipeline records (``id``, ``status``, ``ref``, ``sha``,
|
|
166
|
+
``source``, ``web_url``, ``name``, timestamps, ``duration``; optionally
|
|
167
|
+
``merge_request_iid`` if the caller has resolved the triggering merge request).
|
|
168
|
+
``jobs_by_pipeline``: maps a pipeline ``id`` to its list of raw GitLab job records
|
|
169
|
+
(``id``, ``name``, ``stage``, ``status``, ``failure_reason``, ``web_url``,
|
|
170
|
+
timestamps, ``duration``, optional ``runner``); each becomes a child ``:CheckRun``
|
|
171
|
+
linked via ``hasJob`` (and, when known, its ``:Runner`` via the GitLab-specific
|
|
172
|
+
``ranOnRunner``).
|
|
173
|
+
"""
|
|
174
|
+
pipelines = pipelines or []
|
|
175
|
+
if not pipelines:
|
|
176
|
+
return None
|
|
177
|
+
jobs_by_pipeline = jobs_by_pipeline or {}
|
|
178
|
+
entities: list[dict[str, Any]] = []
|
|
179
|
+
relationships: list[dict[str, Any]] = []
|
|
180
|
+
project_node = f"gitlab:project:{project_id}"
|
|
181
|
+
|
|
182
|
+
for pipe in pipelines:
|
|
183
|
+
pid = pipe.get("id")
|
|
184
|
+
if pid is None:
|
|
185
|
+
continue
|
|
186
|
+
pipe_node = f"gitlab:pipelinerun:{project_id}:{pid}"
|
|
187
|
+
entities.append(
|
|
188
|
+
{
|
|
189
|
+
"id": pipe_node,
|
|
190
|
+
"type": "PipelineRun",
|
|
191
|
+
"status": pipe.get("status"),
|
|
192
|
+
"ref": pipe.get("ref"),
|
|
193
|
+
"sha": pipe.get("sha"),
|
|
194
|
+
"triggerSource": pipe.get("source"),
|
|
195
|
+
"webUrl": pipe.get("web_url"),
|
|
196
|
+
"name": pipe.get("name"),
|
|
197
|
+
"createdAt": pipe.get("created_at"),
|
|
198
|
+
"startedAt": pipe.get("started_at"),
|
|
199
|
+
"finishedAt": pipe.get("finished_at"),
|
|
200
|
+
"duration": pipe.get("duration"),
|
|
201
|
+
"externalToolId": str(pid),
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
relationships.append(
|
|
205
|
+
{"source": pipe_node, "target": project_node, "type": "ranFor"}
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
sha = pipe.get("sha")
|
|
209
|
+
if sha:
|
|
210
|
+
commit_node = f"gitlab:commit:{project_id}:{sha}"
|
|
211
|
+
entities.append({"id": commit_node, "type": "Commit", "sha": sha})
|
|
212
|
+
relationships.append(
|
|
213
|
+
{"source": pipe_node, "target": commit_node, "type": "ranFor"}
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
mr_iid = pipe.get("merge_request_iid")
|
|
217
|
+
if mr_iid is not None:
|
|
218
|
+
mr_node = f"gitlab:mr:{project_id}:{mr_iid}"
|
|
219
|
+
relationships.append(
|
|
220
|
+
{"source": pipe_node, "target": mr_node, "type": "ranFor"}
|
|
221
|
+
)
|
|
222
|
+
|
|
223
|
+
for job in jobs_by_pipeline.get(pid, []) or []:
|
|
224
|
+
jid = job.get("id")
|
|
225
|
+
if jid is None:
|
|
226
|
+
continue
|
|
227
|
+
job_node = f"gitlab:checkrun:{project_id}:{pid}:{jid}"
|
|
228
|
+
web_url = job.get("web_url")
|
|
229
|
+
entities.append(
|
|
230
|
+
{
|
|
231
|
+
"id": job_node,
|
|
232
|
+
"type": "CheckRun",
|
|
233
|
+
"name": job.get("name"),
|
|
234
|
+
"stage": job.get("stage"),
|
|
235
|
+
"status": job.get("status"),
|
|
236
|
+
"failureReason": job.get("failure_reason"),
|
|
237
|
+
"webUrl": web_url,
|
|
238
|
+
"logUrl": f"{web_url}/raw" if web_url else None,
|
|
239
|
+
"triggerSource": job.get("source"),
|
|
240
|
+
"createdAt": job.get("created_at"),
|
|
241
|
+
"startedAt": job.get("started_at"),
|
|
242
|
+
"finishedAt": job.get("finished_at"),
|
|
243
|
+
"duration": job.get("duration"),
|
|
244
|
+
"externalToolId": str(jid),
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
relationships.append(
|
|
248
|
+
{"source": pipe_node, "target": job_node, "type": "hasJob"}
|
|
249
|
+
)
|
|
250
|
+
runner = job.get("runner") or {}
|
|
251
|
+
runner_id = runner.get("id")
|
|
252
|
+
if runner_id is not None:
|
|
253
|
+
runner_node = f"gitlab:runner:{runner_id}"
|
|
254
|
+
entities.append(
|
|
255
|
+
{
|
|
256
|
+
"id": runner_node,
|
|
257
|
+
"type": "Runner",
|
|
258
|
+
"name": runner.get("description") or runner.get("name"),
|
|
259
|
+
}
|
|
260
|
+
)
|
|
261
|
+
relationships.append(
|
|
262
|
+
{
|
|
263
|
+
"source": job_node,
|
|
264
|
+
"target": runner_node,
|
|
265
|
+
"type": "ranOnRunner",
|
|
266
|
+
}
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
return ingest_entities(entities, relationships, client=client, graph=graph)
|
|
@@ -37,7 +37,7 @@ from agent_utilities.mcp_utilities import (
|
|
|
37
37
|
from gitlab_api.api_client import Api
|
|
38
38
|
from gitlab_api.auth import get_client
|
|
39
39
|
|
|
40
|
-
__version__ = "26.
|
|
40
|
+
__version__ = "26.4.0"
|
|
41
41
|
print(f"Gitlab MCP v{__version__}", file=sys.stderr)
|
|
42
42
|
|
|
43
43
|
logger = get_logger(name="mcp_server")
|
|
@@ -112,6 +112,70 @@ def register_misc_tools(mcp: FastMCP):
|
|
|
112
112
|
result = ingest_projects(projects)
|
|
113
113
|
return {"listed": len(projects), "ingested": result}
|
|
114
114
|
|
|
115
|
+
@mcp.tool(tags={"misc", "kg"})
|
|
116
|
+
async def gitlab_ingest_pipelines(
|
|
117
|
+
project_id: str = Field(
|
|
118
|
+
description="GitLab project id or URL-encoded path to ingest recent pipeline runs for."
|
|
119
|
+
),
|
|
120
|
+
params_json: str = Field(
|
|
121
|
+
default="{}",
|
|
122
|
+
description="JSON string of get_pipelines filters (e.g. status, ref, per_page).",
|
|
123
|
+
),
|
|
124
|
+
include_jobs: bool = Field(
|
|
125
|
+
default=True,
|
|
126
|
+
description="Also fetch + ingest each pipeline's jobs as :Job/:CheckRun nodes.",
|
|
127
|
+
),
|
|
128
|
+
client=Depends(get_client),
|
|
129
|
+
ctx: Context | None = None,
|
|
130
|
+
) -> Any:
|
|
131
|
+
"""Natively ingest GitLab CI pipeline runs (+ jobs) into epistemic-graph.
|
|
132
|
+
|
|
133
|
+
Lists recent pipelines for ``project_id`` via the GitLab API (optionally each
|
|
134
|
+
pipeline's jobs) and pushes them as typed ``:PipelineRun``/``:CheckRun`` nodes
|
|
135
|
+
(the SAME classes + ``ranFor``/``hasJob`` edges github-agent uses, so GitLab
|
|
136
|
+
CI/CD and GitHub Actions unify) — ``ranFor`` the ``:Project``, the ``:Commit``,
|
|
137
|
+
and any triggering ``:MergeRequest`` — into the knowledge graph via the fast
|
|
138
|
+
engine client. This is the substrate the autonomous-SDLC loop needs to observe
|
|
139
|
+
CI. Best-effort: returns ``{"ingested": None}`` when no engine is reachable.
|
|
140
|
+
CONCEPT:AU-KG.ingest.enterprise-source-extractor.
|
|
141
|
+
"""
|
|
142
|
+
import json as _json
|
|
143
|
+
|
|
144
|
+
from gitlab_api.kg_ingest import ingest_pipeline_runs
|
|
145
|
+
|
|
146
|
+
kwargs = _json.loads(params_json) if params_json else {}
|
|
147
|
+
kwargs["project_id"] = project_id
|
|
148
|
+
resp = await run_blocking(client.get_pipelines, **kwargs)
|
|
149
|
+
data = getattr(resp, "data", resp)
|
|
150
|
+
records = data if isinstance(data, list) else [data]
|
|
151
|
+
pipelines = [
|
|
152
|
+
r.model_dump() if hasattr(r, "model_dump") else r
|
|
153
|
+
for r in records
|
|
154
|
+
if r is not None
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
jobs_by_pipeline: dict[Any, list[dict[str, Any]]] = {}
|
|
158
|
+
if include_jobs:
|
|
159
|
+
for pipe in pipelines:
|
|
160
|
+
pid = pipe.get("id")
|
|
161
|
+
if pid is None:
|
|
162
|
+
continue
|
|
163
|
+
jresp = await run_blocking(
|
|
164
|
+
client.get_pipeline_jobs, project_id=project_id, pipeline_id=pid
|
|
165
|
+
)
|
|
166
|
+
jdata = getattr(jresp, "data", jresp)
|
|
167
|
+
jrecords = jdata if isinstance(jdata, list) else [jdata]
|
|
168
|
+
jobs_by_pipeline[pid] = [
|
|
169
|
+
j.model_dump() if hasattr(j, "model_dump") else j
|
|
170
|
+
for j in jrecords
|
|
171
|
+
if j is not None
|
|
172
|
+
]
|
|
173
|
+
|
|
174
|
+
result = ingest_pipeline_runs(
|
|
175
|
+
project_id, pipelines, jobs_by_pipeline=jobs_by_pipeline
|
|
176
|
+
)
|
|
177
|
+
return {"listed": len(pipelines), "ingested": result}
|
|
178
|
+
|
|
115
179
|
return None
|
|
116
180
|
|
|
117
181
|
|
|
@@ -27,10 +27,25 @@
|
|
|
27
27
|
rdfs:label "Pipeline" ;
|
|
28
28
|
rdfs:comment "A CI/CD pipeline run for a commit/ref (gitlab_pipelines)." .
|
|
29
29
|
|
|
30
|
+
:PipelineRun a owl:Class ;
|
|
31
|
+
rdfs:label "Pipeline Run" ;
|
|
32
|
+
rdfs:comment """A single CI/CD execution for a commit/ref/merge request (a GitLab pipeline
|
|
33
|
+
run, ingested by gitlab_api.kg_ingest.ingest_pipeline_runs, id gitlab:pipelinerun:<project>:<id>).
|
|
34
|
+
Shares its class name with the twin github-agent producer so GitLab CI/CD and GitHub Actions
|
|
35
|
+
unify under one node shape in the knowledge graph.""" ;
|
|
36
|
+
owl:equivalentClass :Pipeline .
|
|
37
|
+
|
|
30
38
|
:Job a owl:Class ;
|
|
31
39
|
rdfs:label "Job" ;
|
|
32
40
|
rdfs:comment "A single stage/job within a pipeline (gitlab_jobs)." .
|
|
33
41
|
|
|
42
|
+
:CheckRun a owl:Class ;
|
|
43
|
+
rdfs:label "Check Run" ;
|
|
44
|
+
rdfs:comment """A single job/check within a PipelineRun (a GitLab pipeline job, ingested by
|
|
45
|
+
gitlab_api.kg_ingest.ingest_pipeline_runs, id gitlab:checkrun:<project>:<pipeline>:<job>).
|
|
46
|
+
Shares its class name with the twin github-agent producer.""" ;
|
|
47
|
+
owl:equivalentClass :Job .
|
|
48
|
+
|
|
34
49
|
:Issue a owl:Class ;
|
|
35
50
|
rdfs:label "Issue" ;
|
|
36
51
|
rdfs:comment "A tracked work item or defect (gitlab_issues)." .
|
|
@@ -83,9 +98,17 @@
|
|
|
83
98
|
rdfs:comment "Links a Commit or MergeRequest to a Pipeline it started." ;
|
|
84
99
|
rdfs:range :Pipeline .
|
|
85
100
|
|
|
101
|
+
:ranFor a owl:ObjectProperty ;
|
|
102
|
+
rdfs:label "ran for" ;
|
|
103
|
+
rdfs:comment """Links a PipelineRun to what it ran for — its Project, the Commit it built,
|
|
104
|
+
and/or the MergeRequest it validated. Same predicate name as the twin github-agent producer
|
|
105
|
+
(PipelineRun ranFor Repository/Commit/PullRequest), unifying GitLab CI/CD and GitHub Actions.""" ;
|
|
106
|
+
rdfs:domain :PipelineRun .
|
|
107
|
+
|
|
86
108
|
:hasJob a owl:ObjectProperty ;
|
|
87
109
|
rdfs:label "has job" ;
|
|
88
|
-
rdfs:comment "Links a
|
|
110
|
+
rdfs:comment """Links a PipelineRun to a CheckRun (job/check) it contains. Same predicate name
|
|
111
|
+
as the twin github-agent producer (PipelineRun hasJob CheckRun).""" ;
|
|
89
112
|
rdfs:domain :Pipeline ;
|
|
90
113
|
rdfs:range :Job .
|
|
91
114
|
|
|
@@ -143,6 +166,41 @@
|
|
|
143
166
|
rdfs:comment "Full git commit SHA." ;
|
|
144
167
|
rdfs:range xsd:string .
|
|
145
168
|
|
|
169
|
+
:triggerSource a owl:DatatypeProperty ;
|
|
170
|
+
rdfs:label "trigger source" ;
|
|
171
|
+
rdfs:comment "How a Pipeline or Job was triggered (push, web, schedule, api, merge_request_event, …). Named apart from the shared provenance `source` field." ;
|
|
172
|
+
rdfs:range xsd:string .
|
|
173
|
+
|
|
174
|
+
:failureReason a owl:DatatypeProperty ;
|
|
175
|
+
rdfs:label "failure reason" ;
|
|
176
|
+
rdfs:comment "GitLab's classification of why a Job failed (e.g. script_failure, runner_system_failure)." ;
|
|
177
|
+
rdfs:range xsd:string .
|
|
178
|
+
|
|
179
|
+
:duration a owl:DatatypeProperty ;
|
|
180
|
+
rdfs:label "duration" ;
|
|
181
|
+
rdfs:comment "Wall-clock duration of a Pipeline or Job run, in seconds." ;
|
|
182
|
+
rdfs:range xsd:decimal .
|
|
183
|
+
|
|
184
|
+
:createdAt a owl:DatatypeProperty ;
|
|
185
|
+
rdfs:label "created at" ;
|
|
186
|
+
rdfs:comment "Timestamp an object was created." ;
|
|
187
|
+
rdfs:range xsd:dateTime .
|
|
188
|
+
|
|
189
|
+
:startedAt a owl:DatatypeProperty ;
|
|
190
|
+
rdfs:label "started at" ;
|
|
191
|
+
rdfs:comment "Timestamp a Pipeline or Job started running." ;
|
|
192
|
+
rdfs:range xsd:dateTime .
|
|
193
|
+
|
|
194
|
+
:finishedAt a owl:DatatypeProperty ;
|
|
195
|
+
rdfs:label "finished at" ;
|
|
196
|
+
rdfs:comment "Timestamp a Pipeline or Job finished running." ;
|
|
197
|
+
rdfs:range xsd:dateTime .
|
|
198
|
+
|
|
199
|
+
:logUrl a owl:DatatypeProperty ;
|
|
200
|
+
rdfs:label "log url" ;
|
|
201
|
+
rdfs:comment "URL to the raw log output of a Job." ;
|
|
202
|
+
rdfs:range xsd:string .
|
|
203
|
+
|
|
146
204
|
<http://knuckles.team/kg/gitlab> a owl:Ontology ;
|
|
147
205
|
rdfs:label "GitLab DevOps Ontology" ;
|
|
148
206
|
rdfs:comment """GitLab source-control and CI/CD delivery model — groups, projects,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-api
|
|
3
|
-
Version: 26.
|
|
3
|
+
Version: 26.4.0
|
|
4
4
|
Summary: GitLab API + MCP Server + A2A Server
|
|
5
5
|
Author-email: Audel Rouhi <knucklessg1@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -22,7 +22,7 @@ Requires-Dist: agent-utilities[agent,logfire]>=1.0.0; extra == "agent"
|
|
|
22
22
|
Provides-Extra: gql
|
|
23
23
|
Requires-Dist: gql[requests]>=4.0.0; extra == "gql"
|
|
24
24
|
Provides-Extra: all
|
|
25
|
-
Requires-Dist: gitlab-api[agent,gql,logfire,mcp]>=26.
|
|
25
|
+
Requires-Dist: gitlab-api[agent,gql,logfire,mcp]>=26.4.0; extra == "all"
|
|
26
26
|
Provides-Extra: test
|
|
27
27
|
Requires-Dist: pytest-xdist>=3.6.0; extra == "test"
|
|
28
28
|
Requires-Dist: pytest; extra == "test"
|
|
@@ -52,7 +52,7 @@ Dynamic: license-file
|
|
|
52
52
|

|
|
53
53
|

|
|
54
54
|
|
|
55
|
-
*Version: 26.
|
|
55
|
+
*Version: 26.4.0*
|
|
56
56
|
|
|
57
57
|
> **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
|
|
58
58
|
> interfaces, the integrated A2A agent server, and guidance for provisioning the
|
|
@@ -116,6 +116,7 @@ _Auto-generated from the live MCP server — do not edit by hand._
|
|
|
116
116
|
| `gitlab_graphql` | `GRAPHQLTOOL` | Execute raw GraphQL queries and mutations natively on GitLab. |
|
|
117
117
|
| `gitlab_graphql_ops` | `GRAPHQL_OPSTOOL` | Run a typed GitLab GraphQL operation by name. |
|
|
118
118
|
| `gitlab_groups` | `GROUPSTOOL` | Manage gitlab groups operations. |
|
|
119
|
+
| `gitlab_ingest_pipelines` | `MISCTOOL` | Natively ingest GitLab CI pipeline runs (+ jobs) into epistemic-graph. |
|
|
119
120
|
| `gitlab_ingest_projects` | `MISCTOOL` | Natively ingest GitLab projects into epistemic-graph as typed :Project nodes. |
|
|
120
121
|
| `gitlab_instances` | `MISCTOOL` | List the configured GitLab tenants (CONCEPT:AU-KG.backend.declared-columns-so-schema). |
|
|
121
122
|
| `gitlab_issues` | `ISSUESTOOL` | Manage GitLab issues. |
|
|
@@ -346,7 +347,7 @@ _Auto-generated from the live MCP server — do not edit by hand._
|
|
|
346
347
|
|
|
347
348
|
</details>
|
|
348
349
|
|
|
349
|
-
|
|
350
|
+
_34 action-routed tool(s) (default) · 196 verbose 1:1 tool(s). Each is enabled unless its `<DOMAIN>TOOL` toggle is set false; `MCP_TOOL_MODE` selects the surface (`condensed` default · `verbose` 1:1 · `both`). Auto-generated — do not edit._
|
|
350
351
|
<!-- MCP-TOOLS-TABLE:END -->
|
|
351
352
|
|
|
352
353
|
Detailed tool schemas, parameter shapes, and validation constraints are preserved in [docs/mcp.md](docs/mcp.md).
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gitlab-api"
|
|
7
|
-
version = "26.
|
|
7
|
+
version = "26.4.0"
|
|
8
8
|
description = "GitLab API + MCP Server + A2A Server"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
classifiers = [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
|
|
@@ -21,7 +21,7 @@ text = "MIT"
|
|
|
21
21
|
mcp = [ "agent-utilities[mcp]>=1.0.0",]
|
|
22
22
|
agent = [ "agent-utilities[agent,logfire]>=1.0.0",]
|
|
23
23
|
gql = [ "gql[requests]>=4.0.0",]
|
|
24
|
-
all = [ "gitlab-api[mcp,agent,gql,logfire]>=26.
|
|
24
|
+
all = [ "gitlab-api[mcp,agent,gql,logfire]>=26.4.0",]
|
|
25
25
|
test = [
|
|
26
26
|
"pytest-xdist>=3.6.0", "pytest", "pytest-asyncio", "pytest-cov",]
|
|
27
27
|
|