From 1238eb1e84d6a4d34662a6e9d4baa1ce4247ce08 Mon Sep 17 00:00:00 2001 From: Bryan Thompson Date: Thu, 22 Jan 2026 13:46:35 -0600 Subject: [PATCH 1/8] feat: Add MCPB bundle for Claude Desktop installation (#580) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add MCPB bundle for Claude Desktop installation Add Model Context Protocol Bundle (MCPB) support enabling single-click installation in Claude Desktop and other MCP hosts. Changes: - Add manifest.json with uvx-based server configuration - Add icon.png for display in Claude Desktop - Add .mcpbignore for build exclusions - Add pre-built unity-mcp.mcpb bundle 🤖 Generated with [Claude Code](https://claude.com/claude-code) * fix: Generate MCPB as release artifact instead of committing to repo Address review feedback from @msanatan: - Remove pre-built unity-mcp.mcpb and icon.png from repository - Add tools/generate_mcpb.py script for bundle generation - Update release.yml with new publish_mcpb job that: - Generates bundle using generate_mcpb.py - Uploads MCPB file as release artifact - Update manifest.json to reference icon from docs/images/ The bundle is now generated automatically on each release, keeping the repository clean while providing download artifacts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * fix: Use correct mcpb pack CLI syntax (positional args) The mcpb CLI uses 'mcpb pack [directory] [output]' syntax, not '--output' flag. Tested locally - bundle generates correctly. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: triepod-ai <199543909+triepod-ai@users.noreply.github.com> --- .github/workflows/release.yml | 40 +++++++++ .mcpbignore | 82 +++++++++++++++++++ manifest.json | 58 ++++++++++++++ tools/generate_mcpb.py | 147 ++++++++++++++++++++++++++++++++++ 4 files changed, 327 insertions(+) create mode 100644 .mcpbignore create mode 100644 manifest.json create mode 100755 tools/generate_mcpb.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aff446f..291ce8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -194,3 +194,43 @@ jobs: uses: pypa/gh-action-pypi-publish@release/v1 with: packages-dir: Server/dist/ + + publish_mcpb: + name: Generate and publish MCPB bundle + needs: + - bump + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: Check out the repo + uses: actions/checkout@v6 + with: + ref: ${{ needs.bump.outputs.tag }} + fetch-depth: 0 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: "3.11" + + - name: Generate MCPB bundle + env: + NEW_VERSION: ${{ needs.bump.outputs.new_version }} + shell: bash + run: | + set -euo pipefail + python3 tools/generate_mcpb.py "$NEW_VERSION" \ + --output "unity-mcp-${NEW_VERSION}.mcpb" \ + --icon docs/images/coplay-logo.png + + - name: Upload MCPB to release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ needs.bump.outputs.tag }} + files: unity-mcp-${{ needs.bump.outputs.new_version }}.mcpb diff --git a/.mcpbignore b/.mcpbignore new file mode 100644 index 0000000..cd911c3 --- /dev/null +++ b/.mcpbignore @@ -0,0 +1,82 @@ +# MCPB Ignore File +# This bundle uses uvx pattern - package downloaded from PyPI at runtime +# Only manifest.json, icon.png, README.md, and LICENSE are needed + +# Server source code (downloaded via uvx from PyPI) +Server/ + +# Unity Client plugin (separate installation) +MCPForUnity/ + +# Test projects +TestProjects/ + +# Documentation folder +docs/ + +# Custom Tools (shipped separately) +CustomTools/ + +# Development scripts at root +scripts/ +tools/ + +# Claude skill zip (separate distribution) +claude_skill_unity.zip + +# Development batch files +deploy-dev.bat +restore-dev.bat + +# Test files at root +test_unity_socket_framing.py +mcp_source.py +prune_tool_results.py + +# Docker +docker-compose.yml +.dockerignore +Dockerfile + +# Chinese README (keep English only) +README-zh.md + +# GitHub and CI +.github/ +.claude/ + +# IDE +.vscode/ +.idea/ + +# Python artifacts +*.pyc +__pycache__/ +.pytest_cache/ +.mypy_cache/ +*.egg-info/ +dist/ +build/ + +# Environment +.env* +*.local +.venv/ +venv/ + +# Git +.git/ +.gitignore +.gitattributes + +# Package management +uv.lock +poetry.lock +requirements*.txt +pyproject.toml + +# Logs and temp +*.log +*.tmp +.DS_Store +Thumbs.db diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..f77655d --- /dev/null +++ b/manifest.json @@ -0,0 +1,58 @@ +{ + "manifest_version": "0.3", + "name": "Unity MCP", + "version": "9.0.7", + "description": "AI-powered Unity Editor automation via MCP - manage GameObjects, scripts, materials, scenes, prefabs, VFX, and run tests", + "author": { + "name": "Coplay", + "url": "https://www.coplay.dev" + }, + "repository": { + "type": "git", + "url": "https://github.com/CoplayDev/unity-mcp" + }, + "homepage": "https://www.coplay.dev", + "documentation": "https://github.com/CoplayDev/unity-mcp#readme", + "support": "https://github.com/CoplayDev/unity-mcp/issues", + "icon": "coplay-logo.png", + "server": { + "type": "python", + "entry_point": "Server/src/main.py", + "mcp_config": { + "command": "uvx", + "args": ["--from", "mcpforunityserver", "mcp-for-unity"], + "env": {} + } + }, + "tools": [ + {"name": "batch_execute", "description": "Execute multiple Unity operations in a single batch"}, + {"name": "debug_request_context", "description": "Debug and inspect MCP request context"}, + {"name": "execute_custom_tool", "description": "Execute custom Unity Editor tools registered by the project"}, + {"name": "execute_menu_item", "description": "Execute Unity Editor menu items"}, + {"name": "find_gameobjects", "description": "Find GameObjects in the scene by various criteria"}, + {"name": "find_in_file", "description": "Search for content within Unity project files"}, + {"name": "manage_asset", "description": "Create, modify, search, and organize Unity assets"}, + {"name": "manage_components", "description": "Add, remove, and configure GameObject components"}, + {"name": "manage_editor", "description": "Control Unity Editor state, play mode, and preferences"}, + {"name": "manage_gameobject", "description": "Create, modify, transform, and delete GameObjects"}, + {"name": "manage_material", "description": "Create and modify Unity materials and shaders"}, + {"name": "manage_prefabs", "description": "Create, instantiate, unpack, and modify prefabs"}, + {"name": "manage_scene", "description": "Load, save, query hierarchy, and manage Unity scenes"}, + {"name": "manage_script", "description": "Create, read, and modify C# scripts"}, + {"name": "manage_scriptable_object", "description": "Create and modify ScriptableObjects"}, + {"name": "manage_shader", "description": "Work with Unity shaders"}, + {"name": "manage_vfx", "description": "Manage Visual Effects, particle systems, and trails"}, + {"name": "read_console", "description": "Read Unity Editor console output (logs, warnings, errors)"}, + {"name": "refresh_unity", "description": "Refresh Unity Editor asset database"}, + {"name": "run_tests", "description": "Run Unity Test Framework tests"}, + {"name": "get_test_job", "description": "Get status of async test job"}, + {"name": "script_apply_edits", "description": "Apply code edits to C# scripts with validation"}, + {"name": "set_active_instance", "description": "Set the active Unity Editor instance for multi-instance workflows"}, + {"name": "apply_text_edits", "description": "Apply text edits to script content"}, + {"name": "create_script", "description": "Create new C# scripts"}, + {"name": "delete_script", "description": "Delete C# scripts"}, + {"name": "validate_script", "description": "Validate C# script syntax and compilation"}, + {"name": "manage_script_capabilities", "description": "Query script management capabilities"}, + {"name": "get_sha", "description": "Get SHA hash of script content"} + ] +} diff --git a/tools/generate_mcpb.py b/tools/generate_mcpb.py new file mode 100755 index 0000000..7194218 --- /dev/null +++ b/tools/generate_mcpb.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python3 +"""Generate MCPB bundle for Unity MCP. + +This script creates a Model Context Protocol Bundle (.mcpb) file +for distribution as a GitHub release artifact. + +Usage: + python3 tools/generate_mcpb.py VERSION [--output FILE] [--icon PATH] + +Examples: + python3 tools/generate_mcpb.py 9.0.8 + python3 tools/generate_mcpb.py 9.0.8 --output unity-mcp-9.0.8.mcpb + python3 tools/generate_mcpb.py 9.0.8 --icon docs/images/coplay-logo.png +""" +from __future__ import annotations + +import argparse +import json +import shutil +import subprocess +import sys +import tempfile +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[1] +DEFAULT_ICON = REPO_ROOT / "docs" / "images" / "coplay-logo.png" +MANIFEST_TEMPLATE = REPO_ROOT / "manifest.json" + + +def create_manifest(version: str, icon_filename: str) -> dict: + """Create manifest.json content with the specified version.""" + if not MANIFEST_TEMPLATE.exists(): + raise FileNotFoundError(f"Manifest template not found: {MANIFEST_TEMPLATE}") + + manifest = json.loads(MANIFEST_TEMPLATE.read_text(encoding="utf-8")) + manifest["version"] = version + manifest["icon"] = icon_filename + return manifest + + +def generate_mcpb( + version: str, + output_path: Path, + icon_path: Path, +) -> Path: + """Generate MCPB bundle file. + + Args: + version: Semantic version string (e.g., "9.0.8") + output_path: Output path for the .mcpb file + icon_path: Path to the icon file + + Returns: + Path to the generated .mcpb file + """ + if not icon_path.exists(): + raise FileNotFoundError(f"Icon not found: {icon_path}") + + with tempfile.TemporaryDirectory() as tmpdir: + build_dir = Path(tmpdir) / "mcpb-build" + build_dir.mkdir() + + # Copy icon + icon_filename = icon_path.name + shutil.copy2(icon_path, build_dir / icon_filename) + + # Create manifest with version + manifest = create_manifest(version, icon_filename) + manifest_path = build_dir / "manifest.json" + manifest_path.write_text( + json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", + encoding="utf-8", + ) + + # Copy LICENSE and README if they exist + for filename in ["LICENSE", "README.md"]: + src = REPO_ROOT / filename + if src.exists(): + shutil.copy2(src, build_dir / filename) + + # Pack using mcpb CLI + # Syntax: mcpb pack [directory] [output] + try: + result = subprocess.run( + ["npx", "@anthropic-ai/mcpb", "pack", ".", str(output_path.absolute())], + cwd=build_dir, + capture_output=True, + text=True, + check=True, + ) + print(result.stdout) + except subprocess.CalledProcessError as e: + print(f"MCPB pack failed:\n{e.stderr}", file=sys.stderr) + raise + except FileNotFoundError: + print( + "Error: npx not found. Please install Node.js and npm.", + file=sys.stderr, + ) + raise + + if not output_path.exists(): + raise RuntimeError(f"MCPB file was not created: {output_path}") + + print(f"Generated: {output_path} ({output_path.stat().st_size:,} bytes)") + return output_path + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Generate MCPB bundle for Unity MCP", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument( + "version", + help="Version string for the bundle (e.g., 9.0.8)", + ) + parser.add_argument( + "--output", + "-o", + type=Path, + help="Output path for the .mcpb file (default: unity-mcp-VERSION.mcpb)", + ) + parser.add_argument( + "--icon", + type=Path, + default=DEFAULT_ICON, + help=f"Path to icon file (default: {DEFAULT_ICON.relative_to(REPO_ROOT)})", + ) + + args = parser.parse_args() + + # Default output name + if args.output is None: + args.output = Path(f"unity-mcp-{args.version}.mcpb") + + try: + generate_mcpb(args.version, args.output, args.icon) + return 0 + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) From 591e93405f3178bed777db2e13f60a90b7202d37 Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Thu, 22 Jan 2026 16:02:08 -0400 Subject: [PATCH 2/8] Update version --- manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/manifest.json b/manifest.json index f77655d..fac5861 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": "0.3", "name": "Unity MCP", - "version": "9.0.7", + "version": "9.1.0", "description": "AI-powered Unity Editor automation via MCP - manage GameObjects, scripts, materials, scenes, prefabs, VFX, and run tests", "author": { "name": "Coplay", From 067eddd1da0a84252da072a5fb6146c149989e44 Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Thu, 22 Jan 2026 16:08:21 -0400 Subject: [PATCH 3/8] refactor: consolidate version update logic into Python script Replace inline sed/jq commands in release workflow with tools/update_versions.py script that: - Updates MCPForUnity/package.json, manifest.json, Server/pyproject.toml - Updates version references in Server/README.md, README.md, docs/i18n/README-zh.md - Supports --dry-run and --version flags - Auto-detects version from package.json if not specified - Provides better error handling and progress output --- .github/workflows/release.yml | 19 +-- tools/update_versions.py | 297 ++++++++++++++++++++++++++++++++++ 2 files changed, 300 insertions(+), 16 deletions(-) create mode 100755 tools/update_versions.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 291ce8d..2735622 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -75,21 +75,8 @@ jobs: run: | set -euo pipefail - echo "Updating MCPForUnity/package.json to $NEW_VERSION" - jq ".version = \"${NEW_VERSION}\"" MCPForUnity/package.json > MCPForUnity/package.json.tmp - mv MCPForUnity/package.json.tmp MCPForUnity/package.json - - echo "Updating Server/pyproject.toml to $NEW_VERSION" - sed -i '0,/^version = ".*"/s//version = "'"$NEW_VERSION"'"/' "Server/pyproject.toml" - - echo "Updating Server/README.md version references to v$NEW_VERSION" - sed -i 's|git+https://github.com/CoplayDev/unity-mcp@v[0-9]\+\.[0-9]\+\.[0-9]\+#subdirectory=Server|git+https://github.com/CoplayDev/unity-mcp@v'"$NEW_VERSION"'#subdirectory=Server|g' Server/README.md - - echo "Updating root README.md fixed version examples to v$NEW_VERSION" - sed -i 's|https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v[0-9]\+\.[0-9]\+\.[0-9]\+|https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v'"$NEW_VERSION"'|g' README.md - - echo "Updating docs/i18n/README-zh.md fixed version examples to v$NEW_VERSION" - sed -i 's|https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v[0-9]\+\.[0-9]\+\.[0-9]\+|https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v'"$NEW_VERSION"'|g' docs/i18n/README-zh.md + echo "Updating all version references to $NEW_VERSION" + python3 tools/update_versions.py --version "$NEW_VERSION" - name: Commit and push changes env: @@ -99,7 +86,7 @@ jobs: set -euo pipefail git config user.name "GitHub Actions" git config user.email "actions@github.com" - git add MCPForUnity/package.json "Server/pyproject.toml" Server/README.md README.md docs/i18n/README-zh.md + git add MCPForUnity/package.json manifest.json "Server/pyproject.toml" Server/README.md README.md docs/i18n/README-zh.md if git diff --cached --quiet; then echo "No version changes to commit." else diff --git a/tools/update_versions.py b/tools/update_versions.py new file mode 100755 index 0000000..18675e4 --- /dev/null +++ b/tools/update_versions.py @@ -0,0 +1,297 @@ +#!/usr/bin/env python3 +"""Update version across all project files. + +This script updates the version in all files that need it: +- MCPForUnity/package.json (Unity package version) +- manifest.json (MCP bundle manifest) +- Server/pyproject.toml (Python package version) +- Server/README.md (version references) +- README.md (fixed version examples) +- docs/i18n/README-zh.md (fixed version examples) + +Usage: + python3 tools/update_versions.py [--dry-run] [--version VERSION] + +Options: + --dry-run: Show what would be updated without making changes + --version: Specify version to use (auto-detected from package.json if not provided) + +Examples: + # Update all files to match package.json version + python3 tools/update_versions.py + + # Update all files to a specific version + python3 tools/update_versions.py --version 9.2.0 + + # Dry run to see what would be updated + python3 tools/update_versions.py --dry-run +""" + +import argparse +import json +import re +import sys +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[1] +PACKAGE_JSON = REPO_ROOT / "MCPForUnity" / "package.json" +MANIFEST_JSON = REPO_ROOT / "manifest.json" +PYPROJECT_TOML = REPO_ROOT / "Server" / "pyproject.toml" +SERVER_README = REPO_ROOT / "Server" / "README.md" +ROOT_README = REPO_ROOT / "README.md" +ZH_README = REPO_ROOT / "docs" / "i18n" / "README-zh.md" + + +def load_package_version() -> str: + """Load version from package.json.""" + if not PACKAGE_JSON.exists(): + raise FileNotFoundError(f"Package file not found: {PACKAGE_JSON}") + + package_data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8")) + version = package_data.get("version") + + if not version: + raise ValueError("No version found in package.json") + + return version + + +def update_package_json(new_version: str, dry_run: bool = False) -> bool: + """Update version in MCPForUnity/package.json.""" + if not PACKAGE_JSON.exists(): + print(f"Warning: {PACKAGE_JSON.relative_to(REPO_ROOT)} not found") + return False + + package_data = json.loads(PACKAGE_JSON.read_text(encoding="utf-8")) + current_version = package_data.get("version", "unknown") + + if current_version == new_version: + print(f"✓ {PACKAGE_JSON.relative_to(REPO_ROOT)} already at v{new_version}") + return False + + print( + f"Updating {PACKAGE_JSON.relative_to(REPO_ROOT)}: {current_version} → {new_version}") + + if not dry_run: + package_data["version"] = new_version + PACKAGE_JSON.write_text( + json.dumps(package_data, indent=2, ensure_ascii=False) + "\n", + encoding="utf-8", + ) + + return True + + +def update_manifest_json(new_version: str, dry_run: bool = False) -> bool: + """Update version in manifest.json.""" + if not MANIFEST_JSON.exists(): + print(f"Warning: {MANIFEST_JSON.relative_to(REPO_ROOT)} not found") + return False + + manifest = json.loads(MANIFEST_JSON.read_text(encoding="utf-8")) + current_version = manifest.get("version", "unknown") + + if current_version == new_version: + print(f"✓ {MANIFEST_JSON.relative_to(REPO_ROOT)} already at v{new_version}") + return False + + print( + f"Updating {MANIFEST_JSON.relative_to(REPO_ROOT)}: {current_version} → {new_version}") + + if not dry_run: + manifest["version"] = new_version + MANIFEST_JSON.write_text( + json.dumps(manifest, indent=2, ensure_ascii=False) + "\n", + encoding="utf-8", + ) + + return True + + +def update_pyproject_toml(new_version: str, dry_run: bool = False) -> bool: + """Update version in Server/pyproject.toml.""" + if not PYPROJECT_TOML.exists(): + print(f"Warning: {PYPROJECT_TOML.relative_to(REPO_ROOT)} not found") + return False + + content = PYPROJECT_TOML.read_text(encoding="utf-8") + + # Find current version + version_match = re.search(r'^version = "([^"]+)"', content, re.MULTILINE) + if not version_match: + print( + f"Warning: Could not find version in {PYPROJECT_TOML.relative_to(REPO_ROOT)}") + return False + + current_version = version_match.group(1) + + if current_version == new_version: + print(f"✓ {PYPROJECT_TOML.relative_to(REPO_ROOT)} already at v{new_version}") + return False + + print( + f"Updating {PYPROJECT_TOML.relative_to(REPO_ROOT)}: {current_version} → {new_version}") + + if not dry_run: + # Replace only the first occurrence (the version field) + content = re.sub( + r'^version = ".*"', f'version = "{new_version}"', content, count=1, flags=re.MULTILINE) + PYPROJECT_TOML.write_text(content, encoding="utf-8") + + return True + + +def update_server_readme(new_version: str, dry_run: bool = False) -> bool: + """Update version references in Server/README.md.""" + if not SERVER_README.exists(): + print(f"Warning: {SERVER_README.relative_to(REPO_ROOT)} not found") + return False + + content = SERVER_README.read_text(encoding="utf-8") + + # Pattern to match git+https URLs with version tags + pattern = r'git\+https://github\.com/CoplayDev/unity-mcp@v[0-9]+\.[0-9]+\.[0-9]+#subdirectory=Server' + replacement = f'git+https://github.com/CoplayDev/unity-mcp@v{new_version}#subdirectory=Server' + + if not re.search(pattern, content): + print( + f"✓ {SERVER_README.relative_to(REPO_ROOT)} has no version references to update") + return False + + print( + f"Updating version references in {SERVER_README.relative_to(REPO_ROOT)}") + + if not dry_run: + content = re.sub(pattern, replacement, content) + SERVER_README.write_text(content, encoding="utf-8") + + return True + + +def update_root_readme(new_version: str, dry_run: bool = False) -> bool: + """Update fixed version examples in README.md.""" + if not ROOT_README.exists(): + print(f"Warning: {ROOT_README.relative_to(REPO_ROOT)} not found") + return False + + content = ROOT_README.read_text(encoding="utf-8") + + # Pattern to match git URLs with fixed version tags + pattern = r'https://github\.com/CoplayDev/unity-mcp\.git\?path=/MCPForUnity#v[0-9]+\.[0-9]+\.[0-9]+' + replacement = f'https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v{new_version}' + + if not re.search(pattern, content): + print( + f"✓ {ROOT_README.relative_to(REPO_ROOT)} has no version references to update") + return False + + print( + f"Updating version references in {ROOT_README.relative_to(REPO_ROOT)}") + + if not dry_run: + content = re.sub(pattern, replacement, content) + ROOT_README.write_text(content, encoding="utf-8") + + return True + + +def update_zh_readme(new_version: str, dry_run: bool = False) -> bool: + """Update fixed version examples in docs/i18n/README-zh.md.""" + if not ZH_README.exists(): + print(f"Warning: {ZH_README.relative_to(REPO_ROOT)} not found") + return False + + content = ZH_README.read_text(encoding="utf-8") + + # Pattern to match git URLs with fixed version tags + pattern = r'https://github\.com/CoplayDev/unity-mcp\.git\?path=/MCPForUnity#v[0-9]+\.[0-9]+\.[0-9]+' + replacement = f'https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v{new_version}' + + if not re.search(pattern, content): + print( + f"✓ {ZH_README.relative_to(REPO_ROOT)} has no version references to update") + return False + + print(f"Updating version references in {ZH_README.relative_to(REPO_ROOT)}") + + if not dry_run: + content = re.sub(pattern, replacement, content) + ZH_README.write_text(content, encoding="utf-8") + + return True + + +def main() -> int: + parser = argparse.ArgumentParser( + description="Update version across all project files", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=__doc__, + ) + parser.add_argument( + "--dry-run", + action="store_true", + help="Show what would be updated without making changes", + ) + parser.add_argument( + "--version", + help="Version to set (auto-detected from package.json if not provided)", + ) + parser.add_argument( + "--update-package", + action="store_true", + help="Also update MCPForUnity/package.json with the specified version", + ) + + args = parser.parse_args() + + try: + # Determine version + if args.version: + version = args.version + print(f"Using specified version: {version}") + else: + version = load_package_version() + print(f"Auto-detected version from package.json: {version}") + + # Update all files + updates_made = [] + + # Always update package.json if a version is specified + if args.version: + if update_package_json(version, args.dry_run): + updates_made.append("MCPForUnity/package.json") + + if update_manifest_json(version, args.dry_run): + updates_made.append("manifest.json") + + if update_pyproject_toml(version, args.dry_run): + updates_made.append("Server/pyproject.toml") + + if update_server_readme(version, args.dry_run): + updates_made.append("Server/README.md") + + if update_root_readme(version, args.dry_run): + updates_made.append("README.md") + + if update_zh_readme(version, args.dry_run): + updates_made.append("docs/i18n/README-zh.md") + + # Summary + if args.dry_run: + print("\nDry run complete. No files were modified.") + else: + if updates_made: + print( + f"\nUpdated {len(updates_made)} files: {', '.join(updates_made)}") + else: + print("\nAll files already at the correct version.") + + return 0 + + except Exception as e: + print(f"Error: {e}", file=sys.stderr) + return 1 + + +if __name__ == "__main__": + sys.exit(main()) From e73c9c16514677fa28c893bfddf3b48c0ac8f3a6 Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Thu, 22 Jan 2026 16:09:04 -0400 Subject: [PATCH 4/8] docs: add version update workflow documentation to development guides Add comprehensive documentation for the version update process in both English and Chinese development guides: - Document manifest.json and package.json version synchronization during releases - Explain update_versions.py script usage with examples (default, --version, --dry-run) - List all files updated by the script (package.json, manifest.json, pyproject.toml, READMEs) - Provide guidance on manual tool updates outside release --- docs/development/README-DEV-zh.md | 30 ++++++++++++++++++++++++++++++ docs/development/README-DEV.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/docs/development/README-DEV-zh.md b/docs/development/README-DEV-zh.md index 269e09a..c79ba55 100644 --- a/docs/development/README-DEV-zh.md +++ b/docs/development/README-DEV-zh.md @@ -338,6 +338,36 @@ python3 tools/stress_mcp.py \ 4. **迭代** - 按需重复 1-3 5. **Restore** 完成后用 `restore-dev.bat` 恢复原始文件 +## 重要说明 + +### 更新工具和 Manifest + +在 Unity 包中添加或修改 MCP 工具时: +- 工具定义位于仓库根目录的 manifest.json 文件中 +- 在发布过程中,manifest.json 版本会自动与 MCPForUnity/package.json 保持同步 +- 如果在发布过程之外手动更新工具,请确保相应更新 manifest.json 版本 +- 使用综合版本更新脚本:`python3 tools/update_versions.py` 来同步项目中所有版本引用 + +`update_versions.py` 脚本会更新: +- MCPForUnity/package.json(Unity 包版本) +- manifest.json(MCP bundle manifest) +- Server/pyproject.toml(Python 包版本) +- Server/README.md(版本引用) +- README.md(固定版本示例) +- docs/i18n/README-zh.md(固定版本示例) + +使用示例: +```bash +# 更新所有文件以匹配 package.json 版本 +python3 tools/update_versions.py + +# 更新所有文件到指定版本 +python3 tools/update_versions.py --version 9.2.0 + +# 干运行以查看将要更新的内容 +python3 tools/update_versions.py --dry-run +``` + ## Troubleshooting ### 运行 .bat 时出现 "Path not found" diff --git a/docs/development/README-DEV.md b/docs/development/README-DEV.md index c9b3d45..0772947 100644 --- a/docs/development/README-DEV.md +++ b/docs/development/README-DEV.md @@ -328,6 +328,36 @@ We provide a CI job to run a Natural Language Editing suite against the Unity te 4. **Iterate** - repeat steps 1-3 as needed 5. **Restore** original files when done using `restore-dev.bat` +## Important Notes + +### Updating Tools and Manifest + +When adding or modifying MCP tools in the Unity package: +- Tool definitions are located in the manifest.json file at the repository root +- The manifest.json version is automatically kept in sync with MCPForUnity/package.json during releases +- If you manually update tools outside of the release process, ensure to update the manifest.json version accordingly +- Use the comprehensive version update script: `python3 tools/update_versions.py` to sync all version references across the project + +The `update_versions.py` script updates: +- MCPForUnity/package.json (Unity package version) +- manifest.json (MCP bundle manifest) +- Server/pyproject.toml (Python package version) +- Server/README.md (version references) +- README.md (fixed version examples) +- docs/i18n/README-zh.md (fixed version examples) + +Usage examples: +```bash +# Update all files to match package.json version +python3 tools/update_versions.py + +# Update all files to a specific version +python3 tools/update_versions.py --version 9.2.0 + +# Dry run to see what would be updated +python3 tools/update_versions.py --dry-run +``` + ## Troubleshooting ### "Path not found" errors running the .bat file From f32b62d61676e505e78b4acae9b74ecffad073ca Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Thu, 22 Jan 2026 16:23:42 -0400 Subject: [PATCH 5/8] docs: add LLM prompt and checklist for documentation updates Add automated documentation update workflow to ensure consistency when tools/resources change: - Add UPDATE_DOCS_PROMPT.md with copy-paste LLM prompt that: - Instructs LLM to scan Server/src/services/tools/ and resources/ for decorators - Updates manifest.json tools array, README.md tools/resources sections, README-zh.md - Enforces alphabetical ordering and formatting rules (backticks, bullets) - References check_docs_sync.py for --- .github/pull_request_template.md | 8 ++++ tools/UPDATE_DOCS_PROMPT.md | 66 ++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 tools/UPDATE_DOCS_PROMPT.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 302258d..f36df5f 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -19,6 +19,14 @@ Save your change type +## Documentation Updates + +- [ ] I have added/removed/modified tools or resources +- [ ] If yes, I have updated all documentation files using: + - [ ] The LLM prompt at `tools/UPDATE_DOCS_PROMPT.md` (recommended) + - [ ] Manual updates following the guide at `tools/UPDATE_DOCS.md` + + ## Related Issues diff --git a/tools/UPDATE_DOCS_PROMPT.md b/tools/UPDATE_DOCS_PROMPT.md new file mode 100644 index 0000000..efdbe62 --- /dev/null +++ b/tools/UPDATE_DOCS_PROMPT.md @@ -0,0 +1,66 @@ +# LLM Prompt for Updating Documentation + +Copy and paste this prompt into your LLM when you need to update documentation after adding/removing/modifying MCP tools or resources. + +## Example Usage + +After adding a new tool called "manage_new_feature" and a new resource called "feature_resource", you would: +1. Copy the prompt above +2. Paste it into your LLM +3. The LLM will analyze the codebase and update all documentation files +4. Review the changes and run the check script to verify + +This ensures all documentation stays in sync across the repository. + +--- + +## Prompt + +I've just made changes to MCP tools or resources in this Unity MCP repository. Please update all documentation files to keep them in sync. + +Here's what you need to do: + +1. **Check the current tools and resources** by examining: + - `Server/src/services/tools/` - Python tool implementations (look for @mcp_for_unity_tool decorators) + - `Server/src/services/resources/` - Python resource implementations (look for @mcp_for_unity_resource decorators) + +2. **Update these files**: + + a) **manifest.json** (root directory) + - Update the "tools" array (lines 27-57) + - Each tool needs: {"name": "tool_name", "description": "Brief description"} + - Keep tools in alphabetical order + - Note: Resources are not listed in manifest.json, only tools + + b) **README.md** (root directory) + - Update "Available Tools" section (around line 78-79) + - Format: `tool1` • `tool2` • `tool3` + - Keep the same order as manifest.json + + c) **README.md** - Resources section + - Update "Available Resources" section (around line 81-82) + - Format: `resource1` • `resource2` • `resource3` + - Resources come from Server/src/services/resources/ files + - Keep resources in alphabetical order + + d) **docs/i18n/README-zh.md** + - Find and update the "可用工具" (Available Tools) section + - Find and update the "可用资源" (Available Resources) section + - Keep tool/resource names in English, but you can translate descriptions if helpful + +3. **Important formatting rules**: + - Use backticks around tool/resource names + - Separate items with • (bullet point) + - Keep lists on single lines when possible + - Maintain alphabetical ordering + - Tools and resources are listed separately in documentation + +4. **After updating**, run this check to verify: + ```bash + python3 tools/check_docs_sync.py + ``` + It should show "All documentation is synchronized!" + +Please show me the exact changes you're making to each file, and explain any discrepancies you find. + +--- From f314a2367abe75284a1f7b07d9cd629d2da22059 Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Thu, 22 Jan 2026 21:36:54 -0400 Subject: [PATCH 6/8] Update CI flow so that we bump from beta to main, and sync back (#614) * feat: add release workflow concurrency control and main-to-beta sync Add safeguards to prevent concurrent releases and ensure beta stays in sync: - Add concurrency group to prevent overlapping release runs - Enforce workflow runs only on main branch (fail if run elsewhere) - Explicitly checkout and push to main (not dynamic branch) - Fail if release tag already exists (was silently skipping) - Add sync_beta job that merges main back into beta after release - Add docs/guides/RELEASING.md with two * feat: use PRs for version bumps and beta sync instead of direct pushes For release notes to work we need for PRs from beta to main to not be squashed. We also want to enforce all changes to be via PRs, for humans. But that also limits GH Actions. An alternative is creating a GH App with bypass permissions but that felt like overkill Replace direct pushes to main/beta with PR-based workflow for better branch protection compatibility: - Create temporary release/vX.Y.Z branch for version bump - Open PR from release branch into main, enable auto-merge - Poll for PR merge completion (up to 2 minutes) before creating tag - Fetch merged main and create tag on merged commit - Clean up release branch after tag creation - Create PR to merge main into beta (skip if already --- .github/workflows/release.yml | 150 ++++++++++++++++++++++++++++++++-- docs/guides/RELEASING.md | 111 +++++++++++++++++++++++++ 2 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 docs/guides/RELEASING.md diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2735622..fd5fd74 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,5 +1,9 @@ name: Release +concurrency: + group: release-main + cancel-in-progress: false + on: workflow_dispatch: inputs: @@ -19,13 +23,25 @@ jobs: runs-on: ubuntu-latest permissions: contents: write + pull-requests: write outputs: new_version: ${{ steps.compute.outputs.new_version }} tag: ${{ steps.tag.outputs.tag }} + bump_branch: ${{ steps.bump_branch.outputs.name }} steps: + - name: Ensure workflow is running on main + shell: bash + run: | + set -euo pipefail + if [[ "${GITHUB_REF_NAME}" != "main" ]]; then + echo "This workflow must be run on the main branch. Current ref: ${GITHUB_REF_NAME}" >&2 + exit 1 + fi + - name: Checkout repository uses: actions/checkout@v6 with: + ref: main fetch-depth: 0 - name: Compute new version @@ -78,14 +94,19 @@ jobs: echo "Updating all version references to $NEW_VERSION" python3 tools/update_versions.py --version "$NEW_VERSION" - - name: Commit and push changes + - name: Commit version bump to a temporary branch + id: bump_branch env: NEW_VERSION: ${{ steps.compute.outputs.new_version }} shell: bash run: | set -euo pipefail + BRANCH="release/v${NEW_VERSION}" + echo "name=$BRANCH" >> "$GITHUB_OUTPUT" + git config user.name "GitHub Actions" git config user.email "actions@github.com" + git checkout -b "$BRANCH" git add MCPForUnity/package.json manifest.json "Server/pyproject.toml" Server/README.md README.md docs/i18n/README-zh.md if git diff --cached --quiet; then echo "No version changes to commit." @@ -93,26 +114,79 @@ jobs: git commit -m "chore: bump version to ${NEW_VERSION}" fi - BRANCH="${GITHUB_HEAD_REF:-${GITHUB_REF_NAME}}" - echo "Pushing to branch: $BRANCH" + echo "Pushing bump branch $BRANCH" git push origin "$BRANCH" - - name: Create and push tag + - name: Create PR for version bump into main + id: bump_pr + env: + GH_TOKEN: ${{ github.token }} + NEW_VERSION: ${{ steps.compute.outputs.new_version }} + BRANCH: ${{ steps.bump_branch.outputs.name }} + shell: bash + run: | + set -euo pipefail + PR_URL=$(gh pr create \ + --base main \ + --head "$BRANCH" \ + --title "chore: bump version to ${NEW_VERSION}" \ + --body "Automated version bump to ${NEW_VERSION}.") + echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" + PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + + - name: Enable auto-merge and merge PR + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ steps.bump_pr.outputs.pr_number }} + shell: bash + run: | + set -euo pipefail + # Enable auto-merge (requires repo setting "Allow auto-merge") + gh pr merge "$PR_NUMBER" --merge --auto || true + # Wait for PR to be merged (poll up to 2 minutes) + for i in {1..24}; do + STATE=$(gh pr view "$PR_NUMBER" --json state -q '.state') + if [[ "$STATE" == "MERGED" ]]; then + echo "PR merged successfully." + exit 0 + fi + echo "Waiting for PR to merge... (state: $STATE)" + sleep 5 + done + echo "PR did not merge in time. Attempting direct merge..." + gh pr merge "$PR_NUMBER" --merge + + - name: Fetch merged main and create tag env: TAG: ${{ steps.tag.outputs.tag }} shell: bash run: | set -euo pipefail + git fetch origin main + git checkout main + git pull origin main + echo "Preparing to create tag $TAG" if git ls-remote --tags origin | grep -q "refs/tags/$TAG$"; then - echo "Tag $TAG already exists on remote. Skipping tag creation." - exit 0 + echo "Tag $TAG already exists on remote. Refusing to release." >&2 + exit 1 fi git tag -a "$TAG" -m "Version ${TAG#v}" git push origin "$TAG" + - name: Clean up release branch + if: always() + env: + GH_TOKEN: ${{ github.token }} + BRANCH: ${{ steps.bump_branch.outputs.name }} + shell: bash + run: | + set -euo pipefail + git push origin --delete "$BRANCH" || true + - name: Create GitHub release uses: softprops/action-gh-release@v2 with: @@ -120,6 +194,70 @@ jobs: name: ${{ steps.tag.outputs.tag }} generate_release_notes: true + sync_beta: + name: Merge main back into beta via PR + needs: + - bump + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout main + uses: actions/checkout@v6 + with: + ref: main + fetch-depth: 0 + + - name: Create PR to merge main into beta + id: sync_pr + env: + GH_TOKEN: ${{ github.token }} + NEW_VERSION: ${{ needs.bump.outputs.new_version }} + shell: bash + run: | + set -euo pipefail + # Check if beta is behind main + git fetch origin beta + if git merge-base --is-ancestor origin/main origin/beta; then + echo "beta is already up to date with main. Skipping PR." + echo "skipped=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + + PR_URL=$(gh pr create \ + --base beta \ + --head main \ + --title "chore: sync main (v${NEW_VERSION}) into beta" \ + --body "Automated sync of version bump from main into beta.") + echo "pr_url=$PR_URL" >> "$GITHUB_OUTPUT" + PR_NUMBER=$(echo "$PR_URL" | grep -oE '[0-9]+$') + echo "pr_number=$PR_NUMBER" >> "$GITHUB_OUTPUT" + echo "skipped=false" >> "$GITHUB_OUTPUT" + + - name: Enable auto-merge and merge sync PR + if: steps.sync_pr.outputs.skipped != 'true' + env: + GH_TOKEN: ${{ github.token }} + PR_NUMBER: ${{ steps.sync_pr.outputs.pr_number }} + shell: bash + run: | + set -euo pipefail + # Enable auto-merge (requires repo setting "Allow auto-merge") + gh pr merge "$PR_NUMBER" --merge --auto || true + # Wait for PR to be merged (poll up to 2 minutes) + for i in {1..24}; do + STATE=$(gh pr view "$PR_NUMBER" --json state -q '.state') + if [[ "$STATE" == "MERGED" ]]; then + echo "Sync PR merged successfully." + exit 0 + fi + echo "Waiting for sync PR to merge... (state: $STATE)" + sleep 5 + done + echo "Sync PR did not merge in time. Attempting direct merge..." + gh pr merge "$PR_NUMBER" --merge + publish_docker: name: Publish Docker image needs: diff --git a/docs/guides/RELEASING.md b/docs/guides/RELEASING.md new file mode 100644 index 0000000..8911992 --- /dev/null +++ b/docs/guides/RELEASING.md @@ -0,0 +1,111 @@ +# Releasing (Maintainers) + +This repo uses a two-branch flow to keep `main` stable for users: + +- `beta`: integration branch where feature PRs land +- `main`: stable branch that should match the latest release tag + +## Release checklist + +### 1) Promote `beta` to `main` via PR + +- Create a PR with: + - base: `main` + - compare: `beta` +- Ensure required CI checks are green. +- Merge the PR. + +Release note quality depends on how you merge: + +- Squash-merging feature PRs into `beta` is OK. +- Avoid squash-merging the `beta -> main` promotion PR. Prefer a merge commit (or rebase merge) so GitHub can produce better auto-generated release notes. + +### 2) Run the Release workflow (manual) + +- Go to **GitHub → Actions → Release** +- Click **Run workflow** +- Select: + - `patch`, `minor`, or `major` +- Run it on branch: `main` + +What the workflow does: + +1. Creates a temporary `release/vX.Y.Z` branch with the version bump commit +2. Opens a PR from that branch into `main` +3. Auto-merges the PR (or waits for required checks, then merges) +4. Creates an annotated tag `vX.Y.Z` on the merged commit +5. Creates a GitHub Release for the tag +6. Publishes artifacts (Docker / PyPI / MCPB) +7. Opens a PR to merge `main` back into `beta` (so `beta` gets the bump) +8. Auto-merges the sync PR +9. Cleans up the temporary release branch + +### 3) Verify release outputs + +- Confirm a new tag exists: `vX.Y.Z` +- Confirm a GitHub Release exists for the tag +- Confirm artifacts: + - Docker image published with version `X.Y.Z` + - PyPI package published (if configured) + - `unity-mcp-X.Y.Z.mcpb` attached to the GitHub Release + +## Required repo settings + +### Branch protection (Rulesets) + +The release workflow uses PRs instead of direct pushes, so it works with strict branch protection. No bypass actors are required. + +Recommended ruleset for `main`: + +- Require PR before merging +- Allowed merge methods: `merge`, `rebase` (no squash for promotion PRs) +- Required approvals: `0` (so automated PRs can merge without human review) +- Optionally require status checks + +Recommended ruleset for `beta`: + +- Require PR before merging +- Allowed merge methods: `squash` (for feature PRs) +- Required approvals: `0` (so the sync PR can auto-merge) + +### Enable auto-merge (required) + +The workflow uses `gh pr merge --auto` to automatically merge PRs once checks pass. + +To enable: + +1. Go to **Settings → General** +2. Scroll to **Pull Requests** +3. Check **Allow auto-merge** + +Without this setting, the workflow will fall back to direct merge attempts, which may fail if branch protection requires checks. + +## Failure modes and recovery + +### Tag already exists + +The workflow fails if the computed tag already exists. Pick a different bump type or investigate why a tag already exists for that version. + +### Bump PR fails to merge + +If the version bump PR cannot be merged (e.g., required checks fail): + +- The workflow will fail before creating a tag. +- Fix the issue, then either: + - Manually merge the PR and create the tag/release, or + - Close the PR, delete the `release/vX.Y.Z` branch, and re-run the workflow. + +### Sync PR (`main -> beta`) fails + +If the sync PR has merge conflicts: + +- The workflow will fail after the release is published (artifacts are already out). +- Manually resolve conflicts in the sync PR and merge it. + +### Leftover release branch + +If the workflow fails mid-run, a `release/vX.Y.Z` branch may remain. Delete it manually before re-running: + +```bash +git push origin --delete release/vX.Y.Z +``` From 63b666b421655a67eb55535c76600bacde7b4673 Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Thu, 22 Jan 2026 21:45:03 -0400 Subject: [PATCH 7/8] Minor feedback --- .github/pull_request_template.md | 2 +- tools/UPDATE_DOCS_PROMPT.md | 2 +- tools/update_versions.py | 5 ----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f36df5f..cd13fde 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -20,7 +20,7 @@ Save your change type ## Documentation Updates - + - [ ] I have added/removed/modified tools or resources - [ ] If yes, I have updated all documentation files using: - [ ] The LLM prompt at `tools/UPDATE_DOCS_PROMPT.md` (recommended) diff --git a/tools/UPDATE_DOCS_PROMPT.md b/tools/UPDATE_DOCS_PROMPT.md index efdbe62..0ccdc60 100644 --- a/tools/UPDATE_DOCS_PROMPT.md +++ b/tools/UPDATE_DOCS_PROMPT.md @@ -5,7 +5,7 @@ Copy and paste this prompt into your LLM when you need to update documentation a ## Example Usage After adding a new tool called "manage_new_feature" and a new resource called "feature_resource", you would: -1. Copy the prompt above +1. Copy the prompt in the section below 2. Paste it into your LLM 3. The LLM will analyze the codebase and update all documentation files 4. Review the changes and run the check script to verify diff --git a/tools/update_versions.py b/tools/update_versions.py index 18675e4..5cc1102 100755 --- a/tools/update_versions.py +++ b/tools/update_versions.py @@ -236,11 +236,6 @@ def main() -> int: "--version", help="Version to set (auto-detected from package.json if not provided)", ) - parser.add_argument( - "--update-package", - action="store_true", - help="Also update MCPForUnity/package.json with the specified version", - ) args = parser.parse_args() From d3e42a1c321562a3788dd34b648b3fb3bedc67ec Mon Sep 17 00:00:00 2001 From: Marcus Sanatan Date: Fri, 23 Jan 2026 01:14:54 -0400 Subject: [PATCH 8/8] docs: change README installation examples from fixed version to beta branch Remove version-specific installation examples from README.md and README-zh.md, replacing with beta branch references. Update release workflow and update_versions.py to stop modifying README files during version bumps since they no longer contain version-specific URLs. --- .github/workflows/release.yml | 2 +- README.md | 4 ++-- docs/i18n/README-zh.md | 4 ++-- tools/update_versions.py | 5 ----- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd5fd74..198652e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -107,7 +107,7 @@ jobs: git config user.name "GitHub Actions" git config user.email "actions@github.com" git checkout -b "$BRANCH" - git add MCPForUnity/package.json manifest.json "Server/pyproject.toml" Server/README.md README.md docs/i18n/README-zh.md + git add MCPForUnity/package.json manifest.json "Server/pyproject.toml" Server/README.md if git diff --cached --quiet; then echo "No version changes to commit." else diff --git a/README.md b/README.md index b9d55b8..6ed1be3 100644 --- a/README.md +++ b/README.md @@ -36,9 +36,9 @@ In Unity: `Window > Package Manager > + > Add package from git URL...` > https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity > ``` -**Need a stable/fixed version?** Use a tagged URL (requires uninstall to update): +**Want the latest beta?** Use the beta branch: ```text -https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v9.1.0 +https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#beta ```
diff --git a/docs/i18n/README-zh.md b/docs/i18n/README-zh.md index 8bad03d..c92d673 100644 --- a/docs/i18n/README-zh.md +++ b/docs/i18n/README-zh.md @@ -36,9 +36,9 @@ > https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity > ``` -**需要一个稳定/固定版本?** 使用带 tag 的 URL(更新时需要卸载才能更新): +**想要最新的 beta 版本?** 使用 beta 分支: ```text -https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#v9.1.0 +https://github.com/CoplayDev/unity-mcp.git?path=/MCPForUnity#beta ```
diff --git a/tools/update_versions.py b/tools/update_versions.py index 5cc1102..979be4e 100755 --- a/tools/update_versions.py +++ b/tools/update_versions.py @@ -265,11 +265,6 @@ def main() -> int: if update_server_readme(version, args.dry_run): updates_made.append("Server/README.md") - if update_root_readme(version, args.dry_run): - updates_made.append("README.md") - - if update_zh_readme(version, args.dry_run): - updates_made.append("docs/i18n/README-zh.md") # Summary if args.dry_run: