gitlab-api 27.3.2__py3-none-any.whl → 27.3.4__py3-none-any.whl

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.
@@ -1,4 +1,4 @@
1
- connector: gitlab-api
1
+ connector: gitlab-mcp
2
2
  ontology_source: gitlab
3
3
  schema_version: '1'
4
4
  resources:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "algorithm": "agent-connector-sdk:mcp-tool-contract-compat:v2",
3
- "connector": "gitlab-api",
3
+ "connector": "gitlab-mcp",
4
4
  "schema_version": "1",
5
5
  "tools": {
6
6
  "gitlab_get_projects": "18b7c440b1165616ba8455535985becf3c14d643a22f40c34d4f321c736c9e06"
gitlab_api/gitlab_gql.py CHANGED
@@ -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 gql import Client, gql
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.transport = RequestsHTTPTransport(
124
- url=self.url,
125
- headers=headers,
126
- **self.tls_profile.requests_kwargs(),
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
- try:
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(
gitlab_api/kg_ingest.py CHANGED
@@ -23,7 +23,7 @@ from agent_connector_sdk.ingest import (
23
23
  current_ingest,
24
24
  )
25
25
 
26
- _BINDING = IngestBinding(connector="gitlab-api", stream="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"})
gitlab_api/mcp_server.py CHANGED
@@ -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.2"
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": "994ca982e951c529bbc3ae0206bbe94e0f5cc66d5ffb659c94e2d925a15af130",
4
+ "connector_manifest.yml": "ce8e95019a673f0268315c5ec472e7dc7ff3d924f5d3594a90f0f4e10a9ee11a",
5
5
  "gitlab_api/connectors/mcp_source_presets.json": "08401d486ad760f128203a710577be5be0a7c892acd6f46685077d19294b641e",
6
- "gitlab_api/connectors/tool_schema_fingerprints.json": "5e7928f836de01dc652c26eff3dbbdbde221f5cfe03b90b2d1479b83502c05ce",
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-api",
25
+ "connector": "gitlab-mcp",
26
26
  "kind": "ConnectorSourceAttestation",
27
27
  "live_certified": false,
28
28
  "mode": "offline-source",
@@ -1,5 +1,5 @@
1
1
  {
2
- "connector": "gitlab-api",
2
+ "connector": "gitlab-mcp",
3
3
  "sources": [
4
4
  {
5
5
  "source_id": "projects",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitlab-api
3
- Version: 27.3.2
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.5
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
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/gitlab-api)
51
46
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/gitlab-api)
52
47
 
53
- *Version: 27.3.2*
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
@@ -2,15 +2,15 @@ gitlab_api/__init__.py,sha256=AL1xZwPaU1Gzu53VrWYsDptCebPdfucmt3A6yStoPkc,2811
2
2
  gitlab_api/__main__.py,sha256=MlKO_lzO6h18UmnI-D20s27-Ej94gQn8Pa0EqOlwFOM,90
3
3
  gitlab_api/api_client.py,sha256=Id5iu7ID3fjc-sIAu3QhKyGCUCPy_uXxfZi5VxDkmUc,1087
4
4
  gitlab_api/auth.py,sha256=OOY6o1XWDG-ysfgUuOFb_W1bIb9Ub-734ezGVkSirJw,8919
5
- gitlab_api/connector_manifest.yml,sha256=mUypgulRxSm7w64CBrvpTg9cxm1f-2WclOLZJaFa8TA,13588
5
+ gitlab_api/connector_manifest.yml,sha256=zo6VAZpnPwJoMVxexHLn3H_z2ST101lKkPD04Qqe4Ro,13588
6
6
  gitlab_api/connector_prep.py,sha256=f_awZY5i9rvTLNde9iqVA1XLs_iqt5UmK4yLXPSO0Cw,60174
7
- gitlab_api/gitlab_gql.py,sha256=nBEU7K1RzLmZeZ1qD1U0-9NcRBwMu0xt_I0wDfRkGw8,106270
7
+ gitlab_api/gitlab_gql.py,sha256=1fqmsT82TeurA_SKgcnsflstQwYj5gWt1-Z1tTLmwls,105778
8
8
  gitlab_api/gitlab_input_models.py,sha256=35_ySA8E2GEbuGEjBtFeyiWiuqJMMEp3D2vRELiKwwE,115437
9
9
  gitlab_api/gitlab_response_models.py,sha256=m0jU8Xtwbq2y0AogCptVCslWlvi6SztLMDQZLSkefs8,150449
10
10
  gitlab_api/instances.py,sha256=RW7aKRvHWMQAQ5ZRRcjpKgpPgq_5YoncXt-_rC4ReXk,5423
11
- gitlab_api/kg_ingest.py,sha256=Verv5y0OtMYDXmzMoUD5EDUC8PZBiVfTddU5nND38b0,10750
11
+ gitlab_api/kg_ingest.py,sha256=tH-JDsyNUoU0X51ja9wNOxGTxgrfvg5wVyk78ju1AlU,10750
12
12
  gitlab_api/mcp_config.json,sha256=2OOXrwO1sDLyHQqpZwhvDHizPIe3by6YmK4KFE333gI,23
13
- gitlab_api/mcp_server.py,sha256=0Cq9QStZ_YDvciiSNArNJPwALsNWUQbdcE6ffSKRvE8,51850
13
+ gitlab_api/mcp_server.py,sha256=q8JtaqJ0GPYsix313CT4_CauD7TgNYFA5XkWmVebIFM,51850
14
14
  gitlab_api/api/__init__.py,sha256=MQblcZQoMdWyzpfnlAOEmyVlP7pbNcz_BQgAs5JINOI,27
15
15
  gitlab_api/api/api_client_base.py,sha256=0jdaCaV0tCxbNop6mdtq4nXgbrxEXu-ENoOxVmlaORE,8670
16
16
  gitlab_api/api/api_client_environments.py,sha256=2OQ88aStucaKO-VNc6NbXJxQdB761h0aJnPcVaHwBxo,26403
@@ -25,11 +25,11 @@ gitlab_api/api/api_client_users_groups.py,sha256=0tpy-Bxx9mP2imeIQGJMmzlpxSKGaKu
25
25
  gitlab_api/api/api_client_vulnerabilities.py,sha256=O2HNDopoaWlG0_wQNQvhZKNibFOOOzjXCOFzO8GzAZA,6168
26
26
  gitlab_api/connectors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  gitlab_api/connectors/mcp_source_presets.json,sha256=CEAdSGrXYPEoIDpxBXe-W-CnyJKs1vRmhQd9GSlLZB4,733
28
- gitlab_api/connectors/tool_schema_fingerprints.json,sha256=Xnko-DbeAdxlLCbv89u9veIh9c_gO5Cy0Uebg1AsBc4,235
28
+ gitlab_api/connectors/tool_schema_fingerprints.json,sha256=DPjk75SfxY0290uUmuno9ewl3GB9-xhtoese_Dco7cE,235
29
29
  gitlab_api/ontology/__init__.py,sha256=508Z6ZA4AHEfTFVfTLsenl0Lj_3sfI-MZG8icDzlOSo,568
30
- gitlab_api/ontology/certification.json,sha256=1Gfxi5Nu-EdYhtsHJYaHW2dqblLhclfVCzaWgM5Cs4w,1650
30
+ gitlab_api/ontology/certification.json,sha256=bMKifpxXWVF-EAjfPBonuSfUYb0gwbE4oSTSg7p5mgQ,1650
31
31
  gitlab_api/ontology/gitlab.ttl,sha256=qJvCWigVMhMF80HpMwegHGC3cG5pAtC8jBESD4BchXU,8028
32
- gitlab_api/ontology/ingest_sources.json,sha256=ss1dw8bXIQ4NJLlfji1mZhKTK9zsXxUwUR4zCu3BsPk,457
32
+ gitlab_api/ontology/ingest_sources.json,sha256=gVHZeJ9lHgp2P3nzPo8YbMNZa88AhAo51BusTWTMsnw,457
33
33
  gitlab_api/ontology/fixtures/records.json,sha256=XwQXggBTlBkz8Vs_RZdQdT9OjjTPHnhT_QMMEUM1a0A,553
34
34
  gitlab_api/ontology/mappings/source.yaml,sha256=FnIGtTh_fKl84C4PFRZPj-QfBrQTtZHQAIwp6fCpXn8,545
35
35
  gitlab_api/ontology/migrations/manifest.json,sha256=RCw8U98LQshm7vclWxiJuK2m-fnFElytZda1DcY2Kj4,116
@@ -50,7 +50,7 @@ gitlab_api/skills/gitlab-pipelines/SKILL.md,sha256=OuEk9sRMjJQQzCE2eZtRq9-wgtWRO
50
50
  gitlab_api/skills/gitlab-pipelines/WORKFLOW.md,sha256=6C61qo-byMs-7bvry3NKCtyzdRWOEjhC-mOG0ZJvsL0,4314
51
51
  gitlab_api/skills/gitlab-vulnerabilities/SKILL.md,sha256=acBODboYBGccTtuCAv5fv5cY_gEXedMSmepur3q9f9Q,5212
52
52
  gitlab_api/skills/gitlab-vulnerabilities/WORKFLOW.md,sha256=OKnEKILIrhsnnNQTu0MLSQAWR6jL2w6PuX6ztu0Nhdk,5041
53
- gitlab_api-27.3.2.dist-info/licenses/LICENSE,sha256=9eAPQLU4cIYQNvAIt6PNoiVQozaVoPRhMV_N7_UHG7A,1068
53
+ gitlab_api-27.3.4.dist-info/licenses/LICENSE,sha256=9eAPQLU4cIYQNvAIt6PNoiVQozaVoPRhMV_N7_UHG7A,1068
54
54
  scripts/check_import_safety.py,sha256=IjaMe7nWwK261tNPO8vmLdDy-skX1mpMACQKJhvp0ik,13503
55
55
  scripts/security_contract.py,sha256=3517zbvFsLEaWhZOiBwjb9lQiNvH8C-8HzlK4i4SBF8,25137
56
56
  scripts/security_sanitizer.py,sha256=W1LGgsq_uksvJ-oqwHIIcE4szNCCDAWA_PheBYSPnXg,9813
@@ -60,13 +60,14 @@ tests/conftest.py,sha256=srq80Qcj_VFRxMFCYZ6pXtEDfXO1PzVY-HEI4kmm29s,2090
60
60
  tests/test_api_wrapper.py,sha256=jUXDVR4lKOZLTvE3vAS8Xjkc4q57smd6MJr7u_eBU9U,5717
61
61
  tests/test_auth.py,sha256=dpiDD9Z5SfN6re59tb22PqkbsY8A8pWOBX9KuoXoTTc,4404
62
62
  tests/test_connector_prep.py,sha256=YgPoTq0nFqsZ4HA1Iq7F_jJlKxscePvgQJREZB3bczk,10770
63
+ tests/test_fleet_name.py,sha256=HCJLmN-n4mMy--HawJ0x1BYqtUlBIh4WDMcsxYEkwNY,1723
63
64
  tests/test_gitlab_a2a_validation.py,sha256=Wxu7zSIxnmT5bOg-BwFvR6z9TprSzObG5mIEC4NBwwM,5130
64
65
  tests/test_gitlab_api_brute_force_coverage.py,sha256=yS3LoPE6JCC2jcI2agYmNI8kpSBK9jAZsmGnrYq-mPU,14294
65
- tests/test_gitlab_gql.py,sha256=UVMGoYCkaB3EjyGouADp98AYzkyRv7iR-NweHhMrwtQ,11198
66
+ tests/test_gitlab_gql.py,sha256=jgIT-ypNSRlScOZGYvJ9eR9-Tq3PwrpK5_VwBU-eXs4,12336
66
67
  tests/test_gitlab_mcp_validation.py,sha256=Ma2e3ZchIVUHF0OJPPAW1DRYEG6X-I6dUFRpLE31Rwk,2423
67
68
  tests/test_gitlab_models.py,sha256=9buJwE0VmioDXRcKlCfcKYgg6PdQnx7HvDRBPnMC3Ak,542220
68
69
  tests/test_identity_context_scoping.py,sha256=wY_xb37E7qd91F5NNhf0g2Hv1uRyrM0wnCO_6WEEcW4,2269
69
- tests/test_ingest_sources.py,sha256=XCPTezZIdauzQdrIR9P5KiXG9ZuB1YfvIXGVuAo6Hks,1347
70
+ tests/test_ingest_sources.py,sha256=x2RItPOvlnExwOFJStkTfgwFoVU4Pl6gSC5zYpKlxJI,1347
70
71
  tests/test_init_dynamics.py,sha256=fsfRhuT6yCY91JXoHd7gbHfuPjZfLW0A7aJgyXptL6E,1693
71
72
  tests/test_instances.py,sha256=C8csQIJPv1Wdbh4Le2JBg1pM7iFo5rYfL-vp_aGwOtA,4167
72
73
  tests/test_kg_ingest.py,sha256=sgo6KNYKs7xbvbmKZDOXpHDhb3YkXvxjWsIELpxcAGI,7633
@@ -76,8 +77,8 @@ tests/test_startup.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
76
77
  tests/test_tool_modes.py,sha256=aiAaQE0yXp9SKGz9BVgik4HIjE5kar8FBD9uVOK5pwA,721
77
78
  tests/test_verify_agent.py,sha256=XdW2NtR5643rgjDYLu6RajWu-4wqrZjCUsRehfsKCqQ,6465
78
79
  tests/verify_a2a_queries.py,sha256=JMKBexwzo6c59NpVrBfYgW4HnmSG8-qqfdeku5YFtwc,3613
79
- gitlab_api-27.3.2.dist-info/METADATA,sha256=umVBzzDghYU6_Ey2fpEuH4PPnDm1BiMgxKBcNXZ_cUs,40527
80
- gitlab_api-27.3.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
81
- gitlab_api-27.3.2.dist-info/entry_points.txt,sha256=-FUZqPa8FPHty3mGFhNlFRajrMh6fgSgV8fcxAI1KTA,366
82
- gitlab_api-27.3.2.dist-info/top_level.txt,sha256=fJ-T_zkuttbq8Kn1dq0mBvyjtKqPdMic01oCdbzxh_k,48
83
- gitlab_api-27.3.2.dist-info/RECORD,,
80
+ gitlab_api-27.3.4.dist-info/METADATA,sha256=WlK6p0eiUr_yGKrfFCYqJ3NmU644MMGBq2CV_0MuR7I,40299
81
+ gitlab_api-27.3.4.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
82
+ gitlab_api-27.3.4.dist-info/entry_points.txt,sha256=Vtq_7rahKslu8zMAoC7Kqn_BsdnPgsuVvR-5u_MpJRs,423
83
+ gitlab_api-27.3.4.dist-info/top_level.txt,sha256=fJ-T_zkuttbq8Kn1dq0mBvyjtKqPdMic01oCdbzxh_k,48
84
+ gitlab_api-27.3.4.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (84.0.0)
2
+ Generator: setuptools (84.2.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,3 +1,6 @@
1
+ [agent_connector_sdk.connector]
2
+ gitlab-mcp = gitlab_api
3
+
1
4
  [agent_connector_sdk.ontology_providers]
2
5
  gitlab-api = gitlab_api.ontology
3
6
 
@@ -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
tests/test_gitlab_gql.py CHANGED
@@ -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("gitlab_api.gitlab_gql.Client") as mock_client_cls:
15
- mock_client = mock_client_cls.return_value
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
- # Test error returned in execute response
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(method: Any, common_kwargs: dict[str, Any]) -> dict[str, Any]:
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-api"
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")