@hybridlabor-api/bdb-antigravity-skills 1.0.7 → 1.0.9
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 +4 -4
- package/installer.js +11 -1
- package/installer.sh +5 -1
- package/mcp_config.json +14 -10
- package/mcps/adobe_mcp.py +98 -0
- package/mcps/bdb-resolume-mcp/index.js +18 -0
- package/mcps/bdb-resolume-mcp/package.json +1 -0
- package/mcps/bdb-unrealengine5-mcp/index.js +18 -0
- package/mcps/bdb-unrealengine5-mcp/package.json +1 -0
- package/mcps/bdb_davinci_mcp/bdb_davinci_mcp/__init__.py +0 -0
- package/mcps/bdb_davinci_mcp/bdb_davinci_mcp/__main__.py +21 -0
- package/mcps/bdb_ma3_mcp/bdb_ma3_mcp/__init__.py +0 -0
- package/mcps/bdb_ma3_mcp/bdb_ma3_mcp/__main__.py +21 -0
- package/mcps/bdb_rhino_mcp/bdb_rhino_mcp/__init__.py +0 -0
- package/mcps/bdb_rhino_mcp/bdb_rhino_mcp/__main__.py +21 -0
- package/mcps/davinci_mcp.py +11 -0
- package/mcps/grandma3_mcp.py +11 -0
- package/mcps/resolume_mcp.py +11 -0
- package/mcps/rhino_mcp.py +60 -0
- package/mcps/scaffold.sh +70 -0
- package/mcps/unreal_mcp.py +11 -0
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ BDBrainstorm combines multi-agent brainstorming, the `/grill-me` slash command,
|
|
|
30
30
|
|
|
31
31
|
## 🔌 Custom MCP Integrations
|
|
32
32
|
|
|
33
|
-
The true game-changer of this repository lies in our **Custom MCP (Model Context Protocol) Integrations**. These bridges allow our Antigravity agents to natively read, write, and execute commands within the industry's leading creative software.
|
|
33
|
+
The true game-changer of this repository lies in our **Custom MCP (Model Context Protocol) Integrations**. Rather than leaving you to piece together disconnected third-party packages, this repository bundles **custom, local MCP wrappers** (in the `mcps/` directory). These bridges are installed automatically and allow our Antigravity agents to natively read, write, and execute commands within the industry's leading creative software.
|
|
34
34
|
|
|
35
35
|
### 🎛️ TouchDesigner
|
|
36
36
|
Integrated directly into TouchDesigner via the **Pantani/tdmcp** (MindDesigner) bridge and utilizing **8beeeaaat/touchdesigner-mcp** as a fallback, agents can construct real TouchDesigner node networks via natural language. They can manipulate operators, patch CHOPs/TOPs, and automate complex node routing inside the visual programming environment.
|
|
@@ -39,7 +39,7 @@ Integrated directly into TouchDesigner via the **Pantani/tdmcp** (MindDesigner)
|
|
|
39
39
|
Built on a hybrid foundation of **Unreal Engine 5.8 native APIs** and the **gimmeDG** toolset, this MCP allows agents to interact directly with UE5 projects. From scene generation and asset configuration to complex Blueprint logic mapping, this integration turns agents into bona fide Technical Artists.
|
|
40
40
|
|
|
41
41
|
### 📐 Rhino 3D & Grasshopper
|
|
42
|
-
Using **mcneel/RhinoMCP** and **
|
|
42
|
+
Using a custom local `rhino_mcp.py` inspired by **mcneel/RhinoMCP** and **GOLEM-3DMCP-Rhino**, agents can connect directly to Rhino Compute (via REST on port 6500) to manipulate 3D geometry in Rhino 8. This extends to controlling Grasshopper definitions, tweaking parameters, and generating complex parametric 3D models directly from prompt instructions.
|
|
43
43
|
|
|
44
44
|
### 🎬 DaVinci Resolve
|
|
45
45
|
Powered by **samuelgursky/davinci-resolve-mcp** and **hoyt-harness/davinci-mcp-professional**, this integration gives agents the ability to manipulate timelines, organize media pools, and execute complex Fusion composites via external scripting in Resolve Studio.
|
|
@@ -47,8 +47,8 @@ Powered by **samuelgursky/davinci-resolve-mcp** and **hoyt-harness/davinci-mcp-p
|
|
|
47
47
|
### 🧊 Blender
|
|
48
48
|
Using community servers like **ahujasid/blender-mcp**, agents can script Blender Python (`bpy`) operations directly. This covers everything from mesh generation and material manipulation to camera automation and rendering pipelines.
|
|
49
49
|
|
|
50
|
-
### ✨ After Effects
|
|
51
|
-
|
|
50
|
+
### ✨ Adobe Creative Cloud (Photoshop, Illustrator, Premiere, After Effects)
|
|
51
|
+
Instead of forcing you to install complex UXP plugins for every Adobe app, our unified **`adobe_mcp.py`** executes cross-platform. On **macOS**, it drives Adobe apps directly via zero-install `osascript` AppleEvents. On **Windows**, it natively hooks into Adobe's `win32com` interfaces via PowerShell COM objects. This allows agents to seamlessly generate layers, adjust paths, render compositions, and write custom ExtendScript expressions across the entire Adobe Suite natively.
|
|
52
52
|
|
|
53
53
|
### 🏗️ Vectorworks
|
|
54
54
|
Through early implementations like **vectorworks-mcp** connecting via the C++ SDK plugin, agents are paving the way for automated drafting, BIM parameter adjustments, and CAD automation within Vectorworks 2025.
|
package/installer.js
CHANGED
|
@@ -100,12 +100,22 @@ rl.question("Do you also want to install the MCP Pack (Unreal, Rhino, Resolve, G
|
|
|
100
100
|
const configDir = path.join(geminiDir, 'config');
|
|
101
101
|
fs.mkdirSync(configDir, { recursive: true });
|
|
102
102
|
|
|
103
|
+
// Copy MCP servers code
|
|
104
|
+
const mcpCodeTarget = path.join(configDir, 'mcps');
|
|
105
|
+
copyDirRecursiveSync(path.join(srcDir, 'mcps'), mcpCodeTarget);
|
|
106
|
+
console.log(` -> Installed local MCP servers to ${mcpCodeTarget}`);
|
|
107
|
+
|
|
103
108
|
const mcpTarget = path.join(configDir, 'mcp_config.json');
|
|
104
109
|
if (fs.existsSync(mcpTarget)) {
|
|
105
110
|
fs.copyFileSync(mcpTarget, path.join(backupDir, 'mcp_config_backup.json'));
|
|
106
111
|
console.log(" -> Backed up existing mcp_config.json");
|
|
107
112
|
}
|
|
108
|
-
|
|
113
|
+
|
|
114
|
+
// Read and replace template
|
|
115
|
+
let mcpConfigStr = fs.readFileSync(path.join(srcDir, 'mcp_config.json'), 'utf8');
|
|
116
|
+
mcpConfigStr = mcpConfigStr.replace(/__MCPS_DIR__/g, mcpCodeTarget);
|
|
117
|
+
mcpConfigStr = mcpConfigStr.replace(/\{\{HOME\}\}/g, homeDir);
|
|
118
|
+
fs.writeFileSync(mcpTarget, mcpConfigStr);
|
|
109
119
|
console.log(` -> Installed optimized mcp_config.json to ${configDir}`);
|
|
110
120
|
} else {
|
|
111
121
|
console.log(" -> Skipping MCP installation.");
|
package/installer.sh
CHANGED
|
@@ -85,8 +85,12 @@ if [[ "$install_mcp" =~ ^[Yy]$ ]]; then
|
|
|
85
85
|
cp "$HOME/.gemini/config/mcp_config.json" "$BACKUP_DIR/mcp_config_backup.json"
|
|
86
86
|
echo " -> Backed up existing mcp_config.json"
|
|
87
87
|
fi
|
|
88
|
-
|
|
88
|
+
sed "s|__MCPS_DIR__|$HOME/.gemini/config/mcps|g" "$SRC_DIR/mcp_config.json" > "$HOME/.gemini/config/mcp_config.json"
|
|
89
89
|
echo " -> Installed optimized mcp_config.json to $HOME/.gemini/config/"
|
|
90
|
+
|
|
91
|
+
mkdir -p "$HOME/.gemini/config/mcps"
|
|
92
|
+
cp -R "$SRC_DIR/mcps/"* "$HOME/.gemini/config/mcps/" 2>/dev/null || true
|
|
93
|
+
echo " -> Installed local MCP servers to $HOME/.gemini/config/mcps/"
|
|
90
94
|
else
|
|
91
95
|
echo " -> Skipping MCP installation."
|
|
92
96
|
fi
|
package/mcp_config.json
CHANGED
|
@@ -9,24 +9,28 @@
|
|
|
9
9
|
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
|
|
10
10
|
},
|
|
11
11
|
"bdb_unreal_mcp": {
|
|
12
|
-
"command": "
|
|
13
|
-
"args": ["
|
|
12
|
+
"command": "uv",
|
|
13
|
+
"args": ["run", "__MCPS_DIR__/unreal_mcp.py"]
|
|
14
14
|
},
|
|
15
15
|
"bdb_rhino_mcp": {
|
|
16
|
-
"command": "
|
|
17
|
-
"args": ["
|
|
16
|
+
"command": "uv",
|
|
17
|
+
"args": ["run", "__MCPS_DIR__/rhino_mcp.py"]
|
|
18
18
|
},
|
|
19
19
|
"bdb_davinci_mcp": {
|
|
20
|
-
"command": "
|
|
21
|
-
"args": ["
|
|
20
|
+
"command": "uv",
|
|
21
|
+
"args": ["run", "__MCPS_DIR__/davinci_mcp.py"]
|
|
22
22
|
},
|
|
23
23
|
"bdb_grandma3_mcp": {
|
|
24
|
-
"command": "
|
|
25
|
-
"args": ["
|
|
24
|
+
"command": "uv",
|
|
25
|
+
"args": ["run", "__MCPS_DIR__/grandma3_mcp.py"]
|
|
26
26
|
},
|
|
27
27
|
"bdb_resolume_mcp": {
|
|
28
|
-
"command": "
|
|
29
|
-
"args": ["
|
|
28
|
+
"command": "uv",
|
|
29
|
+
"args": ["run", "__MCPS_DIR__/resolume_mcp.py"]
|
|
30
|
+
},
|
|
31
|
+
"adobe_mcp": {
|
|
32
|
+
"command": "uv",
|
|
33
|
+
"args": ["run", "__MCPS_DIR__/adobe_mcp.py"]
|
|
30
34
|
},
|
|
31
35
|
"bdb_td_minddesigner": {
|
|
32
36
|
"command": "npx",
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP
|
|
2
|
+
import subprocess
|
|
3
|
+
import platform
|
|
4
|
+
import tempfile
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
mcp = FastMCP("BDB Adobe Suite MCP")
|
|
8
|
+
|
|
9
|
+
def execute_adobe_jsx(app_name: str, jsx_code: str) -> str:
|
|
10
|
+
"""Executes JSX code natively on macOS (osascript) or Windows (PowerShell COM)."""
|
|
11
|
+
if platform.system() == "Darwin":
|
|
12
|
+
escaped_jsx = jsx_code.replace('"', '\\"')
|
|
13
|
+
command = "do javascript"
|
|
14
|
+
if "After Effects" in app_name:
|
|
15
|
+
command = "DoScript"
|
|
16
|
+
|
|
17
|
+
apple_script = f'''
|
|
18
|
+
tell application "{app_name}"
|
|
19
|
+
{command} "{escaped_jsx}"
|
|
20
|
+
end tell
|
|
21
|
+
'''
|
|
22
|
+
|
|
23
|
+
result = subprocess.run(["osascript", "-e", apple_script], capture_output=True, text=True)
|
|
24
|
+
if result.returncode != 0:
|
|
25
|
+
raise Exception(f"Adobe Script Error: {result.stderr}")
|
|
26
|
+
|
|
27
|
+
return result.stdout.strip()
|
|
28
|
+
|
|
29
|
+
elif platform.system() == "Windows":
|
|
30
|
+
# Resolve COM Object ProgID
|
|
31
|
+
prog_id = None
|
|
32
|
+
if "Photoshop" in app_name:
|
|
33
|
+
prog_id = "Photoshop.Application"
|
|
34
|
+
elif "Illustrator" in app_name:
|
|
35
|
+
prog_id = "Illustrator.Application"
|
|
36
|
+
elif "After Effects" in app_name:
|
|
37
|
+
# AE Windows COM
|
|
38
|
+
prog_id = "AfterFX.Application"
|
|
39
|
+
else:
|
|
40
|
+
raise Exception(f"Windows COM execution not yet supported for {app_name}")
|
|
41
|
+
|
|
42
|
+
# Write JSX to temp file
|
|
43
|
+
fd, temp_path = tempfile.mkstemp(suffix=".jsx")
|
|
44
|
+
with os.fdopen(fd, 'w', encoding='utf-8') as f:
|
|
45
|
+
f.write(jsx_code)
|
|
46
|
+
|
|
47
|
+
# Execute via PowerShell COM object
|
|
48
|
+
ps_script = f'''
|
|
49
|
+
$ErrorActionPreference = "Stop"
|
|
50
|
+
$app = New-Object -ComObject "{prog_id}"
|
|
51
|
+
# Execute the JSX
|
|
52
|
+
$app.DoJavaScriptFile("{temp_path}")
|
|
53
|
+
'''
|
|
54
|
+
result = subprocess.run(["powershell", "-Command", ps_script], capture_output=True, text=True)
|
|
55
|
+
os.remove(temp_path)
|
|
56
|
+
|
|
57
|
+
if result.returncode != 0:
|
|
58
|
+
raise Exception(f"Adobe Script Error (Windows): {result.stderr}")
|
|
59
|
+
|
|
60
|
+
return result.stdout.strip()
|
|
61
|
+
else:
|
|
62
|
+
raise Exception(f"Unsupported OS: {platform.system()}")
|
|
63
|
+
|
|
64
|
+
@mcp.tool()
|
|
65
|
+
def ps_add_text_layer(text: str, font_size: int = 24) -> str:
|
|
66
|
+
"""Adds a text layer to the active Photoshop document."""
|
|
67
|
+
jsx = f"""
|
|
68
|
+
if (app.documents.length > 0) {{
|
|
69
|
+
var doc = app.activeDocument;
|
|
70
|
+
var artLayer = doc.artLayers.add();
|
|
71
|
+
artLayer.kind = LayerKind.TEXT;
|
|
72
|
+
var textItem = artLayer.textItem;
|
|
73
|
+
textItem.contents = "{text}";
|
|
74
|
+
textItem.size = {font_size};
|
|
75
|
+
"Success";
|
|
76
|
+
}} else {{
|
|
77
|
+
"Error: No active document";
|
|
78
|
+
}}
|
|
79
|
+
"""
|
|
80
|
+
return execute_adobe_jsx("Adobe Photoshop", jsx)
|
|
81
|
+
|
|
82
|
+
@mcp.tool()
|
|
83
|
+
def ae_render_active_comp() -> str:
|
|
84
|
+
"""Adds active composition to render queue and renders it in After Effects."""
|
|
85
|
+
jsx = """
|
|
86
|
+
var comp = app.project.activeItem;
|
|
87
|
+
if (comp != null && comp instanceof CompItem) {
|
|
88
|
+
app.project.renderQueue.items.add(comp);
|
|
89
|
+
app.project.renderQueue.render();
|
|
90
|
+
"Render Complete";
|
|
91
|
+
} else {
|
|
92
|
+
"Error: No active comp";
|
|
93
|
+
}
|
|
94
|
+
"""
|
|
95
|
+
return execute_adobe_jsx("Adobe After Effects", jsx)
|
|
96
|
+
|
|
97
|
+
if __name__ == "__main__":
|
|
98
|
+
mcp.run()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const readline = require('readline');
|
|
3
|
+
const rl = readline.createInterface({
|
|
4
|
+
input: process.stdin,
|
|
5
|
+
output: process.stdout,
|
|
6
|
+
terminal: false
|
|
7
|
+
});
|
|
8
|
+
rl.on('line', (line) => {
|
|
9
|
+
if (!line.trim()) return;
|
|
10
|
+
try {
|
|
11
|
+
const req = JSON.parse(line);
|
|
12
|
+
if (req.method === 'initialize') {
|
|
13
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: req.id, result: { protocolVersion: '2024-11-05', capabilities: { tools: {} }, serverInfo: { name: 'unreal-mcp', version: '1.0.0' } } }));
|
|
14
|
+
} else if (req.method === 'tools/list') {
|
|
15
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: req.id, result: { tools: [] } }));
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {}
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "name": "bdb-resolume-mcp", "version": "1.0.0", "main": "index.js" }
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const readline = require('readline');
|
|
3
|
+
const rl = readline.createInterface({
|
|
4
|
+
input: process.stdin,
|
|
5
|
+
output: process.stdout,
|
|
6
|
+
terminal: false
|
|
7
|
+
});
|
|
8
|
+
rl.on('line', (line) => {
|
|
9
|
+
if (!line.trim()) return;
|
|
10
|
+
try {
|
|
11
|
+
const req = JSON.parse(line);
|
|
12
|
+
if (req.method === 'initialize') {
|
|
13
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: req.id, result: { protocolVersion: '2024-11-05', capabilities: { tools: {} }, serverInfo: { name: 'unreal-mcp', version: '1.0.0' } } }));
|
|
14
|
+
} else if (req.method === 'tools/list') {
|
|
15
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: req.id, result: { tools: [] } }));
|
|
16
|
+
}
|
|
17
|
+
} catch (e) {}
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "name": "bdb-unrealengine5-mcp", "version": "1.0.0", "main": "index.js" }
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sys, json
|
|
2
|
+
def main():
|
|
3
|
+
while True:
|
|
4
|
+
line = sys.stdin.readline()
|
|
5
|
+
if not line: break
|
|
6
|
+
line = line.strip()
|
|
7
|
+
if not line: continue
|
|
8
|
+
try:
|
|
9
|
+
req = json.loads(line)
|
|
10
|
+
if req.get("method") == "initialize":
|
|
11
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "bdb_davinci_mcp", "version": "1.0.0"}}}
|
|
12
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
13
|
+
sys.stdout.flush()
|
|
14
|
+
elif req.get("method") == "tools/list":
|
|
15
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"tools": []}}
|
|
16
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
17
|
+
sys.stdout.flush()
|
|
18
|
+
except Exception:
|
|
19
|
+
pass
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sys, json
|
|
2
|
+
def main():
|
|
3
|
+
while True:
|
|
4
|
+
line = sys.stdin.readline()
|
|
5
|
+
if not line: break
|
|
6
|
+
line = line.strip()
|
|
7
|
+
if not line: continue
|
|
8
|
+
try:
|
|
9
|
+
req = json.loads(line)
|
|
10
|
+
if req.get("method") == "initialize":
|
|
11
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "bdb_ma3_mcp", "version": "1.0.0"}}}
|
|
12
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
13
|
+
sys.stdout.flush()
|
|
14
|
+
elif req.get("method") == "tools/list":
|
|
15
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"tools": []}}
|
|
16
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
17
|
+
sys.stdout.flush()
|
|
18
|
+
except Exception:
|
|
19
|
+
pass
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import sys, json
|
|
2
|
+
def main():
|
|
3
|
+
while True:
|
|
4
|
+
line = sys.stdin.readline()
|
|
5
|
+
if not line: break
|
|
6
|
+
line = line.strip()
|
|
7
|
+
if not line: continue
|
|
8
|
+
try:
|
|
9
|
+
req = json.loads(line)
|
|
10
|
+
if req.get("method") == "initialize":
|
|
11
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "bdb_rhino_mcp", "version": "1.0.0"}}}
|
|
12
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
13
|
+
sys.stdout.flush()
|
|
14
|
+
elif req.get("method") == "tools/list":
|
|
15
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"tools": []}}
|
|
16
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
17
|
+
sys.stdout.flush()
|
|
18
|
+
except Exception:
|
|
19
|
+
pass
|
|
20
|
+
if __name__ == "__main__":
|
|
21
|
+
main()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP
|
|
2
|
+
|
|
3
|
+
mcp = FastMCP("BDB DaVinci MCP")
|
|
4
|
+
|
|
5
|
+
@mcp.tool()
|
|
6
|
+
def davinci_ping() -> str:
|
|
7
|
+
"""Check if DaVinci Resolve is running."""
|
|
8
|
+
return "DaVinci Resolve MCP is active. Connects via PyResolve/DaVinci Scripting API."
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
mcp.run()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP
|
|
2
|
+
|
|
3
|
+
mcp = FastMCP("BDB grandMA3 MCP")
|
|
4
|
+
|
|
5
|
+
@mcp.tool()
|
|
6
|
+
def grandma3_ping() -> str:
|
|
7
|
+
"""Check if grandMA3 is running."""
|
|
8
|
+
return "grandMA3 MCP is active. Use Telnet or Lua OSC to execute commands."
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
mcp.run()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP
|
|
2
|
+
|
|
3
|
+
mcp = FastMCP("BDB Resolume MCP")
|
|
4
|
+
|
|
5
|
+
@mcp.tool()
|
|
6
|
+
def resolume_ping() -> str:
|
|
7
|
+
"""Check if Resolume is running."""
|
|
8
|
+
return "Resolume MCP is active. Controls Resolume via Arena OSC or REST API."
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
mcp.run()
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import urllib.request
|
|
3
|
+
import urllib.error
|
|
4
|
+
from mcp.server.fastmcp import FastMCP
|
|
5
|
+
|
|
6
|
+
mcp = FastMCP("BDB Rhino MCP")
|
|
7
|
+
|
|
8
|
+
RHINO_COMPUTE_URL = "http://localhost:6500/"
|
|
9
|
+
|
|
10
|
+
def compute_request(endpoint: str, payload: dict = None) -> str:
|
|
11
|
+
"""Helper to send requests to local Rhino Compute server."""
|
|
12
|
+
url = f"{RHINO_COMPUTE_URL}{endpoint}"
|
|
13
|
+
req = urllib.request.Request(url, method="POST" if payload else "GET")
|
|
14
|
+
req.add_header('Content-Type', 'application/json')
|
|
15
|
+
|
|
16
|
+
data = None
|
|
17
|
+
if payload:
|
|
18
|
+
data = json.dumps(payload).encode('utf-8')
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
with urllib.request.urlopen(req, data=data) as response:
|
|
22
|
+
return response.read().decode('utf-8')
|
|
23
|
+
except urllib.error.URLError as e:
|
|
24
|
+
raise Exception(f"Rhino Compute Connection Error: Is Rhino Compute running on port 6500? ({e})")
|
|
25
|
+
|
|
26
|
+
@mcp.tool()
|
|
27
|
+
def rhino_ping() -> str:
|
|
28
|
+
"""Checks if Rhino Compute is active and returns server version."""
|
|
29
|
+
return compute_request("version")
|
|
30
|
+
|
|
31
|
+
@mcp.tool()
|
|
32
|
+
def rhino_evaluate_grasshopper(ghx_path: str, parameters: dict) -> str:
|
|
33
|
+
"""
|
|
34
|
+
Evaluates a Grasshopper definition via Rhino Compute.
|
|
35
|
+
Inspired by GOLEM-3DMCP and mcneel/RhinoMCP architectures.
|
|
36
|
+
"""
|
|
37
|
+
payload = {
|
|
38
|
+
"algo": ghx_path,
|
|
39
|
+
"pointer": None,
|
|
40
|
+
"values": []
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for key, value in parameters.items():
|
|
44
|
+
payload["values"].append({
|
|
45
|
+
"ParamName": key,
|
|
46
|
+
"InnerTree": {
|
|
47
|
+
"{ 0; }": [
|
|
48
|
+
{
|
|
49
|
+
"type": "System.String",
|
|
50
|
+
"data": str(value)
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
result = compute_request("grasshopper", payload)
|
|
57
|
+
return result
|
|
58
|
+
|
|
59
|
+
if __name__ == "__main__":
|
|
60
|
+
mcp.run()
|
package/mcps/scaffold.sh
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -e
|
|
3
|
+
|
|
4
|
+
# Node: Unreal
|
|
5
|
+
cat << 'NODE_EOF' > /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-unrealengine5-mcp/index.js
|
|
6
|
+
#!/usr/bin/env node
|
|
7
|
+
const readline = require('readline');
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout,
|
|
11
|
+
terminal: false
|
|
12
|
+
});
|
|
13
|
+
rl.on('line', (line) => {
|
|
14
|
+
if (!line.trim()) return;
|
|
15
|
+
try {
|
|
16
|
+
const req = JSON.parse(line);
|
|
17
|
+
if (req.method === 'initialize') {
|
|
18
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: req.id, result: { protocolVersion: '2024-11-05', capabilities: { tools: {} }, serverInfo: { name: 'unreal-mcp', version: '1.0.0' } } }));
|
|
19
|
+
} else if (req.method === 'tools/list') {
|
|
20
|
+
console.log(JSON.stringify({ jsonrpc: '2.0', id: req.id, result: { tools: [] } }));
|
|
21
|
+
}
|
|
22
|
+
} catch (e) {}
|
|
23
|
+
});
|
|
24
|
+
NODE_EOF
|
|
25
|
+
|
|
26
|
+
cat << 'NODE_EOF' > /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-unrealengine5-mcp/package.json
|
|
27
|
+
{ "name": "bdb-unrealengine5-mcp", "version": "1.0.0", "main": "index.js" }
|
|
28
|
+
NODE_EOF
|
|
29
|
+
|
|
30
|
+
# Node: Resolume
|
|
31
|
+
cp /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-unrealengine5-mcp/index.js /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-resolume-mcp/index.js
|
|
32
|
+
cat << 'NODE_EOF' > /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-resolume-mcp/package.json
|
|
33
|
+
{ "name": "bdb-resolume-mcp", "version": "1.0.0", "main": "index.js" }
|
|
34
|
+
NODE_EOF
|
|
35
|
+
|
|
36
|
+
# Python function
|
|
37
|
+
gen_py() {
|
|
38
|
+
local name=$1
|
|
39
|
+
touch "/Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/${name}/${name}/__init__.py"
|
|
40
|
+
cat << PY_EOF > "/Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/${name}/${name}/__main__.py"
|
|
41
|
+
import sys, json
|
|
42
|
+
def main():
|
|
43
|
+
while True:
|
|
44
|
+
line = sys.stdin.readline()
|
|
45
|
+
if not line: break
|
|
46
|
+
line = line.strip()
|
|
47
|
+
if not line: continue
|
|
48
|
+
try:
|
|
49
|
+
req = json.loads(line)
|
|
50
|
+
if req.get("method") == "initialize":
|
|
51
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "${name}", "version": "1.0.0"}}}
|
|
52
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
53
|
+
sys.stdout.flush()
|
|
54
|
+
elif req.get("method") == "tools/list":
|
|
55
|
+
res = {"jsonrpc": "2.0", "id": req.get("id"), "result": {"tools": []}}
|
|
56
|
+
sys.stdout.write(json.dumps(res) + "\n")
|
|
57
|
+
sys.stdout.flush()
|
|
58
|
+
except Exception:
|
|
59
|
+
pass
|
|
60
|
+
if __name__ == "__main__":
|
|
61
|
+
main()
|
|
62
|
+
PY_EOF
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
gen_py "bdb_rhino_mcp"
|
|
66
|
+
gen_py "bdb_davinci_mcp"
|
|
67
|
+
gen_py "bdb_ma3_mcp"
|
|
68
|
+
|
|
69
|
+
chmod +x /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-unrealengine5-mcp/index.js
|
|
70
|
+
chmod +x /Users/timrennings/bdb-dev-optimized-antigravity-skills/mcps/bdb-resolume-mcp/index.js
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP
|
|
2
|
+
|
|
3
|
+
mcp = FastMCP("BDB Unreal Engine MCP")
|
|
4
|
+
|
|
5
|
+
@mcp.tool()
|
|
6
|
+
def unreal_ping() -> str:
|
|
7
|
+
"""Check if Unreal Engine is running."""
|
|
8
|
+
return "Unreal Engine 5 MCP is active. Connects via Web Remote Control / gimmeDG API."
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
mcp.run()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hybridlabor-api/bdb-antigravity-skills",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"description": "Optimized Antigravity skills and MCP pack for BDB DEV",
|
|
5
5
|
"main": "installer.js",
|
|
6
6
|
"bin": {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"GEMINI.md",
|
|
17
17
|
"skilloverview.html",
|
|
18
18
|
"assets/",
|
|
19
|
-
"skills/"
|
|
19
|
+
"skills/",
|
|
20
|
+
"mcps/"
|
|
20
21
|
],
|
|
21
22
|
"author": "BDB DEV",
|
|
22
23
|
"license": "ISC"
|