Files
FsMcp/FsMcp/Tools/SearchAllTools.cs

85 lines
3.1 KiB
C#

using System.ComponentModel;
using System.Net.Http.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using FsMcp;
using ModelContextProtocol.Server;
namespace FsMcp.Tools;
internal sealed class SearchAllTools
{
private readonly FoodsharingApiClient _apiClient;
public SearchAllTools(FoodsharingApiClient apiClient)
{
_apiClient = apiClient;
}
[McpServerTool]
[Description("General search endpoint returning all kinds of searchable entry types from GET /api/search/all.")]
public async Task<MixedSearchResult> GetSearchAllAsync(
[Description("Search query. Value must follow pattern /^.+$/ (cannot be empty).")]
string q,
[Description("Optional boolean to broaden the search to global results.")]
bool? global = null)
{
if (string.IsNullOrEmpty(q) || !Regex.IsMatch(q, "^.+$"))
{
throw new ArgumentException("Search query 'q' must not be empty and must match pattern /^.+$/.", nameof(q));
}
await _apiClient.EnsureLoginAsync();
var result = await _apiClient.HttpClient.GetFromJsonAsync<MixedSearchResult>(Endpoints.SearchAll(q, global));
return result ?? new MixedSearchResult();
}
}
public sealed record MixedSearchResult
{
[JsonPropertyName("regions")]
public IReadOnlyList<BaseSearchResult> Regions { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("workingGroups")]
public IReadOnlyList<BaseSearchResult> WorkingGroups { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("stores")]
public IReadOnlyList<BaseSearchResult> Stores { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("foodSharePoints")]
public IReadOnlyList<BaseSearchResult> FoodSharePoints { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("chats")]
public IReadOnlyList<BaseSearchResult> Chats { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("threads")]
public IReadOnlyList<BaseSearchResult> Threads { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("users")]
public IReadOnlyList<BaseSearchResult> Users { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("mails")]
public IReadOnlyList<BaseSearchResult> Mails { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("events")]
public IReadOnlyList<BaseSearchResult> Events { get; init; } = Array.Empty<BaseSearchResult>();
[JsonPropertyName("polls")]
public IReadOnlyList<BaseSearchResult> Polls { get; init; } = Array.Empty<BaseSearchResult>();
}
public sealed record BaseSearchResult
{
[Description("Unique identifier of the entity represented by the search result.")]
[JsonPropertyName("id")]
public int Id { get; init; }
[Description("Name of the entity represented by the search result.")]
[JsonPropertyName("name")]
public string Name { get; init; } = string.Empty;
[Description("Search criteria to test the search against.")]
[JsonPropertyName("searchString")]
public string? SearchString { get; init; }
}