github-agent 1.0.1__tar.gz → 1.0.3__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.
Files changed (69) hide show
  1. {github_agent-1.0.1 → github_agent-1.0.3}/PKG-INFO +8 -3
  2. {github_agent-1.0.1 → github_agent-1.0.3}/README.md +6 -2
  3. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/agent_server.py +1 -1
  4. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/auth.py +29 -0
  5. github_agent-1.0.3/github_agent/github_gql.py +88 -0
  6. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp_server.py +80 -0
  7. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent.egg-info/PKG-INFO +8 -3
  8. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent.egg-info/SOURCES.txt +2 -0
  9. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent.egg-info/requires.txt +1 -0
  10. {github_agent-1.0.1 → github_agent-1.0.3}/pyproject.toml +2 -2
  11. github_agent-1.0.3/tests/test_github_gql.py +35 -0
  12. {github_agent-1.0.1 → github_agent-1.0.3}/LICENSE +0 -0
  13. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/__init__.py +0 -0
  14. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/__main__.py +0 -0
  15. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/__init__.py +0 -0
  16. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_base.py +0 -0
  17. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_branches.py +0 -0
  18. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_commits.py +0 -0
  19. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_contents.py +0 -0
  20. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_issues.py +0 -0
  21. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_orgs.py +0 -0
  22. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_pages.py +0 -0
  23. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_pulls.py +0 -0
  24. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_releases.py +0 -0
  25. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_repos.py +0 -0
  26. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_search.py +0 -0
  27. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api/api_client_workflows.py +0 -0
  28. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/api_client.py +0 -0
  29. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/github_input_models.py +0 -0
  30. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/github_response_models.py +0 -0
  31. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/__init__.py +0 -0
  32. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_action.py +0 -0
  33. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_branch.py +0 -0
  34. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_collaborator.py +0 -0
  35. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_commit.py +0 -0
  36. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_content.py +0 -0
  37. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_issue.py +0 -0
  38. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_org.py +0 -0
  39. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_pull.py +0 -0
  40. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_release.py +0 -0
  41. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_repo.py +0 -0
  42. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp/mcp_search.py +0 -0
  43. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/mcp_config.json +0 -0
  44. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/prompts/__init__.py +0 -0
  45. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/prompts/main_agent.json +0 -0
  46. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/skills/__init__.py +0 -0
  47. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent/skills/github-starter/SKILL.md +0 -0
  48. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent.egg-info/dependency_links.txt +0 -0
  49. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent.egg-info/entry_points.txt +0 -0
  50. {github_agent-1.0.1 → github_agent-1.0.3}/github_agent.egg-info/top_level.txt +0 -0
  51. {github_agent-1.0.1 → github_agent-1.0.3}/scripts/security_sanitizer.py +0 -0
  52. {github_agent-1.0.1 → github_agent-1.0.3}/scripts/validate_a2a_agent.py +0 -0
  53. {github_agent-1.0.1 → github_agent-1.0.3}/scripts/verify_api_integration.py +0 -0
  54. {github_agent-1.0.1 → github_agent-1.0.3}/setup.cfg +0 -0
  55. {github_agent-1.0.1 → github_agent-1.0.3}/tests/conftest.py +0 -0
  56. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_action_discovery.py +0 -0
  57. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_api_client_endpoints.py +0 -0
  58. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_api_validation.py +0 -0
  59. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_auth_client_edge_cases.py +0 -0
  60. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_concept_parity.py +0 -0
  61. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_github_agent_api_brute_force_coverage.py +0 -0
  62. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_github_agent_brute_force_coverage.py +0 -0
  63. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_hardening.py +0 -0
  64. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_init_dynamics.py +0 -0
  65. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_mcp_coverage.py +0 -0
  66. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_model_fields.py +0 -0
  67. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_org_crud.py +0 -0
  68. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_pages.py +0 -0
  69. {github_agent-1.0.1 → github_agent-1.0.3}/tests/test_startup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-agent
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: GitHub Agent for MCP
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -13,6 +13,7 @@ Requires-Python: <3.15,>=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: agent-utilities[mcp]>=1.0.0
16
+ Requires-Dist: gql[requests]>=4.0.0
16
17
  Provides-Extra: mcp
17
18
  Requires-Dist: agent-utilities[mcp]>=1.0.0; extra == "mcp"
18
19
  Provides-Extra: agent
