using System.ComponentModel; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; namespace Novelly.Mcp.Tools; [McpServerToolType] public static class LocationTools { [McpServerTool(Name = "list_locations")] [Description("List a novel's locations with how many chapters are set there. " + "Read this before inventing a new location so you reuse the writer's vocabulary.")] public static Task ListLocations( NovelApiClient api, [Description("The novel's id.")] Guid novelId, CancellationToken ct) => api.GetAsync($"/api/novels/{novelId}/locations", ct); [McpServerTool(Name = "get_location_references")] [Description("Cross-reference a location: every chapter set there.")] public static Task GetLocationReferences( NovelApiClient api, [Description("The location's id.")] Guid locationId, CancellationToken ct) => api.GetAsync($"/api/locations/{locationId}/references", ct); [McpServerTool(Name = "create_location")] [Description("Create a location explicitly. Applying an unknown location by name to a chapter " + "also creates it, so this is only needed to set one up ahead of time.")] public static Task CreateLocation( NovelApiClient api, [Description("The novel's id.")] Guid novelId, [Description("The location's name. Unique within the novel, matched case-insensitively.")] string name, CancellationToken ct) => api.PostAsync($"/api/novels/{novelId}/locations", new { name }, ct); [McpServerTool(Name = "update_location")] [Description("Rename a location. Renaming updates it everywhere it is applied.")] public static Task UpdateLocation( NovelApiClient api, [Description("The location's id.")] Guid locationId, [Description("New name.")] string name, CancellationToken ct) => api.PatchAsync($"/api/locations/{locationId}", new { name }, ct); [McpServerTool(Name = "delete_location")] [Description("Move a location to the trash. Whatever carried it is left alone — only the label goes. " + "It can be restored from the Trash page within the retention window.")] public static Task DeleteLocation( NovelApiClient api, [Description("The location's id.")] Guid locationId, CancellationToken ct) => api.DeleteAsync($"/api/locations/{locationId}", ct); }