Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
3f37682
Add a function to reload the domain
msanatan Nov 4, 2025
9b08dcb
feat: restructure server instructions into workflow-focused format
msanatan Nov 4, 2025
c3186cd
docs: reorder tool list alphabetically in README + add reload_domain …
msanatan Nov 4, 2025
932703d
feat: add Unity editor state and project info resources
msanatan Nov 4, 2025
2ea5cfa
feat: clarify script management workflow in system prompt
msanatan Nov 4, 2025
fb9f7e4
refactor: remove reload_domain tool and update script management work…
msanatan Nov 4, 2025
4d88c4e
Change name of menu items resource as the LLM seems it
msanatan Nov 5, 2025
bec63f4
refactor: reorganize tests into src/tests/integration directory
msanatan Nov 5, 2025
13274c9
feat: expand Unity test workflow triggers
msanatan Nov 5, 2025
5e20bcb
chore: add GitHub Actions workflow for Python tests
msanatan Nov 5, 2025
2a1e6ac
refactor: update import path for fastmcp Context
msanatan Nov 5, 2025
fd031b4
docs: update development setup instructions to use uv
msanatan Nov 5, 2025
c7208ea
Formatting [skip ci]
msanatan Nov 5, 2025
2d02c54
refactor: optimize CI workflow with path filters and dependency insta…
msanatan Nov 5, 2025
0c60d1a
Update .github/workflows/python-tests.yml
msanatan Nov 5, 2025
6cb77d6
fix: standardize test mode values to match Unity's naming convention
msanatan Nov 5, 2025
8681361
refactor: convert test imports to relative imports
msanatan Nov 5, 2025
35637d3
refactor: use Field with default_factory for mutable default in TagsR…
msanatan Nov 5, 2025
d3fa3d9
refactor: remove duplicate PrefabStageUtility call
msanatan Nov 5, 2025
1b40ce0
Update this as well [skip ci]
msanatan Nov 5, 2025
bfd806e
Merge branch 'main' into marcus/editor-resources
msanatan Nov 5, 2025
5bf3712
Update MCPForUnity/UnityMcpServer~/src/tests/integration/test_script_…
msanatan Nov 5, 2025
49d1fa9
chore: remove pull_request triggers from test workflows [skip ci]
msanatan Nov 5, 2025
730092d
refactor: update resource function return types to include MCPRespons…
msanatan Nov 5, 2025
d76e2b1
refactor: remove manual domain reload tool
msanatan Nov 5, 2025
399d279
refactor: add context support to resource handlers
msanatan Nov 5, 2025
d78ea82
fix: correct grammar in menu items documentation
msanatan Nov 5, 2025
bbe1fb6
docs: update README with expanded tools and resources documentation
msanatan Nov 5, 2025
a734fe6
refactor: convert unity_instances function to async [skip ci]
msanatan Nov 5, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Python Tests