@@ -47,7 +48,7 @@ Dynamic: license-file
47
48
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/github-agent)
48
49
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/github-agent)
49
50
 
50
- *Version: 1.0.1*
51
+ *Version: 1.0.2*
51
52
 
52
53
  > **Documentation** — Installation, deployment, and usage across the MCP, API, and
53
54
  > CLI interfaces, including the integrated A2A agent server, are maintained in the
@@ -241,6 +242,7 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
241
242
  "GITHUB_TOKEN": "your_github_token_here",
242
243
  "GITHUB_URL": "https://api.github.com",
243
244
  "GITHUB_VERIFY": "True",
245
+ "GRAPHQLTOOL": "True",
244
246
  "ISSUETOOL": "True",
245
247
  "ORGTOOL": "True",
246
248
  "PULLTOOL": "True",
@@ -285,6 +287,7 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
285
287
  "GITHUB_TOKEN": "your_github_token_here",
286
288
  "GITHUB_URL": "https://api.github.com",
287
289
  "GITHUB_VERIFY": "True",
290
+ "GRAPHQLTOOL": "True",
288
291
  "ISSUETOOL": "True",
289
292
  "ORGTOOL": "True",
290
293
  "PULLTOOL": "True",
@@ -330,6 +333,7 @@ docker run -d \
330
333
  -e GITHUB_TOKEN=your_github_token_here \
331
334
  -e GITHUB_URL=https://api.github.com \
332
335
  -e GITHUB_VERIFY=True \
336
+ -e GRAPHQLTOOL=True \
333
337
  -e ISSUETOOL=True \
334
338
  -e ORGTOOL=True \
335
339
  -e PULLTOOL=True \
@@ -392,6 +396,7 @@ consumed from a **remote deployment**. The
392
396
  | `COLLABORATORTOOL` | `True` | |
393
397
  | `COMMITTOOL` | `True` | |
394
398
  | `CONTENTTOOL` | `True` | |
399
+ | `GRAPHQLTOOL` | `True` | |
395
400
  | `ISSUETOOL` | `True` | |
396
401
  | `ORGTOOL` | `True` | |
397
402
  | `PULLTOOL` | `True` | |
@@ -416,7 +421,7 @@ consumed from a **remote deployment**. The
416
421
  | `MODEL_ID` | `gpt-4o` | Model id for the agent |
417
422
  | `ENABLE_WEB_UI` | `True` | Serve the AG-UI web interface |
418
423
 
419
- _31 package + 12 inherited variable(s). Auto-generated from `.env.example` + the shared agent-utilities set — do not edit._
424
+ _32 package + 12 inherited variable(s). Auto-generated from `.env.example` + the shared agent-utilities set — do not edit._
420
425
  <!-- ENV-VARS-TABLE:END -->
421
426
 
422
427
 
@@ -20,7 +20,7 @@
20
20
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/github-agent)
21
21
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/github-agent)
22
22
 
23
- *Version: 1.0.1*
23
+ *Version: 1.0.2*
24
24
 
25
25
  > **Documentation** — Installation, deployment, and usage across the MCP, API, and
26
26
  > CLI interfaces, including the integrated A2A agent server, are maintained in the
@@ -214,6 +214,7 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
214
214
  "GITHUB_TOKEN": "your_github_token_here",
215
215
  "GITHUB_URL": "https://api.github.com",
216
216
  "GITHUB_VERIFY": "True",
217
+ "GRAPHQLTOOL": "True",
217
218
  "ISSUETOOL": "True",
218
219
  "ORGTOOL": "True",
219
220
  "PULLTOOL": "True",
@@ -258,6 +259,7 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
258
259
  "GITHUB_TOKEN": "your_github_token_here",
259
260
  "GITHUB_URL": "https://api.github.com",
260
261
  "GITHUB_VERIFY": "True",
262
+ "GRAPHQLTOOL": "True",
261
263
  "ISSUETOOL": "True",
262
264
  "ORGTOOL": "True",
263
265
  "PULLTOOL": "True",
@@ -303,6 +305,7 @@ docker run -d \
303
305
  -e GITHUB_TOKEN=your_github_token_here \
304
306
  -e GITHUB_URL=https://api.github.com \
305
307
  -e GITHUB_VERIFY=True \
308
+ -e GRAPHQLTOOL=True \
306
309
  -e ISSUETOOL=True \
307
310
  -e ORGTOOL=True \
