Add RegionUsers tool and update README; enhance endpoint documentation
This commit is contained in:
@@ -4,6 +4,9 @@ Use this prompt when adding a new MCP tool to this project.
|
||||
|
||||
---
|
||||
|
||||
Here is your documentation of the available endpoints (openapi)
|
||||
https://beta.foodsharing.de/api/doc
|
||||
|
||||
You are working in the `fsmcp` workspace.
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -5,6 +5,7 @@ public static class Endpoints
|
||||
public static string UserLogin => $"{ApiBase}/api/login";
|
||||
public static string UserCurrentDetails => $"{ApiBase}/api/users/current/details";
|
||||
public static string RegionStores(int regionId) => $"{ApiBase}/api/regions/{regionId}/stores";
|
||||
public static string RegionUsers(int regionId) => $"{ApiBase}/api/regions/{regionId}/users";
|
||||
public static string StoreMembers(int storeId) => $"{ApiBase}/api/stores/{storeId}/members";
|
||||
|
||||
private static string ApiBase => "https://beta.foodsharing.de";
|
||||
|
||||
@@ -15,6 +15,7 @@ builder.Services
|
||||
.WithStdioServerTransport()
|
||||
.WithTools<CurrentUserTools>()
|
||||
.WithTools<RegionStoresTools>()
|
||||
.WithTools<StoreMembersTools>();
|
||||
.WithTools<StoreMembersTools>()
|
||||
.WithTools<FsMcp.Tools.RegionUsersTools>();
|
||||
|
||||
await builder.Build().RunAsync();
|
||||
|
||||
@@ -122,6 +122,26 @@ Notes for consumers:
|
||||
|
||||
The tool is strongly typed in `Tools/StoreMembersTools.cs`, with per-field `Description` attributes so MCP clients can surface schema-aware guidance directly in tool UIs.
|
||||
|
||||
### Region users tool
|
||||
|
||||
This server also exposes `get_region_users`.
|
||||
|
||||
- Purpose: Returns all members of a region from `GET /api/regions/{regionId}/users`.
|
||||
- Input:
|
||||
- `regionId` (required, positive integer; OpenAPI path pattern: `[1-9][0-9]*`)
|
||||
- Auth: Uses `USERNAME` and `PASSWORD` environment variables to log in and then sends the `X-CSRF-Token` header.
|
||||
- Output: Array of typed member entries including:
|
||||
- identity fields (`id`, `name`, `lastName`, `avatar`, `isSleeping`, `isAdminOrAmbassadorOfRegion`, `isVerified`, `role`)
|
||||
- extra observed fields (`isHomeRegion`, `lastActivity`, `lastPassDate`)
|
||||
|
||||
Notes for consumers:
|
||||
|
||||
- `isSleeping` indicates whether the member currently uses the sleeping hat function.
|
||||
- `isAdminOrAmbassadorOfRegion` indicates if the member has admin/ambassador privileges in this region.
|
||||
- Some fields (`lastName`, `isHomeRegion`, `lastActivity`, `role`, `lastPassDate`, `isVerified`) are added to handle varying response payloads.
|
||||
|
||||
The tool is strongly typed in `Tools/RegionUsersTools.cs`, with per-field `Description` attributes so MCP clients can surface schema-aware guidance directly in tool UIs.
|
||||
|
||||
## Publishing to NuGet.org
|
||||
|
||||
1. Run `dotnet pack -c Release` to create the NuGet package
|
||||
|
||||
81
FsMcp/Tools/RegionUsersTools.cs
Normal file
81
FsMcp/Tools/RegionUsersTools.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System.ComponentModel;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using FsMcp;
|
||||
using ModelContextProtocol.Server;
|
||||
|
||||
namespace FsMcp.Tools;
|
||||
|
||||
internal sealed class RegionUsersTools
|
||||
{
|
||||
private readonly FoodsharingApiClient _apiClient;
|
||||
|
||||
public RegionUsersTools(FoodsharingApiClient apiClient)
|
||||
{
|
||||
_apiClient = apiClient;
|
||||
}
|
||||
|
||||
[McpServerTool]
|
||||
[Description("Returns a list of all members for a region. Useful for discovering users within a specific foodsharing region.")]
|
||||
public async Task<IReadOnlyList<UnitMemberListItem>> GetRegionUsersAsync(
|
||||
[Description("Region ID as positive integer (OpenAPI path pattern: [1-9][0-9]*).")]
|
||||
int regionId)
|
||||
{
|
||||
if (regionId <= 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(regionId), "regionId must be a positive integer.");
|
||||
}
|
||||
|
||||
await _apiClient.EnsureLoginAsync();
|
||||
|
||||
var users = await _apiClient.HttpClient.GetFromJsonAsync<IReadOnlyList<UnitMemberListItem>>(Endpoints.RegionUsers(regionId));
|
||||
return users ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
public sealed record UnitMemberListItem
|
||||
{
|
||||
[Description("Unique user ID of the member.")]
|
||||
[JsonPropertyName("id")]
|
||||
public int Id { get; init; }
|
||||
|
||||
[Description("Display name of the member.")]
|
||||
[JsonPropertyName("name")]
|
||||
public string Name { get; init; } = string.Empty;
|
||||
|
||||
[Description("Relative API path of the member avatar image.")]
|
||||
[JsonPropertyName("avatar")]
|
||||
public string? Avatar { get; init; }
|
||||
|
||||
[Description("Whether the user is currently using the sleeping hat function.")]
|
||||
[JsonPropertyName("isSleeping")]
|
||||
public bool? IsSleeping { get; init; }
|
||||
|
||||
[Description("Whether the user is an admin or ambassador of the region.")]
|
||||
[JsonPropertyName("isAdminOrAmbassadorOfRegion")]
|
||||
public bool IsAdminOrAmbassadorOfRegion { get; init; }
|
||||
|
||||
[Description("Last name of the member (if available or returned by the API).")]
|
||||
[JsonPropertyName("lastName")]
|
||||
public string? LastName { get; init; }
|
||||
|
||||
[Description("Whether the region is the user's home region (if available).")]
|
||||
[JsonPropertyName("isHomeRegion")]
|
||||
public bool? IsHomeRegion { get; init; }
|
||||
|
||||
[Description("Last activity timestamp of the user (if available).")]
|
||||
[JsonPropertyName("lastActivity")]
|
||||
public DateTimeOffset? LastActivity { get; init; }
|
||||
|
||||
[Description("Numeric role enum from OpenAPI Role: 0, 1, 2, 3, 4, 5.")]
|
||||
[JsonPropertyName("role")]
|
||||
public int? Role { get; init; }
|
||||
|
||||
[Description("Date and time of the last generated pass, format: YYYY-MM-DD HH:mm:ss.")]
|
||||
[JsonPropertyName("lastPassDate")]
|
||||
public string? LastPassDate { get; init; }
|
||||
|
||||
[Description("Whether the member account is verified.")]
|
||||
[JsonPropertyName("isVerified")]
|
||||
public bool? IsVerified { get; init; }
|
||||
}
|
||||
Reference in New Issue
Block a user