85 lines
3.1 KiB
C#
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; }
|
|
} |