308
311
  -e PULLTOOL=True \
@@ -365,6 +368,7 @@ consumed from a **remote deployment**. The
365
368
  | `COLLABORATORTOOL` | `True` | |
366
369
  | `COMMITTOOL` | `True` | |
367
370
  | `CONTENTTOOL` | `True` | |
371
+ | `GRAPHQLTOOL` | `True` | |
368
372
  | `ISSUETOOL` | `True` | |
369
373
  | `ORGTOOL` | `True` | |
370
374
  | `PULLTOOL` | `True` | |
@@ -389,7 +393,7 @@ consumed from a **remote deployment**. The
389
393
  | `MODEL_ID` | `gpt-4o` | Model id for the agent |
390
394
  | `ENABLE_WEB_UI` | `True` | Serve the AG-UI web interface |
391
395
 
392
- _31 package + 12 inherited variable(s). Auto-generated from `.env.example` + the shared agent-utilities set — do not edit._
396
+ _32 package + 12 inherited variable(s). Auto-generated from `.env.example` + the shared agent-utilities set — do not edit._
393
397
  <!-- ENV-VARS-TABLE:END -->
394
398
 
395
399
 
@@ -4,7 +4,7 @@ import os
4
4
  import sys
5
5
  import warnings
6
6
 
7
- __version__ = "1.0.1"
7
+ __version__ = "1.0.2"
8
8
 
9
9
  logging.basicConfig(
10
10
  level=logging.INFO,
@@ -114,3 +114,32 @@ def get_client(config: dict | None = None) -> Api:
114
114
  f"Please check your GITHUB_TOKEN and GITHUB_URL environment variables. "
115
115
  f"Error details: {str(e)}"
116
116
  ) from e
117
+
118
+
119
+ def get_graphql_client(config: dict | None = None):
120
+ """Factory for the GitHub GraphQL client (parity with :func:`get_client`).
121
+
122
+ Resolves the same ``GITHUB_URL`` / ``GITHUB_TOKEN`` / verify settings and
123
+ honours OIDC delegation, then returns a :class:`~github_agent.github_gql.GraphQL`.
124
+ """
125
+ from github_agent.github_gql import GraphQL
126
+
127
+ instance = setting("GITHUB_URL", "https://api.github.com")
128
+ token = setting("GITHUB_TOKEN", None)
129
+ if setting("GITHUB_SSL_VERIFY", None) is not None:
130
+ verify = setting("GITHUB_SSL_VERIFY", True)
131
+ else:
132
+ verify = setting("GITHUB_VERIFY", True)
133
+
134
+ if config is None:
135
+ from agent_utilities.mcp_utilities import config as default_config
136
+
137
+ config = default_config
138
+
139
+ if config.get("enable_delegation"):
140
+ # Reuse the REST factory's OIDC token exchange, then read back the
141
+ # exchanged bearer token for the GraphQL transport.
142
+ api = get_client(config)
143
+ token = getattr(api, "token", None) or token
144
+
145
+ return GraphQL(url=instance, token=token, verify=verify)
@@ -0,0 +1,88 @@
1
+ #!/usr/bin/python
2
+
3
+
4
+ import logging
5
+ from typing import Any
6
+
7
+ from agent_utilities.core.exceptions import MissingParameterError, ParameterError
8
+ from gql import Client, gql
9
+ from gql.transport.requests import RequestsHTTPTransport
10
+
11
+
12
+ class GraphQL:
13
+ """Interact with GitHub's GraphQL API (parity with the REST ``Api`` client).
14
+
15
+ GraphQL lets a single request fan out across many repositories via aliased
16
+ sub-queries — e.g. fetch the latest-commit CI rollup for the whole fleet in
17
+ one call instead of one REST request per repo.
18
+ """
19
+
20
+ def __init__(
21
+ self,
22
+ url: str | None = None,
23
+ token: str | None = None,
24
+ proxies: dict | None = None,
25
+ verify: bool = True,
26
+ debug: bool = False,
27
+ ):
28
+ if not url:
29
+ raise MissingParameterError("URL is required")
30
+ if not token:
31
+ raise MissingParameterError("Token is required")
32
+
33
+ self.url = self._graphql_endpoint(url)
34
+ self.token = token
35
+ self.proxies = proxies
36
+ self.verify = verify
37
+ self.debug = debug
38
+
39
+ logging.basicConfig(
40
+ level=logging.DEBUG if debug else logging.ERROR,
41
+ format="%(asctime)s - %(levelname)s - %(message)s",
42
+ )
43
+
44
+ # GitHub GraphQL authenticates with a bearer token (classic PAT,
45
+ # fine-grained PAT, or OAuth/GitHub-App installation token).
46
+ self.headers = {"Authorization": f"Bearer {token}"}
47
+ self.transport = RequestsHTTPTransport(
48
+ url=self.url,
49
+ headers=self.headers,
50
+ verify=verify,
51
+ proxies=proxies,
52
+ )
53
+ self.client = Client(transport=self.transport, fetch_schema_from_transport=False)
54
+
55
+ @staticmethod
56
+ def _graphql_endpoint(url: str) -> str:
57
+ """Derive the GraphQL endpoint from the REST base URL.
58
+
59
+ github.com → ``https://api.github.com/graphql``; GitHub Enterprise
60
+ (``https://host/api/v3``) → ``https://host/api/graphql``.
61
+ """
62
+ base = url.rstrip("/")
63
+ if base.endswith("/api/v3"):
64
+ return base[: -len("/api/v3")] + "/api/graphql"
65
+ return f"{base}/graphql"
66
+
67
+ def execute_gql(
68
+ self,
69
+ query_str: str,
70
+ variables: dict[str, Any] | None = None,
71
+ operation_name: str | None = None,
72
+ ) -> dict[str, Any]:
73
+ """Execute a GraphQL query or mutation and return the raw data dict.
74
+
75
+ Raises:
76
+ ParameterError: If the query fails or the response carries errors.
77
+ """
78
+ try:
79
+ query = gql(query_str)
80
+ result = self.client.execute(
81
+ query, variable_values=variables, operation_name=operation_name
82
+ )
83
+ if "errors" in result:
84
+ raise ParameterError(f"GraphQL errors: {result['errors']}")
85
+ return result
86
+ except Exception as e:
87
+ logging.error(f"GraphQL execution failed: {str(e)}")
88
+ raise ParameterError(f"Query execution failed: {str(e)}") from e
@@ -1816,6 +1816,85 @@ def register_release_tools(mcp: FastMCP):
1816
1816
  return {"status": 500, "error": str(e), "data": None}
