@weppy/roblox-mcp 2.0.1 → 2.0.3

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 (90) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/CHANGELOG.md +18 -0
  3. package/COMMERCIAL-LICENSE.md +13 -0
  4. package/Dockerfile +13 -0
  5. package/LICENSE +648 -40
  6. package/README.md +31 -2
  7. package/TRADEMARKS.md +18 -0
  8. package/docs/assets/screenshots/license/license-dashboard.png +3 -0
  9. package/docs/assets/screenshots/license/license-plugin.png +3 -0
  10. package/docs/compatibility.md +1 -1
  11. package/docs/en/installation/README.md +25 -2
  12. package/docs/en/installation/ai-apps/cursor.md +77 -0
  13. package/docs/en/installation/roblox-explorer.md +5 -5
  14. package/docs/en/installation/roblox-plugin.md +1 -0
  15. package/docs/en/pro-upgrade.md +36 -12
  16. package/docs/es/README.md +29 -10
  17. package/docs/es/installation/README.md +25 -2
  18. package/docs/es/installation/ai-apps/cursor.md +77 -0
  19. package/docs/es/installation/roblox-plugin.md +1 -0
  20. package/docs/es/pro-upgrade.md +37 -13
  21. package/docs/id/README.md +29 -10
  22. package/docs/id/installation/README.md +25 -2
  23. package/docs/id/installation/ai-apps/cursor.md +77 -0
  24. package/docs/id/installation/roblox-plugin.md +1 -0
  25. package/docs/id/pro-upgrade.md +36 -12
  26. package/docs/ja/README.md +29 -10
  27. package/docs/ja/installation/README.md +25 -2
  28. package/docs/ja/installation/ai-apps/cursor.md +77 -0
  29. package/docs/ja/installation/roblox-plugin.md +1 -0
  30. package/docs/ja/pro-upgrade.md +35 -11
  31. package/docs/ko/README.md +28 -9
  32. package/docs/ko/installation/README.md +25 -2
  33. package/docs/ko/installation/ai-apps/cursor.md +77 -0
  34. package/docs/ko/installation/roblox-explorer.md +5 -5
  35. package/docs/ko/installation/roblox-plugin.md +1 -0
  36. package/docs/ko/pro-upgrade.md +35 -11
  37. package/docs/pt-br/README.md +29 -10
  38. package/docs/pt-br/installation/README.md +25 -2
  39. package/docs/pt-br/installation/ai-apps/cursor.md +77 -0
  40. package/docs/pt-br/installation/roblox-plugin.md +1 -0
  41. package/docs/pt-br/pro-upgrade.md +37 -13
  42. package/glama.json +7 -0
  43. package/install.ps1 +277 -0
  44. package/install.sh +306 -0
  45. package/llms-full.txt +92 -7
  46. package/llms.txt +13 -1
  47. package/package.json +14 -3
  48. package/plugins/weppy-roblox-mcp/.claude-plugin/plugin.json +2 -2
  49. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{ChangelogDetailPage-Ss9rBuou.js → ChangelogDetailPage-IgHLnaEX.js} +1 -1
  50. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ChangelogPage-Br-A5H5t.css +1 -0
  51. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ChangelogPage-Dao4jPQA.js +1 -0
  52. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConfirmModal-CvXLNYq0.js +1 -0
  53. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConfirmModal-tvPLhSO9.css +1 -0
  54. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConnectionPage-Bl7tLgL2.js +1 -0
  55. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConnectionPage-CN3LYLAT.css +1 -0
  56. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/InfoLabel-vz7vtbbV.js +1 -0
  57. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{OverviewPage-BcSHb-KS.js → OverviewPage-BDDctbAl.js} +1 -1
  58. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/PlaytestPage-C0iCoAQp.js +1 -0
  59. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/PlaytestPage-LnuHE5FL.css +1 -0
  60. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{PropertyDiff-BGBA0lal.js → PropertyDiff-CbDafceC.js} +1 -1
  61. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SettingsPage-CJs9ctOf.js +1 -0
  62. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SettingsPage-DP9OFhNb.css +1 -0
  63. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{StatusBadge-C_KxiYEt.js → StatusBadge-BMTgkxDJ.js} +1 -1
  64. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SyncPage-Bf1SdHGg.css +1 -0
  65. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SyncPage-BfXIBNVS.js +4 -0
  66. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{TierPromoPanel-B2hY_Iul.js → TierPromoPanel-CUrTMsXB.js} +1 -1
  67. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/TierPromoProgress-DBA-FZGE.js +1 -0
  68. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ToolsPage-BZZZ3FXe.css +1 -0
  69. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ToolsPage-O4dXhEU-.js +1 -0
  70. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/index-CkXvRg-O.js +69 -0
  71. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{tier-promo-config-BFJCz95t.js → tier-promo-config-B9lIKWCQ.js} +1 -1
  72. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{useLiveUptime-Gqoo4lJE.js → useLiveUptime-DXXyWm6j.js} +1 -1
  73. package/plugins/weppy-roblox-mcp/dashboard/dist/index.html +1 -1
  74. package/plugins/weppy-roblox-mcp/dist/index.js +58 -57
  75. package/plugins/weppy-roblox-mcp/roblox-plugin/WeppyRobloxMCP.rbxm +3 -0
  76. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ChangelogPage-ByQDwNhh.css +0 -1
  77. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ChangelogPage-D_OScUeF.js +0 -1
  78. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConnectionPage-C3QU6eRJ.js +0 -1
  79. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConnectionPage-CkQVyTc5.css +0 -1
  80. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/InfoLabel-Cvotfyns.js +0 -1
  81. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/PlaytestPage-CqIxk3qY.js +0 -1
  82. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/PlaytestPage-emQ5xjZz.css +0 -1
  83. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SettingsPage-D-SyrBho.js +0 -1
  84. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SettingsPage-NF_CPSvZ.css +0 -1
  85. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SyncPage-BNHvpQxD.css +0 -1
  86. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/SyncPage-DeQjKxmi.js +0 -4
  87. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/TierPromoProgress-B9L7tJGd.js +0 -1
  88. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ToolsPage-CzFt06tW.js +0 -1
  89. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ToolsPage-cVoMPYAn.css +0 -1
  90. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/index-mMUjBHCe.js +0 -69
