Skip to content

Commit cd26e2a

Browse files
committed
feat: add delete scene tool
1 parent b8f12f2 commit cd26e2a

File tree

5 files changed

+209
-0
lines changed

5 files changed

+209
-0
lines changed

Editor/Tools/DeleteSceneTool.cs

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
using System;
2+
using System.Linq;
3+
using UnityEngine;
4+
using UnityEditor;
5+
using Newtonsoft.Json.Linq;
6+
using McpUnity.Unity;
7+
using McpUnity.Utils;
8+
9+
namespace McpUnity.Tools
10+
{
11+
/// <summary>
12+
/// Tool for deleting a Unity scene and removing it from Build Settings
13+
/// </summary>
14+
public class DeleteSceneTool : McpToolBase
15+
{
16+
public DeleteSceneTool()
17+
{
18+
Name = "delete_scene";
19+
Description = "Deletes a scene by path or name and removes it from Build Settings";
20+
}
21+
22+
/// <summary>
23+
/// Execute the DeleteScene tool with the provided parameters
24+
/// </summary>
25+
/// <param name="parameters">Tool parameters as a JObject</param>
26+
public override JObject Execute(JObject parameters)
27+
{
28+
string scenePath = parameters["scenePath"]?.ToObject<string>();
29+
string sceneName = parameters["sceneName"]?.ToObject<string>();
30+
string folderPath = parameters["folderPath"]?.ToObject<string>();
31+
32+
if (string.IsNullOrEmpty(scenePath))
33+
{
34+
if (string.IsNullOrEmpty(sceneName))
35+
{
36+
return McpUnitySocketHandler.CreateErrorResponse(
37+
"Provide either 'scenePath' or 'sceneName'",
38+
"validation_error"
39+
);
40+
}
41+
42+
// Resolve scene path by name (optionally within folderPath)
43+
string filter = $"{sceneName} t:Scene";
44+
string[] searchInFolders = null;
45+
if (!string.IsNullOrEmpty(folderPath))
46+
{
47+
// Ensure folder exists
48+
if (!AssetDatabase.IsValidFolder(folderPath))
49+
{
50+
return McpUnitySocketHandler.CreateErrorResponse(
51+
$"Folder '{folderPath}' does not exist",
52+
"not_found_error"
53+
);
54+
}
55+
searchInFolders = new[] { folderPath };
56+
}
57+
58+
var guids = AssetDatabase.FindAssets(filter, searchInFolders);
59+
foreach (var guid in guids)
60+
{
61+
var path = AssetDatabase.GUIDToAssetPath(guid);
62+
if (System.IO.Path.GetFileNameWithoutExtension(path) == sceneName)
63+
{
64+
scenePath = path;
65+
break;
66+
}
67+
}
68+
69+
if (string.IsNullOrEmpty(scenePath))
70+
{
71+
return McpUnitySocketHandler.CreateErrorResponse(
72+
$"Scene named '{sceneName}' not found",
73+
"not_found_error"
74+
);
75+
}
76+
}
77+
78+
try
79+
{
80+
// If the scene is open, close it without saving changes
81+
var scene = UnityEditor.SceneManagement.EditorSceneManager.GetSceneByPath(scenePath);
82+
if (scene.IsValid() && scene.isLoaded)
83+
{
84+
UnityEditor.SceneManagement.EditorSceneManager.CloseScene(scene, true);
85+
}
86+
87+
// Remove from Build Settings
88+
RemoveSceneFromBuildSettings(scenePath);
89+
90+
// Delete asset
91+
bool deleted = AssetDatabase.DeleteAsset(scenePath);
92+
AssetDatabase.Refresh();
93+
94+
if (!deleted)
95+
{
96+
return McpUnitySocketHandler.CreateErrorResponse(
97+
$"Failed to delete scene at '{scenePath}'",
98+
"delete_error"
99+
);
100+
}
101+
102+
McpLogger.LogInfo($"Deleted scene at path '{scenePath}' and removed from Build Settings");
103+
104+
return new JObject
105+
{
106+
["success"] = true,
107+
["type"] = "text",
108+
["message"] = $"Successfully deleted scene at path '{scenePath}' and removed from Build Settings",
109+
["scenePath"] = scenePath
110+
};
111+
}
112+
catch (Exception ex)
113+
{
114+
return McpUnitySocketHandler.CreateErrorResponse(
115+
$"Error deleting scene: {ex.Message}",
116+
"scene_delete_error"
117+
);
118+
}
119+
}
120+
121+
private void RemoveSceneFromBuildSettings(string scenePath)
122+
{
123+
var scenes = UnityEditor.EditorBuildSettings.scenes;
124+
var filtered = scenes.Where(s => s.path != scenePath).ToArray();
125+
if (filtered.Length != scenes.Length)
126+
{
127+
UnityEditor.EditorBuildSettings.scenes = filtered;
128+
}
129+
}
130+
}
131+
}
132+
133+

