dominus-cli 0.5.4 → 0.5.6
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/dist/index.js +50 -46
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +43 -44
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
- package/plugin/Dominus.rbxm +0 -0
- package/plugin/src/Properties.lua +9 -2
- package/plugin/src/init.server.lua +5 -1
package/dist/mcp.js
CHANGED
|
@@ -703,10 +703,19 @@ async function startMcpServer() {
|
|
|
703
703
|
}
|
|
704
704
|
const mcp = new McpServer({
|
|
705
705
|
name: "dominus",
|
|
706
|
-
version: "0.
|
|
706
|
+
version: "0.5.5"
|
|
707
707
|
}, {
|
|
708
708
|
instructions: INTERNAL_MEMORY
|
|
709
709
|
});
|
|
710
|
+
function luaStr(s) {
|
|
711
|
+
return `"${s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r")}"`;
|
|
712
|
+
}
|
|
713
|
+
function resolvePath(dotPath) {
|
|
714
|
+
const parts = dotPath.split(".");
|
|
715
|
+
let r = "game";
|
|
716
|
+
for (const p of parts) r += `[${luaStr(p)}]`;
|
|
717
|
+
return r;
|
|
718
|
+
}
|
|
710
719
|
mcp.tool(
|
|
711
720
|
"read_script",
|
|
712
721
|
"Read the source code of a script in Roblox Studio",
|
|
@@ -758,11 +767,14 @@ async function startMcpServer() {
|
|
|
758
767
|
);
|
|
759
768
|
mcp.tool(
|
|
760
769
|
"get_properties",
|
|
761
|
-
"Get all properties of
|
|
762
|
-
{
|
|
763
|
-
|
|
770
|
+
"Get all properties of a single instance in Roblox Studio. Returns property name, value, type, and category. For inspecting UI trees, prefer serialize_ui (structured tree) or get_descendants_properties (flat list with compact filtering).",
|
|
771
|
+
{
|
|
772
|
+
path: z.string().describe('Full instance path (e.g. "Workspace.Part", "StarterGui.MyUI.Frame")'),
|
|
773
|
+
compact: z.boolean().optional().default(true).describe("Strip read-only, nil, deprecated, and default-valued properties (default true). Set false for full dump.")
|
|
774
|
+
},
|
|
775
|
+
async ({ path: path2, compact }) => {
|
|
764
776
|
assertConnected();
|
|
765
|
-
const res = await bridge.sendRequest(CliMsg.GET_PROPERTIES, { path: path2 });
|
|
777
|
+
const res = await bridge.sendRequest(CliMsg.GET_PROPERTIES, { path: path2, compact });
|
|
766
778
|
return { content: [{ type: "text", text: JSON.stringify(res.payload, null, 2) }] };
|
|
767
779
|
}
|
|
768
780
|
);
|
|
@@ -978,16 +990,10 @@ async function startMcpServer() {
|
|
|
978
990
|
},
|
|
979
991
|
async (params) => {
|
|
980
992
|
assertConnected();
|
|
981
|
-
const
|
|
982
|
-
|
|
983
|
-
for (const p of parts) resolve += `["${p}"]`;
|
|
984
|
-
const lines = [`local orig = ${resolve}`, `local clone = orig:Clone()`];
|
|
985
|
-
if (params.newName) lines.push(`clone.Name = "${params.newName}"`);
|
|
993
|
+
const lines = [`local orig = ${resolvePath(params.path)}`, `local clone = orig:Clone()`];
|
|
994
|
+
if (params.newName) lines.push(`clone.Name = ${luaStr(params.newName)}`);
|
|
986
995
|
if (params.newParent) {
|
|
987
|
-
|
|
988
|
-
let pr = "game";
|
|
989
|
-
for (const p of pp) pr += `["${p}"]`;
|
|
990
|
-
lines.push(`clone.Parent = ${pr}`);
|
|
996
|
+
lines.push(`clone.Parent = ${resolvePath(params.newParent)}`);
|
|
991
997
|
} else {
|
|
992
998
|
lines.push(`clone.Parent = orig.Parent`);
|
|
993
999
|
}
|
|
@@ -1003,7 +1009,7 @@ async function startMcpServer() {
|
|
|
1003
1009
|
);
|
|
1004
1010
|
mcp.tool(
|
|
1005
1011
|
"group_instances",
|
|
1006
|
-
"Group multiple instances into a Model or Folder",
|
|
1012
|
+
"Group multiple instances into a Model or Folder. All listed instances become children of the new group.",
|
|
1007
1013
|
{
|
|
1008
1014
|
paths: z.array(z.string()).describe("Array of instance paths to group"),
|
|
1009
1015
|
groupName: z.string().describe("Name for the group"),
|
|
@@ -1014,20 +1020,11 @@ async function startMcpServer() {
|
|
|
1014
1020
|
assertConnected();
|
|
1015
1021
|
const gc = params.groupClass ?? "Model";
|
|
1016
1022
|
const parent = params.parent ?? "Workspace";
|
|
1017
|
-
const parentParts = parent.split(".");
|
|
1018
|
-
let parentResolve = "game";
|
|
1019
|
-
for (const p of parentParts) parentResolve += `["${p}"]`;
|
|
1020
|
-
const resolves = params.paths.map((path2) => {
|
|
1021
|
-
const parts = path2.split(".");
|
|
1022
|
-
let r = "game";
|
|
1023
|
-
for (const part of parts) r += `["${part}"]`;
|
|
1024
|
-
return r;
|
|
1025
|
-
});
|
|
1026
1023
|
const code = [
|
|
1027
|
-
`local group = Instance.new(
|
|
1028
|
-
`group.Name =
|
|
1029
|
-
`group.Parent = ${
|
|
1030
|
-
...
|
|
1024
|
+
`local group = Instance.new(${luaStr(gc)})`,
|
|
1025
|
+
`group.Name = ${luaStr(params.groupName)}`,
|
|
1026
|
+
`group.Parent = ${resolvePath(parent)}`,
|
|
1027
|
+
...params.paths.map((p) => `${resolvePath(p)}.Parent = group`),
|
|
1031
1028
|
`print("Grouped ${params.paths.length} instances into: " .. group:GetFullName())`
|
|
1032
1029
|
].join("\n");
|
|
1033
1030
|
const res = await bridge.sendRequest(CliMsg.RUN_CODE, { code });
|
|
@@ -1036,7 +1033,7 @@ async function startMcpServer() {
|
|
|
1036
1033
|
);
|
|
1037
1034
|
mcp.tool(
|
|
1038
1035
|
"build_multiple",
|
|
1039
|
-
"Create many parts/instances in one batch. Send an array of specs \u2014 all created in a single round-trip. Ideal for building trees, houses, vehicles.",
|
|
1036
|
+
"Create many parts/instances in one batch. Send an array of specs \u2014 all created in a single round-trip. Ideal for building trees, houses, vehicles. Supports hex colors, rgb() colors, and BrickColor names.",
|
|
1040
1037
|
{
|
|
1041
1038
|
parts: z.array(z.object({
|
|
1042
1039
|
name: z.string(),
|
|
@@ -1044,10 +1041,11 @@ async function startMcpServer() {
|
|
|
1044
1041
|
parent: z.string().optional(),
|
|
1045
1042
|
position: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),
|
|
1046
1043
|
size: z.object({ x: z.number(), y: z.number(), z: z.number() }).optional(),
|
|
1047
|
-
color: z.string().optional().describe('Hex "#RRGGBB" or BrickColor name'),
|
|
1048
|
-
material: z.string().optional(),
|
|
1044
|
+
color: z.string().optional().describe('Hex "#RRGGBB", "rgb(r,g,b)", or BrickColor name'),
|
|
1045
|
+
material: z.string().optional().describe("Enum.Material name: Plastic, Wood, Neon, Glass, etc."),
|
|
1049
1046
|
transparency: z.number().optional(),
|
|
1050
1047
|
anchored: z.boolean().optional(),
|
|
1048
|
+
canCollide: z.boolean().optional(),
|
|
1051
1049
|
shape: z.enum(["Block", "Ball", "Cylinder", "Wedge"]).optional()
|
|
1052
1050
|
})).describe("Array of part specifications"),
|
|
1053
1051
|
groupName: z.string().optional().describe("Group all parts into a Model with this name"),
|
|
@@ -1058,35 +1056,36 @@ async function startMcpServer() {
|
|
|
1058
1056
|
const parts = params.parts;
|
|
1059
1057
|
const groupName = params.groupName;
|
|
1060
1058
|
const groupParent = params.groupParent ?? "Workspace";
|
|
1061
|
-
function resolveP(path2) {
|
|
1062
|
-
const segs = path2.split(".");
|
|
1063
|
-
let r = "game";
|
|
1064
|
-
for (const s of segs) r += `["${s}"]`;
|
|
1065
|
-
return r;
|
|
1066
|
-
}
|
|
1067
1059
|
const lines = [];
|
|
1068
1060
|
if (groupName) {
|
|
1069
1061
|
lines.push(`local _group = Instance.new("Model")`);
|
|
1070
|
-
lines.push(`_group.Name =
|
|
1071
|
-
lines.push(`_group.Parent = ${
|
|
1062
|
+
lines.push(`_group.Name = ${luaStr(groupName)}`);
|
|
1063
|
+
lines.push(`_group.Parent = ${resolvePath(groupParent)}`);
|
|
1072
1064
|
}
|
|
1073
1065
|
for (let i = 0; i < parts.length; i++) {
|
|
1074
1066
|
const p = parts[i];
|
|
1075
1067
|
const v = `_p${i}`;
|
|
1076
1068
|
const cn = p.className ?? (p.shape === "Wedge" ? "WedgePart" : "Part");
|
|
1077
|
-
lines.push(`local ${v} = Instance.new(
|
|
1078
|
-
lines.push(`${v}.Name =
|
|
1069
|
+
lines.push(`local ${v} = Instance.new(${luaStr(cn)})`);
|
|
1070
|
+
lines.push(`${v}.Name = ${luaStr(p.name)}`);
|
|
1079
1071
|
if (p.position) lines.push(`${v}.Position = Vector3.new(${p.position.x}, ${p.position.y}, ${p.position.z})`);
|
|
1080
1072
|
if (p.size) lines.push(`${v}.Size = Vector3.new(${p.size.x}, ${p.size.y}, ${p.size.z})`);
|
|
1081
1073
|
if (p.color) {
|
|
1082
|
-
if (p.color.startsWith("#"))
|
|
1083
|
-
|
|
1074
|
+
if (p.color.startsWith("#")) {
|
|
1075
|
+
lines.push(`${v}.Color = Color3.fromHex(${luaStr(p.color)})`);
|
|
1076
|
+
} else if (p.color.startsWith("rgb(")) {
|
|
1077
|
+
const m = p.color.match(/rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/);
|
|
1078
|
+
if (m) lines.push(`${v}.Color = Color3.fromRGB(${m[1]}, ${m[2]}, ${m[3]})`);
|
|
1079
|
+
} else {
|
|
1080
|
+
lines.push(`${v}.BrickColor = BrickColor.new(${luaStr(p.color)})`);
|
|
1081
|
+
}
|
|
1084
1082
|
}
|
|
1085
1083
|
if (p.material) lines.push(`${v}.Material = Enum.Material.${p.material}`);
|
|
1086
1084
|
if (p.transparency !== void 0) lines.push(`${v}.Transparency = ${p.transparency}`);
|
|
1087
1085
|
lines.push(`${v}.Anchored = ${p.anchored ?? true}`);
|
|
1086
|
+
if (p.canCollide !== void 0) lines.push(`${v}.CanCollide = ${p.canCollide}`);
|
|
1088
1087
|
if (p.shape && p.shape !== "Block" && cn === "Part") lines.push(`${v}.Shape = Enum.PartType.${p.shape}`);
|
|
1089
|
-
lines.push(`${v}.Parent = ${groupName ? "_group" :
|
|
1088
|
+
lines.push(`${v}.Parent = ${groupName ? "_group" : resolvePath(p.parent ?? "Workspace")}`);
|
|
1090
1089
|
}
|
|
1091
1090
|
lines.push(`print("Built ${parts.length} parts${groupName ? ` in ${groupName}` : ""}")`);
|
|
1092
1091
|
const res = await bridge.sendRequest(CliMsg.RUN_CODE, { code: lines.join("\n") });
|