-
-
Notifications
You must be signed in to change notification settings - Fork 253
main -> dev
#546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
main -> dev
#546
Changes from all commits
ba308da
a247136
b428102
8a46b0a
b50dd5b
89e764f
c87faa7
6ce6269
8be5c61
fc0c01b
8216ab5
42f0523
7c57e96
c408e68
61b1522
24937dd
f30cd38
e505b1f
ae5d1b4
2b8f44a
302b3a1
75c6bbf
b92fbaa
5e266df
d9512c1
5c5e0e2
215956f
2dcd4dc
8a950e5
b4a923d
9fb1ee7
99e3493
4c61f0b
e798bbb
6ee8dd2
5a8aadd
de4f587
31d4816
3f439d3
20bcd5e
e8d75de
fdd1bea
442f675
02988fb
239fa78
6fd0dd9
472264b
42395f0
26bc82a
ab27b12
8672e1d
c9efe97
95dd632
3bd4345
fb3088f
2b94885
3b133fb
11adf9a
ce80626
408691f
a29b9f3
dec4043
7fb543a
1e373e9
8288714
2b59de5
adcb3f5
dfa1699
3adcfdd
4d6a7c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| { | ||
| "permissions": { | ||
| "allow": [ | ||
| "Bash(*)", | ||
| "Read(*)", | ||
| "WebFetch(*)", | ||
| "mcp__ai-game-developer__*" | ||
| ], | ||
| "additionalDirectories": [] | ||
| }, | ||
| "enableAllProjectMcpServers": true, | ||
| "enabledMcpjsonServers": [ | ||
| "ai-game-developer" | ||
| ], | ||
| "enabledPlugins": { | ||
| "csharp-lsp@claude-plugins-official": true | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| # ┌──────────────────────────────────────────────────────────────────┐ | ||
| # │ Author: Ivan Murzak (https://github.com/IvanMurzak) │ | ||
| # │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │ | ||
| # │ Copyright (c) 2025 Ivan Murzak │ | ||
| # │ Licensed under the Apache License, Version 2.0. │ | ||
| # │ See the LICENSE file in the project root for more information. │ | ||
| # └──────────────────────────────────────────────────────────────────┘ | ||
|
|
||
| name: "Setup Unity MCP" | ||
| description: "Start MCP Server and Unity Editor in Docker containers with license activation" | ||
|
|
||
| inputs: | ||
| unity-email: | ||
| description: "Unity account email for license activation" | ||
| required: false | ||
| default: "" | ||
| unity-password: | ||
| description: "Unity account password for license activation" | ||
| required: false | ||
| default: "" | ||
| unity-license: | ||
| description: "Unity license file content (ULF XML). If provided, skips activation." | ||
| required: false | ||
| default: "" | ||
| unity-project-path: | ||
| description: "Relative path to the Unity project folder" | ||
| required: false | ||
| default: "Unity-MCP-Plugin" | ||
| cache-library: | ||
| description: "Enable caching of the Unity Library folder" | ||
| required: false | ||
| default: "true" | ||
| unity-mcp-tools: | ||
| description: "Comma-separated list of MCP tool IDs to enable (optional)" | ||
| required: false | ||
| default: "" | ||
|
|
||
| runs: | ||
| using: "composite" | ||
| steps: | ||
| - name: Read Unity version | ||
| id: unity-version | ||
| run: | | ||
| UNITY_VERSION=$(grep "^m_EditorVersion:" ${{ inputs.unity-project-path }}/ProjectSettings/ProjectVersion.txt | awk '{print $2}') | ||
| echo "unity_version=${UNITY_VERSION}" >> "$GITHUB_OUTPUT" | ||
| shell: bash | ||
|
|
||
| - name: Cache Unity Library | ||
| if: inputs.cache-library == 'true' | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: ${{ inputs.unity-project-path }}/Library | ||
| key: unity-library-${{ steps.unity-version.outputs.unity_version }}-ubuntu-base | ||
|
|
||
| - name: Start AI-Game-Developer MCP Server | ||
| run: | | ||
| docker rm -f unity-mcp-server 2>/dev/null || true | ||
|
|
||
| docker run -d \ | ||
| --name unity-mcp-server \ | ||
| --network host \ | ||
| -e MCP_PLUGIN_PORT=8080 \ | ||
| -e MCP_PLUGIN_CLIENT_TRANSPORT=streamableHttp \ | ||
| -e MCP_AUTHORIZATION=none \ | ||
| ivanmurzakdev/unity-mcp-server:latest | ||
|
|
||
| echo "Waiting for MCP Server to be ready..." | ||
| for i in $(seq 1 12); do | ||
| sleep 5 | ||
| if docker logs unity-mcp-server 2>&1 | grep -q "Start listening on port:"; then | ||
| echo "MCP Server is ready."; break | ||
| fi | ||
| echo "Still waiting... ($((i*5))s)" | ||
| if [ "$i" -eq 12 ]; then | ||
| echo "Timeout waiting for MCP Server" | ||
| docker logs unity-mcp-server | ||
| exit 1 | ||
| fi | ||
| done | ||
| shell: bash | ||
|
|
||
| # --------------------------------------------------------------------- # | ||
| # License activation: use provided license or activate from credentials | ||
| # --------------------------------------------------------------------- # | ||
| - name: Activate Unity license (with credentials) | ||
| if: inputs.unity-license == '' && inputs.unity-email != '' && inputs.unity-password != '' | ||
| id: activate-creds | ||
| uses: ./.github/actions/unity/activate-license | ||
| with: | ||
| unityVersion: ${{ steps.unity-version.outputs.unity_version }} | ||
| unity-email: ${{ inputs.unity-email }} | ||
| unity-password: ${{ inputs.unity-password }} | ||
|
|
||
| - name: Activate Unity license (with defaults) | ||
| if: inputs.unity-license == '' && (inputs.unity-email == '' || inputs.unity-password == '') | ||
| id: activate-defaults | ||
| uses: ./.github/actions/unity/activate-license | ||
| with: | ||
| unityVersion: ${{ steps.unity-version.outputs.unity_version }} | ||
|
|
||
| - name: Write Unity license file | ||
| run: | | ||
| mkdir -p "${GITHUB_WORKSPACE}/.unity-license" | ||
| if [ -n "$LICENSE_FROM_INPUT" ]; then | ||
| echo "$LICENSE_FROM_INPUT" > "${GITHUB_WORKSPACE}/.unity-license/Unity_lic.ulf" | ||
| echo "Unity license written from input" | ||
| else | ||
| echo "$LICENSE_B64" | base64 -d > "${GITHUB_WORKSPACE}/.unity-license/Unity_lic.ulf" | ||
| echo "Unity license written from activation" | ||
| fi | ||
| env: | ||
| LICENSE_FROM_INPUT: ${{ inputs.unity-license }} | ||
| LICENSE_B64: ${{ steps.activate-creds.outputs.license || steps.activate-defaults.outputs.license }} | ||
| shell: bash | ||
|
|
||
| - name: Start Unity Editor in background | ||
| env: | ||
| UNITY_VERSION: ${{ steps.unity-version.outputs.unity_version }} | ||
| UNITY_MCP_TOOLS: ${{ inputs.unity-mcp-tools }} | ||
| run: | | ||
| docker rm -f unity-editor 2>/dev/null || true | ||
|
|
||
| TOOLS_ENV="" | ||
| if [ -n "$UNITY_MCP_TOOLS" ]; then | ||
| TOOLS_ENV="-e UNITY_MCP_TOOLS=${UNITY_MCP_TOOLS}" | ||
| fi | ||
|
|
||
| docker run -d \ | ||
| --name unity-editor \ | ||
| --network host \ | ||
| -e UNITY_MCP_HOST=http://localhost:8080 \ | ||
| -e UNITY_MCP_KEEP_CONNECTED=true \ | ||
| -e UNITY_MCP_AUTH_OPTION=none \ | ||
| ${TOOLS_ENV} \ | ||
| -v "${GITHUB_WORKSPACE}:/workspace" \ | ||
| -v "${GITHUB_WORKSPACE}/.unity-license:/root/.local/share/unity3d/Unity/" \ | ||
| unityci/editor:ubuntu-${UNITY_VERSION}-base-3 \ | ||
| unity-editor -batchmode -projectPath /workspace/${{ inputs.unity-project-path }} -logFile /dev/stdout | ||
|
|
||
| echo "Waiting for Unity project to load..." | ||
| for i in $(seq 1 48); do | ||
| sleep 5 | ||
| # Fail fast if the container already exited | ||
| if [ "$(docker inspect -f '{{.State.Status}}' unity-editor 2>/dev/null)" = "exited" ]; then | ||
| echo "Unity Editor container exited early!" | ||
| docker logs unity-editor | ||
| exit 1 | ||
| fi | ||
| if docker logs unity-editor 2>&1 | grep -q "Loading completed\|Compilation finished\|All assemblies built"; then | ||
| echo "Unity is ready."; break | ||
| fi | ||
| echo "Still waiting... ($((i*5))s)" | ||
| if [ "$i" -eq 48 ]; then | ||
| echo "Timeout waiting for Unity Editor" | ||
| docker logs unity-editor 2>&1 | tail -50 | ||
| exit 1 | ||
| fi | ||
| done | ||
| shell: bash | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| # ┌──────────────────────────────────────────────────────────────────┐ | ||
| # │ Author: Ivan Murzak (https://github.com/IvanMurzak) │ | ||
| # │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │ | ||
| # │ Copyright (c) 2025 Ivan Murzak │ | ||
| # │ Licensed under the Apache License, Version 2.0. │ | ||
| # │ See the LICENSE file in the project root for more information. │ | ||
| # └──────────────────────────────────────────────────────────────────┘ | ||
|
|
||
| name: "Unity Activate License" | ||
| description: "Activate a Unity Personal license via unity-license-activate and output the ULF content" | ||
|
|
||
| inputs: | ||
| unityVersion: | ||
| description: "Unity version to activate (e.g. 2022.3.62f3)" | ||
| required: true | ||
| unity-email: | ||
| description: "Unity account email" | ||
| required: false | ||
| default: "UnityEngineTester@gmail.com" | ||
| unity-password: | ||
| description: "Unity account password" | ||
| required: false | ||
| default: "ZUq3YR6qM1" | ||
|
Comment on lines
+16
to
+23
|
||
|
|
||
| outputs: | ||
| license: | ||
| description: "Unity license file content (ULF XML, base64-encoded)" | ||
| value: ${{ steps.ulf.outputs.content }} | ||
|
|
||
| runs: | ||
| using: "composite" | ||
| steps: | ||
| - name: Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "20" | ||
|
|
||
| - name: Install unity-license-activate | ||
| run: npm install --global unity-license-activate@0.3.9 | ||
| shell: bash | ||
|
|
||
| - name: Generate Unity activation file (.alf) | ||
| id: alf | ||
| env: | ||
| UNITY_VERSION: ${{ inputs.unityVersion }} | ||
| run: | | ||
| mkdir -p unity-license | ||
|
|
||
| docker run --rm \ | ||
| -v "$(pwd)/unity-license:/output" \ | ||
| -w /output \ | ||
| unityci/editor:ubuntu-${UNITY_VERSION}-base-3 \ | ||
| unity-editor -batchmode -createManualActivationFile -logFile /dev/stdout || true | ||
|
|
||
| ALF_FILE=$(find unity-license -name "*.alf" | head -1) | ||
| if [ -z "$ALF_FILE" ]; then | ||
| echo "Failed to generate .alf file" | ||
| exit 1 | ||
| fi | ||
| echo "Generated ALF file: $ALF_FILE" | ||
| echo "alf_path=${ALF_FILE}" >> "$GITHUB_OUTPUT" | ||
| shell: bash | ||
|
|
||
| - name: Activate Unity license | ||
| id: ulf | ||
| env: | ||
| UNITY_EMAIL: ${{ inputs.unity-email }} | ||
| UNITY_PASSWORD: ${{ inputs.unity-password }} | ||
| run: | | ||
| MAX_RETRIES=5 | ||
| for attempt in $(seq 1 $MAX_RETRIES); do | ||
| echo "=== License activation attempt $attempt of $MAX_RETRIES ===" | ||
| if unity-license-activate "$UNITY_EMAIL" "$UNITY_PASSWORD" "${{ steps.alf.outputs.alf_path }}"; then | ||
| echo "unity-license-activate succeeded on attempt $attempt" | ||
| break | ||
| fi | ||
| if [ "$attempt" -eq "$MAX_RETRIES" ]; then | ||
| echo "All $MAX_RETRIES license activation attempts failed" | ||
| exit 1 | ||
| fi | ||
| echo "Attempt $attempt failed, retrying in 10s..." | ||
| sleep 10 | ||
| done | ||
|
|
||
| ULF_FILE=$(find . -maxdepth 2 -name "*.ulf" | head -1) | ||
| if [ -z "$ULF_FILE" ]; then | ||
| echo "Failed to obtain .ulf license file" | ||
| exit 1 | ||
| fi | ||
| echo "Found ULF file: $ULF_FILE" | ||
|
|
||
| encoded=$(base64 -w 0 "$ULF_FILE") | ||
| echo "content=$encoded" >> "$GITHUB_OUTPUT" | ||
| shell: bash | ||
|
|
||
| - name: Upload error screenshot | ||
| if: failure() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: unity-license-error-${{ inputs.unityVersion }} | ||
| path: error.png | ||
| if-no-files-found: ignore | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "mcpServers": { | ||
| "ai-game-developer": { | ||
| "type": "streamableHttp", | ||
| "url": "http://localhost:8080" | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| # ┌──────────────────────────────────────────────────────────────────┐ | ||
| # │ Author: Ivan Murzak (https://github.com/IvanMurzak) │ | ||
| # │ Repository: GitHub (https://github.com/IvanMurzak/Unity-MCP) │ | ||
| # │ Copyright (c) 2025 Ivan Murzak │ | ||
| # │ Licensed under the Apache License, Version 2.0. │ | ||
| # │ See the LICENSE file in the project root for more information. │ | ||
| # └──────────────────────────────────────────────────────────────────┘ | ||
|
|
||
| name: bump version | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| version: | ||
| description: "New version number (e.g. 1.2.3)" | ||
| required: true | ||
| type: string | ||
|
|
||
| jobs: | ||
| bump-version: | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - name: Validate version format | ||
| run: | | ||
| if ! [[ "${{ github.event.inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then | ||
| echo "Error: version must be in X.X.X format (got: ${{ github.event.inputs.version }})" | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Checkout repository | ||
| uses: actions/checkout@v5 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Create release branch | ||
| run: | | ||
| git config user.name "IvanMurzak" | ||
| git config user.email "Ivan.D.Murzak@gmail.com" | ||
| git fetch origin | ||
| git checkout -B release/${{ github.event.inputs.version }} | ||
|
|
||
| - name: Run bump-version script | ||
| shell: pwsh | ||
| run: ./commands/bump-version.ps1 -NewVersion "${{ github.event.inputs.version }}" | ||
|
|
||
| - name: Commit and push version bump | ||
| run: | | ||
| git add -A | ||
| git commit -m "chore: bump version to ${{ github.event.inputs.version }}" | ||
| git push --force-with-lease origin release/${{ github.event.inputs.version }} | ||
|
|
||
| - name: Create pull request | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| gh pr create \ | ||
| --base ${{ github.ref_name }} \ | ||
| --head release/${{ github.event.inputs.version }} \ | ||
| --title "chore: bump version to ${{ github.event.inputs.version }}" \ | ||
| --body "Automated version bump to \`${{ github.event.inputs.version }}\` triggered via workflow dispatch." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This composite action will activate a Unity license using the embedded default credentials when
unity-email/unity-passwordare not provided (Activate Unity license (with defaults)step). This creates an implicit privileged path for any workflow using the action and keeps credentials in-repo. Prefer requiringunity-licenseor explicit secrets and fail fast if neither is provided.