-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.py
More file actions
124 lines (109 loc) · 17.1 KB
/
Copy pathserver.py
File metadata and controls
124 lines (109 loc) · 17.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
from __future__ import annotations
import asyncio
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent / "data" / "com.accelbyte.ui-tools" / "Tools"))
import mcp.types as types
from mcp.server import Server
from mcp.server.stdio import stdio_server
from unity_ui_tools import (
UIToolsError,
unity_editor_status,
unity_repair_package_cache,
unity_trigger_recompile,
unity_ui_bridge_health,
unity_ui_kit_inspect,
unity_ui_kit_build,
unity_ui_generate,
unity_ui_inspect_generated_layout,
unity_ui_list_entry_candidates,
unity_ui_patch,
unity_ui_preflight,
unity_ui_project_components_generate,
unity_ui_resolve,
unity_ui_scene_preflight,
unity_ui_scene_setup,
unity_ui_select_recipe,
unity_ui_style_discover,
unity_ui_validate,
unity_ui_verify_backing_class,
)
from unity_sdk_tools import (
get_accelbyte_unity_how_to,
search_unity_example_components,
describe_unity_example_components,
)
from unity_install_tools import unity_install_sdk
server = Server("accelbyte-unity-mcp")
@server.list_tools()
async def list_tools() -> list[types.Tool]:
path = {"type": "string", "description": "Unity project root."}
spec = {"type": "string", "description": "Project-local JSON path or recipe:<name>."}
return [
types.Tool(name="unity_ui_style_discover", description="Discover uGUI/TMP project style and optionally approve its fingerprint.", inputSchema={"type": "object", "properties": {"projectPath": path, "approve": {"type": "boolean", "default": False}, "roleOverrides": {"type": "object", "additionalProperties": {"type": "string"}}, "clearRoleOverrides": {"type": "array", "items": {"type": "string"}}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_validate", description="Validate a shared AGS Unity UI recipe without opening Unity.", inputSchema={"type": "object", "properties": {"projectPath": path, "specPath": spec}, "required": ["projectPath", "specPath"]}),
types.Tool(name="unity_ui_preflight", description="Return one read-only readiness report for Unity UI generation, including style approval, recipe selection, validation blockers, entry candidates, missing project roles, and compile/bridge readiness.", inputSchema={"type": "object", "properties": {"projectPath": path, "specPath": spec, "feature": {"type": "string", "description": "Natural-language feature description, e.g. 'login', 'leaderboard', 'friends list'."}, "allowGenericAsync": {"type": "boolean", "default": False}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_resolve", description="Resolve an AGS recipe into a Unity uGUI prefab spec without creating assets.", inputSchema={"type": "object", "properties": {"projectPath": path, "specPath": spec}, "required": ["projectPath", "specPath"]}),
types.Tool(name="unity_ui_kit_inspect", description="Inspect package-owned AGS uGUI kit prefabs against component specs without modifying assets.", inputSchema={"type": "object", "properties": {"projectPath": path, "kit": {"type": "string", "default": "ags"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_kit_build", description="Rebuild all AGS core kit prefabs under Packages/com.accelbyte.ui-tools/Prefabs/Core/ with force=true. Use after plugin C# changes to regenerate existing prefabs. Uses the live editor bridge when Unity is open, batch mode when closed.", inputSchema={"type": "object", "properties": {"projectPath": path, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_generate", description="Generate a project-owned Unity uGUI prefab through the live editor bridge when Unity is open, or batch mode when it is closed. Refuses generate-blocking validation warnings, Unity compile errors, unverified backing classes, and failed post-generation verification/layout gates unless explicitly overridden where supported.", inputSchema={"type": "object", "properties": {"projectPath": path, "specPath": spec, "force": {"type": "boolean", "default": False}, "allowWarnings": {"type": "boolean", "default": False}, "allowGenerationIssues": {"type": "boolean", "default": False}, "allowNonstandardClassPath": {"type": "boolean", "default": False, "description": "Allow generated backing C# outside Assets/AGS/Scripts. Use only for an intentional project convention."}, "backingClassPath": {"type": "string", "description": "Project-local path to the generated C# backing class. Required when the recipe declares backing_class."}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath", "specPath"]}),
types.Tool(name="unity_ui_list_entry_candidates", description="Report approved project prefab candidates for generated list or collection rows.", inputSchema={"type": "object", "properties": {"projectPath": path, "screen": {"type": "string"}, "feature": {"type": "string"}, "itemView": {"type": "string"}, "item_view": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_inspect_generated_layout", description="Inspect generated Unity UI prefabs for layout, backing-class, component, and collection health.", inputSchema={"type": "object", "properties": {"projectPath": path, "assetPath": {"type": "string"}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_scene_preflight", description="Return scene readiness for generated Unity UI, including Input System mode, EventSystem module compatibility, Canvas presence, generated panel candidates, active panel state, blockers, warnings, and next actions.", inputSchema={"type": "object", "properties": {"projectPath": path, "scenePath": {"type": "string", "description": "Project-local scene path. If omitted, the live bridge inspects the active scene."}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_scene_setup", description="Set up and validate a Unity scene for generated UI through the live editor bridge. Creates/reuses Canvas and EventSystem, selects the compatible input module, instantiates panels, optionally attaches a compiled MenuManager MonoBehaviour and assigns generated panel fields, activates only initialPanel, and saves the scene on success.", inputSchema={"type": "object", "properties": {"projectPath": path, "scenePath": {"type": "string", "description": "Project-local scene path. If omitted, the live bridge uses the active scene."}, "panels": {"type": "array", "items": {"type": "string"}, "description": "Project-local generated panel prefab paths to instantiate."}, "initialPanel": {"type": "string", "description": "Panel prefab path from panels that should be active at startup."}, "menuManagerClass": {"type": "string", "description": "Optional fully-qualified compiled MonoBehaviour type to attach to a scene GameObject named MenuManager."}, "menuBindings": {"type": "array", "items": {"type": "object", "properties": {"fieldName": {"type": "string"}, "panel": {"type": "string"}}, "required": ["fieldName", "panel"]}, "description": "Optional serialized field assignments for menuManagerClass. fieldName is a field on the MenuManager; panel is one of the panel prefab paths."}, "mode": {"type": "string", "default": "setup_and_validate", "enum": ["setup_and_validate"]}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath", "panels", "initialPanel"]}),
types.Tool(name="unity_ui_project_components_generate", description="Generate project-owned reusable UI component prefabs under Assets/AGS/UI/Components.", inputSchema={"type": "object", "properties": {"projectPath": path, "roles": {"type": "array", "items": {"type": "string"}}, "role": {"type": "string"}, "force": {"type": "boolean", "default": False}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_patch", description="Patch existing generated or package-owned UI prefabs with narrow property operations.", inputSchema={"type": "object", "properties": {"projectPath": path, "patchPath": {"type": "string"}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath", "patchPath"]}),
types.Tool(name="unity_editor_status", description="Report the expected Unity editor, whether Unity is running, and whether com.accelbyte.ui-tools is installed (ui_tools_installed, ui_tools_path).", inputSchema={"type": "object", "properties": {"projectPath": path, "editorPath": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_repair_package_cache", description="Force a clean re-resolve of a stale UPM git-dependency package. Use on a packages-lock.json hash mismatch against Library/PackageCache, or a 'Failed to rename ... EPERM' error during resolve. Deletes the stale Library/PackageCache/<package>@* folder(s) and removes the package's packages-lock.json entry so Package Manager re-resolves it fresh on next editor launch. Refuses to run while a Unity editor process is open unless force=true.", inputSchema={"type": "object", "properties": {"projectPath": path, "packageName": {"type": "string", "description": "UPM package name to repair, e.g. 'com.accelbyte.ui-tools'."}, "force": {"type": "boolean", "default": False, "description": "Repair even if a Unity editor process is currently running. Leave false unless you've independently confirmed it's safe."}}, "required": ["projectPath", "packageName"]}),
types.Tool(name="unity_ui_bridge_health", description="Check whether the AccelByte UI Tools bridge is healthy in the Unity editor. Returns ok, bridge URL, and the health response (including isCompiling). Lighter than unity_editor_status — use for a quick bridge-only check.", inputSchema={"type": "object", "properties": {"bridgeUrl": {"type": "string", "description": "Bridge URL (default: http://127.0.0.1:48758)."}}, "required": []}),
types.Tool(name="unity_trigger_recompile", description="Refresh Unity's AssetDatabase, then ask the Unity editor to recompile all C# scripts via CompilationPipeline.RequestScriptCompilation(). Use after writing a C# backing class to import new/changed files without switching focus to the editor manually. Poll unity_ui_bridge_health.response.isCompiling until false.", inputSchema={"type": "object", "properties": {"projectPath": path, "changedAssetPaths": {"type": "array", "items": {"type": "string"}, "description": "Project-local changed asset paths Unity should import before compiling."}, "classPath": {"type": "string", "description": "Project-local generated C# backing class path to import before compiling."}, "backingClassPath": {"type": "string", "description": "Alias for classPath."}, "editorPath": {"type": "string"}, "bridgeUrl": {"type": "string"}}, "required": ["projectPath"]}),
types.Tool(name="unity_ui_select_recipe", description="Select the best AGS Unity UI recipe for a feature and return a partial spec stub. Unknown broad screens do not silently accept generic_async; pass allowGenericAsync=true only for intentional one-shot async/status panels.", inputSchema={"type": "object", "properties": {"projectPath": path, "feature": {"type": "string", "description": "Natural-language feature description, e.g. 'login', 'leaderboard', 'friends list'."}, "allowGenericAsync": {"type": "boolean", "default": False}}, "required": ["projectPath", "feature"]}),
types.Tool(name="unity_ui_verify_backing_class", description="Validate that [SerializeField] fields in a C# backing class match the cs_bindings from unity_ui_resolve. Call after writing the C# class and before unity_ui_generate.", inputSchema={"type": "object", "properties": {"projectPath": path, "specPath": {"type": "string", "description": "Path to the authored ags-ui-recipe/v1 spec JSON."}, "classPath": {"type": "string", "description": "Path to the C# backing class file."}, "allowNonstandardClassPath": {"type": "boolean", "default": False, "description": "Allow generated backing C# outside Assets/AGS/Scripts. Use only for an intentional project convention."}}, "required": ["projectPath", "specPath", "classPath"]}),
types.Tool(name="get_accelbyte_unity_how_to", description="Query the AccelByte Unity SDK best-practices knowledge base for a topic. Returns SDK guides with C# code templates, best practices, and related component names. Use before writing a C# backing class.", inputSchema={"type": "object", "properties": {"topic": {"type": "string", "description": "Feature or SDK topic, e.g. 'login', 'leaderboard', 'friends', 'user profile'."}, "projectPath": path}, "required": ["topic"]}),
types.Tool(name="search_unity_example_components", description="Search the bytewars C# source index for classes matching a feature. Returns ranked component metadata (class name, URI, feature tags, public methods). Use URIs with describe_unity_example_components.", inputSchema={"type": "object", "properties": {"feature": {"type": "string", "description": "Feature to search for, e.g. 'login', 'leaderboard'."}, "projectPath": path, "limit": {"type": "integer", "default": 5}}, "required": ["feature"]}),
types.Tool(name="describe_unity_example_components", description="Read C# source files for one or more bytewars components. Pass 'uris' from search_unity_example_components. Returns full C# source text for each file.", inputSchema={"type": "object", "properties": {"uris": {"type": "array", "items": {"type": "string"}, "description": "URI list from search_unity_example_components."}, "projectPath": path}, "required": ["uris"]}),
types.Tool(name="unity_install_sdk", description="Set up AccelByte Unity SDK config in a Unity project. By default writes only config files and preserves valid split SDK/OAuth config; pass patchManifest=true only when manifest package installation is intended.", inputSchema={"type": "object", "properties": {"projectPath": path, "clientId": {"type": "string", "description": "OAuth client ID from AGS Console > IAM > Clients."}, "namespace": {"type": "string", "description": "AccelByte game namespace."}, "clientSecret": {"type": "string", "description": "OAuth client secret (leave empty for public client)."}, "baseUrl": {"type": "string", "description": "AGS environment base URL (default: https://prod.gamingservices.accelbyte.io)."}, "sdkVersion": {"type": "string", "description": "UPM package version. Required to add a dependency when patchManifest=true; default latest will not write '*'.", "default": "latest"}, "patchManifest": {"type": "boolean", "default": False, "description": "Opt in to patching Packages/manifest.json. Existing SDK dependency values are preserved."}, "overwriteConfig": {"type": "boolean", "default": False, "description": "Rewrite valid existing SDK/OAuth config files. Default false preserves split config."}, "publisherNamespace": {"type": "string"}, "appId": {"type": "string"}}, "required": ["projectPath", "clientId", "namespace"]}),
]
@server.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
handlers = {
"unity_ui_style_discover": unity_ui_style_discover,
"unity_ui_validate": unity_ui_validate,
"unity_ui_preflight": unity_ui_preflight,
"unity_ui_resolve": unity_ui_resolve,
"unity_ui_scene_preflight": unity_ui_scene_preflight,
"unity_ui_scene_setup": unity_ui_scene_setup,
"unity_ui_kit_inspect": unity_ui_kit_inspect,
"unity_ui_kit_build": unity_ui_kit_build,
"unity_ui_generate": unity_ui_generate,
"unity_ui_inspect_generated_layout": unity_ui_inspect_generated_layout,
"unity_ui_list_entry_candidates": unity_ui_list_entry_candidates,
"unity_ui_project_components_generate": unity_ui_project_components_generate,
"unity_ui_patch": unity_ui_patch,
"unity_editor_status": unity_editor_status,
"unity_repair_package_cache": unity_repair_package_cache,
"unity_ui_bridge_health": unity_ui_bridge_health,
"unity_trigger_recompile": unity_trigger_recompile,
"unity_ui_select_recipe": unity_ui_select_recipe,
"unity_ui_verify_backing_class": unity_ui_verify_backing_class,
"get_accelbyte_unity_how_to": get_accelbyte_unity_how_to,
"search_unity_example_components": search_unity_example_components,
"describe_unity_example_components": describe_unity_example_components,
"unity_install_sdk": unity_install_sdk,
}
try:
handler = handlers[name]
result = handler(arguments or {})
except KeyError:
result = {"ok": False, "errors": [{"code": "unknown_tool", "message": name}]}
except (UIToolsError, KeyError, OSError, ValueError) as exc:
result = {"ok": False, "errors": [{"code": "tool_error", "message": str(exc)}]}
return [types.TextContent(type="text", text=json.dumps(result, indent=2))]
async def _main() -> None:
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream, server.create_initialization_options())
def main() -> None:
asyncio.run(_main())
if __name__ == "__main__":
main()