-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsetup_wizard.py
More file actions
183 lines (143 loc) · 5.55 KB
/
setup_wizard.py
File metadata and controls
183 lines (143 loc) · 5.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
"""
Interactive setup wizard for github-insight-mcp.
Guides the user through optional GitHub token configuration
and Claude Desktop MCP server registration.
"""
import json
import os
import platform
import shutil
import sys
from datetime import datetime
from pathlib import Path
def get_claude_config_path() -> Path | None:
"""Auto-detect Claude Desktop config path based on OS."""
system = platform.system()
if system == "Windows":
appdata = os.environ.get("APPDATA", "")
if appdata:
return Path(appdata) / "Claude" / "claude_desktop_config.json"
elif system == "Darwin":
home = Path.home()
return home / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json"
elif system == "Linux":
home = Path.home()
return home / ".config" / "Claude" / "claude_desktop_config.json"
return None
def backup_config(config_path: Path) -> Path | None:
"""Create a backup of the existing config file."""
if not config_path.exists():
return None
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
backup_path = config_path.with_suffix(f".json.bak.{timestamp}")
shutil.copy2(config_path, backup_path)
return backup_path
def load_config(config_path: Path) -> dict:
"""Load existing config or return empty structure."""
if config_path.exists():
with open(config_path, "r", encoding="utf-8") as f:
return json.load(f)
return {}
def save_config(config_path: Path, config: dict) -> None:
"""Save config to file, creating parent directories if needed."""
config_path.parent.mkdir(parents=True, exist_ok=True)
with open(config_path, "w", encoding="utf-8") as f:
json.dump(config, f, indent=2, ensure_ascii=False)
def main() -> None:
print("=" * 60)
print(" github-insight-mcp Setup Wizard")
print("=" * 60)
print()
# --- Explain requirements ---
print("[INFO] This MCP server works WITHOUT any API keys.")
print("[INFO] All core features (repo analysis, package info,")
print(" security advisories) are available immediately.")
print()
print("[INFO] Optional: A GitHub Personal Access Token increases")
print(" the rate limit from 60 to 5,000 requests/hour.")
print(" Create one at: https://github.com/settings/tokens")
print(" (no special scopes needed)")
print()
# --- GitHub token setup ---
token = ""
setup_token = input("Set up a GitHub token now? (y/N): ").strip().lower()
if setup_token == "y":
token = input("Enter your GitHub Personal Access Token: ").strip()
if not token:
print("[INFO] No token provided. Skipping token setup.")
token = ""
# --- Write .env file ---
project_dir = Path(__file__).parent.resolve()
env_path = project_dir / ".env"
if token:
with open(env_path, "w", encoding="utf-8") as f:
f.write(f"GITHUB_TOKEN={token}\n")
print(f"[INFO] Token saved to {env_path}")
else:
with open(env_path, "w", encoding="utf-8") as f:
f.write("# GITHUB_TOKEN=your_github_token_here\n")
print("[INFO] Created .env without token (using public rate limits).")
print()
# --- Claude Desktop config ---
print("-" * 60)
print(" Claude Desktop Configuration")
print("-" * 60)
print()
config_path = get_claude_config_path()
if config_path is None:
print("[INFO] Could not auto-detect Claude Desktop config path.")
print("[INFO] You will need to manually add the MCP server entry.")
_print_manual_config(project_dir, token)
return
print(f"[INFO] Detected config path: {config_path}")
proceed = input("Add github-insight to Claude Desktop config? (y/N): ").strip().lower()
if proceed != "y":
print("[INFO] Skipping Claude Desktop configuration.")
_print_manual_config(project_dir, token)
return
# Backup existing config
backup = backup_config(config_path)
if backup:
print(f"[INFO] Config backup saved to {backup}")
# Load and update config
config = load_config(config_path)
if "mcpServers" not in config:
config["mcpServers"] = {}
server_entry: dict = {
"command": sys.executable,
"args": [str(project_dir / "server.py")],
}
if token:
server_entry["env"] = {"GITHUB_TOKEN": token}
config["mcpServers"]["github-insight"] = server_entry
save_config(config_path, config)
print(f"[INFO] Added 'github-insight' to {config_path}")
print()
print("=" * 60)
print(" Setup Complete")
print("=" * 60)
print()
print("[INFO] Restart Claude Desktop to load the new MCP server.")
print()
print("Usage examples after restart:")
print(" - \"Analyze the mass/express repository on GitHub\"")
print(" - \"Show me security advisories for lodash 4.17.20\"")
print(" - \"What are the dependencies of requests 2.31.0 on PyPI?\"")
print(" - \"Compare download stats for express vs fastify\"")
print()
def _print_manual_config(project_dir: Path, token: str) -> None:
"""Print manual configuration instructions."""
print()
print("[INFO] To manually configure, add this to your Claude Desktop config:")
print()
entry: dict = {
"command": sys.executable,
"args": [str(project_dir / "server.py")],
}
if token:
entry["env"] = {"GITHUB_TOKEN": token}
snippet = {"mcpServers": {"github-insight": entry}}
print(json.dumps(snippet, indent=2))
print()
if __name__ == "__main__":
main()