|  | 
|  | 1 | +using System.ComponentModel; | 
|  | 2 | +using System.Diagnostics; | 
|  | 3 | +using ModelContextProtocol.Server; | 
|  | 4 | + | 
|  | 5 | +namespace GC.Infrastructure.MCPServer | 
|  | 6 | +{ | 
|  | 7 | +    [McpServerToolType] | 
|  | 8 | +    internal class CoreRun | 
|  | 9 | +    { | 
|  | 10 | +        private static readonly string[] ValidBuildConfigs = new string[] { "Debug", "Release", "Checked" }; | 
|  | 11 | +        private static readonly string[] ValidArchs = new string[] { "x64", "x86", "arm64" }; | 
|  | 12 | + | 
|  | 13 | +        [McpServerTool(Name = "build_clr_libs"), Description("Builds the CoreCLR runtime and base class libraries for the .NET runtime. This is a prerequisite step before generating CoreRun executables for performance testing and benchmarking.")] | 
|  | 14 | +        public async Task<string> BuildCLRAndLibs( | 
|  | 15 | +            [Description("The absolute path to the root directory of the .NET runtime repository (e.g., 'C:\\runtime'). This should contain the build.cmd script.")] string runtimeRoot, | 
|  | 16 | +            [Description("The build configuration for CoreCLR compilation. Debug includes debugging symbols and assertions, Release is optimized for performance, and Checked includes some debugging features with optimizations. Valid options: Debug, Release, Checked.")] string buildConfig, | 
|  | 17 | +            [Description("The target CPU architecture for the build. Determines which instruction set and calling conventions to use. Valid options: x64 (64-bit Intel/AMD), x86 (32-bit Intel/AMD), arm64 (64-bit ARM).")] string arch = "x64") | 
|  | 18 | +        { | 
|  | 19 | +            if (!ValidBuildConfigs.Contains(buildConfig)) | 
|  | 20 | +            { | 
|  | 21 | +                return $"Invalid build configuration: '{buildConfig}'. Valid options are: {string.Join(", ", ValidBuildConfigs)}. Choose Debug for development with full debugging info, Release for optimized production builds, or Checked for optimized builds with some debugging features."; | 
|  | 22 | +            } | 
|  | 23 | +            if (!ValidArchs.Contains(arch)) | 
|  | 24 | +            { | 
|  | 25 | +                return $"Invalid architecture: '{arch}'. Valid options are: {string.Join(", ", ValidArchs)}. Use x64 for 64-bit Intel/AMD, x86 for 32-bit Intel/AMD, or arm64 for 64-bit ARM processors."; | 
|  | 26 | +            } | 
|  | 27 | + | 
|  | 28 | +            string fileName = "cmd.exe"; | 
|  | 29 | +            string arguments = $"/C build.cmd clr+libs -runtimeConfiguration {buildConfig} -librariesConfiguration Release -arch {arch}"; | 
|  | 30 | +            try | 
|  | 31 | +            { | 
|  | 32 | +                bool isSuccess = true; | 
|  | 33 | +                using (var process = new Process()) | 
|  | 34 | +                { | 
|  | 35 | +                    process.StartInfo.FileName = fileName; | 
|  | 36 | +                    process.StartInfo.Arguments = arguments; | 
|  | 37 | +                    process.StartInfo.RedirectStandardOutput = true; | 
|  | 38 | +                    process.StartInfo.RedirectStandardError = true; | 
|  | 39 | +                    process.StartInfo.UseShellExecute = false; | 
|  | 40 | +                    process.StartInfo.CreateNoWindow = true; | 
|  | 41 | +                    process.StartInfo.WorkingDirectory = runtimeRoot; | 
|  | 42 | +                    process.OutputDataReceived += (sender, e) => | 
|  | 43 | +                    { | 
|  | 44 | +                        if (!string.IsNullOrEmpty(e.Data)) | 
|  | 45 | +                        { | 
|  | 46 | +                            if (e.Data.ToLower().Contains("build failed with exit code")) | 
|  | 47 | +                            { | 
|  | 48 | +                                isSuccess = false; | 
|  | 49 | +                            } | 
|  | 50 | +                        } | 
|  | 51 | +                    }; | 
|  | 52 | +                    process.ErrorDataReceived += (sender, e) => | 
|  | 53 | +                    { | 
|  | 54 | +                        if (!string.IsNullOrEmpty(e.Data)) | 
|  | 55 | +                        { | 
|  | 56 | +                            if (e.Data.ToLower().Contains("build failed with exit code")) | 
|  | 57 | +                            { | 
|  | 58 | +                                isSuccess = false; | 
|  | 59 | +                            } | 
|  | 60 | +                        } | 
|  | 61 | +                    }; | 
|  | 62 | +                    process.Start(); | 
|  | 63 | +                    process.BeginOutputReadLine(); | 
|  | 64 | +                    process.BeginErrorReadLine(); | 
|  | 65 | +                    await process.WaitForExitAsync(); | 
|  | 66 | + | 
|  | 67 | +                    if (!isSuccess) | 
|  | 68 | +                    { | 
|  | 69 | +                        return "Failed to build CoreCLR and libraries. Please check the build log output above for detailed error information. Common issues include missing dependencies, incorrect paths, or insufficient permissions."; | 
|  | 70 | +                    } | 
|  | 71 | +                    else | 
|  | 72 | +                    { | 
|  | 73 | +                        return "Successfully built CoreCLR and libraries. The runtime components are now available for generating CoreRun executables."; | 
|  | 74 | +                    } | 
|  | 75 | +                } | 
|  | 76 | +            } | 
|  | 77 | +            catch (Exception ex) | 
|  | 78 | +            { | 
|  | 79 | +                return $"Failed to execute build command '{fileName} {arguments}'. Error: {ex.Message}. Please verify the runtime root path is correct and the build.cmd script exists."; | 
|  | 80 | +            } | 
|  | 81 | +        } | 
|  | 82 | + | 
|  | 83 | +        [McpServerTool(Name = "generate_corerun"), Description("Generates a CoreRun executable for the .NET runtime. CoreRun is a lightweight host that can run .NET applications without the full SDK, commonly used for performance testing, benchmarking, and isolated runtime scenarios.")] | 
|  | 84 | +        public async Task<string> GenerateCoreRun( | 
|  | 85 | +            [Description("The absolute path to the root directory of the .NET runtime repository (e.g., 'C:\\runtime'). This should contain the build.cmd script.")] string runtimeRoot, | 
|  | 86 | +            [Description("The build configuration for CoreCLR compilation. Debug includes debugging symbols and assertions, Release is optimized for performance, and Checked includes some debugging features with optimizations. Valid options: Debug, Release, Checked.")] string buildConfig, | 
|  | 87 | +            [Description("The target CPU architecture for the build. Determines which instruction set and calling conventions to use. Valid options: x64 (64-bit Intel/AMD), x86 (32-bit Intel/AMD), arm64 (64-bit ARM).")] string arch = "x64") | 
|  | 88 | +        { | 
|  | 89 | +            if (!ValidBuildConfigs.Contains(buildConfig)) | 
|  | 90 | +            { | 
|  | 91 | +                return $"Invalid build configuration: '{buildConfig}'. Valid options are: {string.Join(", ", ValidBuildConfigs)}. Choose Debug for development with full debugging info, Release for optimized production builds, or Checked for optimized builds with some debugging features."; | 
|  | 92 | +            } | 
|  | 93 | +            if (!ValidArchs.Contains(arch)) | 
|  | 94 | +            { | 
|  | 95 | +                return $"Invalid architecture: '{arch}'. Valid options are: {string.Join(", ", ValidArchs)}. Use x64 for 64-bit Intel/AMD, x86 for 32-bit Intel/AMD, or arm64 for 64-bit ARM processors."; | 
|  | 96 | +            } | 
|  | 97 | + | 
|  | 98 | +            string workingDirectory = Path.Combine(runtimeRoot, "src", "tests"); | 
|  | 99 | +            if (!Directory.Exists(workingDirectory)) | 
|  | 100 | +            { | 
|  | 101 | +                return $"The required directory '{workingDirectory}' does not exist. Please ensure you have a complete .NET runtime repository with the src/tests folder."; | 
|  | 102 | +            } | 
|  | 103 | +            string fileName = "cmd.exe"; | 
|  | 104 | +            string arguments = $"/C build.cmd generatelayoutonly {arch} {buildConfig}"; | 
|  | 105 | +            try | 
|  | 106 | +            { | 
|  | 107 | +                bool isSuccess = true; | 
|  | 108 | +                using (var process = new Process()) | 
|  | 109 | +                { | 
|  | 110 | +                    process.StartInfo.FileName = fileName; | 
|  | 111 | +                    process.StartInfo.Arguments = arguments; | 
|  | 112 | +                    process.StartInfo.RedirectStandardOutput = true; | 
|  | 113 | +                    process.StartInfo.RedirectStandardError = true; | 
|  | 114 | +                    process.StartInfo.UseShellExecute = false; | 
|  | 115 | +                    process.StartInfo.CreateNoWindow = true; | 
|  | 116 | +                    process.StartInfo.WorkingDirectory = workingDirectory; | 
|  | 117 | +                    process.OutputDataReceived += (sender, e) => | 
|  | 118 | +                    { | 
|  | 119 | +                        if (!string.IsNullOrEmpty(e.Data)) | 
|  | 120 | +                        { | 
|  | 121 | +                            if (e.Data.ToLower().Contains("build failed with exit code")) | 
|  | 122 | +                            { | 
|  | 123 | +                                isSuccess = false; | 
|  | 124 | +                            } | 
|  | 125 | +                        } | 
|  | 126 | +                    }; | 
|  | 127 | +                    process.ErrorDataReceived += (sender, e) => | 
|  | 128 | +                    { | 
|  | 129 | +                        if (!string.IsNullOrEmpty(e.Data)) | 
|  | 130 | +                        { | 
|  | 131 | +                            if (e.Data.ToLower().Contains("build failed with exit code")) | 
|  | 132 | +                            { | 
|  | 133 | +                                isSuccess = false; | 
|  | 134 | +                            } | 
|  | 135 | +                        } | 
|  | 136 | +                    }; | 
|  | 137 | +                    process.Start(); | 
|  | 138 | +                    process.BeginOutputReadLine(); | 
|  | 139 | +                    process.BeginErrorReadLine(); | 
|  | 140 | +                    await process.WaitForExitAsync(); | 
|  | 141 | + | 
|  | 142 | +                    if (!isSuccess) | 
|  | 143 | +                    { | 
|  | 144 | +                        return "Failed to generate CoreRun executable. Please check the build log output above for detailed error information. Ensure that CoreCLR and libraries were built successfully first using the build_clr_libs tool."; | 
|  | 145 | +                    } | 
|  | 146 | +                    else | 
|  | 147 | +                    { | 
|  | 148 | +                        return $"Successfully generated CoreRun executable. You can find the CoreRun.exe in the test layout directory for {arch} {buildConfig} configuration."; | 
|  | 149 | +                    } | 
|  | 150 | +                } | 
|  | 151 | +            } | 
|  | 152 | +            catch (Exception ex) | 
|  | 153 | +            { | 
|  | 154 | +                return $"Failed to execute CoreRun generation command '{fileName} {arguments}'. Error: {ex.Message}. Please verify the runtime root path is correct and the src/tests/build.cmd script exists."; | 
|  | 155 | +            } | 
|  | 156 | +        } | 
|  | 157 | +    } | 
|  | 158 | +} | 
0 commit comments