Editor/Tools/DeleteSceneTool.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Editor/UnityBridge/McpUnityServer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,10 @@ private void RegisterTools()
257257
// Register CreateSceneTool
258258
CreateSceneTool createSceneTool = new CreateSceneTool();
259259
_tools.Add(createSceneTool.Name, createSceneTool);
260+
261+
// Register DeleteSceneTool
262+
DeleteSceneTool deleteSceneTool = new DeleteSceneTool();
263+
_tools.Add(deleteSceneTool.Name, deleteSceneTool);
260264
}
261265

262266
/// <summary>

Server~/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { registerUpdateComponentTool } from './tools/updateComponentTool.js';
1414
import { registerAddAssetToSceneTool } from './tools/addAssetToSceneTool.js';
1515
import { registerUpdateGameObjectTool } from './tools/updateGameObjectTool.js';
1616
import { registerCreatePrefabTool } from './tools/createPrefabTool.js';
17+
import { registerDeleteSceneTool } from './tools/deleteSceneTool.js';
1718
import { registerGetMenuItemsResource } from './resources/getMenuItemResource.js';
1819
import { registerGetConsoleLogsResource } from './resources/getConsoleLogsResource.js';
1920
import { registerGetHierarchyResource } from './resources/getScenesHierarchyResource.js';
@@ -59,6 +60,7 @@ registerAddAssetToSceneTool(server, mcpUnity, toolLogger);
5960
registerUpdateGameObjectTool(server, mcpUnity, toolLogger);
6061
registerCreatePrefabTool(server, mcpUnity, toolLogger);
6162
registerCreateSceneTool(server, mcpUnity, toolLogger);
63+
registerDeleteSceneTool(server, mcpUnity, toolLogger);
6264

6365
// Register all resources into the MCP server
6466
registerGetTestsResource(server, mcpUnity, resourceLogger);
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2+
import { McpUnity } from '../unity/mcpUnity.js';
3+
import { McpUnityError, ErrorType } from '../utils/errors.js';
4+
import * as z from 'zod';
5+
import { Logger } from '../utils/logger.js';
6+
7+
const toolName = 'delete_scene';
8+
const toolDescription = 'Deletes a scene by path or name and removes it from Build Settings';
9+
10+
const paramsSchema = z.object({
11+
scenePath: z.string().optional().describe("Full asset path to the scene (e.g., 'Assets/Scenes/MyScene.unity')"),
12+
sceneName: z.string().optional().describe('Scene name without extension (used if scenePath not provided)'),
13+
folderPath: z.string().optional().describe("Optional folder scope to resolve sceneName under 'Assets'")
14+
});
15+
16+
export function registerDeleteSceneTool(server: McpServer, mcpUnity: McpUnity, logger: Logger) {
17+
logger.info(`Registering tool: ${toolName}`);
18+
19+
server.tool(
20+
toolName,
21+
toolDescription,
22+
paramsSchema.shape,
23+
async (params: any) => {
24+
try {
25+
logger.info(`Executing tool: ${toolName}`, params);
26+
const result = await toolHandler(mcpUnity, params);
27+
logger.info(`Tool execution successful: ${toolName}`);
28+
return result;
29+
} catch (error) {
30+
logger.error(`Tool execution failed: ${toolName}`, error);
31+
throw error;
32+
}
33+
}
34+
);
35+
}
36+
37+
async function toolHandler(mcpUnity: McpUnity, params: any) {
38+
if (!params.scenePath && !params.sceneName) {
39+
throw new McpUnityError(
40+
ErrorType.VALIDATION,
41+
"Either 'scenePath' or 'sceneName' must be provided"
42+
);
43+
}
44+
45+
const response = await mcpUnity.sendRequest({
46+
method: toolName,
47+
params
48+
});
49+
50+
if (!response.success) {
51+
throw new McpUnityError(
52+
ErrorType.TOOL_EXECUTION,
53+
response.message || 'Failed to delete scene'
54+
);
55+
}
56+
57+
return {
58+
content: [{
59+
type: response.type,
60+
text: response.message || 'Successfully deleted scene'
61+
}],
62+
data: {
63+
scenePath: response.scenePath
64+
}
65+
};
66+
}
67+
68+

0 commit comments

Comments
 (0)