1817
1817
 
1818
1818
 
1819
+ def register_graphql_tools(mcp: FastMCP):
1820
+ from github_agent.auth import get_graphql_client
1821
+
1822
+ @mcp.tool(tags={"graphql"})
1823
+ async def github_graphql(
1824
+ query: str = Field(
1825
+ description="The raw GraphQL query or mutation string to execute against the GitHub API."
1826
+ ),
1827
+ variables: str = Field(
1828
+ default="{}",
1829
+ description="JSON string of variables to pass along with the query.",
1830
+ ),
1831
+ operation_name: str | None = Field(
1832
+ default=None,
1833
+ description="Optional operation name if executing a specific query within the document.",
1834
+ ),
1835
+ client=Depends(get_graphql_client),
1836
+ ctx: Context | None = Field(
1837
+ default=None, description="MCP context for progress reporting"
1838
+ ),
1839
+ ) -> Any:
1840
+ """Execute raw GraphQL queries and mutations natively on GitHub.
1841
+
1842
+ One request can fan out across many repositories via aliased sub-queries
1843
+ (e.g. fetch the latest-commit CI status for the whole fleet in a single
1844
+ call) — far cheaper than one REST request per repository.
1845
+ """
1846
+ if ctx:
1847
+ await ctx.info("Executing GitHub GraphQL query...")
1848
+ import json
1849
+
1850
+ try:
1851
+ vars_dict = json.loads(variables) if variables else None
1852
+ except Exception as e:
1853
+ return {"error": f"Invalid variables JSON: {e}"}
1854
+
1855
+ try:
1856
+ return await run_blocking(
1857
+ client.execute_gql,
1858
+ query_str=query,
1859
+ variables=vars_dict,
1860
+ operation_name=operation_name,
1861
+ )
1862
+ except Exception as e:
1863
+ return {"error": f"GraphQL execution failed: {str(e)}"}
1864
+
1865
+ @mcp.tool(tags={"graphql"})
1866
+ async def github_discover_graphql_schema(
1867
+ type_name: str | None = Field(
1868
+ default=None,
1869
+ description="Optional GraphQL type name to inspect (e.g. 'Repository', 'CheckSuite'). If omitted, lists all available types.",
1870
+ ),
1871
+ client=Depends(get_graphql_client),
1872
+ ctx: Context | None = Field(
1873
+ default=None, description="MCP context for progress reporting"
1874
+ ),
1875
+ ) -> dict:
1876
+ """Discover the live GitHub GraphQL schema (types, fields, and attributes) in real-time."""
1877
+ from agent_utilities.mcp.context_helpers import (
1878
+ ctx_graphql_get_type_details,
1879
+ ctx_graphql_list_types,
1880
+ )
1881
+
1882
+ if ctx:
1883
+ await ctx.info("Retrieving live GitHub GraphQL schema...")
1884
+
1885
+ async def execute_fn(q, variables=None):
1886
+ return await run_blocking(
1887
+ client.execute_gql, query_str=q, variables=variables
1888
+ )
1889
+
1890
+ try:
1891
+ if type_name:
1892
+ return await ctx_graphql_get_type_details(execute_fn, type_name)
1893
+ return await ctx_graphql_list_types(execute_fn)
1894
+ except Exception as e:
1895
+ return {"error": f"Failed to discover GitHub GraphQL schema: {str(e)}"}
1896
+
1897
+
1819
1898
  #: (tag, env-toggle, registrar) — toggle names are the framework-derived
