2025-03-18 19:00:50 +08:00
|
|
|
from mcp.server.fastmcp import FastMCP, Context, Image
|
|
|
|
|
import logging
|
|
|
|
|
from dataclasses import dataclass
|
|
|
|
|
from contextlib import asynccontextmanager
|
|
|
|
|
from typing import AsyncIterator, Dict, Any, List
|
|
|
|
|
from config import config
|
|
|
|
|
from tools import register_all_tools
|
|
|
|
|
from unity_connection import get_unity_connection, UnityConnection
|
|
|
|
|
|
|
|
|
|
# Configure logging using settings from config
|
|
|
|
|
logging.basicConfig(
|
|
|
|
|
level=getattr(logging, config.log_level),
|
|
|
|
|
format=config.log_format
|
|
|
|
|
)
|
2025-03-19 04:06:48 +08:00
|
|
|
logger = logging.getLogger("UnityMCP")
|
2025-03-18 19:00:50 +08:00
|
|
|
|
2025-03-19 01:24:17 +08:00
|
|
|
# Global connection state
|
|
|
|
|
_unity_connection: UnityConnection = None
|
|
|
|
|
|
2025-03-18 19:00:50 +08:00
|
|
|
@asynccontextmanager
|
|
|
|
|
async def server_lifespan(server: FastMCP) -> AsyncIterator[Dict[str, Any]]:
|
|
|
|
|
"""Handle server startup and shutdown."""
|
2025-03-19 01:24:17 +08:00
|
|
|
global _unity_connection
|
2025-03-18 19:00:50 +08:00
|
|
|
logger.info("UnityMCP server starting up")
|
|
|
|
|
try:
|
2025-03-19 01:24:17 +08:00
|
|
|
_unity_connection = get_unity_connection()
|
2025-03-18 19:00:50 +08:00
|
|
|
logger.info("Connected to Unity on startup")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.warning(f"Could not connect to Unity on startup: {str(e)}")
|
2025-03-19 01:24:17 +08:00
|
|
|
_unity_connection = None
|
2025-03-18 19:00:50 +08:00
|
|
|
try:
|
2025-03-31 03:58:01 +08:00
|
|
|
# Yield the connection object so it can be attached to the context
|
|
|
|
|
# The key 'bridge' matches how tools like read_console expect to access it (ctx.bridge)
|
|
|
|
|
yield {"bridge": _unity_connection}
|
2025-03-18 19:00:50 +08:00
|
|
|
finally:
|
|
|
|
|
if _unity_connection:
|
|
|
|
|
_unity_connection.disconnect()
|
|
|
|
|
_unity_connection = None
|
|
|
|
|
logger.info("UnityMCP server shut down")
|
|
|
|
|
|
|
|
|
|
# Initialize MCP server
|
|
|
|
|
mcp = FastMCP(
|
|
|
|
|
"UnityMCP",
|
|
|
|
|
description="Unity Editor integration via Model Context Protocol",
|
|
|
|
|
lifespan=server_lifespan
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Register all tools
|
|
|
|
|
register_all_tools(mcp)
|
|
|
|
|
|
|
|
|
|
# Asset Creation Strategy
|
|
|
|
|
|
|
|
|
|
@mcp.prompt()
|
|
|
|
|
def asset_creation_strategy() -> str:
|
2025-03-31 03:58:01 +08:00
|
|
|
"""Guide for discovering and using Unity MCP tools effectively."""
|
2025-03-18 19:00:50 +08:00
|
|
|
return (
|
2025-03-31 03:58:01 +08:00
|
|
|
"Available Unity MCP Server Tools:\\n\\n"
|
|
|
|
|
"For detailed usage, please refer to the specific tool's documentation.\\n\\n"
|
|
|
|
|
"- `manage_editor`: Controls editor state (play/pause/stop) and queries info (state, selection).\\n"
|
|
|
|
|
"- `execute_menu_item`: Executes Unity Editor menu items by path (e.g., 'File/Save Project').\\n"
|
|
|
|
|
"- `read_console`: Reads or clears Unity console messages, with filtering options.\\n"
|
|
|
|
|
"- `manage_scene`: Manages scenes (load, save, create, get hierarchy).\\n"
|
|
|
|
|
"- `manage_gameobject`: Manages GameObjects in the scene (CRUD, find, components, assign properties).\\n"
|
|
|
|
|
"- `manage_script`: Manages C# script files (CRUD).\\n"
|
|
|
|
|
"- `manage_asset`: Manages project assets (import, create, modify, delete, search).\\n\\n"
|
2025-03-18 19:00:50 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Run the server
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
mcp.run(transport='stdio')
|