@adiholick/nvstudio-mcp 2.0.1 → 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.
package/README.md CHANGED
@@ -8,9 +8,14 @@ Sistem ini didesain menggunakan **Hybrid Architecture** yang memisahkan logika E
8
8
 
9
9
  ## 📥 Instalasi
10
10
 
11
- Langkah instalasinya **sangat gampang!**
11
+ Langkah instalasi dirancang **sangat mudah dan otomatis!**
12
12
 
13
- ### 1. Jalankan Installer (Otomatis)
13
+ > 💡 **Apakah perlu install plugin Roblox secara manual?**
14
+ > **TIDAK PERLU.** Jika Anda menjalankan skrip installer di bawah (Langkah 1), installer akan **secara otomatis menyalin plugin (`nvstudio_mcp.rbxmx`)** langsung ke folder plugin Roblox Studio di sistem operasi Anda.
15
+
16
+ ---
17
+
18
+ ### Langkah 1: Jalankan Installer (Otomatis & Direkomendasikan)
14
19
 
15
20
  Pilih perintah sesuai terminal yang Anda gunakan:
16
21
 
@@ -24,25 +29,40 @@ irm https://raw.githubusercontent.com/Adiholick/nvstudio-mcp/main/install.ps1 |
24
29
  curl -fsSL https://raw.githubusercontent.com/Adiholick/nvstudio-mcp/main/install.sh | bash
25
30
  ```
26
31
 
32
+ **Apa saja yang dilakukan installer ini secara otomatis?**
33
+ 1. 📦 Mengunduh source code, memasang dependensi Node.js, dan mengkompilasi TypeScript (*Bridge Server*).
34
+ 2. 🧩 **Memasang Plugin Roblox Studio (`nvstudio_mcp.rbxmx`) otomatis** ke folder sistem Roblox Studio Anda (`%LOCALAPPDATA%\Roblox\Plugins` di Windows atau `~/Documents/ROBLOX/Plugins` di macOS).
35
+ 3. 🤖 Mengintegrasikan *AI Agent Skills* anti-halusinasi langsung ke **Antigravity IDE** (`~/.gemini/config/plugins/nvstudio-mcp`).
36
+ 4. ⚙️ Melakukan auto-konfigurasi jika mendeteksi editor **Cursor** (`.cursor/mcp.json`).
27
37
 
28
- **Installer ini akan secara otomatis melakukan hal berikut:**
29
- - Memasang dependensi Node.js dan melakukan kompilasi TypeScript (*Bridge Server*).
30
- - Menyalin file plugin `nvstudio_mcp.rbxmx` ke dalam sistem Plugin Roblox Studio di OS Anda (Windows/macOS/WSL) secara otomatis.
31
- - Mengintegrasikan *AI Agent Skills* langsung ke **Antigravity IDE** (`~/.gemini/config/plugins/nvstudio-mcp`).
32
- - Melakukan auto-konfigurasi JSON jika Anda menggunakan **Cursor Editor**.
38
+ ---
33
39
 
34
- ### 2. Mengaktifkan Izin di Roblox Studio
35
- 1. Buka proyek game Anda di Roblox Studio.
36
- 2. Di pojok kiri atas, buka **Home** -> **Game Settings** -> **Security**.
37
- 3. Centang (aktifkan) opsi **`Allow HTTP Requests`** agar plugin dapat berkomunikasi dengan AI.
40
+ ### Langkah 2: Mengaktifkan Izin di Roblox Studio (Wajib)
41
+
42
+ Karena pembatasan keamanan bawaan Roblox Studio, akses HTTP harus diizinkan sekali per place/game:
43
+ 1. Buka game/place Anda di **Roblox Studio**.
44
+ 2. Di toolbar atas, buka tab **Home** ➔ **Game Settings** ➔ pilih menu **Security**.
45
+ 3. Centang (aktifkan) **`Allow HTTP Requests`**, lalu klik **Save**.
46
+ 4. **Auto-Detect Aktif!** Plugin Roblox Studio kini memiliki heartbeat pintar yang akan otomatis terhubung (*Auto-Connect*) segera setelah MCP server aktif — Anda tidak perlu lagi repot menekan tombol connect secara manual.
38
47
 
39
48
  ---
40
49
 
41
- ## 🔌 Cara Menggunakan (Untuk AI Lain)
50
+ ### 📂 Alternatif: Instalasi Plugin Secara Manual (Opsional)
51
+
52
+ Jika Anda **tidak** menggunakan skrip installer otomatis di atas (misalnya hanya menambahkan server via `npx` di klien AI), pasang file plugin Roblox Studio secara manual:
53
+ 1. Ambil file `nvstudio_mcp.rbxmx` dari folder [studio-plugin/nvstudio_mcp.rbxmx](file:///studio-plugin/nvstudio_mcp.rbxmx).
54
+ 2. Pindahkan/salin file tersebut ke direktori plugin Roblox di komputer Anda:
55
+ - **Windows:** `%LOCALAPPDATA%\Roblox\Plugins` (atau `C:\Users\<Username>\AppData\Local\Roblox\Plugins`)
56
+ - **macOS:** `~/Documents/ROBLOX/Plugins`
57
+ 3. Restart atau buka kembali Roblox Studio. Plugin akan muncul di tab **Plugins**.
42
58
 
43
- Jika Anda menggunakan AI Client lain (misalnya: **Claude Desktop** atau klien yang tidak dikonfigurasi otomatis), Anda dapat menambahkan `nvstudio-mcp` secara manual ke konfigurasi `mcp.json` Anda.
59
+ ---
44
60
 
45
- Salin konfigurasi ini:
61
+ ## 🔌 Cara Menggunakan (Konfigurasi MCP Klien AI)
62
+
63
+ Jika Anda menggunakan AI Client lain seperti **Claude Desktop**, **Windsurf**, atau ingin menambahkan konfigurasi secara manual:
64
+
65
+ Tambahkan konfigurasi berikut ke file `mcp.json` Anda:
46
66
  ```json