package/install.ps1 ADDED
@@ -0,0 +1,277 @@
1
+ #
2
+ # Weppy Roblox MCP — One-line install script (Windows PowerShell)
3
+ #
4
+ # Usage:
5
+ # irm https://raw.githubusercontent.com/hope1026/weppy-roblox-mcp/main/install.ps1 | iex
6
+ #
7
+ # Interactive 3 steps:
8
+ # [1/3] MCP server install (npm)
9
+ # [2/3] Roblox Studio Plugin install (.rbxm)
10
+ # [3/3] Register MCP with AI apps (user selection)
11
+ #
12
+
13
+ $ErrorActionPreference = "Stop"
14
+
15
+ # ── Utilities ──
16
+ function Write-Step($step, $msg) { Write-Host "`n[$step] $msg" -ForegroundColor Cyan -NoNewline; Write-Host "" }
17
+ function Write-Ok($msg) { Write-Host " ✓ $msg" -ForegroundColor Green }
18
+ function Write-Warn($msg) { Write-Host " ⚠ $msg" -ForegroundColor Yellow }
19
+ function Write-Fail($msg) { Write-Host " ✗ $msg" -ForegroundColor Red }
20
+ function Write-Info($msg) { Write-Host " [INFO] $msg" -ForegroundColor Blue }
21
+
22
+ function Confirm-Action($prompt) {
23
+ $reply = Read-Host "$prompt (Y/n)"
24
+ if ([string]::IsNullOrWhiteSpace($reply)) { $reply = "Y" }
25
+ return $reply -match '^[Yy]'
26
+ }
27
+
28
+ # Add MCP server to JSON config file (PowerShell 5.1 compatible — edits JSON via node)
29
+ function Add-McpToConfig($configPath) {
30
+ $parentDir = Split-Path $configPath -Parent
31
+ if (-not (Test-Path $parentDir)) { New-Item -ItemType Directory -Path $parentDir -Force | Out-Null }
32
+ $env:MCP_CONFIG_PATH = $configPath
33
+ try {
34
+ node -e @"
35
+ const fs = require('fs');
36
+ const configPath = process.env.MCP_CONFIG_PATH;
37
+ let config = {};
38
+ try { config = JSON.parse(fs.readFileSync(configPath, 'utf8')); } catch {}
39
+ if (!config.mcpServers) config.mcpServers = {};
40
+ config.mcpServers['weppy-roblox-mcp'] = { command: 'npx', args: ['-y', '@weppy/roblox-mcp'] };
41
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + '\n');
42
+ "@
43
+ } finally {
44
+ Remove-Item Env:\MCP_CONFIG_PATH -ErrorAction SilentlyContinue
45
+ }
46
+ }
47
+
48
+ # ── Header ──
49
+ Write-Host ""
50
+ Write-Host "Weppy Roblox MCP Installer" -ForegroundColor White -BackgroundColor DarkCyan
51
+ Write-Host "AI-powered Roblox Studio integration" -ForegroundColor DarkGray
52
+ Write-Host ("=" * 40)
53
+
54
+ # ── Node.js check ──
55
+ try {
56
+ $nodeVersion = (node -v) -replace 'v', ''
57
+ $majorVersion = [int]($nodeVersion.Split('.')[0])
58
+ if ($majorVersion -lt 18) {
59
+ Write-Fail "Node.js 18 or higher required (current: v$nodeVersion)"
60
+ Write-Host " Upgrade: https://nodejs.org"
61
+ exit 1
62
+ }
63
+ Write-Ok "Node.js v$nodeVersion detected"
64
+ }
65
+ catch {
66
+ Write-Fail "Node.js is not installed"
67
+ Write-Host " Install Node.js 18+: https://nodejs.org"
68
+ exit 1
69
+ }
70
+
71
+ # ═══════════════════════════════════
72
+ # [1/3] MCP server install
73
+ # ═══════════════════════════════════
74
+ Write-Step "1/3" "Install @weppy/roblox-mcp via npm"
75
+
76
+ if (Confirm-Action " Run npm install -g @weppy/roblox-mcp?") {
77
+ try {
78
+ npm install -g "@weppy/roblox-mcp"
79
+ Write-Ok "Installed @weppy/roblox-mcp"
80
+ }
81
+ catch {
82
+ Write-Fail "npm install failed: $_"
83
+ exit 1
84
+ }
85
+ }
86
+ else {
87
+ Write-Warn "MCP server install skipped"
88
+ }
89
+
90
+ # ═══════════════════════════════════
91
+ # [2/3] Roblox Studio Plugin install
92
+ # ═══════════════════════════════════
93
+ Write-Step "2/3" "Install Roblox Studio Plugin"
94
+
95
+ $pluginsDir = Join-Path $env:LOCALAPPDATA "Roblox\Plugins"
96
+ $pluginName = "WeppyRobloxMCP.rbxm"
97
+
98
+ # Search for .rbxm in npm global path
99
+ $npmPrefix = (npm prefix -g 2>$null).Trim()
100
+ $bundledPlugin = $null
101
+ $searchPaths = @(
102
+ (Join-Path $npmPrefix "node_modules\@weppy\roblox-mcp\plugins\weppy-roblox-mcp\roblox-plugin\$pluginName"),
103
+ (Join-Path $npmPrefix "node_modules\@weppy\roblox-mcp\roblox-plugin\$pluginName")
104
+ )
105
+ foreach ($p in $searchPaths) {
106
+ if (Test-Path $p) {
107
+ $bundledPlugin = $p
108
+ break
109
+ }
110
+ }
111
+
112
+ if ($bundledPlugin) {
113
+ Write-Host " → $pluginsDir\$pluginName"
114
+ if (Confirm-Action " Copy plugin to Roblox Plugins folder?") {
115
+ if (-not (Test-Path $pluginsDir)) {
116
+ New-Item -ItemType Directory -Path $pluginsDir -Force | Out-Null
117
+ }
118
+ Copy-Item $bundledPlugin -Destination (Join-Path $pluginsDir $pluginName) -Force
119
+ Write-Ok "Plugin installed → $pluginsDir\$pluginName"
120
+ }
121
+ else {
122
+ Write-Warn "Plugin install skipped"
123
+ }
124
+ }
125
+ else {
126
+ Write-Warn "Bundled plugin file not found"
127
+ Write-Info "Will be installed automatically on first MCP server run"
128
+ }
129
+
130
+ # ═══════════════════════════════════
131
+ # [3/3] Register MCP with AI apps
132
+ # ═══════════════════════════════════
133
+ Write-Step "3/3" "Register MCP with AI apps"
134
+
135
+ $detectedNames = @()
136
+ $detectedTypes = @()
137
+ $notDetected = @()
138
+
139
+ # Claude Code CLI
140
+ if (Get-Command claude -ErrorAction SilentlyContinue) {
141
+ $detectedNames += "Claude Code (CLI)"
142
+ $detectedTypes += "claude-code"
143
+ }
144
+ else {
145
+ $notDetected += "Claude Code CLI (not found)"
146
+ }
147
+
148
+ # Claude Desktop
149
+ $claudeDesktopConfig = Join-Path $env:APPDATA "Claude\claude_desktop_config.json"
150
+ if (Test-Path $claudeDesktopConfig) {
151
+ $detectedNames += "Claude Desktop"
152
+ $detectedTypes += "claude-desktop"
153
+ }
154
+ else {
155
+ $notDetected += "Claude Desktop (config not found)"
156
+ }
157
+
158
+ # Cursor (detect only when mcp.json or binary exists)
159
+ $cursorDir = Join-Path $env:USERPROFILE ".cursor"
160
+ if ((Test-Path (Join-Path $cursorDir "mcp.json")) -or (Get-Command cursor -ErrorAction SilentlyContinue)) {
161
+ $detectedNames += "Cursor"
162
+ $detectedTypes += "cursor"
163
+ }
164
+ else {
165
+ $notDetected += "Cursor (not found)"
166
+ }
167
+
168
+ # Codex CLI
169
+ if (Get-Command codex -ErrorAction SilentlyContinue) {
170
+ $detectedNames += "Codex CLI"
171
+ $detectedTypes += "codex-cli"
172
+ }
173
+ else {
174
+ $notDetected += "Codex CLI (not found)"
175
+ }
176
+
177
+ # Gemini CLI
178
+ if (Get-Command gemini -ErrorAction SilentlyContinue) {
179
+ $detectedNames += "Gemini CLI"
180
+ $detectedTypes += "gemini-cli"
181
+ }
182
+ else {
183
+ $notDetected += "Gemini CLI (not found)"
184
+ }
185
+
186
+ if ($detectedNames.Count -eq 0) {
187
+ Write-Warn "No AI apps detected"
188
+ Write-Info "Register MCP server manually: npx -y @weppy/roblox-mcp"
189
+ }
190
+ else {
191
+ Write-Host ""
192
+ Write-Host " Detected:" -ForegroundColor White
193
+ for ($i = 0; $i -lt $detectedNames.Count; $i++) {
194
+ Write-Host " $($i + 1). $($detectedNames[$i])" -ForegroundColor Green
195
+ }
196
+
197
+ if ($notDetected.Count -gt 0) {
198
+ Write-Host ""
199
+ Write-Host " Not detected:" -ForegroundColor DarkGray
200
+ foreach ($item in $notDetected) {
201
+ Write-Host " - $item" -ForegroundColor DarkGray
202
+ }
203
+ }
204
+
205
+ Write-Host ""
206
+ $selection = Read-Host " Select apps to register (comma-separated, 'a' for all, 'n' to skip)"
207
+ if ([string]::IsNullOrWhiteSpace($selection)) { $selection = "n" }
208
+
209
+ $selectedIndices = @()
210
+ switch -Regex ($selection) {
211
+ '^[Nn]$' { Write-Warn "MCP registration skipped" }
212
+ '^[Aa]$' { $selectedIndices = 0..($detectedNames.Count - 1) }
213
+ default {
214
+ foreach ($part in ($selection -split ',')) {
215
+ $part = $part.Trim()
216
+ if ($part -match '^\d+$') {
217
+ $idx = [int]$part - 1
218
+ if ($idx -ge 0 -and $idx -lt $detectedNames.Count) {
219
+ $selectedIndices += $idx
220
+ }
221
+ }
222
+ }
223
+ }
224
+ }
225
+
226
+ foreach ($idx in $selectedIndices) {
227
+ $appType = $detectedTypes[$idx]
228
+ $appName = $detectedNames[$idx]
229
+
230
+ try {
231
+ switch ($appType) {
232
+ "claude-code" {
233
+ claude mcp add weppy-roblox-mcp -- npx -y "@weppy/roblox-mcp"
234
+ Write-Ok "Registered: $appName"
235
+ }
236
+ "claude-desktop" {
237
+ Add-McpToConfig $claudeDesktopConfig
238
+ Write-Ok "Registered: $appName"
239
+ }
240
+ "cursor" {
241
+ $cursorConfig = Join-Path $env:USERPROFILE ".cursor\mcp.json"
242
+ Add-McpToConfig $cursorConfig
243
+ Write-Ok "Registered: $appName"
244
+ }
245
+ "codex-cli" {
246
+ try { codex mcp remove weppy-roblox-mcp *> $null } catch {}
247
+ codex mcp add weppy-roblox-mcp -- npx -y "@weppy/roblox-mcp"
248
+ Write-Ok "Registered: $appName"
249
+ }
250
+ "gemini-cli" {
251
+ # Config path/format is best-effort — update when CLI stabilizes
252
+ $geminiConfig = Join-Path $env:USERPROFILE ".gemini\settings.json"
253
+ Add-McpToConfig $geminiConfig
254
+ Write-Ok "Registered: $appName"
255
+ }
256
+ }
257
+ }
258
+ catch {
259
+ Write-Fail "Failed: $appName ($_)"
260
+ }
261
+ }
262
+ }
263
+
264
+ # ═══════════════════════════════════
265
+ # Installation summary
266
+ # ═══════════════════════════════════
267
+ Write-Host ""
268
+ Write-Host ("=" * 40)
269
+ Write-Host "Installation complete!" -ForegroundColor Green
270
+ Write-Host ""
271
+ Write-Host " Next steps:"
272
+ Write-Host " 1. Restart Roblox Studio"
273
+ Write-Host " 2. Look for the W-MCP button in the Plugins tab"
274
+ Write-Host " 3. Click Connect and start building with AI!"
275
+ Write-Host ""
276
+ Write-Host " Docs: https://github.com/hope1026/weppy-roblox-mcp" -ForegroundColor DarkGray
277
+ Write-Host ""
package/install.sh ADDED
@@ -0,0 +1,306 @@
1
+ #!/usr/bin/env bash
2
+ #
3
+ # Weppy Roblox MCP — One-line install script (macOS/Linux)
4
+ #
5
+ # Usage:
6
+ # curl -fsSL https://raw.githubusercontent.com/hope1026/weppy-roblox-mcp/main/install.sh | bash
7
+ #
8
+ # Interactive 3 steps:
9
+ # [1/3] MCP server install (npm)
10
+ # [2/3] Roblox Studio Plugin install (.rbxm)
11
+ # [3/3] Register MCP with AI apps (user selection)
12
+ #
13
+
14
+ set -euo pipefail
15
+
16
+ # ── Color definitions ──
17
+ GREEN='\033[0;32m'
18
+ YELLOW='\033[0;33m'
19
+ RED='\033[0;31m'
20
+ BLUE='\033[0;34m'
21
+ CYAN='\033[0;36m'
22
+ DIM='\033[2m'
23
+ BOLD='\033[1m'
24
+ NC='\033[0m'
25
+
26
+ # ── Utilities ──
27
+ # shellcheck disable=SC2059
28
+ info() { printf "${BLUE}[INFO]${NC} %s\n" "$1"; }
29
+ # shellcheck disable=SC2059
30
+ success() { printf "${GREEN} ✓${NC} %s\n" "$1"; }
31
+ # shellcheck disable=SC2059
32
+ warn() { printf "${YELLOW} ⚠${NC} %s\n" "$1"; }
33
+ # shellcheck disable=SC2059
34
+ fail() { printf "${RED} ✗${NC} %s\n" "$1"; }
35
+ # shellcheck disable=SC2059
36
+ step() { printf "\n${BOLD}${CYAN}[%s]${NC} ${BOLD}%s${NC}\n" "$1" "$2"; }
37
+
38
+ # Y/n prompt (default Y)
39
+ confirm() {
40
+ local prompt="$1"
41
+ local reply
42
+ printf "%s (Y/n): " "$prompt"
43
+ read -r reply </dev/tty
44
+ reply="${reply:-Y}"
45
+ case "$reply" in
46
+ [Yy]*) return 0 ;;
47
+ *) return 1 ;;
48
+ esac
49
+ }
50
+
51
+ # Add MCP server to JSON config file (path via env var — prevents shell injection)
52
+ add_mcp_to_config() {
53
+ local config_path="$1"
54
+ local parent_dir
55
+ parent_dir=$(dirname "$config_path")
56
+ mkdir -p "$parent_dir"
57
+ MCP_CONFIG_PATH="$config_path" node -e '
58
+ const fs = require("fs");
59
+ const configPath = process.env.MCP_CONFIG_PATH;
60
+ let config = {};
61
+ try { config = JSON.parse(fs.readFileSync(configPath, "utf8")); } catch {}
62
+ if (!config.mcpServers) config.mcpServers = {};
63
+ config.mcpServers["weppy-roblox-mcp"] = { command: "npx", args: ["-y", "@weppy/roblox-mcp"] };
64
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
65
+ '
66
+ }
67
+
68
+ # ── Header ──
69
+ # shellcheck disable=SC2059
70
+ printf "\n${BOLD}Weppy Roblox MCP Installer${NC}\n"
71
+ # shellcheck disable=SC2059
72
+ printf "${DIM}AI-powered Roblox Studio integration${NC}\n"
73
+ printf "%s\n" "════════════════════════════════════"
74
+
75
+ # ── Node.js check ──
76
+ if ! command -v node &>/dev/null; then
77
+ fail "Node.js is not installed"
78
+ printf " Install Node.js 18+: https://nodejs.org\n"
79
+ exit 1
80
+ fi
81
+
82
+ NODE_VERSION=$(node -v | sed 's/v//' | cut -d. -f1)
83
+ if [ "$NODE_VERSION" -lt 18 ]; then
84
+ fail "Node.js 18 or higher required (current: $(node -v))"
85
+ printf " Upgrade: https://nodejs.org\n"
86
+ exit 1
87
+ fi
88
+ success "Node.js $(node -v) detected"
89
+
90
+ # ═══════════════════════════════════
91
+ # [1/3] MCP server install
92
+ # ═══════════════════════════════════
93
+ step "1/3" "Install @weppy/roblox-mcp via npm"
94
+
95
+ if confirm " Run npm install -g @weppy/roblox-mcp?"; then
96
+ if npm install -g @weppy/roblox-mcp; then
97
+ success "Installed @weppy/roblox-mcp"
98
+ else
99
+ fail "npm install failed"
100
+ exit 1
101
+ fi
102
+ else
103
+ warn "MCP server install skipped"
104
+ fi
105
+
106
+ # ═══════════════════════════════════
107
+ # [2/3] Roblox Studio Plugin install
108
+ # ═══════════════════════════════════
109
+ step "2/3" "Install Roblox Studio Plugin"
110
+
111
+ PLUGINS_DIR="$HOME/Documents/Roblox/Plugins"
112
+ PLUGIN_NAME="WeppyRobloxMCP.rbxm"
113
+
114
+ # Search for .rbxm in npm global prefix
115
+ NPM_PREFIX=$(npm prefix -g 2>/dev/null)
116
+ BUNDLED_PLUGIN=""
117
+
118
+ # Search for .rbxm in npm global path
119
+ for search_dir in \
120
+ "${NPM_PREFIX}/lib/node_modules/@weppy/roblox-mcp/plugins/weppy-roblox-mcp/roblox-plugin" \
121
+ "${NPM_PREFIX}/lib/node_modules/@weppy/roblox-mcp/roblox-plugin"; do
122
+ if [ -f "${search_dir}/${PLUGIN_NAME}" ]; then
123
+ BUNDLED_PLUGIN="${search_dir}/${PLUGIN_NAME}"
124
+ break
125
+ fi
126
+ done
127
+
128
+ if [ -n "$BUNDLED_PLUGIN" ]; then
129
+ printf " → %s/%s\n" "$PLUGINS_DIR" "$PLUGIN_NAME"
130
+ if confirm " Copy plugin to Roblox Plugins folder?"; then
131
+ mkdir -p "$PLUGINS_DIR"
132
+ cp "$BUNDLED_PLUGIN" "$PLUGINS_DIR/$PLUGIN_NAME"
133
+ success "Plugin installed → $PLUGINS_DIR/$PLUGIN_NAME"
134
+ else
135
+ warn "Plugin install skipped"
136
+ fi
137
+ else
138
+ warn "Bundled plugin file not found"
139
+ info "Will be installed automatically on first MCP server run"
140
+ fi
141
+
142
+ # ═══════════════════════════════════
143
+ # [3/3] Register MCP with AI apps
144
+ # ═══════════════════════════════════
145
+ step "3/3" "Register MCP with AI apps"
146
+
147
+ MCP_COMMAND='npx -y @weppy/roblox-mcp'
148
+
149
+ # AI app detection
150
+ declare -a DETECTED_NAMES=()
151
+ declare -a DETECTED_TYPES=()
152
+ declare -a NOT_DETECTED=()
153
+
154
+ # Claude Code CLI
155
+ if command -v claude &>/dev/null; then
156
+ DETECTED_NAMES+=("Claude Code (CLI)")
157
+ DETECTED_TYPES+=("claude-code")
158
+ fi
159
+
160
+ # Claude Desktop (macOS)
161
+ CLAUDE_DESKTOP_CONFIG="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
162
+ if [ -f "$CLAUDE_DESKTOP_CONFIG" ]; then
163
+ DETECTED_NAMES+=("Claude Desktop")
164
+ DETECTED_TYPES+=("claude-desktop")
165
+ elif [ "$(uname)" = "Darwin" ]; then
166
+ NOT_DETECTED+=("Claude Desktop (config not found)")
167
+ fi
168
+
169
+ # Cursor (detect only when mcp.json or binary exists)
170
+ CURSOR_MCP_CONFIG="$HOME/.cursor/mcp.json"
171
+ if [ -f "$CURSOR_MCP_CONFIG" ] || command -v cursor &>/dev/null; then
172
+ DETECTED_NAMES+=("Cursor")
173
+ DETECTED_TYPES+=("cursor")
174
+ else
175
+ NOT_DETECTED+=("Cursor (not found)")
176
+ fi
177
+
178
+ # Codex CLI
179
+ if command -v codex &>/dev/null; then
180
+ DETECTED_NAMES+=("Codex CLI")
181
+ DETECTED_TYPES+=("codex-cli")
182
+ else
183
+ NOT_DETECTED+=("Codex CLI (not found)")
184
+ fi
185
+
186
+ # Gemini CLI
187
+ if command -v gemini &>/dev/null; then
188
+ DETECTED_NAMES+=("Gemini CLI")
189
+ DETECTED_TYPES+=("gemini-cli")
190
+ else
191
+ NOT_DETECTED+=("Gemini CLI (not found)")
192
+ fi
193
+
194
+ if [ ${#DETECTED_NAMES[@]} -eq 0 ]; then
195
+ warn "No AI apps detected"
196
+ info "Register MCP server manually: $MCP_COMMAND"
197
+ else
198
+ # shellcheck disable=SC2059
199
+ printf "\n ${BOLD}Detected:${NC}\n"
200
+ for i in "${!DETECTED_NAMES[@]}"; do
201
+ # shellcheck disable=SC2059
202
+ printf " ${GREEN}%d.${NC} %s\n" "$((i + 1))" "${DETECTED_NAMES[$i]}"
203
+ done
204
+
205
+ if [ ${#NOT_DETECTED[@]} -gt 0 ]; then
206
+ # shellcheck disable=SC2059
207
+ printf "\n ${DIM}Not detected:${NC}\n"
208
+ for item in "${NOT_DETECTED[@]}"; do
209
+ # shellcheck disable=SC2059
210
+ printf " ${DIM}- %s${NC}\n" "$item"
211
+ done
212
+ fi
213
+
214
+ # shellcheck disable=SC2059
215
+ printf "\n Select apps to register ${DIM}(comma-separated, 'a' for all, 'n' to skip)${NC}\n"
216
+ printf " → "
217
+ read -r selection </dev/tty
218
+ selection="${selection:-n}"
219
+
220
+ # Parse selection
221
+ declare -a SELECTED_INDICES=()
222
+ case "$selection" in
223
+ [Nn])
224
+ warn "MCP registration skipped"
225
+ ;;
226
+ [Aa])
227
+ for i in "${!DETECTED_NAMES[@]}"; do
228
+ SELECTED_INDICES+=("$i")
229
+ done
230
+ ;;
231
+ *)
232
+ IFS=',' read -ra PARTS <<< "$selection"
233
+ for part in "${PARTS[@]}"; do
234
+ part=$(echo "$part" | tr -d ' ')
235
+ if [[ "$part" =~ ^[0-9]+$ ]]; then
236
+ idx=$((part - 1))
237
+ if [ "$idx" -ge 0 ] && [ "$idx" -lt ${#DETECTED_NAMES[@]} ]; then
238
+ SELECTED_INDICES+=("$idx")
239
+ fi
240
+ fi
241
+ done
242
+ ;;
243
+ esac
244
+
245
+ # Register selected apps
246
+ for idx in "${SELECTED_INDICES[@]}"; do
247
+ app_type="${DETECTED_TYPES[$idx]}"
248
+ app_name="${DETECTED_NAMES[$idx]}"
249
+
250
+ case "$app_type" in
251
+ claude-code)
252
+ if claude mcp add weppy-roblox-mcp -- npx -y @weppy/roblox-mcp 2>/dev/null; then
253
+ success "Registered: $app_name"
254
+ else
255
+ fail "Failed: $app_name"
256
+ fi
257
+ ;;
258
+ claude-desktop)
259
+ if add_mcp_to_config "$CLAUDE_DESKTOP_CONFIG"; then
260
+ success "Registered: $app_name"
261
+ else
262
+ fail "Failed: $app_name"
263
+ fi
264
+ ;;
265
+ cursor)
266
+ if add_mcp_to_config "$HOME/.cursor/mcp.json"; then
267
+ success "Registered: $app_name"
268
+ else
269
+ fail "Failed: $app_name"
270
+ fi
271
+ ;;
272
+ codex-cli)
273
+ codex mcp remove weppy-roblox-mcp >/dev/null 2>&1 || true
274
+ if codex mcp add weppy-roblox-mcp -- npx -y @weppy/roblox-mcp 2>/dev/null; then
275
+ success "Registered: $app_name"
276
+ else
277
+ fail "Failed: $app_name"
278
+ fi
279
+ ;;
280
+ gemini-cli)
281
+ # Config path/format is best-effort — update when CLI stabilizes
282
+ if add_mcp_to_config "$HOME/.gemini/settings.json"; then
283
+ success "Registered: $app_name"
284
+ else
285
+ fail "Failed: $app_name"
286
+ fi
287
+ ;;
288
+ esac
289
+ done
290
+ fi
291
+
292
+ # ═══════════════════════════════════
293
+ # Installation summary
294
+ # ═══════════════════════════════════
295
+ # shellcheck disable=SC2059
296
+ printf "\n%s\n" "════════════════════════════════════"
297
+ # shellcheck disable=SC2059
298
+ printf "${BOLD}Installation complete!${NC}\n\n"
299
+ # shellcheck disable=SC2059
300
+ printf " ${BOLD}Next steps:${NC}\n"
301
+ printf " 1. Restart Roblox Studio\n"
302
+ # shellcheck disable=SC2059
303
+ printf " 2. Look for the ${BOLD}W-MCP${NC} button in the Plugins tab\n"
304
+ printf " 3. Click Connect and start building with AI!\n\n"
305
+ # shellcheck disable=SC2059
306
+ printf " ${DIM}Docs: https://github.com/hope1026/weppy-roblox-mcp${NC}\n\n"