unity-mcp-cli 0.1.0__tar.gz

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.
@@ -0,0 +1,42 @@
1
+ # Unity
2
+ unity-project/Library/
3
+ unity-project/Temp/
4
+ unity-project/Logs/
5
+ unity-project/UserSettings/
6
+ unity-project/obj/
7
+ unity-project/*.csproj
8
+ unity-project/*.sln
9
+ *.meta
10
+
11
+ # Python
12
+ __pycache__/
13
+ *.pyc
14
+ *.pyo
15
+ *.egg-info/
16
+ dist/
17
+ build/
18
+ .ruff_cache/
19
+ .mypy_cache/
20
+ .pytest_cache/
21
+ *.egg
22
+
23
+ # IDE
24
+ .idea/
25
+ .vscode/
26
+ *.swp
27
+ *.swo
28
+ *~
29
+
30
+ # OS
31
+ .DS_Store
32
+ Thumbs.db
33
+
34
+ # Benchmark temp files
35
+ *.log
36
+ *.pid
37
+ bench/reports/*.log
38
+ bench/reports/*.pid
39
+
40
+ # Session / conversation logs
41
+ docs/conversation-*.md
42
+ bench/reports/conversation-*.md
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ArtisanCodesmith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,130 @@
1
+ Metadata-Version: 2.4
2
+ Name: unity-mcp-cli
3
+ Version: 0.1.0
4
+ Summary: Token-efficient CLI for LLM agents to control Unity Editor
5
+ Project-URL: Homepage, https://github.com/NaturaAurum/uni-cli
6
+ Project-URL: Repository, https://github.com/NaturaAurum/uni-cli
7
+ Project-URL: Issues, https://github.com/NaturaAurum/uni-cli/issues
8
+ Author: ArtisanCodesmith
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 ArtisanCodesmith
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: agent,cli,llm,mcp,unity
32
+ Classifier: Development Status :: 3 - Alpha
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3 :: Only
37
+ Classifier: Programming Language :: Python :: 3.10
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Programming Language :: Python :: 3.13
41
+ Classifier: Topic :: Software Development :: Build Tools
42
+ Requires-Python: >=3.10
43
+ Provides-Extra: test
44
+ Requires-Dist: pytest>=7.0; extra == 'test'
45
+ Description-Content-Type: text/markdown
46
+
47
+ # uni-cli
48
+
49
+ Token-efficient CLI for LLM agents to control Unity Editor via [MCP](https://modelcontextprotocol.io). Reduces token overhead by ~31x compared to raw MCP tool schemas.
50
+
51
+ Part of the [uni-cli](https://github.com/NaturaAurum/uni-cli) project — extends [unity-mcp](https://github.com/CoplayDev/unity-mcp) with additional Unity subsystem tools.
52
+
53
+ ## Why
54
+
55
+ LLM agents talking to Unity through MCP pay a heavy token tax — large tool schemas and verbose JSON responses eat context window budget. uni-cli solves this with a compact CLI layer:
56
+
57
+ | Metric | Value |
58
+ |--------|-------|
59
+ | Per-response output reduction | **79–98%** (median 92.8%) |
60
+ | Tool schema overhead | **MCP 14,877 → CLI 480 tokens** (31x reduction) |
61
+
62
+ ## Install
63
+
64
+ ```bash
65
+ pip install unity-mcp-cli
66
+ ```
67
+
68
+ **Prerequisites:**
69
+ - Python 3.10+
70
+ - [unity-mcp](https://github.com/CoplayDev/unity-mcp) running in your Unity project
71
+
72
+ ## Usage
73
+
74
+ ```bash
75
+ # List scene hierarchy (compact output)
76
+ uni-cli hierarchy ls --instance MyProject --fields id,name,parent --limit 50
77
+
78
+ # Create a GameObject
79
+ uni-cli object create --instance MyProject --name "Player" --preset Cube --pos 0,1,0
80
+
81
+ # Search assets
82
+ uni-cli asset search --instance MyProject --query "*.prefab" --limit 20
83
+
84
+ # Get full JSON output
85
+ uni-cli hierarchy ls --format json --limit 10
86
+
87
+ # List available MCP tools
88
+ uni-cli tools
89
+ ```
90
+
91
+ ### Output Format
92
+
93
+ Compact row-based format designed for minimal token usage:
94
+
95
+ ```
96
+ row id=12345 name="Main Camera" active=1 parent=-1
97
+ row id=12346 name="Directional Light" active=1 parent=-1
98
+ ok op=hierarchy.ls count=2 next="" truncated=0
99
+ ```
100
+
101
+ ### Commands
102
+
103
+ | Command | Description |
104
+ |---------|-------------|
105
+ | `hierarchy ls` | List scene hierarchy |
106
+ | `object create/get/modify/delete` | GameObject operations |
107
+ | `asset search/info/create/delete` | Asset operations |
108
+ | `batch apply` | Execute batch commands from file |
109
+ | `ui-toolkit <action>` | UI Toolkit (UXML, USS, VisualElement) |
110
+ | `addressables <action>` | Addressable Asset System |
111
+ | `dots <action>` | DOTS / ECS |
112
+ | `shader-graph <action>` | Shader Graph |
113
+ | `tools` | List available MCP tools |
114
+
115
+ ### Global Options
116
+
117
+ | Option | Default | Description |
118
+ |--------|---------|-------------|
119
+ | `--url` | `http://127.0.0.1:8080/mcp` | MCP server URL |
120
+ | `--instance` | auto-detect | Unity instance selector |
121
+ | `--format` | `compact` | Output format (`compact` or `json`) |
122
+ | `--timeout` | `30` | Request timeout in seconds |
123
+
124
+ ## Zero Dependencies
125
+
126
+ uni-cli uses only Python standard library — no external packages required.
127
+
128
+ ## License
129
+
130
+ [MIT](https://github.com/NaturaAurum/uni-cli/blob/main/LICENSE)
@@ -0,0 +1,84 @@
1
+ # uni-cli
2
+
3
+ Token-efficient CLI for LLM agents to control Unity Editor via [MCP](https://modelcontextprotocol.io). Reduces token overhead by ~31x compared to raw MCP tool schemas.
4
+
5
+ Part of the [uni-cli](https://github.com/NaturaAurum/uni-cli) project — extends [unity-mcp](https://github.com/CoplayDev/unity-mcp) with additional Unity subsystem tools.
6
+
7
+ ## Why
8
+
9
+ LLM agents talking to Unity through MCP pay a heavy token tax — large tool schemas and verbose JSON responses eat context window budget. uni-cli solves this with a compact CLI layer:
10
+
11
+ | Metric | Value |
12
+ |--------|-------|
13
+ | Per-response output reduction | **79–98%** (median 92.8%) |
14
+ | Tool schema overhead | **MCP 14,877 → CLI 480 tokens** (31x reduction) |
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install unity-mcp-cli
20
+ ```
21
+
22
+ **Prerequisites:**
23
+ - Python 3.10+
24
+ - [unity-mcp](https://github.com/CoplayDev/unity-mcp) running in your Unity project
25
+
26
+ ## Usage
27
+
28
+ ```bash
29
+ # List scene hierarchy (compact output)
30
+ uni-cli hierarchy ls --instance MyProject --fields id,name,parent --limit 50
31
+
32
+ # Create a GameObject
33
+ uni-cli object create --instance MyProject --name "Player" --preset Cube --pos 0,1,0
34
+
35
+ # Search assets
36
+ uni-cli asset search --instance MyProject --query "*.prefab" --limit 20
37
+
38
+ # Get full JSON output
39
+ uni-cli hierarchy ls --format json --limit 10
40
+
41
+ # List available MCP tools
42
+ uni-cli tools
43
+ ```
44
+
45
+ ### Output Format
46
+
47
+ Compact row-based format designed for minimal token usage:
48
+
49
+ ```
50
+ row id=12345 name="Main Camera" active=1 parent=-1
51
+ row id=12346 name="Directional Light" active=1 parent=-1
52
+ ok op=hierarchy.ls count=2 next="" truncated=0
53
+ ```
54
+
55
+ ### Commands
56
+
57
+ | Command | Description |
58
+ |---------|-------------|
59
+ | `hierarchy ls` | List scene hierarchy |
60
+ | `object create/get/modify/delete` | GameObject operations |
61
+ | `asset search/info/create/delete` | Asset operations |
62
+ | `batch apply` | Execute batch commands from file |
63
+ | `ui-toolkit <action>` | UI Toolkit (UXML, USS, VisualElement) |
64
+ | `addressables <action>` | Addressable Asset System |
65
+ | `dots <action>` | DOTS / ECS |
66
+ | `shader-graph <action>` | Shader Graph |
67
+ | `tools` | List available MCP tools |
68
+
69
+ ### Global Options
70
+
71
+ | Option | Default | Description |
72
+ |--------|---------|-------------|
73
+ | `--url` | `http://127.0.0.1:8080/mcp` | MCP server URL |
74
+ | `--instance` | auto-detect | Unity instance selector |
75
+ | `--format` | `compact` | Output format (`compact` or `json`) |
76
+ | `--timeout` | `30` | Request timeout in seconds |
77
+
78
+ ## Zero Dependencies
79
+
80
+ uni-cli uses only Python standard library — no external packages required.
81
+
82
+ ## License
83
+
84
+ [MIT](https://github.com/NaturaAurum/uni-cli/blob/main/LICENSE)
@@ -0,0 +1,52 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "unity-mcp-cli"
7
+ version = "0.1.0"
8
+ description = "Token-efficient CLI for LLM agents to control Unity Editor"
9
+ readme = "README.md"
10
+ license = {file = "LICENSE"}
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "ArtisanCodesmith" },
14
+ ]
15
+ keywords = ["unity", "llm", "cli", "mcp", "agent"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: MIT License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3 :: Only",
26
+ "Topic :: Software Development :: Build Tools",
27
+ ]
28
+ dependencies = []
29
+
30
+ [project.urls]
31
+ Homepage = "https://github.com/NaturaAurum/uni-cli"
32
+ Repository = "https://github.com/NaturaAurum/uni-cli"
33
+ Issues = "https://github.com/NaturaAurum/uni-cli/issues"
34
+
35
+ [project.optional-dependencies]
36
+ test = ["pytest>=7.0"]
37
+
38
+ [project.scripts]
39
+ uni-cli = "uni_cli.main:main"
40
+
41
+ [tool.hatch.build.targets.wheel]
42
+ packages = ["src/uni_cli"]
43
+
44
+ [tool.hatch.build.targets.sdist]
45
+ include = ["src/uni_cli", "README.md", "LICENSE"]
46
+
47
+ [tool.hatch.build.targets.wheel.force-include]
48
+ "LICENSE" = "uni_cli/LICENSE"
49
+
50
+ [tool.pytest.ini_options]
51
+ testpaths = ["tests"]
52
+ pythonpath = ["src", "tests"]
@@ -0,0 +1,8 @@
1
+ """uni-cli: Token-efficient CLI for LLM agents to control Unity Editor."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("uni-cli")
7
+ except PackageNotFoundError:
8
+ __version__ = "0.0.0-dev"
@@ -0,0 +1 @@
1
+ """CLI command implementations."""
@@ -0,0 +1,94 @@
1
+ """asset subcommand — Asset operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from uni_cli.transport.mcp_client import McpClient, extract_text, parse_result_json
8
+
9
+
10
+ def run_search(
11
+ client: McpClient,
12
+ instance_id: str,
13
+ query: str,
14
+ filter_type: str | None,
15
+ fields: str,
16
+ limit: int,
17
+ ) -> dict[str, Any]:
18
+ """Search assets via manage_asset search."""
19
+ args: dict[str, Any] = {
20
+ "action": "search",
21
+ "path": "Assets",
22
+ "page_size": limit,
23
+ "page_number": 1,
24
+ "generate_preview": False,
25
+ "unity_instance": instance_id,
26
+ }
27
+ if query:
28
+ args["search_pattern"] = query
29
+ if filter_type:
30
+ args["filter_type"] = filter_type
31
+ result = client.call_tool("manage_asset", args)
32
+ parsed = parse_result_json(result)
33
+ if parsed is not None:
34
+ return parsed
35
+ return {"raw_text": extract_text(result)}
36
+
37
+
38
+ def run_info(
39
+ client: McpClient,
40
+ instance_id: str,
41
+ path: str,
42
+ ) -> dict[str, Any]:
43
+ """Get asset info via manage_asset get_info."""
44
+ args: dict[str, Any] = {
45
+ "action": "get_info",
46
+ "path": path,
47
+ "unity_instance": instance_id,
48
+ }
49
+ result = client.call_tool("manage_asset", args)
50
+ parsed = parse_result_json(result)
51
+ if parsed is not None:
52
+ return parsed
53
+ return {"raw_text": extract_text(result)}
54
+
55
+
56
+ def run_create(
57
+ client: McpClient,
58
+ instance_id: str,
59
+ path: str,
60
+ asset_type: str,
61
+ **properties: Any,
62
+ ) -> dict[str, Any]:
63
+ """Create an asset via manage_asset create."""
64
+ args: dict[str, Any] = {
65
+ "action": "create",
66
+ "path": path,
67
+ "asset_type": asset_type,
68
+ "unity_instance": instance_id,
69
+ }
70
+ if properties:
71
+ args["properties"] = properties
72
+ result = client.call_tool("manage_asset", args)
73
+ parsed = parse_result_json(result)
74
+ if parsed is not None:
75
+ return parsed
76
+ return {"raw_text": extract_text(result)}
77
+
78
+
79
+ def run_delete(
80
+ client: McpClient,
81
+ instance_id: str,
82
+ path: str,
83
+ ) -> dict[str, Any]:
84
+ """Delete an asset via manage_asset delete."""
85
+ args: dict[str, Any] = {
86
+ "action": "delete",
87
+ "path": path,
88
+ "unity_instance": instance_id,
89
+ }
90
+ result = client.call_tool("manage_asset", args)
91
+ parsed = parse_result_json(result)
92
+ if parsed is not None:
93
+ return parsed
94
+ return {"raw_text": extract_text(result)}
@@ -0,0 +1,43 @@
1
+ """batch subcommand — Batch operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ from typing import Any
7
+
8
+ from uni_cli.transport.mcp_client import McpClient, extract_text, parse_result_json
9
+
10
+
11
+ def run_apply(
12
+ client: McpClient,
13
+ instance_id: str,
14
+ file_path: str,
15
+ ) -> dict[str, Any]:
16
+ """Execute batch commands from a JSON file via batch_execute."""
17
+ with open(file_path) as f:
18
+ batch_data = json.load(f)
19
+
20
+ # Batch file format: {"commands": [{"tool": "...", "params": {...}}, ...]}
21
+ commands = batch_data.get("commands", [])
22
+ if not commands:
23
+ return {"success": False, "error": "No commands in batch file"}
24
+
25
+ # Inject unity_instance into each command's params
26
+ for cmd in commands:
27
+ params = cmd.get("params", {})
28
+ if "unity_instance" not in params:
29
+ params["unity_instance"] = instance_id
30
+ cmd["params"] = params
31
+
32
+ args: dict[str, Any] = {
33
+ "commands": commands,
34
+ "parallel": batch_data.get("parallel", False),
35
+ "fail_fast": batch_data.get("fail_fast", True),
36
+ "max_parallelism": batch_data.get("max_parallelism", 1),
37
+ "unity_instance": instance_id,
38
+ }
39
+ result = client.call_tool("batch_execute", args)
40
+ parsed = parse_result_json(result)
41
+ if parsed is not None:
42
+ return parsed
43
+ return {"raw_text": extract_text(result)}
@@ -0,0 +1,31 @@
1
+ """hierarchy subcommand — Scene hierarchy operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from uni_cli.transport.mcp_client import McpClient, extract_text, parse_result_json
8
+
9
+
10
+ def run_ls(
11
+ client: McpClient,
12
+ instance_id: str,
13
+ fields: str,
14
+ limit: int,
15
+ cursor: str,
16
+ ) -> dict[str, Any]:
17
+ """List scene hierarchy via manage_scene get_hierarchy."""
18
+ args: dict[str, Any] = {
19
+ "action": "get_hierarchy",
20
+ "page_size": limit,
21
+ "cursor": int(cursor) if cursor.isdigit() else 0,
22
+ "include_transform": True,
23
+ "max_depth": 4,
24
+ "unity_instance": instance_id,
25
+ }
26
+ result = client.call_tool("manage_scene", args)
27
+ text = extract_text(result)
28
+ parsed = parse_result_json(result)
29
+ if parsed is not None:
30
+ return parsed
31
+ return {"raw_text": text}
@@ -0,0 +1,102 @@
1
+ """object subcommand — GameObject operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any
6
+
7
+ from uni_cli.transport.mcp_client import McpClient, extract_text, parse_result_json
8
+
9
+
10
+ def run_create(
11
+ client: McpClient,
12
+ instance_id: str,
13
+ name: str,
14
+ preset: str,
15
+ pos: str,
16
+ ) -> dict[str, Any]:
17
+ """Create a GameObject via manage_gameobject create."""
18
+ position = [float(x) for x in pos.split(",")]
19
+ args: dict[str, Any] = {
20
+ "action": "create",
21
+ "name": name,
22
+ "unity_instance": instance_id,
23
+ }
24
+ if preset != "empty":
25
+ args["primitive_type"] = preset
26
+ if position != [0.0, 0.0, 0.0]:
27
+ args["position"] = position
28
+ result = client.call_tool("manage_gameobject", args)
29
+ parsed = parse_result_json(result)
30
+ if parsed is not None:
31
+ return parsed
32
+ return {"raw_text": extract_text(result)}
33
+
34
+
35
+ def run_get(
36
+ client: McpClient,
37
+ instance_id: str,
38
+ target: str,
39
+ ) -> dict[str, Any]:
40
+ """Get GameObject info via manage_gameobject get."""
41
+ args: dict[str, Any] = {
42
+ "action": "get",
43
+ "target": target,
44
+ "search_method": "by_name",
45
+ "unity_instance": instance_id,
46
+ }
47
+ result = client.call_tool("manage_gameobject", args)
48
+ parsed = parse_result_json(result)
49
+ if parsed is not None:
50
+ return parsed
51
+ return {"raw_text": extract_text(result)}
52
+
53
+
54
+ def run_modify(
55
+ client: McpClient,
56
+ instance_id: str,
57
+ target: str,
58
+ *,
59
+ pos: str | None = None,
60
+ parent: str | None = None,
61
+ name: str | None = None,
62
+ active: bool | None = None,
63
+ ) -> dict[str, Any]:
64
+ """Modify a GameObject via manage_gameobject modify."""
65
+ args: dict[str, Any] = {
66
+ "action": "modify",
67
+ "target": target,
68
+ "search_method": "by_name",
69
+ "unity_instance": instance_id,
70
+ }
71
+ if pos is not None:
72
+ args["position"] = [float(x) for x in pos.split(",")]
73
+ if parent is not None:
74
+ args["parent"] = parent
75
+ if name is not None:
76
+ args["name"] = name
77
+ if active is not None:
78
+ args["active"] = active
79
+ result = client.call_tool("manage_gameobject", args)
80
+ parsed = parse_result_json(result)
81
+ if parsed is not None:
82
+ return parsed
83
+ return {"raw_text": extract_text(result)}
84
+
85
+
86
+ def run_delete(
87
+ client: McpClient,
88
+ instance_id: str,
89
+ target: str,
90
+ ) -> dict[str, Any]:
91
+ """Delete a GameObject via manage_gameobject delete."""
92
+ args: dict[str, Any] = {
93
+ "action": "delete",
94
+ "target": target,
95
+ "search_method": "by_name",
96
+ "unity_instance": instance_id,
97
+ }
98
+ result = client.call_tool("manage_gameobject", args)
99
+ parsed = parse_result_json(result)
100
+ if parsed is not None:
101
+ return parsed
102
+ return {"raw_text": extract_text(result)}
@@ -0,0 +1,53 @@
1
+ """Subsystem commands — ui-toolkit, addressables, dots, shader-graph.
2
+
3
+ These proxy to the uni-cli UPM package tools (manage_ui_toolkit, etc.)
4
+ which are auto-registered via [McpForUnityTool] attribute.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from typing import Any
10
+
11
+ from uni_cli.transport.mcp_client import McpClient, extract_text, parse_result_json
12
+
13
+ # Tool name mapping: CLI command name -> MCP tool name
14
+ _TOOL_MAP = {
15
+ "ui-toolkit": "manage_ui_toolkit",
16
+ "addressables": "manage_addressables",
17
+ "dots": "manage_dots",
18
+ "shader-graph": "manage_shader_graph",
19
+ }
20
+
21
+
22
+ def run_subsystem(
23
+ client: McpClient,
24
+ instance_id: str,
25
+ command: str,
26
+ action: str,
27
+ extra_args: dict[str, Any] | None = None,
28
+ ) -> dict[str, Any]:
29
+ """Generic dispatcher for subsystem tool commands.
30
+
31
+ Args:
32
+ client: MCP client
33
+ instance_id: Unity instance ID
34
+ command: CLI command name (e.g. "ui-toolkit")
35
+ action: Tool action (e.g. "list_documents")
36
+ extra_args: Additional parameters for the tool
37
+ """
38
+ tool_name = _TOOL_MAP.get(command)
39
+ if not tool_name:
40
+ return {"success": False, "error": f"Unknown subsystem: {command}"}
41
+
42
+ args: dict[str, Any] = {
43
+ "action": action,
44
+ "unity_instance": instance_id,
45
+ }
46
+ if extra_args:
47
+ args.update(extra_args)
48
+
49
+ result = client.call_tool(tool_name, args)
50
+ parsed = parse_result_json(result)
51
+ if parsed is not None:
52
+ return parsed
53
+ return {"raw_text": extract_text(result)}
@@ -0,0 +1 @@
1
+ """Compact output formatters for uni-cli."""