Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
┌──────────────────────────────────────────────────────────────────┐
│ 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. │
└──────────────────────────────────────────────────────────────────┘
*/

#nullable enable
using System;
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;
using com.IvanMurzak.McpPlugin.Common.Model;
using com.IvanMurzak.ReflectorNet.Utils;
using UnityEngine;
using Profiler = UnityEngine.Profiling.Profiler;

namespace com.IvanMurzak.Unity.MCP.Editor.API
{
public partial class Tool_Profiler
{
[McpPluginTool
(
"Profiler_CaptureFrame",
Title = "Capture Frame Data"
)]
[Description(@"Captures current frame data from the Unity Profiler.
Returns frame timing information, FPS, and frame counts.
Note: This captures a snapshot of the current frame only. Historical frame data requires using Unity's Profiler window.")]
public ResponseCallValueTool<FrameCaptureData?> CaptureFrame()
{
return MainThread.Instance.Run(() =>
{
if (!Profiler.enabled)
return ResponseCallValueTool<FrameCaptureData?>.Error(Error.ProfilerNotEnabled());

var data = new FrameCaptureData
{
FrameTimeMs = Time.deltaTime * 1000f,
Fps = Time.deltaTime > 0 ? 1f / Time.deltaTime : 0f,
TotalFrameCount = Time.frameCount,
RealtimeSinceStartup = Time.realtimeSinceStartup,
RenderedFrameCount = Time.renderedFrameCount
};

var mcpPlugin = UnityMcpPlugin.Instance.McpPluginInstance
?? throw new InvalidOperationException("MCP Plugin instance is not available.");
var jsonNode = mcpPlugin.McpManager.Reflector.JsonSerializer.SerializeToNode(data);
var jsonString = jsonNode?.ToJsonString();
return ResponseCallValueTool<FrameCaptureData?>.SuccessStructured(jsonNode, jsonString);
});
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
┌──────────────────────────────────────────────────────────────────┐
│ 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. │
└──────────────────────────────────────────────────────────────────┘
*/

#nullable enable
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;
using com.IvanMurzak.ReflectorNet.Utils;
using UnityEditorInternal;

namespace com.IvanMurzak.Unity.MCP.Editor.API
{
public partial class Tool_Profiler
{
[McpPluginTool
(
"Profiler_ClearData",
Title = "Clear Profiler Data"
)]
[Description("Clears all recorded profiler frames and data.")]
public string ClearData()
=> MainThread.Instance.Run(() =>
{
ProfilerDriver.ClearAllFrames();
return "[Success] Profiler data cleared successfully. All recorded frames have been removed.";
Comment on lines +27 to +31
});
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
┌──────────────────────────────────────────────────────────────────┐
│ 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. │
└──────────────────────────────────────────────────────────────────┘
*/

#nullable enable
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;
using com.IvanMurzak.ReflectorNet.Utils;

namespace com.IvanMurzak.Unity.MCP.Editor.API
{
public partial class Tool_Profiler
{
[McpPluginTool
(
"Profiler_EnableModule",
Title = "Enable/Disable Profiler Module"
)]
[Description(@"Enables or disables a specific profiler module.
Available modules: CPU, GPU, Rendering, Memory, Audio, Video, Physics, Physics2D, NetworkMessages, NetworkOperations, UI, UIDetails, GlobalIllumination, VirtualTexturing.
Note: Module enabling/disabling is tracked locally. Use Unity's Profiler window for actual module control.")]
public string EnableModule
(
[Description("The name of the profiler module (e.g., 'CPU', 'GPU', 'Memory').")]
string moduleName,
[Description("Whether to enable (true) or disable (false) the module.")]
Comment on lines +28 to +32
bool enabled = true
)
=> MainThread.Instance.Run(() =>
{
if (string.IsNullOrEmpty(moduleName))
return Error.ModuleNameIsRequired();

if (!AvailableModules.Contains(moduleName))
return Error.UnknownModule(moduleName);

if (enabled)
enabledModules.Add(moduleName);
else
enabledModules.Remove(moduleName);

var status = enabled ? "enabled" : "disabled";
return $"[Success] Profiler module '{moduleName}' has been {status}.\nNote: Module enabling/disabling is tracked locally. Use Unity's Profiler window for actual module control.";
});
}
}

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

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. │
└──────────────────────────────────────────────────────────────────┘
*/

#nullable enable
using System;
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;
using com.IvanMurzak.McpPlugin.Common.Model;
using com.IvanMurzak.ReflectorNet.Utils;
using Profiler = UnityEngine.Profiling.Profiler;

namespace com.IvanMurzak.Unity.MCP.Editor.API
{
public partial class Tool_Profiler
{
[McpPluginTool
(
"Profiler_GetMemoryStats",
Title = "Get Memory Statistics"
)]
[Description(@"Gets current memory statistics from the Unity Profiler.
Returns detailed memory information including reserved, allocated, mono heap, and graphics memory.
All values are in megabytes (MB).")]
public ResponseCallValueTool<MemoryStatsData?> GetMemoryStats()
{
return MainThread.Instance.Run(() =>
{
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetMemoryStats() method doesn't check if the profiler is enabled before accessing profiler data, unlike other stat methods (GetRenderingStats and GetScriptStats). While Unity's Profiler API methods like GetTotalReservedMemoryLong() can be called without enabling the profiler, this inconsistency may be confusing for API consumers. Consider adding the same profiler enabled check for consistency, or document why memory stats don't require it.

Suggested change
{
{
if (!Profiler.enabled)
{
return ResponseCallValueTool<MemoryStatsData?>.Error("Unity Profiler is not enabled. Enable the Profiler to retrieve memory statistics.");
}

Copilot uses AI. Check for mistakes.
if (!Profiler.enabled)
return ResponseCallValueTool<MemoryStatsData?>.Error(Error.ProfilerNotEnabled());

var data = new MemoryStatsData
{
TotalReservedMemoryMB = Profiler.GetTotalReservedMemoryLong() / 1048576f,
TotalAllocatedMemoryMB = Profiler.GetTotalAllocatedMemoryLong() / 1048576f,
TotalUnusedReservedMemoryMB = Profiler.GetTotalUnusedReservedMemoryLong() / 1048576f,
MonoHeapSizeMB = Profiler.GetMonoHeapSizeLong() / 1048576f,
MonoUsedSizeMB = Profiler.GetMonoUsedSizeLong() / 1048576f,
TempAllocatorSizeMB = Profiler.GetTempAllocatorSize() / 1048576f,
GraphicsMemoryMB = Profiler.GetAllocatedMemoryForGraphicsDriver() / 1048576f,
MaxUsedMemoryMB = Profiler.maxUsedMemory / 1048576f,
UsedHeapSizeMB = Profiler.usedHeapSizeLong / 1048576f
};

var mcpPlugin = UnityMcpPlugin.Instance.McpPluginInstance
?? throw new InvalidOperationException("MCP Plugin instance is not available.");
var jsonNode = mcpPlugin.McpManager.Reflector.JsonSerializer.SerializeToNode(data);
var jsonString = jsonNode?.ToJsonString();
return ResponseCallValueTool<MemoryStatsData?>.SuccessStructured(jsonNode, jsonString);
});
Comment on lines +31 to +56
Copy link

Copilot AI Dec 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetMemoryStats() method doesn't check if the profiler is enabled before collecting statistics, unlike GetRenderingStats() and GetScriptStats() which both return an error when !profilerEnabled.

This inconsistency is confusing for API consumers. Memory statistics from Unity's Profiler API are available regardless of whether profiling is enabled, so either:

  1. Document this difference clearly in the method's Description attribute
  2. Make the behavior consistent by removing the profiler-enabled check from the other stats methods
  3. Add the check to GetMemoryStats for consistency (though this might be less useful since memory stats are always available)

Copilot uses AI. Check for mistakes.
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
┌──────────────────────────────────────────────────────────────────┐
│ 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. │
└──────────────────────────────────────────────────────────────────┘
*/

#nullable enable
using System;
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;
using com.IvanMurzak.McpPlugin.Common.Model;
using com.IvanMurzak.ReflectorNet.Utils;
using UnityEngine;
using Profiler = UnityEngine.Profiling.Profiler;

namespace com.IvanMurzak.Unity.MCP.Editor.API
{
public partial class Tool_Profiler
{
[McpPluginTool
(
"Profiler_GetRenderingStats",
Title = "Get Rendering Statistics"
)]
[Description(@"Gets current rendering statistics from the Unity Profiler.
Returns frame time, FPS, VSync settings, and graphics device information.
Note: Detailed rendering statistics (draw calls, batches, etc.) require Unity's Frame Debugger or Profiler window.")]
public ResponseCallValueTool<RenderingStatsData?> GetRenderingStats()
{
return MainThread.Instance.Run(() =>
{
if (!Profiler.enabled)
return ResponseCallValueTool<RenderingStatsData?>.Error(Error.ProfilerNotEnabled());

var data = new RenderingStatsData
{
FrameTimeMs = Time.deltaTime * 1000f,
Fps = Time.deltaTime > 0 ? 1f / Time.deltaTime : 0f,
VSyncCount = QualitySettings.vSyncCount,
TargetFrameRate = Application.targetFrameRate,
RenderingThreadingMode = SystemInfo.renderingThreadingMode.ToString(),
GraphicsDeviceType = SystemInfo.graphicsDeviceType.ToString()
};

var mcpPlugin = UnityMcpPlugin.Instance.McpPluginInstance
?? throw new InvalidOperationException("MCP Plugin instance is not available.");
var jsonNode = mcpPlugin.McpManager.Reflector.JsonSerializer.SerializeToNode(data);
var jsonString = jsonNode?.ToJsonString();
return ResponseCallValueTool<RenderingStatsData?>.SuccessStructured(jsonNode, jsonString);
});
}
}
}

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
┌──────────────────────────────────────────────────────────────────┐
│ 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. │
└──────────────────────────────────────────────────────────────────┘
*/

#nullable enable
using System;
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;
using com.IvanMurzak.McpPlugin.Common.Model;
using com.IvanMurzak.ReflectorNet.Utils;
using UnityEngine;
using Profiler = UnityEngine.Profiling.Profiler;

namespace com.IvanMurzak.Unity.MCP.Editor.API
{
public partial class Tool_Profiler
{
[McpPluginTool
(
"Profiler_GetScriptStats",
Title = "Get Script Statistics"
)]
[Description(@"Gets current script execution statistics from the Unity Profiler.
Returns frame time, time scale, frame count, and memory usage.
Note: Detailed script profiling requires deep profiling mode in Unity's Profiler window.")]
public ResponseCallValueTool<ScriptStatsData?> GetScriptStats()
{
return MainThread.Instance.Run(() =>
{
if (!Profiler.enabled)
return ResponseCallValueTool<ScriptStatsData?>.Error(Error.ProfilerNotEnabled());

var data = new ScriptStatsData
{
FrameTimeMs = Time.deltaTime * 1000f,
FixedDeltaTimeMs = Time.fixedDeltaTime * 1000f,
TimeScale = Time.timeScale,
TotalFrameCount = Time.frameCount,
RealtimeSinceStartup = Time.realtimeSinceStartup,
MonoMemoryUsageMB = Profiler.GetMonoUsedSizeLong() / 1048576f,
GCMemoryUsageMB = GC.GetTotalMemory(false) / 1048576f
};

var mcpPlugin = UnityMcpPlugin.Instance.McpPluginInstance
?? throw new InvalidOperationException("MCP Plugin instance is not available.");
var jsonNode = mcpPlugin.McpManager.Reflector.JsonSerializer.SerializeToNode(data);
var jsonString = jsonNode?.ToJsonString();
return ResponseCallValueTool<ScriptStatsData?>.SuccessStructured(jsonNode, jsonString);
});
}
}
}

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

Loading
Loading