@weppy/roblox-mcp 2.0.0 → 2.0.2

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 +19 -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 +307 -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-BOp7G4Fi.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-DS-g_EC0.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-qdFEmTM4.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-CC_OzjmT.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-DzFynur7.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-CckH43fU.js → tier-promo-config-B9lIKWCQ.js} +1 -1
  72. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/{useLiveUptime-DZCw70vn.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-DGhZm1j7.js +0 -1
  78. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConnectionPage-CkQVyTc5.css +0 -1
  79. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ConnectionPage-DXv_C7i6.js +0 -1
  80. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/InfoLabel-CszBT8rJ.js +0 -1
  81. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/PlaytestPage-C4X6-jp-.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-BtjNT-j0.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-BOYoftuM.js +0 -4
  87. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/TierPromoProgress-DkpXj7Ui.js +0 -1
  88. package/plugins/weppy-roblox-mcp/dashboard/dist/assets/ToolsPage-CZsA-7CL.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-BYvG5KEz.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,307 @@
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
+ INSTALLED_VERSION=$(npx -y @weppy/roblox-mcp --version 2>/dev/null || echo "unknown")
98
+ success "Installed @weppy/roblox-mcp (${INSTALLED_VERSION})"
99
+ else
100
+ fail "npm install failed"
101
+ exit 1
102
+ fi
103
+ else
104
+ warn "MCP server install skipped"
105
+ fi
106
+
107
+ # ═══════════════════════════════════
108
+ # [2/3] Roblox Studio Plugin install
109
+ # ═══════════════════════════════════
110
+ step "2/3" "Install Roblox Studio Plugin"
111
+
112
+ PLUGINS_DIR="$HOME/Documents/Roblox/Plugins"
113
+ PLUGIN_NAME="WeppyRobloxMCP.rbxm"
114
+
115
+ # Search for .rbxm in npm global prefix
116
+ NPM_PREFIX=$(npm prefix -g 2>/dev/null)
117
+ BUNDLED_PLUGIN=""
118
+
119
+ # Search for .rbxm in npm global path
120
+ for search_dir in \
121
+ "${NPM_PREFIX}/lib/node_modules/@weppy/roblox-mcp/plugins/weppy-roblox-mcp/roblox-plugin" \
122
+ "${NPM_PREFIX}/lib/node_modules/@weppy/roblox-mcp/roblox-plugin"; do
123
+ if [ -f "${search_dir}/${PLUGIN_NAME}" ]; then
124
+ BUNDLED_PLUGIN="${search_dir}/${PLUGIN_NAME}"
125
+ break
126
+ fi
127
+ done
128
+
129
+ if [ -n "$BUNDLED_PLUGIN" ]; then
130
+ printf " → %s/%s\n" "$PLUGINS_DIR" "$PLUGIN_NAME"
131
+ if confirm " Copy plugin to Roblox Plugins folder?"; then
132
+ mkdir -p "$PLUGINS_DIR"
133
+ cp "$BUNDLED_PLUGIN" "$PLUGINS_DIR/$PLUGIN_NAME"
134
+ success "Plugin installed → $PLUGINS_DIR/$PLUGIN_NAME"
135
+ else
136
+ warn "Plugin install skipped"
137
+ fi
138
+ else
139
+ warn "Bundled plugin file not found"
140
+ info "Will be installed automatically on first MCP server run"
141
+ fi
142
+
143
+ # ═══════════════════════════════════
144
+ # [3/3] Register MCP with AI apps
145
+ # ═══════════════════════════════════
146
+ step "3/3" "Register MCP with AI apps"
147
+
148
+ MCP_COMMAND='npx -y @weppy/roblox-mcp'
149
+
150
+ # AI app detection
151
+ declare -a DETECTED_NAMES=()
152
+ declare -a DETECTED_TYPES=()
153
+ declare -a NOT_DETECTED=()
154
+
155
+ # Claude Code CLI
156
+ if command -v claude &>/dev/null; then
157
+ DETECTED_NAMES+=("Claude Code (CLI)")
158
+ DETECTED_TYPES+=("claude-code")
159
+ fi
160
+
161
+ # Claude Desktop (macOS)
162
+ CLAUDE_DESKTOP_CONFIG="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
163
+ if [ -f "$CLAUDE_DESKTOP_CONFIG" ]; then
164
+ DETECTED_NAMES+=("Claude Desktop")
165
+ DETECTED_TYPES+=("claude-desktop")
166
+ elif [ "$(uname)" = "Darwin" ]; then
167
+ NOT_DETECTED+=("Claude Desktop (config not found)")
168
+ fi
169
+
170
+ # Cursor (detect only when mcp.json or binary exists)
171
+ CURSOR_MCP_CONFIG="$HOME/.cursor/mcp.json"
172
+ if [ -f "$CURSOR_MCP_CONFIG" ] || command -v cursor &>/dev/null; then
173
+ DETECTED_NAMES+=("Cursor")
174
+ DETECTED_TYPES+=("cursor")
175
+ else
176
+ NOT_DETECTED+=("Cursor (not found)")
177
+ fi
178
+
179
+ # Codex CLI
180
+ if command -v codex &>/dev/null; then
181
+ DETECTED_NAMES+=("Codex CLI")
182
+ DETECTED_TYPES+=("codex-cli")
183
+ else
184
+ NOT_DETECTED+=("Codex CLI (not found)")
185
+ fi
186
+
187
+ # Gemini CLI
188
+ if command -v gemini &>/dev/null; then
189
+ DETECTED_NAMES+=("Gemini CLI")
190
+ DETECTED_TYPES+=("gemini-cli")
191
+ else
192
+ NOT_DETECTED+=("Gemini CLI (not found)")
193
+ fi
194
+
195
+ if [ ${#DETECTED_NAMES[@]} -eq 0 ]; then
196
+ warn "No AI apps detected"
197
+ info "Register MCP server manually: $MCP_COMMAND"
198
+ else
199
+ # shellcheck disable=SC2059
200
+ printf "\n ${BOLD}Detected:${NC}\n"
201
+ for i in "${!DETECTED_NAMES[@]}"; do
202
+ # shellcheck disable=SC2059
203
+ printf " ${GREEN}%d.${NC} %s\n" "$((i + 1))" "${DETECTED_NAMES[$i]}"
204
+ done
205
+
206
+ if [ ${#NOT_DETECTED[@]} -gt 0 ]; then
207
+ # shellcheck disable=SC2059
208
+ printf "\n ${DIM}Not detected:${NC}\n"
209
+ for item in "${NOT_DETECTED[@]}"; do
210
+ # shellcheck disable=SC2059
211
+ printf " ${DIM}- %s${NC}\n" "$item"
212
+ done
213
+ fi
214
+
215
+ # shellcheck disable=SC2059
216
+ printf "\n Select apps to register ${DIM}(comma-separated, 'a' for all, 'n' to skip)${NC}\n"
217
+ printf " → "
218
+ read -r selection </dev/tty
219
+ selection="${selection:-n}"
220
+
221
+ # Parse selection
222
+ declare -a SELECTED_INDICES=()
223
+ case "$selection" in
224
+ [Nn])
225
+ warn "MCP registration skipped"
226
+ ;;
227
+ [Aa])
228
+ for i in "${!DETECTED_NAMES[@]}"; do
229
+ SELECTED_INDICES+=("$i")
230
+ done
231
+ ;;
232
+ *)
233
+ IFS=',' read -ra PARTS <<< "$selection"
234
+ for part in "${PARTS[@]}"; do
235
+ part=$(echo "$part" | tr -d ' ')
236
+ if [[ "$part" =~ ^[0-9]+$ ]]; then
237
+ idx=$((part - 1))
238
+ if [ "$idx" -ge 0 ] && [ "$idx" -lt ${#DETECTED_NAMES[@]} ]; then
239
+ SELECTED_INDICES+=("$idx")
240
+ fi
241
+ fi
242
+ done
243
+ ;;
244
+ esac
245
+
246
+ # Register selected apps
247
+ for idx in "${SELECTED_INDICES[@]}"; do
248
+ app_type="${DETECTED_TYPES[$idx]}"
249
+ app_name="${DETECTED_NAMES[$idx]}"
250
+
251
+ case "$app_type" in
252
+ claude-code)
253
+ if claude mcp add weppy-roblox-mcp -- npx -y @weppy/roblox-mcp 2>/dev/null; then
254
+ success "Registered: $app_name"
255
+ else
256
+ fail "Failed: $app_name"
257
+ fi
258
+ ;;
259
+ claude-desktop)
260
+ if add_mcp_to_config "$CLAUDE_DESKTOP_CONFIG"; then
261
+ success "Registered: $app_name"
262
+ else
263
+ fail "Failed: $app_name"
264
+ fi
265
+ ;;
266
+ cursor)
267
+ if add_mcp_to_config "$HOME/.cursor/mcp.json"; then
268
+ success "Registered: $app_name"
269
+ else
270
+ fail "Failed: $app_name"
271
+ fi
272
+ ;;
273
+ codex-cli)
274
+ codex mcp remove weppy-roblox-mcp >/dev/null 2>&1 || true
275
+ if codex mcp add weppy-roblox-mcp -- npx -y @weppy/roblox-mcp 2>/dev/null; then
276
+ success "Registered: $app_name"
277
+ else
278
+ fail "Failed: $app_name"
279
+ fi
280
+ ;;
281
+ gemini-cli)
282
+ # Config path/format is best-effort — update when CLI stabilizes
283
+ if add_mcp_to_config "$HOME/.gemini/settings.json"; then
284
+ success "Registered: $app_name"
285
+ else
286
+ fail "Failed: $app_name"
287
+ fi
288
+ ;;
289
+ esac
290
+ done
291
+ fi
292
+
293
+ # ═══════════════════════════════════
294
+ # Installation summary
295
+ # ═══════════════════════════════════
296
+ # shellcheck disable=SC2059
297
+ printf "\n%s\n" "════════════════════════════════════"
298
+ # shellcheck disable=SC2059
299
+ printf "${BOLD}Installation complete!${NC}\n\n"
300
+ # shellcheck disable=SC2059
301
+ printf " ${BOLD}Next steps:${NC}\n"
302
+ printf " 1. Restart Roblox Studio\n"
303
+ # shellcheck disable=SC2059
304
+ printf " 2. Look for the ${BOLD}W-MCP${NC} button in the Plugins tab\n"
305
+ printf " 3. Click Connect and start building with AI!\n\n"
306
+ # shellcheck disable=SC2059
307
+ printf " ${DIM}Docs: https://github.com/hope1026/weppy-roblox-mcp${NC}\n\n"