Replace chapter setting with multi-select locations; add chapter character summary
Chapters now carry many Locations (new Tags-style entity with cross-referencing) instead of a single free-text Setting field, with a Locations tab on the novel for browsing them and seeing every chapter set at each one. Also surfaces the distinct characters appearing in a chapter's beats, linked, under the beat/word count on the outline tab.
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
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<CallToolResult> 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<CallToolResult> 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<CallToolResult> 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<CallToolResult> 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("Delete a location. Whatever carried it is left alone — only the label goes.")]
|
||||
public static Task<CallToolResult> DeleteLocation(
|
||||
NovelApiClient api,
|
||||
[Description("The location's id.")] Guid locationId,
|
||||
CancellationToken ct) =>
|
||||
api.DeleteAsync($"/api/locations/{locationId}", ct);
|
||||
}
|
||||
Reference in New Issue
Block a user