Skip to content

Commit 8b54779

Browse files
authored
fix(build): check for active debug session before building (#50)
Build, build project, and clean tools now check if a debug session is active and return a message directing the agent to use debugger_stop first, preventing VS from showing a blocking modal dialog.
1 parent 65a3fbd commit 8b54779

1 file changed

Lines changed: 27 additions & 3 deletions

File tree

src/CodingWithCalvin.MCPServer.Server/Tools/BuildTools.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ namespace CodingWithCalvin.MCPServer.Server.Tools;
88
[McpServerToolType]
99
public class BuildTools
1010
{
11+
private const string DebugSessionActiveMessage =
12+
"A debug session is currently active. Stop debugging first using debugger_stop before building.";
13+
1114
private readonly RpcClient _rpcClient;
1215
private readonly JsonSerializerOptions _jsonOptions;
1316

@@ -17,27 +20,48 @@ public BuildTools(RpcClient rpcClient)
1720
_jsonOptions = new JsonSerializerOptions { WriteIndented = true };
1821
}
1922

23+
private async Task<bool> IsDebuggingActiveAsync()
24+
{
25+
var status = await _rpcClient.GetDebuggerStatusAsync();
26+
return status.Mode != "Design";
27+
}
28+
2029
[McpServerTool(Name = "build_solution", Destructive = false)]
21-
[Description("Build the entire solution. The build runs asynchronously; use build_status to check progress. Returns immediately after starting the build.")]
30+
[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.")]
2231
public async Task<string> BuildSolutionAsync()
2332
{
33+
if (await IsDebuggingActiveAsync())
34+
{
35+
return DebugSessionActiveMessage;
36+
}
37+
2438
var success = await _rpcClient.BuildSolutionAsync();
2539
return success ? "Build started" : "Failed to start build (is a solution open?)";
2640
}
2741

2842
[McpServerTool(Name = "build_project", Destructive = false)]
29-
[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.")]
43+
[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.")]
3044
public async Task<string> BuildProjectAsync(
3145
[Description("The full absolute path to the project file (.csproj). Get this from project_list. Supports forward slashes (/) or backslashes (\\).")] string projectName)
3246
{
47+
if (await IsDebuggingActiveAsync())
48+
{
49+
return DebugSessionActiveMessage;
50+
}
51+
3352
var success = await _rpcClient.BuildProjectAsync(projectName);
3453
return success ? $"Build started for project: {projectName}" : $"Failed to build project: {projectName}";
3554
}
3655

3756
[McpServerTool(Name = "clean_solution", Destructive = true, Idempotent = true)]
38-
[Description("Clean the entire solution by removing all build outputs (bin/obj folders). The clean runs asynchronously; use build_status to check progress.")]
57+
[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.")]
3958
public async Task<string> CleanSolutionAsync()
4059
{
60+
if (await IsDebuggingActiveAsync())
61+
{
62+
return DebugSessionActiveMessage;
63+
}
64+
4165
var success = await _rpcClient.CleanSolutionAsync();
4266
return success ? "Clean started" : "Failed to start clean (is a solution open?)";
4367
}

0 commit comments

Comments
 (0)