1820
1899
  #: ``<TAG>TOOL`` form (``register_<x>_tools`` ⇒ ``<X>TOOL``) so config mirrors
1821
1900
  #: and the drift guard agree on one canonical set.
@@ -1831,6 +1910,7 @@ TOOL_REGISTRY = [
1831
1910
  ("collaborators", "COLLABORATORTOOL", register_collaborator_tools),
1832
1911
  ("actions", "ACTIONTOOL", register_action_tools),
1833
1912
  ("releases", "RELEASETOOL", register_release_tools),
1913
+ ("graphql", "GRAPHQLTOOL", register_graphql_tools),
1834
1914
  ]
1835
1915
 
1836
1916
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: github-agent
3
- Version: 1.0.1
3
+ Version: 1.0.3
4
4
  Summary: GitHub Agent for MCP
5
5
  Author-email: Audel Rouhi <knucklessg1@gmail.com>
6
6
  License: MIT
@@ -13,6 +13,7 @@ Requires-Python: <3.15,>=3.11
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
15
  Requires-Dist: agent-utilities[mcp]>=1.0.0
16
+ Requires-Dist: gql[requests]>=4.0.0
16
17
  Provides-Extra: mcp
17
18
  Requires-Dist: agent-utilities[mcp]>=1.0.0; extra == "mcp"
18
19
  Provides-Extra: agent