on:
push:
branches: ["**"]
paths:
- MCPForUnity/UnityMcpServer~/src/**
- .github/workflows/python-tests.yml
workflow_dispatch: {}

jobs:
test:
name: Run Python Tests
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
version: "latest"

- name: Set up Python
run: uv python install 3.10

- name: Install dependencies
run: |
cd MCPForUnity/UnityMcpServer~/src
uv sync
uv pip install -e ".[dev]"

- name: Run tests
run: |
cd MCPForUnity/UnityMcpServer~/src
uv run pytest tests/ -v --tb=short

- name: Upload test results
uses: actions/upload-artifact@v4
if: always()
with:
name: pytest-results
path: |
MCPForUnity/UnityMcpServer~/src/.pytest_cache/
MCPForUnity/UnityMcpServer~/src/tests/
2 changes: 1 addition & 1 deletion .github/workflows/unity-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Unity Tests
on:
workflow_dispatch: {}
push:
branches: [main]
branches: ["**"]
paths:
- TestProjects/UnityMCPTests/**
- MCPForUnity/Editor/**
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

64 changes: 64 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/ActiveTool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System;
using MCPForUnity.Editor.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor;

namespace MCPForUnity.Editor.Resources.Editor
{
/// <summary>
/// Provides information about the currently active editor tool.
/// </summary>
[McpForUnityResource("get_active_tool")]
public static class ActiveTool
{
public static object HandleCommand(JObject @params)
{
try
{
Tool currentTool = UnityEditor.Tools.current;
string toolName = currentTool.ToString();
bool customToolActive = UnityEditor.Tools.current == Tool.Custom;
string activeToolName = customToolActive ? EditorTools.GetActiveToolName() : toolName;

var toolInfo = new
{
activeTool = activeToolName,
isCustom = customToolActive,
pivotMode = UnityEditor.Tools.pivotMode.ToString(),
pivotRotation = UnityEditor.Tools.pivotRotation.ToString(),
handleRotation = new
{
x = UnityEditor.Tools.handleRotation.eulerAngles.x,
y = UnityEditor.Tools.handleRotation.eulerAngles.y,
z = UnityEditor.Tools.handleRotation.eulerAngles.z
},
handlePosition = new
{
x = UnityEditor.Tools.handlePosition.x,
y = UnityEditor.Tools.handlePosition.y,
z = UnityEditor.Tools.handlePosition.z
}
};

return Response.Success("Retrieved active tool information.", toolInfo);
}
catch (Exception e)
{
return Response.Error($"Error getting active tool: {e.Message}");
}
}
}

// Helper class for custom tool names
internal static class EditorTools
{
public static string GetActiveToolName()
{
if (UnityEditor.Tools.current == Tool.Custom)
{
return "Unknown Custom Tool";
}
return UnityEditor.Tools.current.ToString();
}
}
}
11 changes: 11 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/ActiveTool.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/EditorState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using MCPForUnity.Editor.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEditor.SceneManagement;

namespace MCPForUnity.Editor.Resources.Editor
{
/// <summary>
/// Provides dynamic editor state information that changes frequently.
/// </summary>
[McpForUnityResource("get_editor_state")]
public static class EditorState
{
public static object HandleCommand(JObject @params)
{
try
{
var activeScene = EditorSceneManager.GetActiveScene();
var state = new
{
isPlaying = EditorApplication.isPlaying,
isPaused = EditorApplication.isPaused,
isCompiling = EditorApplication.isCompiling,
isUpdating = EditorApplication.isUpdating,
timeSinceStartup = EditorApplication.timeSinceStartup,
activeSceneName = activeScene.name ?? "",
selectionCount = UnityEditor.Selection.count,
activeObjectName = UnityEditor.Selection.activeObject?.name
};

return Response.Success("Retrieved editor state.", state);
}
catch (Exception e)
{
return Response.Error($"Error getting editor state: {e.Message}");
}
}
}
}
11 changes: 11 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/EditorState.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/PrefabStage.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using System;
using MCPForUnity.Editor.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor.SceneManagement;

namespace MCPForUnity.Editor.Resources.Editor
{
/// <summary>
/// Provides information about the current prefab editing context.
/// </summary>
[McpForUnityResource("get_prefab_stage")]
public static class PrefabStage
{
public static object HandleCommand(JObject @params)
{
try
{
var stage = PrefabStageUtility.GetCurrentPrefabStage();

if (stage == null)
{
return Response.Success("No prefab stage is currently open.", new { isOpen = false });
}

var stageInfo = new
{
isOpen = true,
assetPath = stage.assetPath,
prefabRootName = stage.prefabContentsRoot?.name,
mode = stage.mode.ToString(),
isDirty = stage.scene.isDirty
};

return Response.Success("Prefab stage info retrieved.", stageInfo);
}
catch (Exception e)
{
return Response.Error($"Error getting prefab stage info: {e.Message}");
}
}
}
}
11 changes: 11 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/PrefabStage.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 52 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/Selection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Linq;
using MCPForUnity.Editor.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor;

namespace MCPForUnity.Editor.Resources.Editor
{
/// <summary>
/// Provides detailed information about the current editor selection.
/// </summary>
[McpForUnityResource("get_selection")]
public static class Selection
{
public static object HandleCommand(JObject @params)
{
try
{
var selectionInfo = new
{
activeObject = UnityEditor.Selection.activeObject?.name,
activeGameObject = UnityEditor.Selection.activeGameObject?.name,
activeTransform = UnityEditor.Selection.activeTransform?.name,
activeInstanceID = UnityEditor.Selection.activeInstanceID,
count = UnityEditor.Selection.count,
objects = UnityEditor.Selection.objects
.Select(obj => new
{
name = obj?.name,
type = obj?.GetType().FullName,
instanceID = obj?.GetInstanceID()
})
.ToList(),
gameObjects = UnityEditor.Selection.gameObjects
.Select(go => new
{
name = go?.name,
instanceID = go?.GetInstanceID()
})
.ToList(),
assetGUIDs = UnityEditor.Selection.assetGUIDs
};

return Response.Success("Retrieved current selection details.", selectionInfo);
}
catch (Exception e)
{
return Response.Error($"Error getting selection: {e.Message}");
}
}
}
}
11 changes: 11 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/Selection.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

59 changes: 59 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using MCPForUnity.Editor.Helpers;
using Newtonsoft.Json.Linq;
using UnityEditor;
using UnityEngine;

namespace MCPForUnity.Editor.Resources.Editor
{
/// <summary>
/// Provides list of all open editor windows.
/// </summary>
[McpForUnityResource("get_windows")]
public static class Windows
{
public static object HandleCommand(JObject @params)
{
try
{
EditorWindow[] allWindows = UnityEngine.Resources.FindObjectsOfTypeAll<EditorWindow>();
var openWindows = new List<object>();

foreach (EditorWindow window in allWindows)
{
if (window == null)
continue;

try
{
openWindows.Add(new
{
title = window.titleContent.text,
typeName = window.GetType().FullName,
isFocused = EditorWindow.focusedWindow == window,
position = new
{
x = window.position.x,
y = window.position.y,
width = window.position.width,
height = window.position.height
},
instanceID = window.GetInstanceID()
});
}
catch (Exception ex)
{
Debug.LogWarning($"Could not get info for window {window.GetType().Name}: {ex.Message}");
}
}

return Response.Success("Retrieved list of open editor windows.", openWindows);
}
catch (Exception e)
{
return Response.Error($"Error getting editor windows: {e.Message}");
}
}
}
}
11 changes: 11 additions & 0 deletions MCPForUnity/Editor/Resources/Editor/Windows.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions MCPForUnity/Editor/Resources/Project.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading