105 lines
3.3 KiB
C#
105 lines
3.3 KiB
C#
using System.ComponentModel;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json.Serialization;
|
|
using FsMcp;
|
|
using ModelContextProtocol.Server;
|
|
|
|
namespace FsMcp.Tools;
|
|
|
|
internal sealed class StorePickupsTools
|
|
{
|
|
private readonly FoodsharingApiClient _apiClient;
|
|
|
|
public StorePickupsTools(FoodsharingApiClient apiClient)
|
|
{
|
|
_apiClient = apiClient;
|
|
}
|
|
|
|
[McpServerTool]
|
|
[Description("List upcoming pickups for a store from GET /api/stores/{storeId}/pickups.")]
|
|
public async Task<IReadOnlyList<StorePickup>> GetStorePickupsAsync(
|
|
[Description("Store ID as positive integer.")]
|
|
int storeId)
|
|
{
|
|
if (storeId <= 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException(nameof(storeId), "storeId must be a positive integer.");
|
|
}
|
|
|
|
await _apiClient.EnsureLoginAsync();
|
|
|
|
var pickups = await _apiClient.HttpClient.GetFromJsonAsync<IReadOnlyList<StorePickup>>(Endpoints.StorePickups(storeId));
|
|
return pickups ?? [];
|
|
}
|
|
}
|
|
|
|
public sealed record StorePickup
|
|
{
|
|
[Description("Date and time of the pickup.")]
|
|
[JsonPropertyName("date")]
|
|
public DateTime Date { get; init; }
|
|
|
|
[Description("Total number of available slots for this pickup.")]
|
|
[JsonPropertyName("totalSlots")]
|
|
public int TotalSlots { get; init; }
|
|
|
|
[Description("List of slots already occupied by users.")]
|
|
[JsonPropertyName("occupiedSlots")]
|
|
[JsonConverter(typeof(ObjectOrArrayConverter<OccupiedSlot>))]
|
|
public IReadOnlyList<OccupiedSlot> OccupiedSlots { get; init; } = [];
|
|
|
|
[Description("Whether slots are still available for this pickup.")]
|
|
[JsonPropertyName("isAvailable")]
|
|
[JsonConverter(typeof(NumberOrBoolConverter))]
|
|
public bool IsAvailable { get; init; }
|
|
|
|
[Description("Description or instructions for the pickup.")]
|
|
[JsonPropertyName("description")]
|
|
public string Description { get; init; } = string.Empty;
|
|
}
|
|
|
|
public sealed record OccupiedSlot
|
|
{
|
|
[Description("Whether the user's participation is confirmed.")]
|
|
[JsonPropertyName("isConfirmed")]
|
|
[JsonConverter(typeof(NumberOrBoolConverter))]
|
|
public bool IsConfirmed { get; init; }
|
|
|
|
[Description("Profile of the user who occupied the slot.")]
|
|
[JsonPropertyName("profile")]
|
|
public PickupUserProfile Profile { get; init; } = new();
|
|
}
|
|
|
|
public sealed record PickupUserProfile
|
|
{
|
|
[Description("User identifier.")]
|
|
[JsonPropertyName("id")]
|
|
public int Id { get; init; }
|
|
|
|
[Description("User display name.")]
|
|
[JsonPropertyName("name")]
|
|
public string Name { get; init; } = string.Empty;
|
|
|
|
[Description("URL to the user's avatar image.")]
|
|
[JsonPropertyName("avatar")]
|
|
public string? Avatar { get; init; }
|
|
|
|
[Description("Whether the user is currently in sleep mode.")]
|
|
[JsonPropertyName("isSleeping")]
|
|
[JsonConverter(typeof(NumberOrBoolConverter))]
|
|
public bool IsSleeping { get; init; }
|
|
|
|
[Description("Mobile phone number.")]
|
|
[JsonPropertyName("mobile")]
|
|
public string? Mobile { get; init; }
|
|
|
|
[Description("Landline phone number.")]
|
|
[JsonPropertyName("landline")]
|
|
public string? Landline { get; init; }
|
|
|
|
[Description("Whether the user is a store manager.")]
|
|
[JsonPropertyName("isManager")]
|
|
[JsonConverter(typeof(NumberOrBoolConverter))]
|
|
public bool IsManager { get; init; }
|
|
}
|