2025-08-10 06:08:28 +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-08-21 03:59:49 +08:00
|
|
|
logger = logging.getLogger("mcp-for-unity-server")
|
2025-08-10 06:08:28 +08:00
|
|
|
|
|
|
|
|
# Global connection state
|
|
|
|
|
_unity_connection: UnityConnection = None
|
|
|
|
|
|
|
|
|
|
@asynccontextmanager
|
|
|
|
|
async def server_lifespan(server: FastMCP) -> AsyncIterator[Dict[str, Any]]:
|
|
|
|
|
"""Handle server startup and shutdown."""
|
|
|
|
|
global _unity_connection
|
2025-08-21 03:59:49 +08:00
|
|
|
logger.info("MCP for Unity Server starting up")
|
2025-08-10 06:08:28 +08:00
|
|
|
try:
|
|
|
|
|
_unity_connection = get_unity_connection()
|
|
|
|
|
logger.info("Connected to Unity on startup")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.warning(f"Could not connect to Unity on startup: {str(e)}")
|
|
|
|
|
_unity_connection = None
|
|
|
|
|
try:
|
|
|
|
|
# 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}
|
|
|
|
|
finally:
|
|
|
|
|
if _unity_connection:
|
|
|
|
|
_unity_connection.disconnect()
|
|
|
|
|
_unity_connection = None
|
2025-08-21 03:59:49 +08:00
|
|
|
logger.info("MCP for Unity Server shut down")
|
2025-08-10 06:08:28 +08:00
|
|
|
|
|
|
|
|
# Initialize MCP server
|
|
|
|
|
mcp = FastMCP(
|
2025-08-21 03:59:49 +08:00
|
|
|
"mcp-for-unity-server",
|
2025-08-10 06:08:28 +08:00
|
|
|
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-08-21 03:59:49 +08:00
|
|
|
"""Guide for discovering and using MCP for Unity tools effectively."""
|
2025-08-10 06:08:28 +08:00
|
|
|
return (
|
2025-08-21 03:59:49 +08:00
|
|
|
"Available MCP for Unity Server Tools:\\n\\n"
|
2025-08-10 06:08:28 +08:00
|
|
|
"- `manage_editor`: Controls editor state and queries info.\\n"
|
|
|
|
|
"- `execute_menu_item`: Executes Unity Editor menu items by path.\\n"
|
|
|
|
|
"- `read_console`: Reads or clears Unity console messages, with filtering options.\\n"
|
|
|
|
|
"- `manage_scene`: Manages scenes.\\n"
|
|
|
|
|
"- `manage_gameobject`: Manages GameObjects in the scene.\\n"
|
|
|
|
|
"- `manage_script`: Manages C# script files.\\n"
|
|
|
|
|
"- `manage_asset`: Manages prefabs and assets.\\n"
|
|
|
|
|
"- `manage_shader`: Manages shaders.\\n\\n"
|
|
|
|
|
"Tips:\\n"
|
|
|
|
|
"- Create prefabs for reusable GameObjects.\\n"
|
|
|
|
|
"- Always include a camera and main light in your scenes.\\n"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Run the server
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
mcp.run(transport='stdio')
|