diff --git a/src/CodingWithCalvin.MCPServer.Server/Tools/BuildTools.cs b/src/CodingWithCalvin.MCPServer.Server/Tools/BuildTools.cs index 0efd610..6778ec4 100644 --- a/src/CodingWithCalvin.MCPServer.Server/Tools/BuildTools.cs +++ b/src/CodingWithCalvin.MCPServer.Server/Tools/BuildTools.cs @@ -8,6 +8,9 @@ namespace CodingWithCalvin.MCPServer.Server.Tools; [McpServerToolType] public class BuildTools { + private const string DebugSessionActiveMessage = + "A debug session is currently active. Stop debugging first using debugger_stop before building."; + private readonly RpcClient _rpcClient; private readonly JsonSerializerOptions _jsonOptions; @@ -17,27 +20,48 @@ public BuildTools(RpcClient rpcClient) _jsonOptions = new JsonSerializerOptions { WriteIndented = true }; } + private async Task IsDebuggingActiveAsync() + { + var status = await _rpcClient.GetDebuggerStatusAsync(); + return status.Mode != "Design"; + } + [McpServerTool(Name = "build_solution", Destructive = false)] - [Description("Build the entire solution. The build runs asynchronously; use build_status to check progress. Returns immediately after starting the build.")] + [Description("Build the entire solution. The build runs asynchronously; use build_status to check progress. Returns immediately after starting the build. If a debug session is active, the build cannot proceed — use debugger_stop first.")] public async Task BuildSolutionAsync() { + if (await IsDebuggingActiveAsync()) + { + return DebugSessionActiveMessage; + } + var success = await _rpcClient.BuildSolutionAsync(); return success ? "Build started" : "Failed to start build (is a solution open?)"; } [McpServerTool(Name = "build_project", Destructive = false)] - [Description("Build a specific project. The build runs asynchronously; use build_status to check progress. IMPORTANT: Requires the full path to the .csproj file, not just the project name. Use project_list first to get the correct path.")] + [Description("Build a specific project. The build runs asynchronously; use build_status to check progress. IMPORTANT: Requires the full path to the .csproj file, not just the project name. Use project_list first to get the correct path. If a debug session is active, the build cannot proceed — use debugger_stop first.")] public async Task BuildProjectAsync( [Description("The full absolute path to the project file (.csproj). Get this from project_list. Supports forward slashes (/) or backslashes (\\).")] string projectName) { + if (await IsDebuggingActiveAsync()) + { + return DebugSessionActiveMessage; + } + var success = await _rpcClient.BuildProjectAsync(projectName); return success ? $"Build started for project: {projectName}" : $"Failed to build project: {projectName}"; } [McpServerTool(Name = "clean_solution", Destructive = true, Idempotent = true)] - [Description("Clean the entire solution by removing all build outputs (bin/obj folders). The clean runs asynchronously; use build_status to check progress.")] + [Description("Clean the entire solution by removing all build outputs (bin/obj folders). The clean runs asynchronously; use build_status to check progress. If a debug session is active, the clean cannot proceed — use debugger_stop first.")] public async Task CleanSolutionAsync() { + if (await IsDebuggingActiveAsync()) + { + return DebugSessionActiveMessage; + } + var success = await _rpcClient.CleanSolutionAsync(); return success ? "Clean started" : "Failed to start clean (is a solution open?)"; }