diff --git a/Editor/Tools/AddPackageTool.cs b/Editor/Tools/AddPackageTool.cs
index e48d576..90d92c0 100644
--- a/Editor/Tools/AddPackageTool.cs
+++ b/Editor/Tools/AddPackageTool.cs
@@ -1,13 +1,10 @@
using System;
-using System.Linq;
using System.Collections.Generic;
-using UnityEngine;
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEditor.PackageManager.Requests;
using Newtonsoft.Json.Linq;
using System.Threading.Tasks;
-using McpUnity.Tools;
using McpUnity.Unity;
using McpUnity.Utils;
diff --git a/Editor/Tools/LoadSceneTool.cs b/Editor/Tools/LoadSceneTool.cs
index 500be43..df9676d 100644
--- a/Editor/Tools/LoadSceneTool.cs
+++ b/Editor/Tools/LoadSceneTool.cs
@@ -1,5 +1,4 @@
using System;
-using UnityEngine;
using UnityEditor;
using Newtonsoft.Json.Linq;
using McpUnity.Unity;
diff --git a/Editor/Tools/RecompileScriptsTool.cs b/Editor/Tools/RecompileScriptsTool.cs
new file mode 100644
index 0000000..5ea87ab
--- /dev/null
+++ b/Editor/Tools/RecompileScriptsTool.cs
@@ -0,0 +1,225 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using McpUnity.Utils;
+using Newtonsoft.Json.Linq;
+using UnityEditor;
+using UnityEditor.Compilation;
+using UnityEngine;
+
+namespace McpUnity.Tools {
+ ///
+ /// Tool to recompile all scripts in the Unity project
+ ///
+ public class RecompileScriptsTool : McpToolBase
+ {
+ private class CompilationRequest
+ {
+ public readonly bool ReturnWithLogs;
+ public readonly int LogsLimit;
+ public readonly TaskCompletionSource CompletionSource;
+
+ public CompilationRequest(bool returnWithLogs, int logsLimit, TaskCompletionSource completionSource)
+ {
+ ReturnWithLogs = returnWithLogs;
+ LogsLimit = logsLimit;
+ CompletionSource = completionSource;
+ }
+ }
+
+ private class CompilationResult
+ {
+ public readonly List SortedLogs;
+ public readonly int WarningsCount;
+ public readonly int ErrorsCount;
+
+ public bool HasErrors => ErrorsCount > 0;
+
+ public CompilationResult(List sortedLogs, int warningsCount, int errorsCount)
+ {
+ SortedLogs = sortedLogs;
+ WarningsCount = warningsCount;
+ ErrorsCount = errorsCount;
+ }
+ }
+
+ private readonly List _pendingRequests = new List();
+ private readonly List _compilationLogs = new List();
+ private int _processedAssemblies = 0;
+
+ public RecompileScriptsTool()
+ {
+ Name = "recompile_scripts";
+ Description = "Recompiles all scripts in the Unity project";
+ IsAsync = true; // Compilation is asynchronous
+ }
+
+ ///
+ /// Execute the Recompile tool asynchronously
+ ///
+ /// Tool parameters as a JObject
+ /// TaskCompletionSource to set the result or exception
+ public override void ExecuteAsync(JObject parameters, TaskCompletionSource tcs)
+ {
+ // Extract and store parameters
+ var returnWithLogs = GetBoolParameter(parameters, "returnWithLogs", true);
+ var logsLimit = Mathf.Clamp(GetIntParameter(parameters, "logsLimit", 100), 0, 1000);
+ var request = new CompilationRequest(returnWithLogs, logsLimit, tcs);
+
+ bool hasActiveRequest = false;
+ lock (_pendingRequests)
+ {
+ hasActiveRequest = _pendingRequests.Count > 0;
+ _pendingRequests.Add(request);
+ }
+
+ if (hasActiveRequest)
+ {
+ McpLogger.LogInfo("Recompilation already in progress. Waiting for completion...");
+ return;
+ }
+
+ // On first request, initialize compilation listeners and start compilation
+ StartCompilationTracking();
+
+ if (EditorApplication.isCompiling == false)
+ {
+ McpLogger.LogInfo("Recompiling all scripts in the Unity project");
+ CompilationPipeline.RequestScriptCompilation();
+ }
+ }
+
+ ///
+ /// Subscribe to compilation events, reset tracked state
+ ///
+ private void StartCompilationTracking()
+ {
+ _compilationLogs.Clear();
+ _processedAssemblies = 0;
+ CompilationPipeline.assemblyCompilationFinished += OnAssemblyCompilationFinished;
+ CompilationPipeline.compilationFinished += OnCompilationFinished;
+ }
+
+ ///
+ /// Unsubscribe from compilation events
+ ///
+ private void StopCompilationTracking()
+ {
+ CompilationPipeline.assemblyCompilationFinished -= OnAssemblyCompilationFinished;
+ CompilationPipeline.compilationFinished -= OnCompilationFinished;
+ }
+
+ ///
+ /// Record compilation logs for every single assembly
+ ///
+ private void OnAssemblyCompilationFinished(string assemblyPath, CompilerMessage[] messages)
+ {
+ _processedAssemblies++;
+ _compilationLogs.AddRange(messages);
+ }
+
+ ///
+ /// Stop tracking and complete all pending requests
+ ///
+ private void OnCompilationFinished(object _)
+ {
+ McpLogger.LogInfo($"Recompilation completed. Processed {_processedAssemblies} assemblies with {_compilationLogs.Count} compiler messages");
+
+ // Sort logs by type: first errors, then warnings and info
+ List sortedLogs = _compilationLogs.OrderBy(x => x.type).ToList();
+ int errorsCount = _compilationLogs.Count(l => l.type == CompilerMessageType.Error);
+ int warningsCount = _compilationLogs.Count(l => l.type == CompilerMessageType.Warning);
+ CompilationResult result = new CompilationResult(sortedLogs, warningsCount, errorsCount);
+
+ // Stop tracking before completing requests
+ StopCompilationTracking();
+
+ // Complete all requests received before compilation end, the next received request will start a new compilation
+ List requestsToComplete = new List();
+
+ lock (_pendingRequests)
+ {
+ requestsToComplete.AddRange(_pendingRequests);
+ _pendingRequests.Clear();
+ }
+
+ foreach (var request in requestsToComplete)
+ {
+ CompleteRequest(request, result);
+ }
+ }
+
+ ///
+ /// Process a completed compilation request
+ ///
+ private static void CompleteRequest(CompilationRequest request, CompilationResult result)
+ {
+ JArray logsArray = new JArray();
+ IEnumerable logsToReturn = request.ReturnWithLogs ? result.SortedLogs.Take(request.LogsLimit) : Enumerable.Empty();
+
+ foreach (var message in logsToReturn)
+ {
+ var logObject = new JObject
+ {
+ ["message"] = message.message,
+ ["type"] = message.type.ToString()
+ };
+
+ // Add file information if available
+ if (!string.IsNullOrEmpty(message.file))
+ {
+ logObject["file"] = message.file;
+ logObject["line"] = message.line;
+ logObject["column"] = message.column;
+ }
+
+ logsArray.Add(logObject);
+ }
+
+ string summaryMessage = result.HasErrors
+ ? $"Recompilation completed with {result.ErrorsCount} error(s) and {result.WarningsCount} warning(s)"
+ : $"Successfully recompiled all scripts with {result.WarningsCount} warning(s)";
+
+ summaryMessage += $" (returnWithLogs: {request.ReturnWithLogs}, logsLimit: {request.LogsLimit})";
+
+ var response = new JObject
+ {
+ ["success"] = true,
+ ["type"] = "text",
+ ["message"] = summaryMessage,
+ ["logs"] = logsArray
+ };
+
+ request.CompletionSource.SetResult(response);
+ }
+
+ ///
+ /// Helper method to safely extract integer parameters with default values
+ ///
+ /// JObject containing parameters
+ /// Parameter key to extract
+ /// Default value if parameter is missing or invalid
+ /// Extracted integer value or default
+ private static int GetIntParameter(JObject parameters, string key, int defaultValue)
+ {
+ if (parameters?[key] != null && int.TryParse(parameters[key].ToString(), out int value))
+ return value;
+ return defaultValue;
+ }
+
+ ///
+ /// Helper method to safely extract boolean parameters with default values
+ ///
+ /// JObject containing parameters
+ /// Parameter key to extract
+ /// Default value if parameter is missing or invalid
+ /// Extracted boolean value or default
+ private static bool GetBoolParameter(JObject parameters, string key, bool defaultValue)
+ {
+ if (parameters?[key] != null && bool.TryParse(parameters[key].ToString(), out bool value))
+ return value;
+ return defaultValue;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Editor/Tools/RecompileScriptsTool.cs.meta b/Editor/Tools/RecompileScriptsTool.cs.meta
new file mode 100644
index 0000000..98c53a5
--- /dev/null
+++ b/Editor/Tools/RecompileScriptsTool.cs.meta
@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 9db4c0c982944b9da2e14745cf799f99
+timeCreated: 1758591273
\ No newline at end of file
diff --git a/Editor/UnityBridge/McpUnityEditorWindow.cs b/Editor/UnityBridge/McpUnityEditorWindow.cs
index b53a222..d955d5a 100644
--- a/Editor/UnityBridge/McpUnityEditorWindow.cs
+++ b/Editor/UnityBridge/McpUnityEditorWindow.cs
@@ -401,6 +401,14 @@ private void DrawHelpTab()
WrappedLabel("Add the Player prefab from my project to the current scene", new GUIStyle(EditorStyles.miniLabel) { fontStyle = FontStyle.Italic });
EditorGUILayout.EndVertical();
+ // recompile_scripts
+ WrappedLabel("recompile_scripts", EditorStyles.boldLabel);
+ WrappedLabel("Recompiles all scripts in the Unity project");
+ EditorGUILayout.BeginVertical(EditorStyles.helpBox);
+ EditorGUILayout.LabelField("Example prompt:", EditorStyles.miniLabel);
+ WrappedLabel("Recompile scripts in my project", new GUIStyle(EditorStyles.miniLabel) { fontStyle = FontStyle.Italic });
+ EditorGUILayout.EndVertical();
+
EditorGUILayout.EndVertical();
// Available Resources section
diff --git a/Editor/UnityBridge/McpUnityServer.cs b/Editor/UnityBridge/McpUnityServer.cs
index d623c2d..f7fd0d9 100644
--- a/Editor/UnityBridge/McpUnityServer.cs
+++ b/Editor/UnityBridge/McpUnityServer.cs
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
-using UnityEngine;
using UnityEditor;
using McpUnity.Tools;
using McpUnity.Resources;
@@ -9,8 +8,8 @@
using McpUnity.Utils;
using WebSocketSharp.Server;
using System.IO;
-using System.Diagnostics;
using System.Net.Sockets;
+using UnityEditor.Callbacks;
namespace McpUnity.Unity
{
@@ -30,16 +29,15 @@ public class McpUnityServer : IDisposable
private CancellationTokenSource _cts;
private TestRunnerService _testRunnerService;
private ConsoleLogsService _consoleLogsService;
-
+
///
- /// Static constructor that gets called when Unity loads due to InitializeOnLoad attribute
+ /// Called after every domain reload
///
- static McpUnityServer()
+ [DidReloadScripts]
+ private static void AfterReload()
{
- EditorApplication.delayCall += () => {
- // Ensure Instance is created and hooks are set up after initial domain load
- var currentInstance = Instance;
- };
+ // Ensure Instance is created and hooks are set up after initial domain load
+ var currentInstance = Instance;
}
///
@@ -265,6 +263,10 @@ private void RegisterTools()
// Register LoadSceneTool
LoadSceneTool loadSceneTool = new LoadSceneTool();
_tools.Add(loadSceneTool.Name, loadSceneTool);
+
+ // Register RecompileScriptsTool
+ RecompileScriptsTool recompileScriptsTool = new RecompileScriptsTool();
+ _tools.Add(recompileScriptsTool.Name, recompileScriptsTool);
}
///
diff --git a/README-ja.md b/README-ja.md
index f64a866..d99c890 100644
--- a/README-ja.md
+++ b/README-ja.md
@@ -86,6 +86,9 @@ MCP Unityは、Unityの`Library/PackedCache`フォルダーをワークスペー
- `create_prefab`: プレハブを作成し、オプションでMonoBehaviourスクリプトとシリアライズされたフィールド値を設定
> **例:** "'PlayerController'スクリプトから'Player'という名前のプレハブを作成"
+- `recompile_scripts`: Unityプロジェクト内のすべてのスクリプトを再コンパイル
+ > **例:** "Unityプロジェクト内のすべてのスクリプトを再コンパイル"
+
### MCPサーバーリソース
- `unity://menu-items`: `execute_menu_item`ツールを容易にするために、Unityエディターで利用可能なすべてのメニュー項目のリストを取得
diff --git a/README.md b/README.md
index db28e90..30547bd 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,9 @@ The following tools are available for manipulating and querying Unity scenes and
- `create_prefab`: Creates a prefab with optional MonoBehaviour script and serialized field values
> **Example prompt:** "Create a prefab named 'Player' from the 'PlayerController' script"
+- `recompile_scripts`: Recompiles all scripts in the Unity project
+ > **Example prompt:** "Recompile scripts in my Unity project"
+
### MCP Server Resources
- `unity://menu-items`: Retrieves a list of all available menu items in the Unity Editor to facilitate `execute_menu_item` tool
diff --git a/README_zh-CN.md b/README_zh-CN.md
index c5a70fb..9b6f5a1 100644
--- a/README_zh-CN.md
+++ b/README_zh-CN.md
@@ -87,6 +87,9 @@ MCP Unity 通过将 Unity `Library/PackedCache` 文件夹添加到您的工作
- `create_prefab`: 创建预制体,并可选择添加 MonoBehaviour 脚本和设置序列化字段值
> **示例提示:** "从 'PlayerController' 脚本创建一个名为 'Player' 的预制体"
+- `recompile_scripts`: 重新编译 Unity 项目中的所有脚本
+ > **示例提示:** "重新编译我 Unity 项目中的所有脚本"
+
### MCP 服务器资源
- `unity://menu-items`: 获取 Unity 编辑器中所有可用的菜单项列表,以方便 `execute_menu_item` 工具
diff --git a/Server~/src/index.ts b/Server~/src/index.ts
index f5c12c0..3ff840c 100644
--- a/Server~/src/index.ts
+++ b/Server~/src/index.ts
@@ -16,6 +16,7 @@ import { registerUpdateGameObjectTool } from './tools/updateGameObjectTool.js';
import { registerCreatePrefabTool } from './tools/createPrefabTool.js';
import { registerDeleteSceneTool } from './tools/deleteSceneTool.js';
import { registerLoadSceneTool } from './tools/loadSceneTool.js';
+import { registerRecompileScriptsTool } from './tools/recompileScriptsTool.js';
import { registerGetMenuItemsResource } from './resources/getMenuItemResource.js';
import { registerGetConsoleLogsResource } from './resources/getConsoleLogsResource.js';
import { registerGetHierarchyResource } from './resources/getScenesHierarchyResource.js';
@@ -63,6 +64,7 @@ registerCreatePrefabTool(server, mcpUnity, toolLogger);
registerCreateSceneTool(server, mcpUnity, toolLogger);
registerDeleteSceneTool(server, mcpUnity, toolLogger);
registerLoadSceneTool(server, mcpUnity, toolLogger);
+registerRecompileScriptsTool(server, mcpUnity, toolLogger);
// Register all resources into the MCP server
registerGetTestsResource(server, mcpUnity, resourceLogger);
diff --git a/Server~/src/tools/recompileScriptsTool.ts b/Server~/src/tools/recompileScriptsTool.ts
new file mode 100644
index 0000000..4b12190
--- /dev/null
+++ b/Server~/src/tools/recompileScriptsTool.ts
@@ -0,0 +1,89 @@
+import * as z from 'zod';
+import { Logger } from '../utils/logger.js';
+import { McpUnity } from '../unity/mcpUnity.js';
+import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
+import { McpUnityError, ErrorType } from '../utils/errors.js';
+import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
+
+// Constants for the tool
+const toolName = 'recompile_scripts';
+const toolDescription = 'Recompiles all scripts in the Unity project.';
+const paramsSchema = z.object({
+ returnWithLogs: z.boolean().optional().default(true).describe('Whether to return compilation logs'),
+ logsLimit: z.number().int().min(0).max(1000).optional().default(100).describe('Maximum number of compilation logs to return')
+});
+
+/**
+ * Creates and registers the Recompile Scripts tool with the MCP server
+ * This tool allows recompiling all scripts in the Unity project
+ *
+ * @param server The MCP server instance to register with
+ * @param mcpUnity The McpUnity instance to communicate with Unity
+ * @param logger The logger instance for diagnostic information
+ */
+export function registerRecompileScriptsTool(server: McpServer, mcpUnity: McpUnity, logger: Logger) {
+ logger.info(`Registering tool: ${toolName}`);
+
+ // Register this tool with the MCP server
+ server.tool(
+ toolName,
+ toolDescription,
+ paramsSchema.shape,
+ async (params: any) => {
+ try {
+ logger.info(`Executing tool: ${toolName}`, params);
+ const result = await toolHandler(mcpUnity, params);
+ logger.info(`Tool execution successful: ${toolName}`);
+ return result;
+ } catch (error) {
+ logger.error(`Tool execution failed: ${toolName}`, error);
+ throw error;
+ }
+ }
+ );
+}
+
+/**
+ * Handles recompile scripts tool requests
+ *
+ * @param mcpUnity The McpUnity instance to communicate with Unity
+ * @param params The parameters for the tool
+ * @returns A promise that resolves to the tool execution result
+ * @throws McpUnityError if the request to Unity fails
+ */
+async function toolHandler(mcpUnity: McpUnity, params: z.infer): Promise {
+ // Validate and prepare parameters
+ const returnWithLogs = params.returnWithLogs ?? true;
+ const logsLimit = Math.max(0, Math.min(1000, params.logsLimit || 100));
+
+ // Send to Unity with validated parameters
+ const response = await mcpUnity.sendRequest({
+ method: toolName,
+ params: {
+ returnWithLogs,
+ logsLimit
+ }
+ });
+
+ if (!response.success) {
+ throw new McpUnityError(
+ ErrorType.TOOL_EXECUTION,
+ response.message || `Failed to recompile scripts`
+ );
+ }
+
+ return {
+ content: [
+ {
+ type: 'text',
+ text: response.message
+ },
+ {
+ type: 'text',
+ text: JSON.stringify({
+ logs: response.logs
+ }, null, 2)
+ }
+ ]
+ };
+}