github-mcp-agent 0.2.0__tar.gz → 0.2.1__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.
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/.gitignore +2 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/PKG-INFO +5 -3
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/README.md +4 -2
- github_mcp_agent-0.2.1/assets/demo1.png +0 -0
- github_mcp_agent-0.2.1/assets/demo2.png +0 -0
- github_mcp_agent-0.2.1/assets/demo3.png +0 -0
- github_mcp_agent-0.2.1/github_mcp_agent/providers/copilot.py +117 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/pyproject.toml +1 -1
- github_mcp_agent-0.2.0/github_mcp_agent/providers/copilot.py +0 -32
- github_mcp_agent-0.2.0/uv.lock +0 -2693
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/.claude/settings.json +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/.claude/settings.local.json +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/.env.example +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/LICENSE +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/__init__.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/agent.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/cli.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/providers/__init__.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/providers/anthropic.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/providers/bedrock.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/providers/gemini.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/providers/ollama.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/providers/openai.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/setup_wizard.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/system_prompt.txt +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/github_mcp_agent/tools.py +0 -0
- {github_mcp_agent-0.2.0 → github_mcp_agent-0.2.1}/system_prompt.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: github-mcp-agent
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Talk to your GitHub repos, issues, and project boards in plain English from your terminal
|
|
5
5
|
Project-URL: Homepage, https://github.com/OmarCodes022/GitHub-MCP-Agent
|
|
6
6
|
Project-URL: Repository, https://github.com/OmarCodes022/GitHub-MCP-Agent
|
|
@@ -35,6 +35,8 @@ Description-Content-Type: text/markdown
|
|
|
35
35
|
|
|
36
36
|
Talk to your GitHub repos, issues, and project boards in plain English from your terminal.
|
|
37
37
|
|
|
38
|
+

|
|
39
|
+
|
|
38
40
|
```
|
|
39
41
|
You > list open issues in my raytracer repo
|
|
40
42
|
You > set priority of issue #42 to urgent
|
|
@@ -72,7 +74,7 @@ Interactive wizard:
|
|
|
72
74
|
- **Anthropic API** — API key from console.anthropic.com
|
|
73
75
|
- **OpenAI** — API key from platform.openai.com
|
|
74
76
|
- **Google Gemini** — API key from aistudio.google.com
|
|
75
|
-
- **GitHub Copilot** —
|
|
77
|
+
- **GitHub Copilot** — browser OAuth flow, requires a Copilot subscription
|
|
76
78
|
- **Local (Ollama)** — picks from your installed models, no API key needed
|
|
77
79
|
3. Model selection (scrollable menu)
|
|
78
80
|
4. Pulls the GitHub MCP Docker image
|
|
@@ -142,4 +144,4 @@ Uses the [Strands Agents SDK](https://github.com/strands-agents/sdk-python) with
|
|
|
142
144
|
|
|
143
145
|
**Ollama model not found** — run `ollama list` to confirm the model name, re-run `github-agent model`
|
|
144
146
|
|
|
145
|
-
**`No module named github_mcp_agent`** — reinstall with `
|
|
147
|
+
**`No module named github_mcp_agent`** — reinstall with `pip install github-mcp-agent` or `uv tool install github-mcp-agent`
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Talk to your GitHub repos, issues, and project boards in plain English from your terminal.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
```
|
|
6
8
|
You > list open issues in my raytracer repo
|
|
7
9
|
You > set priority of issue #42 to urgent
|
|
@@ -39,7 +41,7 @@ Interactive wizard:
|
|
|
39
41
|
- **Anthropic API** — API key from console.anthropic.com
|
|
40
42
|
- **OpenAI** — API key from platform.openai.com
|
|
41
43
|
- **Google Gemini** — API key from aistudio.google.com
|
|
42
|
-
- **GitHub Copilot** —
|
|
44
|
+
- **GitHub Copilot** — browser OAuth flow, requires a Copilot subscription
|
|
43
45
|
- **Local (Ollama)** — picks from your installed models, no API key needed
|
|
44
46
|
3. Model selection (scrollable menu)
|
|
45
47
|
4. Pulls the GitHub MCP Docker image
|
|
@@ -109,4 +111,4 @@ Uses the [Strands Agents SDK](https://github.com/strands-agents/sdk-python) with
|
|
|
109
111
|
|
|
110
112
|
**Ollama model not found** — run `ollama list` to confirm the model name, re-run `github-agent model`
|
|
111
113
|
|
|
112
|
-
**`No module named github_mcp_agent`** — reinstall with `
|
|
114
|
+
**`No module named github_mcp_agent`** — reinstall with `pip install github-mcp-agent` or `uv tool install github-mcp-agent`
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import time
|
|
3
|
+
import urllib.error
|
|
4
|
+
import urllib.parse
|
|
5
|
+
import urllib.request
|
|
6
|
+
|
|
7
|
+
import questionary
|
|
8
|
+
|
|
9
|
+
MODELS = [
|
|
10
|
+
("gpt-4o", "gpt-4o", "flagship"),
|
|
11
|
+
("gpt-4o-mini", "gpt-4o-mini", "fast, cheap"),
|
|
12
|
+
("claude-sonnet-4-5", "claude-sonnet-4-5", "Anthropic via Copilot"),
|
|
13
|
+
("o3-mini", "o3-mini", "reasoning"),
|
|
14
|
+
("gemini-1.5-pro", "gemini-1.5-pro", "Google via Copilot"),
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
_CLIENT_ID = "Iv1.b507a08c87ecfe98"
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _device_flow() -> str:
|
|
21
|
+
"""Run GitHub device flow with the Copilot OAuth client, return an access token."""
|
|
22
|
+
from rich.console import Console
|
|
23
|
+
console = Console()
|
|
24
|
+
|
|
25
|
+
data = urllib.parse.urlencode({"client_id": _CLIENT_ID, "scope": "read:user"}).encode()
|
|
26
|
+
req = urllib.request.Request(
|
|
27
|
+
"https://github.com/login/device/code",
|
|
28
|
+
data=data,
|
|
29
|
+
headers={"Accept": "application/json"},
|
|
30
|
+
)
|
|
31
|
+
with urllib.request.urlopen(req) as r:
|
|
32
|
+
device = json.loads(r.read())
|
|
33
|
+
|
|
34
|
+
console.print(f"\n Open: [bold cyan]{device['verification_uri']}[/bold cyan]")
|
|
35
|
+
console.print(f" Code: [bold yellow]{device['user_code']}[/bold yellow]\n")
|
|
36
|
+
|
|
37
|
+
interval = device.get("interval", 5)
|
|
38
|
+
deadline = time.time() + device.get("expires_in", 900)
|
|
39
|
+
|
|
40
|
+
while time.time() < deadline:
|
|
41
|
+
time.sleep(interval)
|
|
42
|
+
poll_data = urllib.parse.urlencode({
|
|
43
|
+
"client_id": _CLIENT_ID,
|
|
44
|
+
"device_code": device["device_code"],
|
|
45
|
+
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
|
|
46
|
+
}).encode()
|
|
47
|
+
poll_req = urllib.request.Request(
|
|
48
|
+
"https://github.com/login/oauth/access_token",
|
|
49
|
+
data=poll_data,
|
|
50
|
+
headers={"Accept": "application/json"},
|
|
51
|
+
)
|
|
52
|
+
with urllib.request.urlopen(poll_req) as r:
|
|
53
|
+
result = json.loads(r.read())
|
|
54
|
+
|
|
55
|
+
if "access_token" in result:
|
|
56
|
+
return result["access_token"]
|
|
57
|
+
error = result.get("error", "")
|
|
58
|
+
if error == "slow_down":
|
|
59
|
+
interval += 5
|
|
60
|
+
elif error not in ("authorization_pending",):
|
|
61
|
+
raise RuntimeError(f"Auth failed: {result.get('error_description', error)}")
|
|
62
|
+
|
|
63
|
+
raise RuntimeError("Authentication timed out.")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _get_copilot_token(oauth_token: str) -> str:
|
|
67
|
+
"""Exchange a Copilot OAuth token for a short-lived Copilot API token."""
|
|
68
|
+
req = urllib.request.Request("https://api.github.com/copilot_internal/v2/token")
|
|
69
|
+
req.add_header("Authorization", f"token {oauth_token}")
|
|
70
|
+
req.add_header("Accept", "application/json")
|
|
71
|
+
req.add_header("Editor-Version", "vscode/1.85.0")
|
|
72
|
+
req.add_header("Editor-Plugin-Version", "copilot/1.138.0")
|
|
73
|
+
req.add_header("User-Agent", "GithubCopilot/1.138.0")
|
|
74
|
+
try:
|
|
75
|
+
with urllib.request.urlopen(req) as r:
|
|
76
|
+
return json.loads(r.read())["token"]
|
|
77
|
+
except urllib.error.HTTPError as e:
|
|
78
|
+
raise RuntimeError(
|
|
79
|
+
f"Failed to get Copilot token (HTTP {e.code}).\n"
|
|
80
|
+
"Make sure you have an active Copilot subscription."
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def build_model(model_id: str):
|
|
85
|
+
import os
|
|
86
|
+
from strands.models.litellm import LiteLLMModel
|
|
87
|
+
oauth_token = os.environ.get("COPILOT_OAUTH_TOKEN")
|
|
88
|
+
if not oauth_token:
|
|
89
|
+
raise RuntimeError("Copilot token not set. Run 'github-agent provider' and pick GitHub Copilot.")
|
|
90
|
+
token = _get_copilot_token(oauth_token)
|
|
91
|
+
return LiteLLMModel(
|
|
92
|
+
model_id=f"openai/{model_id}",
|
|
93
|
+
params={
|
|
94
|
+
"api_base": "https://api.githubcopilot.com",
|
|
95
|
+
"api_key": token,
|
|
96
|
+
"extra_headers": {
|
|
97
|
+
"Editor-Version": "vscode/1.85.0",
|
|
98
|
+
"Editor-Plugin-Version": "copilot/1.138.0",
|
|
99
|
+
"User-Agent": "GithubCopilot/1.138.0",
|
|
100
|
+
"Copilot-Integration-Id": "vscode-chat",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def setup(_ask) -> dict:
|
|
107
|
+
from rich.console import Console
|
|
108
|
+
console = Console()
|
|
109
|
+
console.print(" [dim]Requires an active Copilot subscription (student pack, individual, or business).[/dim]")
|
|
110
|
+
console.print(" [dim]Opening browser to authenticate with GitHub Copilot...[/dim]\n")
|
|
111
|
+
|
|
112
|
+
oauth_token = _device_flow()
|
|
113
|
+
|
|
114
|
+
model_choices = [f"{name} ({desc})" for _, name, desc in MODELS]
|
|
115
|
+
model_display = _ask(questionary.select, "Model:", choices=model_choices)
|
|
116
|
+
model_id = MODELS[model_choices.index(model_display)][0]
|
|
117
|
+
return {"COPILOT_OAUTH_TOKEN": oauth_token, "MODEL_ID": model_id}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
import questionary
|
|
4
|
-
|
|
5
|
-
MODELS = [
|
|
6
|
-
("gpt-4o", "gpt-4o", "flagship"),
|
|
7
|
-
("gpt-4o-mini", "gpt-4o-mini", "fast, cheap"),
|
|
8
|
-
("claude-sonnet-4-5", "claude-sonnet-4-5", "Anthropic via Copilot"),
|
|
9
|
-
("o3-mini", "o3-mini", "reasoning"),
|
|
10
|
-
("gemini-1.5-pro", "gemini-1.5-pro", "Google via Copilot"),
|
|
11
|
-
]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def build_model(model_id: str):
|
|
15
|
-
from strands.models.litellm import LiteLLMModel
|
|
16
|
-
token = os.environ.get("GITHUB_TOKEN")
|
|
17
|
-
if not token:
|
|
18
|
-
raise RuntimeError("GITHUB_TOKEN is not set. Run 'github-agent setup' to configure.")
|
|
19
|
-
return LiteLLMModel(
|
|
20
|
-
model_id=f"openai/{model_id}",
|
|
21
|
-
params={"api_base": "https://api.githubcopilot.com", "api_key": token},
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def setup(_ask) -> dict:
|
|
26
|
-
from rich.console import Console
|
|
27
|
-
console = Console()
|
|
28
|
-
console.print(" [dim]Uses your GitHub token - no extra API key needed.[/dim]")
|
|
29
|
-
console.print(" [dim]Requires an active Copilot subscription (student pack, individual, or business).[/dim]")
|
|
30
|
-
model_choices = [f"{name} ({desc})" for _, name, desc in MODELS]
|
|
31
|
-
model_display = _ask(questionary.select, "Model:", choices=model_choices)
|
|
32
|
-
return {"MODEL_ID": MODELS[model_choices.index(model_display)][0]}
|