diff --git a/PepApi.Core/Controllers/DrawingsController.cs b/PepApi.Core/Controllers/DrawingsController.cs new file mode 100644 index 0000000..5b86520 --- /dev/null +++ b/PepApi.Core/Controllers/DrawingsController.cs @@ -0,0 +1,228 @@ +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using PepApi.Core.Models; +using PepLib.Data; + +namespace PepApi.Core.Controllers; + +[ApiController] +[Route("drawings")] +public class DrawingsController : ControllerBase +{ + private readonly PepDB _db; + + public DrawingsController(PepDB db) + { + _db = db; + } + + /// + /// Get a list of drawings with optional filtering. + /// + [HttpGet] + public async Task>> GetDrawings([FromQuery] DrawingFilterData? filter) + { + var drawings = await _db.Drawings + .Select(d => new DrawingSummary + { + ID = d.ID, + Name = d.Name, + Customer = d.Customer, + CustID = d.CustID, + Revision = d.Revision, + Description = d.Description, + Material = d.Material, + MaterialGrade = d.MatGrade, + Status = d.Status, + Type = d.Type, + Application = d.Application, + Programmer = d.Programmer, + CreatedBy = d.CreatedBy, + Width = d.Width, + Length = d.Length, + TrueArea = d.TrueArea, + CutLength = d.CutLength, + CreationDate = d.CreationDate, + LastEditDate = d.LastEditDate, + ModifiedDate = d.ModifiedDate, + HasBevel = d.HasBevel != 0, + HasLeadIn = d.HasLeadIn != 0, + HasTab = d.HasTab != 0 + }) + .ToListAsync(); + + if (filter != null) + { + var filtered = filter.Apply(drawings.AsQueryable()).ToList(); + var paginated = filtered.Skip(filter.Offset).Take(filter.Limit).ToList(); + return Ok(paginated); + } + + return Ok(drawings.Take(100).ToList()); + } + + /// + /// Get a drawing by ID. + /// + [HttpGet("{id:int}")] + public async Task> GetDrawingById(int id) + { + var drawing = await _db.Drawings + .Where(d => d.ID == id) + .FirstOrDefaultAsync(); + + if (drawing == null) + return NotFound(new { message = "Drawing not found" }); + + return Ok(ConvertToDetails(drawing)); + } + + /// + /// Get a drawing by exact name. + /// + [HttpGet("name/{name}")] + public async Task> GetDrawingByName(string name) + { + var drawing = await _db.Drawings + .Where(d => d.Name.ToUpper() == name.ToUpper()) + .FirstOrDefaultAsync(); + + if (drawing == null) + return NotFound(new { message = "Drawing not found" }); + + return Ok(ConvertToDetails(drawing)); + } + + /// + /// Search drawings by partial name. + /// + [HttpGet("search")] + public async Task> SearchDrawings( + [FromQuery] string search, + [FromQuery] int limit = 100) + { + if (string.IsNullOrWhiteSpace(search)) + return BadRequest(new { message = "Search term is required" }); + + var searchUpper = search.Trim().ToUpper(); + + var allMatches = await _db.Drawings + .Where(d => d.Name.ToUpper().Contains(searchUpper)) + .Select(d => new DrawingSummary + { + ID = d.ID, + Name = d.Name, + Customer = d.Customer, + CustID = d.CustID, + Revision = d.Revision, + Description = d.Description, + Material = d.Material, + MaterialGrade = d.MatGrade, + Status = d.Status, + Type = d.Type, + Application = d.Application, + Programmer = d.Programmer, + CreatedBy = d.CreatedBy, + Width = d.Width, + Length = d.Length, + TrueArea = d.TrueArea, + CutLength = d.CutLength, + CreationDate = d.CreationDate, + LastEditDate = d.LastEditDate, + ModifiedDate = d.ModifiedDate, + HasBevel = d.HasBevel != 0, + HasLeadIn = d.HasLeadIn != 0, + HasTab = d.HasTab != 0 + }) + .ToListAsync(); + + var limitedResults = limit > 0 ? allMatches.Take(limit).ToList() : allMatches; + + return Ok(new DrawingSearchResponse + { + SearchTerm = search, + TotalMatches = allMatches.Count, + ResultsReturned = limitedResults.Count, + Results = limitedResults + }); + } + + private static DrawingDetails ConvertToDetails(Drawing drawing) + { + return new DrawingDetails + { + ID = drawing.ID, + Name = drawing.Name, + CustID = drawing.CustID, + Revision = drawing.Revision, + Path = drawing.Path, + File = drawing.File, + InUseBy = drawing.InUseBy, + InUseDate = drawing.InUseDate, + Status = drawing.Status, + StatusModifiedBy = drawing.StatusModifiedBy, + StatusModifiedDate = drawing.StatusModifiedDate, + CreationDate = drawing.CreationDate, + LastEditDate = drawing.LastEditDate, + LastRefDate = drawing.LastRefDate, + Description = drawing.Description, + Customer = drawing.Customer, + Comment = drawing.Comment, + Notes = drawing.Notes, + Grain = drawing.Grain, + GrainAngle = drawing.GrainAngle, + Material = drawing.Material, + MaterialGrade = drawing.MatGrade, + Programmer = drawing.Programmer, + CreatedBy = drawing.CreatedBy, + Type = drawing.Type, + CommonCut = drawing.CommonCut, + CombineCut = drawing.CombineCut, + Errors = drawing.Errors, + Hardness = drawing.Hardness, + Specification = drawing.Specification, + NestInCutOuts = drawing.NestInCutOuts, + UserDefined1 = drawing.UserDefined1, + UserDefined2 = drawing.UserDefined2, + UserDefined3 = drawing.UserDefined3, + UserDefined4 = drawing.UserDefined4, + UserDefined5 = drawing.UserDefined5, + UserDefined6 = drawing.UserDefined6, + Machine = drawing.Machine, + Application = drawing.Application, + PartCount = drawing.PartCount, + Color = drawing.Color, + CombineMethod = drawing.CombineMethod, + SeqCutouts = drawing.SeqCutouts, + AllowMirror = drawing.AllowMirror, + SourceFile = drawing.SourceFile, + SourceDate = drawing.SourceDate, + SourceSize = drawing.SourceSize, + CadScaled = drawing.CadScaled, + CadDimVerified = drawing.CadDimVerified, + CadDimCount = drawing.CadDimCount, + Width = drawing.Width, + Length = drawing.Length, + RectArea = drawing.RectArea, + ExtArea = drawing.ExtArea, + TrueArea = drawing.TrueArea, + ExtUtil = drawing.ExtUtil, + TrueUtil = drawing.TrueUtil, + SmallestAreaAng = drawing.SmallestAreaAng, + SmallestAreaLen = drawing.SmallestAreaLen, + SmallestAreaWid = drawing.SmallestAreaWid, + SmallestYAng = drawing.SmallestYAng, + SmallestYLen = drawing.SmallestYLen, + SmallestYWid = drawing.SmallestYWid, + CutLength = drawing.CutLength, + ScribeLength = drawing.ScribeLength, + Checked = drawing.Checked, + PepBendStatus = drawing.PepBendStatus, + HasBevel = drawing.HasBevel != 0, + HasLeadIn = drawing.HasLeadIn != 0, + HasTab = drawing.HasTab != 0, + ModifiedDate = drawing.ModifiedDate, + ModifiedBy = drawing.ModifiedBy + }; + } +} diff --git a/PepApi.Core/Models/DrawingDetails.cs b/PepApi.Core/Models/DrawingDetails.cs new file mode 100644 index 0000000..7a7aa52 --- /dev/null +++ b/PepApi.Core/Models/DrawingDetails.cs @@ -0,0 +1,149 @@ +namespace PepApi.Core.Models +{ + public class DrawingDetails + { + public int ID { get; set; } + + public required string Name { get; set; } + + public required string CustID { get; set; } + + public required string Revision { get; set; } + + public required string Path { get; set; } + + public required string File { get; set; } + + public required string InUseBy { get; set; } + + public DateTime? InUseDate { get; set; } + + public required string Status { get; set; } + + public required string StatusModifiedBy { get; set; } + + public DateTime? StatusModifiedDate { get; set; } + + public DateTime? CreationDate { get; set; } + + public DateTime? LastEditDate { get; set; } + + public DateTime? LastRefDate { get; set; } + + public required string Description { get; set; } + + public required string Customer { get; set; } + + public required string Comment { get; set; } + + public required string Notes { get; set; } + + public byte Grain { get; set; } + + public double GrainAngle { get; set; } + + public required string Material { get; set; } + + public required string MaterialGrade { get; set; } + + public required string Programmer { get; set; } + + public required string CreatedBy { get; set; } + + public required string Type { get; set; } + + public byte CommonCut { get; set; } + + public byte CombineCut { get; set; } + + public required string Errors { get; set; } + + public required string Hardness { get; set; } + + public required string Specification { get; set; } + + public byte NestInCutOuts { get; set; } + + public required string UserDefined1 { get; set; } + + public required string UserDefined2 { get; set; } + + public required string UserDefined3 { get; set; } + + public required string UserDefined4 { get; set; } + + public required string UserDefined5 { get; set; } + + public required string UserDefined6 { get; set; } + + public short Machine { get; set; } + + public required string Application { get; set; } + + public int PartCount { get; set; } + + public int Color { get; set; } + + public short CombineMethod { get; set; } + + public byte SeqCutouts { get; set; } + + public byte AllowMirror { get; set; } + + public required string SourceFile { get; set; } + + public DateTime? SourceDate { get; set; } + + public int SourceSize { get; set; } + + public required string CadScaled { get; set; } + + public int CadDimVerified { get; set; } + + public int CadDimCount { get; set; } + + public double Width { get; set; } + + public double Length { get; set; } + + public double RectArea { get; set; } + + public double ExtArea { get; set; } + + public double TrueArea { get; set; } + + public double ExtUtil { get; set; } + + public double TrueUtil { get; set; } + + public double SmallestAreaAng { get; set; } + + public double SmallestAreaLen { get; set; } + + public double SmallestAreaWid { get; set; } + + public double SmallestYAng { get; set; } + + public double SmallestYLen { get; set; } + + public double SmallestYWid { get; set; } + + public double CutLength { get; set; } + + public double ScribeLength { get; set; } + + public int Checked { get; set; } + + public byte PepBendStatus { get; set; } + + public bool HasBevel { get; set; } + + public bool HasLeadIn { get; set; } + + public bool HasTab { get; set; } + + public DateTime? ModifiedDate { get; set; } + + public required string ModifiedBy { get; set; } + } +} diff --git a/PepApi.Core/Models/DrawingFilterData.cs b/PepApi.Core/Models/DrawingFilterData.cs new file mode 100644 index 0000000..21a047a --- /dev/null +++ b/PepApi.Core/Models/DrawingFilterData.cs @@ -0,0 +1,210 @@ +namespace PepApi.Core.Models +{ + public class DrawingFilterData + { + // Text filters (partial, case-insensitive) + public string? Name { get; set; } + public string? Customer { get; set; } + public string? CustID { get; set; } + public string? Description { get; set; } + public string? Revision { get; set; } + public string? Material { get; set; } + public string? MaterialGrade { get; set; } + public string? Hardness { get; set; } + public string? Specification { get; set; } + public string? Programmer { get; set; } + public string? CreatedBy { get; set; } + public string? ModifiedBy { get; set; } + + // Exact match filters + public string? Status { get; set; } + public string? Type { get; set; } + public string? Application { get; set; } + + // Date range filters + public DateTime? CreatedAfter { get; set; } + public DateTime? CreatedBefore { get; set; } + public DateTime? ModifiedAfter { get; set; } + public DateTime? ModifiedBefore { get; set; } + public DateTime? LastEditAfter { get; set; } + public DateTime? LastEditBefore { get; set; } + + // Dimension range filters + public double? MinWidth { get; set; } + public double? MaxWidth { get; set; } + public double? MinLength { get; set; } + public double? MaxLength { get; set; } + public double? MinArea { get; set; } + public double? MaxArea { get; set; } + + // Boolean filters + public bool? HasBevel { get; set; } + public bool? HasLeadIn { get; set; } + public bool? HasTab { get; set; } + + // Pagination + public int Offset { get; set; } = 0; + public int Limit { get; set; } = 100; + + public IQueryable Apply(IQueryable drawings) + { + // Text filters (partial, case-insensitive) + if (this.Name != null) + { + var x = this.Name.ToUpper(); + drawings = drawings.Where(d => d.Name.ToUpper().Contains(x)); + } + + if (this.Customer != null) + { + var x = this.Customer.ToUpper(); + drawings = drawings.Where(d => d.Customer.ToUpper().Contains(x)); + } + + if (this.CustID != null) + { + var x = this.CustID.ToUpper(); + drawings = drawings.Where(d => d.CustID.ToUpper().Contains(x)); + } + + if (this.Description != null) + { + var x = this.Description.ToUpper(); + drawings = drawings.Where(d => d.Description.ToUpper().Contains(x)); + } + + if (this.Revision != null) + { + var x = this.Revision.ToUpper(); + drawings = drawings.Where(d => d.Revision.ToUpper().Contains(x)); + } + + if (this.Material != null) + { + var x = this.Material.ToUpper(); + drawings = drawings.Where(d => d.Material.ToUpper().Contains(x)); + } + + if (this.MaterialGrade != null) + { + var x = this.MaterialGrade.ToUpper(); + drawings = drawings.Where(d => d.MaterialGrade.ToUpper().Contains(x)); + } + + if (this.Programmer != null) + { + var x = this.Programmer.ToUpper(); + drawings = drawings.Where(d => d.Programmer.ToUpper().Contains(x)); + } + + if (this.CreatedBy != null) + { + var x = this.CreatedBy.ToUpper(); + drawings = drawings.Where(d => d.CreatedBy.ToUpper().Contains(x)); + } + + // Exact match filters + if (this.Status != null) + { + var x = this.Status.ToUpper(); + drawings = drawings.Where(d => d.Status.ToUpper() == x); + } + + if (this.Type != null) + { + var x = this.Type.ToUpper(); + drawings = drawings.Where(d => d.Type.ToUpper() == x); + } + + if (this.Application != null) + { + var x = this.Application.ToUpper(); + drawings = drawings.Where(d => d.Application.ToUpper() == x); + } + + // Date range filters - CreationDate + if (this.CreatedAfter != null) + { + drawings = drawings.Where(d => d.CreationDate >= this.CreatedAfter); + } + + if (this.CreatedBefore != null) + { + drawings = drawings.Where(d => d.CreationDate <= this.CreatedBefore); + } + + // Date range filters - ModifiedDate + if (this.ModifiedAfter != null) + { + drawings = drawings.Where(d => d.ModifiedDate >= this.ModifiedAfter); + } + + if (this.ModifiedBefore != null) + { + drawings = drawings.Where(d => d.ModifiedDate <= this.ModifiedBefore); + } + + // Date range filters - LastEditDate + if (this.LastEditAfter != null) + { + drawings = drawings.Where(d => d.LastEditDate >= this.LastEditAfter); + } + + if (this.LastEditBefore != null) + { + drawings = drawings.Where(d => d.LastEditDate <= this.LastEditBefore); + } + + // Dimension range filters - Width + if (this.MinWidth != null) + { + drawings = drawings.Where(d => d.Width >= this.MinWidth); + } + + if (this.MaxWidth != null) + { + drawings = drawings.Where(d => d.Width <= this.MaxWidth); + } + + // Dimension range filters - Length + if (this.MinLength != null) + { + drawings = drawings.Where(d => d.Length >= this.MinLength); + } + + if (this.MaxLength != null) + { + drawings = drawings.Where(d => d.Length <= this.MaxLength); + } + + // Dimension range filters - Area (TrueArea) + if (this.MinArea != null) + { + drawings = drawings.Where(d => d.TrueArea >= this.MinArea); + } + + if (this.MaxArea != null) + { + drawings = drawings.Where(d => d.TrueArea <= this.MaxArea); + } + + // Boolean filters + if (this.HasBevel != null) + { + drawings = drawings.Where(d => d.HasBevel == this.HasBevel); + } + + if (this.HasLeadIn != null) + { + drawings = drawings.Where(d => d.HasLeadIn == this.HasLeadIn); + } + + if (this.HasTab != null) + { + drawings = drawings.Where(d => d.HasTab == this.HasTab); + } + + return drawings; + } + } +} diff --git a/PepApi.Core/Models/DrawingSearchResponse.cs b/PepApi.Core/Models/DrawingSearchResponse.cs new file mode 100644 index 0000000..5bd039b --- /dev/null +++ b/PepApi.Core/Models/DrawingSearchResponse.cs @@ -0,0 +1,9 @@ +namespace PepApi.Core.Models; + +public class DrawingSearchResponse +{ + public required string SearchTerm { get; set; } + public int TotalMatches { get; set; } + public int ResultsReturned { get; set; } + public List Results { get; set; } = []; +} diff --git a/PepApi.Core/Models/DrawingSummary.cs b/PepApi.Core/Models/DrawingSummary.cs new file mode 100644 index 0000000..c9e79dc --- /dev/null +++ b/PepApi.Core/Models/DrawingSummary.cs @@ -0,0 +1,51 @@ +namespace PepApi.Core.Models +{ + public class DrawingSummary + { + public int ID { get; set; } + + public required string Name { get; set; } + + public required string Customer { get; set; } + + public required string CustID { get; set; } + + public required string Revision { get; set; } + + public required string Description { get; set; } + + public required string Material { get; set; } + + public required string MaterialGrade { get; set; } + + public required string Status { get; set; } + + public required string Type { get; set; } + + public required string Application { get; set; } + + public required string Programmer { get; set; } + + public required string CreatedBy { get; set; } + + public double Width { get; set; } + + public double Length { get; set; } + + public double TrueArea { get; set; } + + public double CutLength { get; set; } + + public DateTime? CreationDate { get; set; } + + public DateTime? LastEditDate { get; set; } + + public DateTime? ModifiedDate { get; set; } + + public bool HasBevel { get; set; } + + public bool HasLeadIn { get; set; } + + public bool HasTab { get; set; } + } +} diff --git a/PepMcp/PepTools.cs b/PepMcp/PepTools.cs index 1c74bb1..73a0c49 100644 --- a/PepMcp/PepTools.cs +++ b/PepMcp/PepTools.cs @@ -400,4 +400,175 @@ public class PepTools return $"Error calling PEP API: {ex.Message}"; } } + + [McpServerTool, Description("Get a list of drawings with comprehensive filtering options for all fields including dimensions, dates, and boolean flags.")] + public static async Task GetDrawings( + [Description("Filter by partial name (case-insensitive)")] string? name = null, + [Description("Filter by partial customer name (case-insensitive)")] string? customer = null, + [Description("Filter by partial customer ID (case-insensitive)")] string? custId = null, + [Description("Filter by partial description (case-insensitive)")] string? description = null, + [Description("Filter by partial revision (case-insensitive)")] string? revision = null, + [Description("Filter by partial material (case-insensitive)")] string? material = null, + [Description("Filter by partial material grade (case-insensitive)")] string? materialGrade = null, + [Description("Filter by partial programmer name (case-insensitive)")] string? programmer = null, + [Description("Filter by partial created by (case-insensitive)")] string? createdBy = null, + [Description("Filter by exact status match")] string? status = null, + [Description("Filter by exact type match")] string? type = null, + [Description("Filter by exact application match")] string? application = null, + [Description("Filter by creation date after (yyyy-MM-dd)")] string? createdAfter = null, + [Description("Filter by creation date before (yyyy-MM-dd)")] string? createdBefore = null, + [Description("Filter by modified date after (yyyy-MM-dd)")] string? modifiedAfter = null, + [Description("Filter by modified date before (yyyy-MM-dd)")] string? modifiedBefore = null, + [Description("Filter by minimum width")] double? minWidth = null, + [Description("Filter by maximum width")] double? maxWidth = null, + [Description("Filter by minimum length")] double? minLength = null, + [Description("Filter by maximum length")] double? maxLength = null, + [Description("Filter by minimum area")] double? minArea = null, + [Description("Filter by maximum area")] double? maxArea = null, + [Description("Filter by has bevel")] bool? hasBevel = null, + [Description("Filter by has lead-in")] bool? hasLeadIn = null, + [Description("Filter by has tab")] bool? hasTab = null, + [Description("Number of results to skip (default 0)")] int offset = 0, + [Description("Maximum number of results to return (default 100)")] int limit = 100) + { + try + { + var queryParams = new List(); + + if (!string.IsNullOrWhiteSpace(name)) + queryParams.Add($"name={Uri.EscapeDataString(name)}"); + if (!string.IsNullOrWhiteSpace(customer)) + queryParams.Add($"customer={Uri.EscapeDataString(customer)}"); + if (!string.IsNullOrWhiteSpace(custId)) + queryParams.Add($"custId={Uri.EscapeDataString(custId)}"); + if (!string.IsNullOrWhiteSpace(description)) + queryParams.Add($"description={Uri.EscapeDataString(description)}"); + if (!string.IsNullOrWhiteSpace(revision)) + queryParams.Add($"revision={Uri.EscapeDataString(revision)}"); + if (!string.IsNullOrWhiteSpace(material)) + queryParams.Add($"material={Uri.EscapeDataString(material)}"); + if (!string.IsNullOrWhiteSpace(materialGrade)) + queryParams.Add($"materialGrade={Uri.EscapeDataString(materialGrade)}"); + if (!string.IsNullOrWhiteSpace(programmer)) + queryParams.Add($"programmer={Uri.EscapeDataString(programmer)}"); + if (!string.IsNullOrWhiteSpace(createdBy)) + queryParams.Add($"createdBy={Uri.EscapeDataString(createdBy)}"); + if (!string.IsNullOrWhiteSpace(status)) + queryParams.Add($"status={Uri.EscapeDataString(status)}"); + if (!string.IsNullOrWhiteSpace(type)) + queryParams.Add($"type={Uri.EscapeDataString(type)}"); + if (!string.IsNullOrWhiteSpace(application)) + queryParams.Add($"application={Uri.EscapeDataString(application)}"); + if (!string.IsNullOrWhiteSpace(createdAfter)) + queryParams.Add($"createdAfter={Uri.EscapeDataString(createdAfter)}"); + if (!string.IsNullOrWhiteSpace(createdBefore)) + queryParams.Add($"createdBefore={Uri.EscapeDataString(createdBefore)}"); + if (!string.IsNullOrWhiteSpace(modifiedAfter)) + queryParams.Add($"modifiedAfter={Uri.EscapeDataString(modifiedAfter)}"); + if (!string.IsNullOrWhiteSpace(modifiedBefore)) + queryParams.Add($"modifiedBefore={Uri.EscapeDataString(modifiedBefore)}"); + if (minWidth.HasValue) + queryParams.Add($"minWidth={minWidth.Value}"); + if (maxWidth.HasValue) + queryParams.Add($"maxWidth={maxWidth.Value}"); + if (minLength.HasValue) + queryParams.Add($"minLength={minLength.Value}"); + if (maxLength.HasValue) + queryParams.Add($"maxLength={maxLength.Value}"); + if (minArea.HasValue) + queryParams.Add($"minArea={minArea.Value}"); + if (maxArea.HasValue) + queryParams.Add($"maxArea={maxArea.Value}"); + if (hasBevel.HasValue) + queryParams.Add($"hasBevel={hasBevel.Value.ToString().ToLower()}"); + if (hasLeadIn.HasValue) + queryParams.Add($"hasLeadIn={hasLeadIn.Value.ToString().ToLower()}"); + if (hasTab.HasValue) + queryParams.Add($"hasTab={hasTab.Value.ToString().ToLower()}"); + + queryParams.Add($"offset={offset}"); + queryParams.Add($"limit={limit}"); + + var query = "?" + string.Join("&", queryParams); + var response = await _httpClient.GetAsync($"/drawings{query}"); + + if (!response.IsSuccessStatusCode) + return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"; + + var json = await response.Content.ReadAsStringAsync(); + return json; + } + catch (Exception ex) + { + return $"Error calling PEP API: {ex.Message}"; + } + } + + [McpServerTool, Description("Get detailed information about a specific drawing by its ID.")] + public static async Task GetDrawing( + [Description("The drawing ID to look up")] int id) + { + try + { + var response = await _httpClient.GetAsync($"/drawings/{id}"); + + if (!response.IsSuccessStatusCode) + return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"; + + var json = await response.Content.ReadAsStringAsync(); + return json; + } + catch (Exception ex) + { + return $"Error calling PEP API: {ex.Message}"; + } + } + + [McpServerTool, Description("Get detailed information about a specific drawing by its exact name.")] + public static async Task GetDrawingByName( + [Description("The exact drawing name to look up")] string name) + { + try + { + var response = await _httpClient.GetAsync($"/drawings/name/{Uri.EscapeDataString(name)}"); + + if (!response.IsSuccessStatusCode) + return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"; + + var json = await response.Content.ReadAsStringAsync(); + return json; + } + catch (Exception ex) + { + return $"Error calling PEP API: {ex.Message}"; + } + } + + [McpServerTool, Description("Search for drawings by partial name match. Returns matching drawings with basic information.")] + public static async Task SearchDrawings( + [Description("The partial drawing name to search for")] string searchTerm, + [Description("Maximum number of results to return (default 100)")] int limit = 100) + { + try + { + var queryParams = new List + { + $"search={Uri.EscapeDataString(searchTerm)}", + $"limit={limit}" + }; + + var query = "?" + string.Join("&", queryParams); + var response = await _httpClient.GetAsync($"/drawings/search{query}"); + + if (!response.IsSuccessStatusCode) + return $"Error: {response.StatusCode} - {await response.Content.ReadAsStringAsync()}"; + + var json = await response.Content.ReadAsStringAsync(); + return json; + } + catch (Exception ex) + { + return $"Error calling PEP API: {ex.Message}"; + } + } }