@@ -47,7 +48,7 @@ Dynamic: license-file
47
48
  ![PyPI - Wheel](https://img.shields.io/pypi/wheel/github-agent)
48
49
  ![PyPI - Implementation](https://img.shields.io/pypi/implementation/github-agent)
49
50
 
50
- *Version: 1.0.1*
51
+ *Version: 1.0.2*
51
52
 
52
53
  > **Documentation** — Installation, deployment, and usage across the MCP, API, and
53
54
  > CLI interfaces, including the integrated A2A agent server, are maintained in the
@@ -241,6 +242,7 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
241
242
  "GITHUB_TOKEN": "your_github_token_here",
242
243
  "GITHUB_URL": "https://api.github.com",
243
244
  "GITHUB_VERIFY": "True",
245
+ "GRAPHQLTOOL": "True",
244
246
  "ISSUETOOL": "True",
245
247
  "ORGTOOL": "True",
246
248
  "PULLTOOL": "True",
@@ -285,6 +287,7 @@ When query strings or parameters are supplied, an LLM-free **Knowledge Graph res
285
287
  "GITHUB_TOKEN": "your_github_token_here",
286
288
  "GITHUB_URL": "https://api.github.com",
287
289
  "GITHUB_VERIFY": "True",
290
+ "GRAPHQLTOOL": "True",
288
291
  "ISSUETOOL": "True",
289
292
  "ORGTOOL": "True",
290
293
  "PULLTOOL": "True",
@@ -330,6 +333,7 @@ docker run -d \
330
333
  -e GITHUB_TOKEN=your_github_token_here \
331
334
  -e GITHUB_URL=https://api.github.com \
332
335
  -e GITHUB_VERIFY=True \
336
+ -e GRAPHQLTOOL=True \
333
337
  -e ISSUETOOL=True \
334
338
  -e ORGTOOL=True \
335
339
  -e PULLTOOL=True \
@@ -392,6 +396,7 @@ consumed from a **remote deployment**. The
392
396
  | `COLLABORATORTOOL` | `True` | |
393
397
  | `COMMITTOOL` | `True` | |
394
398
  | `CONTENTTOOL` | `True` | |
399
+ | `GRAPHQLTOOL` | `True` | |
395
400
  | `ISSUETOOL` | `True` | |
396
401
  | `ORGTOOL` | `True` | |
397
402
  | `PULLTOOL` | `True` | |
@@ -416,7 +421,7 @@ consumed from a **remote deployment**. The
416
421
  | `MODEL_ID` | `gpt-4o` | Model id for the agent |
417
422
  | `ENABLE_WEB_UI` | `True` | Serve the AG-UI web interface |
418
423
 
419
- _31 package + 12 inherited variable(s). Auto-generated from `.env.example` + the shared agent-utilities set — do not edit._
424
+ _32 package + 12 inherited variable(s). Auto-generated from `.env.example` + the shared agent-utilities set — do not edit._
420
425
  <!-- ENV-VARS-TABLE:END -->
421
426
 
422
427
 
@@ -6,6 +6,7 @@ github_agent/__main__.py
6
6
  github_agent/agent_server.py
7
7
  github_agent/api_client.py
8
8
  github_agent/auth.py
9
+ github_agent/github_gql.py
9
10
  github_agent/github_input_models.py
10
11
  github_agent/github_response_models.py
11
12
  github_agent/mcp_config.json
@@ -56,6 +57,7 @@ tests/test_auth_client_edge_cases.py
56
57
  tests/test_concept_parity.py
57
58
  tests/test_github_agent_api_brute_force_coverage.py
58
59
  tests/test_github_agent_brute_force_coverage.py
60
+ tests/test_github_gql.py
59
61
  tests/test_hardening.py
60
62
  tests/test_init_dynamics.py
61
63
  tests/test_mcp_coverage.py
@@ -1,4 +1,5 @@
1
1
  agent-utilities[mcp]>=1.0.0
2
+ gql[requests]>=4.0.0
2
3
 
3
4
  [agent]
4
5
  agent-utilities[agent,logfire]>=1.0.0
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "github-agent"
7
- version = "1.0.1"
7
+ version = "1.0.3"
8
8
  readme = "README.md"
9
9
  description = "GitHub Agent for MCP"
10
10
  requires-python = ">=3.11, <3.15"
11
11
  classifiers = [ "Development Status :: 5 - Production/Stable", "License :: Public Domain", "Environment :: Console", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3",]
12
- dependencies = [ "agent-utilities[mcp]>=1.0.0",]
12
+ dependencies = [ "agent-utilities[mcp]>=1.0.0", "gql[requests]>=4.0.0",]
13
13
  [[project.authors]]
14
14
  name = "Audel Rouhi"
15
15
  email = "knucklessg1@gmail.com"
@@ -0,0 +1,35 @@
1
+ """GitHub GraphQL client — endpoint derivation + construction (no network)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import pytest
6
+
7
+ from github_agent.github_gql import GraphQL
8
+
9
+
10
+ def test_endpoint_github_com():
11
+ assert GraphQL._graphql_endpoint("https://api.github.com") == (
12
+ "https://api.github.com/graphql"
13
+ )
14
+ assert GraphQL._graphql_endpoint("https://api.github.com/") == (
15
+ "https://api.github.com/graphql"
16
+ )
17
+
18
+
19
+ def test_endpoint_enterprise():
20
+ assert GraphQL._graphql_endpoint("https://ghe.corp/api/v3") == (
21
+ "https://ghe.corp/api/graphql"
22
+ )
23
+
24
+
25
+ def test_requires_url_and_token():
26
+ with pytest.raises(Exception):
27
+ GraphQL(url=None, token="x")
28
+ with pytest.raises(Exception):
29
+ GraphQL(url="https://api.github.com", token=None)
30
+
31
+
32
+ def test_construction_sets_bearer_header():
33
+ g = GraphQL(url="https://api.github.com", token="tok123")
34
+ assert g.headers["Authorization"] == "Bearer tok123"
35
+ assert g.url.endswith("/graphql")
File without changes
File without changes