47
67
  {
48
68
  "mcpServers": {
@@ -56,7 +76,15 @@ Salin konfigurasi ini:
56
76
  }
57
77
  }
58
78
  ```
59
- *(Dengan ini, AI Anda akan selalu mengunduh dan menjalankan versi terbaru dari server Bridge langsung dari NPM, tanpa perlu path folder lokal!)*
79
+ *(AI Anda akan selalu menjalankan versi terbaru dari server Bridge langsung dari NPM!)*
80
+
81
+ ---
82
+
83
+ ## 🖥️ Dashboard Visual & Fitur Pintar v2.0
84
+
85
+ - **Visual Dashboard Real-time:** Buka [http://localhost:3055](http://localhost:3055) di browser Anda untuk melihat monitor antrean perintah, log aktivitas AI, status koneksi Studio, dan statistik eksekusi secara visual.
86
+ - **Auto-Detect & Auto-Connect:** Plugin Roblox Studio otomatis menyambung ke server saat aktif dan kembali menunggu (*Waiting*) saat server mati tanpa interupsi manual.
87
+ - **Anti-Zombie Port Handling:** Tidak perlu khawatir error `EADDRINUSE`. Jika port `3055` tertahan oleh proses zombie akibat restart editor/IDE, server akan otomatis membersihkan port tersebut secara aman.
60
88
 
61
89
  ---
62
90
 
@@ -39,7 +39,7 @@ function buildRbxmx() {
39
39
  xml += `\t\t\t<bool name="DefinesCapabilities">false</bool>\n`;
40
40
  xml += `\t\t\t<string name="Name">nvstudio_mcp</string>\n`;
41
41
  xml += `\t\t\t<int64 name="SourceAssetId">-1</int64>\n`;
42
- xml += `\t\t\t<SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>\n`;
42
+ xml += `\t\t\t<SharedString name="Tags"></SharedString>\n`;
43
43
  xml += `\t\t</Properties>\n`;
44
44
  // Process files
45
45
  for (const file of files) {
@@ -49,8 +49,9 @@ function buildRbxmx() {
49
49
  // Main.server.lua is a Script, others are ModuleScripts
50
50
  const isMain = name === 'Main.server';
51
51
  const className = isMain ? 'Script' : 'ModuleScript';
52
- // Use a simple hash-like referent
53
- const referent = `RBX_${name.replace(/[^a-zA-Z0-9]/g, '_')}`;
52
+ const scriptName = isMain ? 'Main' : name;
53
+ // Use a clean referent
54
+ const referent = `RBX_${scriptName.replace(/[^a-zA-Z0-9]/g, '_')}`;
54
55
  xml += `\t\t<Item class="${className}" referent="${referent}">\n`;
55
56
  xml += `\t\t\t<Properties>\n`;
56
57
  xml += `\t\t\t\t<BinaryString name="AttributesSerialize"></BinaryString>\n`;
@@ -58,7 +59,7 @@ function buildRbxmx() {
58
59
  xml += `\t\t\t\t<bool name="DefinesCapabilities">false</bool>\n`;
59
60
  xml += `\t\t\t\t<bool name="Disabled">false</bool>\n`;
60
61
  xml += `\t\t\t\t<Content name="LinkedSource"><null></null></Content>\n`;
61
- xml += `\t\t\t\t<string name="Name">${name}</string>\n`;
62
+ xml += `\t\t\t\t<string name="Name">${scriptName}</string>\n`;
62
63
  xml += `\t\t\t\t<int64 name="SourceAssetId">-1</int64>\n`;
63
64
  xml += `\t\t\t\t<SharedString name="Tags"></SharedString>\n`;
64
65
  if (isMain) {
@@ -73,11 +74,7 @@ function buildRbxmx() {
73
74
  }
74
75
  // Close Folder
75
76
  xml += `\t</Item>\n`;
76
- // Shared Strings definition (required by Roblox XML format if Tags is used)
77
- xml += `\t<SharedStrings>\n`;
78
- xml += `\t\t<SharedString md5="yuZpQdnvvUBOTYh1jqZ2cA=="></SharedString>\n`;
79
- xml += `\t</SharedStrings>\n`;
80
- // Close Roblox
77
+ // Close Roblox root (No SharedStrings block needed when all Tags are empty)
81
78
  xml += `</roblox>\n`;
82
79
  fs_1.default.writeFileSync(OUTPUT_FILE, xml, 'utf-8');
83
80
  console.log(`[Build] Berhasil membuat ${OUTPUT_FILE}`);
@@ -111,5 +108,14 @@ function copyToRobloxPlugins() {
111
108
  else {
112
109
  console.log(`[Build] Platform ${process.platform} tidak didukung untuk auto-copy plugin.`);
113
110
  }
111
+ // Also update ~/.nvstudio-mcp/studio-plugin/nvstudio_mcp.rbxmx if present
112
+ const homeClonePlugin = path_1.default.join(os_1.default.homedir(), '.nvstudio-mcp', 'studio-plugin', 'nvstudio_mcp.rbxmx');
113
+ if (fs_1.default.existsSync(path_1.default.dirname(homeClonePlugin))) {
114
+ try {
115
+ fs_1.default.copyFileSync(OUTPUT_FILE, homeClonePlugin);
116
+ console.log(`[Build] ✅ Berhasil memperbarui ${homeClonePlugin}`);
117
+ }
118
+ catch { }
119
+ }
114
120
  }
115
121
  buildRbxmx();
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@adiholick/nvstudio-mcp",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "description": "Local Bridge Server MCP for Roblox Studio",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "nvstudio-mcp": "./dist/index.js"
7
+ "nvstudio-mcp": "dist/index.js"
8
8
  },
9
9
  "files": [
10
10
  "dist",
@@ -13,7 +13,7 @@ local ui = nil
13
13
 
14
14
  -- Membangun Tombol Toolbar (Toggle)
15
15
  local toolbar = plugin:CreateToolbar("NVStudio MCP")
16
- local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722")
16
+ local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722", "NVStudio")
17
17
 
18
18
  -- Global State & Context AI
19
19
  local ctx = {
@@ -41,6 +41,14 @@ if uiModule then
41
41
  ui:setAutoConnectState(autoConnect)
42
42
  ui:setStatus("disconnected")
43
43
 
44
+ -- Sync state tombol toolbar dengan status widget
45
+ if ui.widget then
46
+ toggleBtn:SetActive(ui.widget.Enabled)
47
+ ui.widget:GetPropertyChangedSignal("Enabled"):Connect(function()
48
+ toggleBtn:SetActive(ui.widget.Enabled)
49
+ end)
50
+ end
51
+
44
52
  -- Event Toggle GUI Panel
45
53
  toggleBtn.Click:Connect(function()
46
54
  ui:toggleVisibility()
@@ -8,7 +8,7 @@
8
8
  <bool name="DefinesCapabilities">false</bool>
9
9
  <string name="Name">nvstudio_mcp</string>
10
10
  <int64 name="SourceAssetId">-1</int64>
11
- <SharedString name="Tags">yuZpQdnvvUBOTYh1jqZ2cA==</SharedString>
11
+ <SharedString name="Tags"></SharedString>
12
12
  </Properties>
13
13
  <Item class="ModuleScript" referent="RBX_create_instance">
14
14
  <Properties>
@@ -367,14 +367,14 @@ end
367
367
  ]]></ProtectedString>
368
368
  </Properties>
369
369
  </Item>
370
- <Item class="Script" referent="RBX_Main_server">
370
+ <Item class="Script" referent="RBX_Main">
371
371
  <Properties>
372
372
  <BinaryString name="AttributesSerialize"></BinaryString>
373
373
  <SecurityCapabilities name="Capabilities">0</SecurityCapabilities>
374
374
  <bool name="DefinesCapabilities">false</bool>
375
375
  <bool name="Disabled">false</bool>
376
376
  <Content name="LinkedSource"><null></null></Content>
377
- <string name="Name">Main.server</string>
377
+ <string name="Name">Main</string>
378
378
  <int64 name="SourceAssetId">-1</int64>
379
379
  <SharedString name="Tags"></SharedString>
380
380
  <token name="RunContext">0</token>
@@ -393,7 +393,7 @@ local ui = nil
393
393
 
394
394
  -- Membangun Tombol Toolbar (Toggle)
395
395
  local toolbar = plugin:CreateToolbar("NVStudio MCP")
396
- local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722")
396
+ local toggleBtn = toolbar:CreateButton("Dashboard", "Buka Dashboard NVStudio MCP", "rbxassetid://82696893597722", "NVStudio")
397
397
 
398
398
  -- Global State & Context AI
399
399
  local ctx = {
@@ -421,6 +421,14 @@ if uiModule then
421
421
  ui:setAutoConnectState(autoConnect)
422
422
  ui:setStatus("disconnected")
423
423
 
424
+ -- Sync state tombol toolbar dengan status widget
425
+ if ui.widget then
426
+ toggleBtn:SetActive(ui.widget.Enabled)
427
+ ui.widget:GetPropertyChangedSignal("Enabled"):Connect(function()
428
+ toggleBtn:SetActive(ui.widget.Enabled)
429
+ end)
430
+ end
431
+
424
432
  -- Event Toggle GUI Panel
425
433
  toggleBtn.Click:Connect(function()
426
434
  ui:toggleVisibility()
@@ -945,8 +953,8 @@ function UIManager.init(pluginInstance, studioId)
945
953
  -- Membuat Widget Panel yang bisa di-dock (menempel)
946
954
  local widgetInfo = DockWidgetPluginGuiInfo.new(
947
955
  Enum.InitialDockState.Right,
948
- false, -- Initially hidden until toolbar button is clicked
949
- false, -- Override enabled
956
+ true, -- Initially visible on first install so user immediately sees the dashboard
957
+ false, -- Don't override user's saved state on subsequent launches
950
958
  380, -- Default width
951
959
  520, -- Default height
952
960
  280, -- Min width
@@ -1414,7 +1422,4 @@ end
1414
1422
  </Properties>
1415
1423
  </Item>
1416
1424
  </Item>
1417
- <SharedStrings>
1418
- <SharedString md5="yuZpQdnvvUBOTYh1jqZ2cA=="></SharedString>
1419
- </SharedStrings>
1420
1425
  </roblox>
@@ -5,8 +5,8 @@ function UIManager.init(pluginInstance, studioId)
5
5
  -- Membuat Widget Panel yang bisa di-dock (menempel)
6
6
  local widgetInfo = DockWidgetPluginGuiInfo.new(
7
7
  Enum.InitialDockState.Right,
8
- false, -- Initially hidden until toolbar button is clicked
9
- false, -- Override enabled
8
+ true, -- Initially visible on first install so user immediately sees the dashboard
9
+ false, -- Don't override user's saved state on subsequent launches
10
10
  380, -- Default width
11
11
  520, -- Default height
12
12
  280, -- Min width