diff --git a/MCPForUnity/Editor/Helpers/ComponentOps.cs b/MCPForUnity/Editor/Helpers/ComponentOps.cs
index 60069079a..ae4d0d40e 100644
--- a/MCPForUnity/Editor/Helpers/ComponentOps.cs
+++ b/MCPForUnity/Editor/Helpers/ComponentOps.cs
@@ -376,6 +376,9 @@ internal static FieldInfo FindSerializedFieldInHierarchy(Type type, string field
private static string CheckPhysicsConflict(GameObject target, Type componentType)
{
+ // A 2D-vs-3D conflict is only possible when both physics modules are installed;
+ // if either is absent, its component types can't exist, so there's nothing to check.
+#if MCP_HAS_PHYSICS && MCP_HAS_PHYSICS_2D
bool isAdding2DPhysics =
typeof(Rigidbody2D).IsAssignableFrom(componentType) ||
typeof(Collider2D).IsAssignableFrom(componentType);
@@ -398,6 +401,7 @@ private static string CheckPhysicsConflict(GameObject target, Type componentType
return $"Cannot add 3D physics component '{componentType.Name}' because the GameObject '{target.name}' already has a 2D Rigidbody or Collider.";
}
}
+#endif
return null;
}
diff --git a/MCPForUnity/Editor/Helpers/GameObjectSerializer.cs b/MCPForUnity/Editor/Helpers/GameObjectSerializer.cs
index f97113618..4237f1cb0 100644
--- a/MCPForUnity/Editor/Helpers/GameObjectSerializer.cs
+++ b/MCPForUnity/Editor/Helpers/GameObjectSerializer.cs
@@ -528,6 +528,7 @@ public static object GetComponentData(Component c, bool includeNonPublicSerializ
}
// --- End Skip Transform Properties ---
+#if MCP_HAS_PHYSICS
// --- Skip Collider properties that cause native crashes via PhysX ---
if (typeof(Collider).IsAssignableFrom(componentType) &&
propName == "GeometryHolder")
@@ -535,6 +536,7 @@ public static object GetComponentData(Component c, bool includeNonPublicSerializ
skipProperty = true;
}
// --- End Skip Collider Properties ---
+#endif
// Skip if flagged
if (skipProperty)
diff --git a/MCPForUnity/Editor/MCPForUnity.Editor.asmdef b/MCPForUnity/Editor/MCPForUnity.Editor.asmdef
index e8f0ecd6d..e0e6bdb1c 100644
--- a/MCPForUnity/Editor/MCPForUnity.Editor.asmdef
+++ b/MCPForUnity/Editor/MCPForUnity.Editor.asmdef
@@ -19,6 +19,21 @@
"name": "com.unity.visualeffectgraph",
"expression": "0.0.0",
"define": "UNITY_VFX_GRAPH"
+ },
+ {
+ "name": "com.unity.modules.physics",
+ "expression": "1.0.0",
+ "define": "MCP_HAS_PHYSICS"
+ },
+ {
+ "name": "com.unity.modules.physics2d",
+ "expression": "1.0.0",
+ "define": "MCP_HAS_PHYSICS_2D"
+ },
+ {
+ "name": "com.unity.modules.screencapture",
+ "expression": "1.0.0",
+ "define": "MCP_HAS_SCREEN_CAPTURE"
}
],
"noEngineReferences": false
diff --git a/MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs b/MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs
index 1e7063ae6..aa95c69c2 100644
--- a/MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs
+++ b/MCPForUnity/Editor/Tools/GameObjects/GameObjectComponentHelpers.cs
@@ -32,6 +32,9 @@ internal static object AddComponentInternal(GameObject targetGo, string typeName
return new ErrorResponse("Cannot add another Transform component.");
}
+ // A 2D-vs-3D conflict is only possible when both physics modules are installed;
+ // if either is absent, its component types can't exist, so there's nothing to check.
+#if MCP_HAS_PHYSICS && MCP_HAS_PHYSICS_2D
bool isAdding2DPhysics = typeof(Rigidbody2D).IsAssignableFrom(componentType) || typeof(Collider2D).IsAssignableFrom(componentType);
bool isAdding3DPhysics = typeof(Rigidbody).IsAssignableFrom(componentType) || typeof(Collider).IsAssignableFrom(componentType);
@@ -49,6 +52,7 @@ internal static object AddComponentInternal(GameObject targetGo, string typeName
return new ErrorResponse($"Cannot add 3D physics component '{typeName}' because the GameObject '{targetGo.name}' already has a 2D Rigidbody or Collider.");
}
}
+#endif
Component existingComponent = targetGo.GetComponent(componentType);
if (existingComponent != null && !AllowsMultiple(componentType))
diff --git a/MCPForUnity/Editor/Tools/ManageAsset.cs b/MCPForUnity/Editor/Tools/ManageAsset.cs
index 69aaf53cc..ea1d6e3a0 100644
--- a/MCPForUnity/Editor/Tools/ManageAsset.cs
+++ b/MCPForUnity/Editor/Tools/ManageAsset.cs
@@ -10,6 +10,7 @@
using MCPForUnity.Editor.Tools;
using MCPForUnity.Runtime.Helpers;
+#if MCP_HAS_PHYSICS
#if UNITY_6000_0_OR_NEWER
using PhysicsMaterialType = UnityEngine.PhysicsMaterial;
using PhysicsMaterialCombine = UnityEngine.PhysicsMaterialCombine;
@@ -17,6 +18,7 @@
using PhysicsMaterialType = UnityEngine.PhysicMaterial;
using PhysicsMaterialCombine = UnityEngine.PhysicMaterialCombine;
#endif
+#endif
namespace MCPForUnity.Editor.Tools
{
@@ -224,11 +226,17 @@ private static object CreateAsset(JObject @params)
}
else if (lowerAssetType == "physicsmaterial")
{
+#if MCP_HAS_PHYSICS
PhysicsMaterialType pmat = new PhysicsMaterialType();
if (properties != null)
ApplyPhysicsMaterialProperties(pmat, properties);
AssetDatabase.CreateAsset(pmat, fullPath);
newAsset = pmat;
+#else
+ return new ErrorResponse(
+ "Cannot create a PhysicsMaterial: the Physics module (com.unity.modules.physics) is not installed. "
+ + "Enable it via Window > Package Manager > Built-in > Physics.");
+#endif
}
else if (lowerAssetType == "prefab")
{
@@ -876,6 +884,7 @@ private static void EnsureDirectoryExists(string directoryPath)
+#if MCP_HAS_PHYSICS
///
/// Applies properties from JObject to a PhysicsMaterial.
///
@@ -946,6 +955,7 @@ private static bool ApplyPhysicsMaterialProperties(PhysicsMaterialType pmat, JOb
return modified;
}
+#endif
///
/// Generic helper to set properties on any UnityEngine.Object using reflection.
diff --git a/MCPForUnity/Editor/Tools/ManageScene.cs b/MCPForUnity/Editor/Tools/ManageScene.cs
index c3c66b3fa..f202440be 100644
--- a/MCPForUnity/Editor/Tools/ManageScene.cs
+++ b/MCPForUnity/Editor/Tools/ManageScene.cs
@@ -1460,8 +1460,9 @@ private static bool TryGetRendererBounds(GameObject target, out Bounds bounds)
private static bool TryGetColliderBounds(GameObject target, out Bounds bounds)
{
bounds = default(Bounds);
- var colliders = target.GetComponentsInChildren(true);
bool hasBounds = false;
+#if MCP_HAS_PHYSICS
+ var colliders = target.GetComponentsInChildren(true);
foreach (var collider in colliders)
{
if (collider == null || !collider.gameObject.activeInHierarchy)
@@ -1477,7 +1478,9 @@ private static bool TryGetColliderBounds(GameObject target, out Bounds bounds)
bounds.Encapsulate(collider.bounds);
}
}
+#endif
+#if MCP_HAS_PHYSICS_2D
var colliders2D = target.GetComponentsInChildren(true);
foreach (var collider in colliders2D)
{
@@ -1494,6 +1497,7 @@ private static bool TryGetColliderBounds(GameObject target, out Bounds bounds)
bounds.Encapsulate(collider.bounds);
}
}
+#endif
return hasBounds;
}
diff --git a/MCPForUnity/Editor/Tools/ManageUI.cs b/MCPForUnity/Editor/Tools/ManageUI.cs
index cad174139..cc3cd8b5a 100644
--- a/MCPForUnity/Editor/Tools/ManageUI.cs
+++ b/MCPForUnity/Editor/Tools/ManageUI.cs
@@ -811,10 +811,12 @@ private static object SerializeVisualElement(VisualElement element, int depth, i
// Play-mode coroutine capture state. Only one capture is in-flight at a
// time; concurrent render_ui calls while a capture is pending are rejected
- // with an explicit error.
+ // with an explicit error. Only used when the Screen Capture module is present.
+#if MCP_HAS_SCREEN_CAPTURE
private static Texture2D s_pendingCaptureTex;
private static bool s_pendingCaptureDone;
private static bool s_pendingCaptureStarted;
+#endif
private static object RenderUI(JObject @params)
{
@@ -854,6 +856,7 @@ private static object RenderUI(JObject @params)
// Second call: result is ready – save PNG and return data.
if (Application.isPlaying)
{
+#if MCP_HAS_SCREEN_CAPTURE
// Build the output paths (used by both the pending and ready branches)
string resolvedPlayName = string.IsNullOrWhiteSpace(fileName)
? $"ui-render-{DateTime.Now:yyyyMMdd-HHmmss}.png"
@@ -954,6 +957,12 @@ private static object RenderUI(JObject @params)
{ "gameObject", (object)target ?? uxmlPath },
{ "note", "A screen capture was scheduled for the end of this frame. Call render_ui once more to get the result." }
});
+#else
+ return new ErrorResponse(
+ "Play-mode UI capture requires the Screen Capture module (com.unity.modules.screencapture), " +
+ "which is not installed. Enable it via Window > Package Manager > Built-in > Screen Capture, " +
+ "or render the UI outside Play mode (which captures via a RenderTexture instead).");
+#endif
}
// ── End play-mode branch ────────────────────────────────────────────────
diff --git a/MCPForUnity/Editor/Tools/Physics/CollisionMatrixOps.cs b/MCPForUnity/Editor/Tools/Physics/CollisionMatrixOps.cs
index 3482d47aa..00bcd8234 100644
--- a/MCPForUnity/Editor/Tools/Physics/CollisionMatrixOps.cs
+++ b/MCPForUnity/Editor/Tools/Physics/CollisionMatrixOps.cs
@@ -16,6 +16,19 @@ public static object GetCollisionMatrix(JObject @params)
if (dimension != "3d" && dimension != "2d")
return new ErrorResponse($"Invalid dimension: '{dimension}'. Use '3d' or '2d'.");
+ if (dimension == "2d")
+ {
+#if !MCP_HAS_PHYSICS_2D
+ return new ErrorResponse("Physics 2D module (com.unity.modules.physics2d) is not installed.");
+#endif
+ }
+ else
+ {
+#if !MCP_HAS_PHYSICS
+ return new ErrorResponse("Physics module (com.unity.modules.physics) is not installed.");
+#endif
+ }
+
var layers = new List