From 558f9232d3938c846f3fb1c11c126b8b919359bc Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Wed, 22 Oct 2025 17:36:24 -0400 Subject: [PATCH] Allow the MCP server to be run by `uvx` remotely (#336) * feat: add entry point script and additional Python modules to server package Now we can run this server with `uvx` * refactor: improve package version detection to support both installed and development environments * refactor: simplify release workflow by removing server packaging step --- .github/workflows/bump-version.yml | 19 +++------------ .../UnityMcpServer~/src/pyproject.toml | 17 +++++++++++-- MCPForUnity/UnityMcpServer~/src/server.py | 7 +++++- MCPForUnity/UnityMcpServer~/src/telemetry.py | 24 +++++++++++++------ 4 files changed, 41 insertions(+), 26 deletions(-) diff --git a/.github/workflows/bump-version.yml b/.github/workflows/bump-version.yml index e9c3b0a..9cb8e1c 100644 --- a/.github/workflows/bump-version.yml +++ b/.github/workflows/bump-version.yml @@ -109,19 +109,7 @@ jobs: git tag -a "$TAG" -m "Version ${NEW_VERSION}" git push origin "$TAG" - - name: Package server for release - env: - NEW_VERSION: ${{ steps.compute.outputs.new_version }} - shell: bash - run: | - set -euo pipefail - cd MCPForUnity - zip -r ../mcp-for-unity-server-v${NEW_VERSION}.zip UnityMcpServer~ - cd .. - ls -lh mcp-for-unity-server-v${NEW_VERSION}.zip - echo "Server package created: mcp-for-unity-server-v${NEW_VERSION}.zip" - - - name: Create GitHub release with server artifact + - name: Create GitHub release env: NEW_VERSION: ${{ steps.compute.outputs.new_version }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -130,8 +118,7 @@ jobs: set -euo pipefail TAG="v${NEW_VERSION}" - # Create release + # Create release with auto-generated notes gh release create "$TAG" \ --title "v${NEW_VERSION}" \ - --notes "Release v${NEW_VERSION}" \ - "mcp-for-unity-server-v${NEW_VERSION}.zip#MCP Server v${NEW_VERSION}" + --generate-notes diff --git a/MCPForUnity/UnityMcpServer~/src/pyproject.toml b/MCPForUnity/UnityMcpServer~/src/pyproject.toml index dda99f1..fafc46c 100644 --- a/MCPForUnity/UnityMcpServer~/src/pyproject.toml +++ b/MCPForUnity/UnityMcpServer~/src/pyproject.toml @@ -17,10 +17,23 @@ dev = [ "pytest-asyncio>=0.23", ] +[project.scripts] +mcp-for-unity = "server:main" + [build-system] requires = ["setuptools>=64.0.0", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools] -py-modules = ["config", "server", "unity_connection"] -packages = ["tools"] +py-modules = [ + "config", + "models", + "module_discovery", + "port_discovery", + "reload_sentinel", + "server", + "telemetry", + "telemetry_decorator", + "unity_connection" +] +packages = ["tools", "resources", "registry"] diff --git a/MCPForUnity/UnityMcpServer~/src/server.py b/MCPForUnity/UnityMcpServer~/src/server.py index e4442ee..cf54a0e 100644 --- a/MCPForUnity/UnityMcpServer~/src/server.py +++ b/MCPForUnity/UnityMcpServer~/src/server.py @@ -189,6 +189,11 @@ def asset_creation_strategy() -> str: ) +def main(): + """Entry point for uvx and console scripts.""" + mcp.run(transport='stdio') + + # Run the server if __name__ == "__main__": - mcp.run(transport='stdio') + main() diff --git a/MCPForUnity/UnityMcpServer~/src/telemetry.py b/MCPForUnity/UnityMcpServer~/src/telemetry.py index c14e9c4..a28e14f 100644 --- a/MCPForUnity/UnityMcpServer~/src/telemetry.py +++ b/MCPForUnity/UnityMcpServer~/src/telemetry.py @@ -10,7 +10,7 @@ Fire-and-forget telemetry sender with a single background worker. import contextlib from dataclasses import dataclass from enum import Enum -import importlib +from importlib import import_module, metadata import json import logging import os @@ -38,12 +38,22 @@ logger = logging.getLogger("unity-mcp-telemetry") def get_package_version() -> str: """ - Open pyproject.toml and parse version - We use the tomli library instead of tomllib to support Python 3.10 + Get package version in different ways: + 1. First we try the installed metadata - this is because uvx is used on the asset store + 2. If that fails, we try to read from pyproject.toml - this is available for users who download via Git + Default is "unknown", but that should never happen """ - with open("pyproject.toml", "rb") as f: - data = tomli.load(f) - return data["project"]["version"] + try: + return metadata.version("MCPForUnityServer") + except Exception: + # Fallback for development: read from pyproject.toml + try: + pyproject_path = Path(__file__).parent / "pyproject.toml" + with open(pyproject_path, "rb") as f: + data = tomli.load(f) + return data["project"]["version"] + except Exception: + return "unknown" MCP_VERSION = get_package_version() @@ -100,7 +110,7 @@ class TelemetryConfig: "MCPForUnity.UnityMcpServer.src.config", ): try: - mod = importlib.import_module(modname) + mod = import_module(modname) server_config = getattr(mod, "config", None) if server_config is not None: break