gitlab-api 27.3.2__tar.gz → 27.3.4__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-27.3.2/gitlab_api.egg-info → gitlab_api-27.3.4}/PKG-INFO +3 -8
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/README.md +1 -1
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/connector_manifest.yml +1 -1
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/connectors/tool_schema_fingerprints.json +1 -1
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/gitlab_gql.py +8 -18
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/kg_ingest.py +1 -1
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/mcp_server.py +1 -1
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/certification.json +3 -3
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/ingest_sources.json +1 -1
- {gitlab_api-27.3.2 → gitlab_api-27.3.4/gitlab_api.egg-info}/PKG-INFO +3 -8
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api.egg-info/SOURCES.txt +1 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api.egg-info/entry_points.txt +3 -0
- gitlab_api-27.3.4/gitlab_api.egg-info/requires.txt +12 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/pyproject.toml +8 -5
- gitlab_api-27.3.4/tests/test_fleet_name.py +50 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_gitlab_gql.py +42 -10
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_ingest_sources.py +1 -1
- gitlab_api-27.3.2/gitlab_api.egg-info/requires.txt +0 -18
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/LICENSE +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/MANIFEST.in +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/__main__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_base.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_environments.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_issues.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_merge_requests.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_other.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_pipelines.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_projects.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_repositories.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_system.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_users_groups.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api/api_client_vulnerabilities.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/api_client.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/auth.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/connector_prep.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/connectors/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/connectors/mcp_source_presets.json +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/gitlab_input_models.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/gitlab_response_models.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/instances.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/mcp_config.json +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/fixtures/records.json +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/gitlab.ttl +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/mappings/source.yaml +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/migrations/manifest.json +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/ontology/shapes/connector.shacl.ttl +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/prompts/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/prompts/devops_specialist.json +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-api-operations/SKILL.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-api-operations/agents/openai.yaml +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-api-operations/references/catalog.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-issues/SKILL.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-issues/WORKFLOW.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-create/SKILL.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-create/WORKFLOW.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-review/SKILL.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-review/WORKFLOW.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-pipelines/SKILL.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-pipelines/WORKFLOW.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-vulnerabilities/SKILL.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-vulnerabilities/WORKFLOW.md +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api.egg-info/dependency_links.txt +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api.egg-info/top_level.txt +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/requirements.txt +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/scripts/check_import_safety.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/scripts/security_contract.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/scripts/security_sanitizer.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/scripts/verify_api_integration.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/setup.cfg +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/__init__.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/conftest.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_api_wrapper.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_auth.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_connector_prep.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_gitlab_a2a_validation.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_gitlab_api_brute_force_coverage.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_gitlab_mcp_validation.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_gitlab_models.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_identity_context_scoping.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_init_dynamics.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_instances.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_kg_ingest.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_mock_coverage.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_security_sanitizer.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_startup.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_tool_modes.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/test_verify_agent.py +0 -0
- {gitlab_api-27.3.2 → gitlab_api-27.3.4}/tests/verify_a2a_queries.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-api
|
|
3
|
-
Version: 27.3.
|
|
3
|
+
Version: 27.3.4
|
|
4
4
|
Summary: GitLab API + MCP Server
|
|
5
5
|
Author-email: Project Maintainers <maintainers@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,15 +12,10 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.3.
|
|
15
|
+
Requires-Dist: agent-connector-sdk[graphql,mcp]<1.0.0,>=0.3.13
|
|
16
16
|
Requires-Dist: python-dotenv>=1.2.4
|
|
17
|
-
Requires-Dist: gql[requests]>=4.4.0
|
|
18
17
|
Provides-Extra: mcp
|
|
19
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.3.5; extra == "mcp"
|
|
20
|
-
Provides-Extra: gql
|
|
21
|
-
Requires-Dist: gql[requests]>=4.4.0; extra == "gql"
|
|
22
18
|
Provides-Extra: all
|
|
23
|
-
Requires-Dist: gitlab-api[gql,mcp]>=27.2.0; extra == "all"
|
|
24
19
|
Provides-Extra: test
|
|
25
20
|
Requires-Dist: pytest-xdist>=3.8.0; extra == "test"
|
|
26
21
|
Requires-Dist: pytest>=9.1.1; extra == "test"
|
|
@@ -50,7 +45,7 @@ Dynamic: license-file
|
|
|
50
45
|

