feat: add compare_geometry MCP tool to PepMcp

- Add LaserQuoteBaseUrl config property to PepTools
- Implement CompareGeometry() MCP tool to compare part geometry between PEP and LaserQuote
- Read LaserQuoteBaseUrl from appsettings.json in Program.cs
- Add appsettings.json with LaserQuoteBaseUrl config
- Update PepMcp.csproj to copy appsettings.json to output directory
This commit is contained in:
aj
2026-06-23 07:17:22 -04:00
parent f59c5bd32e
commit 5a15b552a3
4 changed files with 59 additions and 0 deletions
+6
View File
@@ -12,4 +12,10 @@
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.1" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
+47
View File
@@ -10,6 +10,9 @@ public class PepTools
BaseAddress = new Uri("http://localhost:8085")
};
public static string LaserQuoteBaseUrl { get; set; } = "http://localhost:5260";
private static readonly HttpClient _laserQuoteClient = new();
private static readonly JsonSerializerOptions _jsonOptions = new()
{
PropertyNameCaseInsensitive = true,
@@ -571,4 +574,48 @@ public class PepTools
return $"Error calling PEP API: {ex.Message}";
}
}
[McpServerTool, Description("Compare the geometry of a part between PEP (nesting software) and LaserQuote (quoting software). Returns bounding box dimensions, cut length, entity counts, pixel diff %, and alignment strategy. Use this to detect when part drawings have drifted between systems.")]
public static async Task<string> CompareGeometry(
[Description("The part number to compare (e.g., 'SULLYS-003')")] string partNumber)
{
try
{
var url = $"{LaserQuoteBaseUrl}/api/geometry/compare?partNumber={Uri.EscapeDataString(partNumber)}";
var response = await _laserQuoteClient.GetAsync(url);
var json = await response.Content.ReadAsStringAsync();
var result = System.Text.Json.JsonSerializer.Deserialize<GeometryCompareResult>(json, _jsonOptions);
if (result?.Error != null)
return $"Note: {result.Error}";
var sb = new System.Text.StringBuilder();
sb.AppendLine($"Geometry Comparison: {partNumber}");
sb.AppendLine($"Result: {(result?.IsMatch == true ? "MATCH " : "MISMATCH ")}");
sb.AppendLine($"Pixel Diff: {result?.PixelDiffPercent:F3}%");
sb.AppendLine($"Alignment: {result?.AlignmentLabel}");
sb.AppendLine();
sb.AppendLine("| Metric | LaserQuote | PEP |");
sb.AppendLine("|---------------|-----------------|-----------------|");
sb.AppendLine($"| Width (in) | {result?.LaserQuote?.Width,15:F4} | {result?.Pep?.Width,15:F4} |");
sb.AppendLine($"| Height (in) | {result?.LaserQuote?.Height,15:F4} | {result?.Pep?.Height,15:F4} |");
sb.AppendLine($"| Cut Length | {result?.LaserQuote?.CutLength,15:F3} | {result?.Pep?.CutLength,15:F3} |");
sb.AppendLine($"| Entity Count | {result?.LaserQuote?.EntityCount,15} | {result?.Pep?.EntityCount,15} |");
return sb.ToString();
}
catch (Exception ex)
{
return $"Error calling LaserQuote API: {ex.Message}";
}
}
private record GeometryMetricDto(double Width, double Height, double CutLength, int EntityCount);
private record GeometryCompareResult(
bool IsMatch,
GeometryMetricDto? LaserQuote,
GeometryMetricDto? Pep,
double PixelDiffPercent,
string? AlignmentLabel,
string? Error);
}
+3
View File
@@ -8,4 +8,7 @@ builder.Services
.WithTools<PepTools>();
var app = builder.Build();
PepTools.LaserQuoteBaseUrl = builder.Configuration["LaserQuoteBaseUrl"] ?? "http://localhost:5260";
await app.RunAsync();
+3
View File
@@ -0,0 +1,3 @@
{
"LaserQuoteBaseUrl": "http://localhost:5260"
}