|
|
51
46
|

|
|
52
47
|
|
|
53
|
-
*Version: 27.3.
|
|
48
|
+
*Version: 27.3.4*
|
|
54
49
|
|
|
55
50
|
> **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
|
|
56
51
|
> backing GitLab instance are maintained in the
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|

|
|
21
21
|

|
|
22
22
|
|
|
23
|
-
*Version: 27.3.
|
|
23
|
+
*Version: 27.3.4*
|
|
24
24
|
|
|
25
25
|
> **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
|
|
26
26
|
> backing GitLab instance are maintained in the
|
|
@@ -12,8 +12,7 @@ from agent_connector_sdk.exceptions import (
|
|
|
12
12
|
)
|
|
13
13
|
from agent_connector_sdk.tls.profile import ResolvedTLSProfile
|
|
14
14
|
from agent_connector_sdk.tls.resolve import resolve_tls_profile
|
|
15
|
-
from
|
|
16
|
-
from gql.transport.requests import RequestsHTTPTransport
|
|
15
|
+
from agent_connector_sdk.transports.graphql import GraphQLAuth, GraphQLClient
|
|
17
16
|
|
|
18
17
|
from gitlab_api.gitlab_input_models import (
|
|
19
18
|
BranchModel,
|
|
@@ -120,12 +119,13 @@ class GraphQL:
|
|
|
120
119
|
|
|
121
120
|
headers = {"Authorization": f"Bearer {token}"}
|
|
122
121
|
self.headers = headers
|
|
123
|
-
self.
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
self.client = GraphQLClient(
|
|
123
|
+
self.url,
|
|
124
|
+
auth=GraphQLAuth.bearer(token),
|
|
125
|
+
tls_profile=self.tls_profile,
|
|
126
|
+
tls_service="gitlab",
|
|
127
|
+
fetch_schema=True,
|
|
127
128
|
)
|
|
128
|
-
self.client = Client(transport=self.transport, fetch_schema_from_transport=True)
|
|
129
129
|
|
|
130
130
|
@require_auth
|
|
131
131
|
def execute_gql(
|
|
@@ -148,17 +148,7 @@ class GraphQL:
|
|
|
148
148
|
Raises:
|
|
149
149
|
ParameterError: If the query execution fails or returns errors.
|
|
150
150
|
"""
|
|
151
|
-
|
|
152
|
-
query = gql(query_str)
|
|
153
|
-
result = self.client.execute(
|
|
154
|
-
query, variable_values=variables, operation_name=operation_name
|
|
155
|
-
)
|
|
156
|
-
if "errors" in result:
|
|
157
|
-
raise ParameterError(f"GraphQL errors: {result['errors']}")
|
|
158
|
-
return result
|
|
159
|
-
except Exception as e:
|
|
160
|
-
logging.error("GraphQL execution failed: error_type=%s", type(e).__name__)
|
|
161
|
-
raise ParameterError(f"Query execution failed: {type(e).__name__}") from e
|
|
151
|
+
return self.client.execute(query_str, variables, operation_name)
|
|
162
152
|
|
|
163
153
|
@require_auth
|
|
164
154
|
def get_branches(
|
|
@@ -23,7 +23,7 @@ from agent_connector_sdk.ingest import (
|
|
|
23
23
|
current_ingest,
|
|
24
24
|
)
|
|
25
25
|
|
|
26
|
-
_BINDING = IngestBinding(connector="gitlab-
|
|
26
|
+
_BINDING = IngestBinding(connector="gitlab-mcp", stream="gitlab")
|
|
27
27
|
|
|
28
28
|
_ENTITY_RESERVED_KEYS = frozenset({"id", "node_type"})
|
|
29
29
|
_RELATIONSHIP_RESERVED_KEYS = frozenset({"source", "target", "relationship"})
|
|
@@ -35,7 +35,7 @@ from agent_connector_sdk.mcp.tool_surface import register_tool_surface
|
|
|
35
35
|
from gitlab_api.api_client import Api
|
|
36
36
|
from gitlab_api.auth import get_client
|
|
37
37
|
|
|
38
|
-
__version__ = "27.3.
|
|
38
|
+
__version__ = "27.3.4"
|
|
39
39
|
print(f"Gitlab MCP v{__version__}", file=sys.stderr)
|
|
40
40
|
|
|
41
41
|
logger = get_logger(name="mcp_server")
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"api_version": "arbora.io/v1",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"connector_manifest.yml": "
|
|
4
|
+
"connector_manifest.yml": "ce8e95019a673f0268315c5ec472e7dc7ff3d924f5d3594a90f0f4e10a9ee11a",
|
|
5
5
|
"gitlab_api/connectors/mcp_source_presets.json": "08401d486ad760f128203a710577be5be0a7c892acd6f46685077d19294b641e",
|
|
6
|
-
"gitlab_api/connectors/tool_schema_fingerprints.json": "
|
|
6
|
+
"gitlab_api/connectors/tool_schema_fingerprints.json": "0cf8e4ef949fc58d36f74b949ae9e8f5ec25dc607dfb186da1eb1efc3728edc1",
|
|
7
7
|
"gitlab_api/ontology/fixtures/records.json": "5f0417820053941933f15b3f459750753f4e8e34cf1e7853fd030c1143356b40",
|
|
8
8
|
"gitlab_api/ontology/gitlab.ttl": "19fa64000d2e51c60c53074b1fae4ab98aed85318337b5a2199f4837ae9f3fc0",
|
|
9
9
|
"gitlab_api/ontology/mappings/source.yaml": "167206b5387f7ca97ce02e0f15164f8fe41f06b413b591d0008c29e9f0a95e7f",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"bundle_schema": "2",
|
|
23
23
|
"epistemic_graph": ">=2.27.0,<3"
|
|
24
24
|
},
|
|
25
|
-
"connector": "gitlab-
|
|
25
|
+
"connector": "gitlab-mcp",
|
|
26
26
|
"kind": "ConnectorSourceAttestation",
|
|
27
27
|
"live_certified": false,
|
|
28
28
|
"mode": "offline-source",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gitlab-api
|
|
3
|
-
Version: 27.3.
|
|
3
|
+
Version: 27.3.4
|
|
4
4
|
Summary: GitLab API + MCP Server
|
|
5
5
|
Author-email: Project Maintainers <maintainers@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,15 +12,10 @@ Classifier: Programming Language :: Python :: 3
|
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
License-File: LICENSE
|
|
15
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.3.
|
|
15
|
+
Requires-Dist: agent-connector-sdk[graphql,mcp]<1.0.0,>=0.3.13
|
|
16
16
|
Requires-Dist: python-dotenv>=1.2.4
|
|
17
|
-
Requires-Dist: gql[requests]>=4.4.0
|
|
18
17
|
Provides-Extra: mcp
|
|
19
|
-
Requires-Dist: agent-connector-sdk[mcp]<1.0.0,>=0.3.5; extra == "mcp"
|
|
20
|
-
Provides-Extra: gql
|
|
21
|
-
Requires-Dist: gql[requests]>=4.4.0; extra == "gql"
|
|
22
18
|
Provides-Extra: all
|
|
23
|
-
Requires-Dist: gitlab-api[gql,mcp]>=27.2.0; extra == "all"
|
|
24
19
|
Provides-Extra: test
|
|
25
20
|
Requires-Dist: pytest-xdist>=3.8.0; extra == "test"
|
|
26
21
|
Requires-Dist: pytest>=9.1.1; extra == "test"
|
|
@@ -50,7 +45,7 @@ Dynamic: license-file
|
|
|
50
45
|

|
|
51
46
|

|
|
52
47
|
|
|
53
|
-
*Version: 27.3.
|
|
48
|
+
*Version: 27.3.4*
|
|
54
49
|
|
|
55
50
|
> **Documentation** — Installation, deployment, usage across the API, CLI, and MCP
|
|
56
51
|
> backing GitLab instance are maintained in the
|
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gitlab-api"
|
|
7
|
-
version = "27.3.
|
|
7
|
+
version = "27.3.4"
|
|
8
8
|
description = "GitLab API + MCP 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",]
|
|
11
11
|
requires-python = ">=3.12"
|
|
12
|
-
dependencies = [ "agent-connector-sdk[mcp]>=0.3.
|
|
12
|
+
dependencies = [ "agent-connector-sdk[mcp,graphql]>=0.3.13,<1.0.0", "python-dotenv>=1.2.4",]
|
|
13
13
|
[[project.authors]]
|
|
14
14
|
name = "Project Maintainers"
|
|
15
15
|
email = "maintainers@users.noreply.github.com"
|
|
@@ -18,9 +18,8 @@ email = "maintainers@users.noreply.github.com"
|
|
|
18
18
|
text = "MIT"
|
|
19
19
|
|
|
20
20
|
[project.optional-dependencies]
|
|
21
|
-
mcp = [
|
|
22
|
-
|
|
23
|
-
all = [ "gitlab-api[mcp,gql]>=27.2.0",]
|
|
21
|
+
mcp = []
|
|
22
|
+
all = []
|
|
24
23
|
test = [
|
|
25
24
|
"pytest-xdist>=3.8.0", "pytest>=9.1.1", "pytest-asyncio>=1.4.0", "pytest-cov>=7.1.0",]
|
|
26
25
|
|
|
@@ -39,6 +38,10 @@ gitlab-api = "gitlab_api.connectors"
|
|
|
39
38
|
[project.entry-points."agent_connector_sdk.prompt_providers"]
|
|
40
39
|
gitlab-api = "gitlab_api.prompts"
|
|
41
40
|
|
|
41
|
+
# The one declared connector identity: the fleet name (SDK-CONNECTOR-CONTROL-R071).
|
|
42
|
+
[project.entry-points."agent_connector_sdk.connector"]
|
|
43
|
+
gitlab-mcp = "gitlab_api"
|
|
44
|
+
|
|
42
45
|
[tool.uv.workspace]
|
|
43
46
|
members = ["."]
|
|
44
47
|
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""CONN-GITLAB-API-R002: the connector is filed under its fleet name, gitlab-mcp."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import ast
|
|
6
|
+
import json
|
|
7
|
+
import re
|
|
8
|
+
import tomllib
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
14
|
+
PACKAGE = ROOT / "gitlab_api"
|
|
15
|
+
FLEET = "gitlab-mcp"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _call_connectors(path: Path) -> list[str]:
|
|
19
|
+
names = []
|
|
20
|
+
for node in ast.walk(ast.parse(path.read_text(encoding="utf-8"))):
|
|
21
|
+
if isinstance(node, ast.Call) and getattr(
|
|
22
|
+
node.func, "id", getattr(node.func, "attr", "")
|
|
23
|
+
) in {
|
|
24
|
+
"IngestBinding",
|
|
25
|
+
"ConnectorContent",
|
|
26
|
+
}:
|
|
27
|
+
names += [
|
|
28
|
+
str(k.value.value)
|
|
29
|
+
for k in node.keywords
|
|
30
|
+
if k.arg == "connector" and isinstance(k.value, ast.Constant)
|
|
31
|
+
]
|
|
32
|
+
return names
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.spec("CONN-GITLAB-API-R002")
|
|
36
|
+
def test_connector_name_is_the_fleet_name() -> None:
|
|
37
|
+
pyproject = tomllib.loads((ROOT / "pyproject.toml").read_text(encoding="utf-8"))
|
|
38
|
+
assert pyproject["project"]["entry-points"]["agent_connector_sdk.connector"] == {
|
|
39
|
+
FLEET: "gitlab_api"
|
|
40
|
+
}
|
|
41
|
+
manifest = (PACKAGE / "connector_manifest.yml").read_text(encoding="utf-8")
|
|
42
|
+
match = re.search(r'^\s*"?connector"?\s*:\s*"?([^"\s,]+)', manifest, re.MULTILINE)
|
|
43
|
+
assert match is not None and match.group(1) == FLEET
|
|
44
|
+
fingerprints = PACKAGE / "connectors" / "tool_schema_fingerprints.json"
|
|
45
|
+
if fingerprints.is_file():
|
|
46
|
+
assert (
|
|
47
|
+
json.loads(fingerprints.read_text(encoding="utf-8"))["connector"] == FLEET
|
|
48
|
+
)
|
|
49
|
+
for module in sorted(PACKAGE.glob("*.py")):
|
|
50
|
+
assert all(name == FLEET for name in _call_connectors(module)), module.name
|
|
@@ -5,14 +5,18 @@ from unittest.mock import MagicMock, patch
|
|
|
5
5
|
|
|
6
6
|
import pytest
|
|
7
7
|
from agent_connector_sdk.exceptions import MissingParameterError, ParameterError
|
|
8
|
+
from agent_connector_sdk.transports.graphql import GraphQLExecutionError
|
|
8
9
|
|
|
9
10
|
from gitlab_api.gitlab_gql import GraphQL
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
@pytest.fixture
|
|
13
14
|
def mock_gql_client():
|
|
14
|
-
with patch(
|
|
15
|
-
|
|
15
|
+
with patch(
|
|
16
|
+
"agent_connector_sdk.transports.graphql.GraphQLClient.execute"
|
|
17
|
+
) as mock_execute:
|
|
18
|
+
mock_client = MagicMock()
|
|
19
|
+
mock_client.execute = mock_execute
|
|
16
20
|
# Mock the execute method to return a standard structure
|
|
17
21
|
mock_client.execute.return_value = {
|
|
18
22
|
"project": {
|
|
@@ -208,17 +212,43 @@ def test_graphql_init_exceptions():
|
|
|
208
212
|
def test_graphql_execute_exceptions(mock_gql_client):
|
|
209
213
|
gql_client = GraphQL(url="http://test", token="test")
|
|
210
214
|
|
|
211
|
-
|
|
212
|
-
mock_gql_client.execute.return_value = {"errors": ["some error"]}
|
|
213
|
-
with pytest.raises(ParameterError, match="Query execution failed: ParameterError"):
|
|
214
|
-
gql_client.execute_gql("query { test }")
|
|
215
|
-
|
|
216
|
-
# Test exception raised by client execute
|
|
217
|
-
mock_gql_client.execute.side_effect = Exception("network error")
|
|
215
|
+
mock_gql_client.execute.side_effect = GraphQLExecutionError(Exception("x"))
|
|
218
216
|
with pytest.raises(ParameterError, match="Query execution failed: Exception"):
|
|
219
217
|
gql_client.execute_gql("query { test }")
|
|
220
218
|
|
|
221
219
|
|
|
220
|
+
@pytest.mark.spec("CONN-GITLAB-API-R003")
|
|
221
|
+
def test_wrapper_delegates_to_shared_graphql_client():
|
|
222
|
+
tls = MagicMock()
|
|
223
|
+
with patch("gitlab_api.gitlab_gql.GraphQLClient") as cls:
|
|
224
|
+
cls.return_value.execute.return_value = {"ok": 1}
|
|
225
|
+
g = GraphQL(url="https://gl.example/", token="tok", tls_profile=tls)
|
|
226
|
+
assert g.execute_gql("query { x }", {"a": 1}, "X") == {"ok": 1}
|
|
227
|
+
args, kwargs = cls.call_args
|
|
228
|
+
assert args == ("https://gl.example/api/graphql",)
|
|
229
|
+
assert kwargs["auth"].headers() == {"Authorization": "Bearer tok"}
|
|
230
|
+
assert kwargs["tls_profile"] is tls
|
|
231
|
+
assert kwargs["tls_service"] == "gitlab"
|
|
232
|
+
assert kwargs["fetch_schema"] is True
|
|
233
|
+
assert g.headers == {"Authorization": "Bearer tok"}
|
|
234
|
+
cls.return_value.execute.assert_called_once_with("query { x }", {"a": 1}, "X")
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
@pytest.mark.spec("CONN-GITLAB-API-R003")
|
|
238
|
+
def test_graphql_declared_only_via_sdk_extra():
|
|
239
|
+
import tomllib
|
|
240
|
+
from pathlib import Path
|
|
241
|
+
|
|
242
|
+
data = tomllib.loads(
|
|
243
|
+
(Path(__file__).resolve().parents[1] / "pyproject.toml").read_text()
|
|
244
|
+
)
|
|
245
|
+
blob = str(data["project"]["dependencies"]) + str(
|
|
246
|
+
data["project"]["optional-dependencies"]
|
|
247
|
+
)
|
|
248
|
+
assert "graphql]" in blob or "graphql," in blob
|
|
249
|
+
assert "gql" not in blob.replace("graphql", "")
|
|
250
|
+
|
|
251
|
+
|
|
222
252
|
def test_graphql_parameter_errors(mock_gql_client):
|
|
223
253
|
gql_client = GraphQL(url="http://test", token="test")
|
|
224
254
|
with pytest.raises(ParameterError, match="Cannot provide more than 50 full paths"):
|
|
@@ -289,7 +319,9 @@ def _build_graphql_brute_force_kwargs() -> dict[str, Any]:
|
|
|
289
319
|
}
|
|
290
320
|
|
|
291
321
|
|
|
292
|
-
def _kwargs_for_graphql_method(
|
|
322
|
+
def _kwargs_for_graphql_method(
|
|
323
|
+
method: Any, common_kwargs: dict[str, Any]
|
|
324
|
+
) -> dict[str, Any]:
|
|
293
325
|
if sys.version_info >= (3, 14):
|
|
294
326
|
# Annotations are lazy on 3.14; the module-level ProjectModel patch above
|
|
295
327
|
# would otherwise be evaluated inside `X | None`.
|
|
@@ -18,7 +18,7 @@ from gitlab_api.api_client import Api
|
|
|
18
18
|
def test_declares_ingestible_sources() -> None:
|
|
19
19
|
declaration = load_ingest_sources(Path(gitlab_api.__file__).parent)
|
|
20
20
|
assert declaration is not None
|
|
21
|
-
assert declaration.connector == "gitlab-
|
|
21
|
+
assert declaration.connector == "gitlab-mcp"
|
|
22
22
|
source = declaration.source("projects")
|
|
23
23
|
assert source is not None and source.record_type == "Project"
|
|
24
24
|
prefix = operation_prefix("gitlab-api")
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
agent-connector-sdk[mcp]<1.0.0,>=0.3.5
|
|
2
|
-
python-dotenv>=1.2.4
|
|
3
|
-
gql[requests]>=4.4.0
|
|
4
|
-
|
|
5
|
-
[all]
|
|
6
|
-
gitlab-api[gql,mcp]>=27.2.0
|
|
7
|
-
|
|
8
|
-
[gql]
|
|
9
|
-
gql[requests]>=4.4.0
|
|
10
|
-
|
|
11
|
-
[mcp]
|
|
12
|
-
agent-connector-sdk[mcp]<1.0.0,>=0.3.5
|
|
13
|
-
|
|
14
|
-
[test]
|
|
15
|
-
pytest-xdist>=3.8.0
|
|
16
|
-
pytest>=9.1.1
|
|
17
|
-
pytest-asyncio>=1.4.0
|
|
18
|
-
pytest-cov>=7.1.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-api-operations/agents/openai.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-create/SKILL.md
RENAMED
|
File without changes
|
{gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-create/WORKFLOW.md
RENAMED
|
File without changes
|
{gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-review/SKILL.md
RENAMED
|
File without changes
|
{gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-merge-request-review/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{gitlab_api-27.3.2 → gitlab_api-27.3.4}/gitlab_api/skills/gitlab-vulnerabilities/WORKFLOW.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|