using System.ComponentModel; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; namespace Novelly.Mcp.Tools; [McpServerToolType] public static class NovelTools { [McpServerTool(Name = "list_novels")] [Description("List every novel, with counts of characters, chapters and drafted words. " + "Start here to find the novel id everything else needs.")] public static Task ListNovels(NovelApiClient api, CancellationToken ct) => api.GetAsync("/api/novels", ct); [McpServerTool(Name = "get_novel_brief")] [Description("Read a novel's title, author, genre, logline, synopsis, notes and word-count target.")] public static Task GetNovel( NovelApiClient api, [Description("The novel's id.")] Guid novelId, CancellationToken ct) => api.GetAsync($"/api/novels/{novelId}", ct); [McpServerTool(Name = "create_novel")] [Description("Create a new novel.")] public static Task CreateNovel( NovelApiClient api, [Description("Working title.")] string title, CancellationToken ct, [Description("Author name.")] string? author = null, [Description("Genre or category.")] string? genre = null, [Description("One-sentence pitch.")] string? logline = null, [Description("Paragraph-length summary of the whole book.")] string? synopsis = null, [Description("Free-form notes on theme, tone, comparable titles.")] string? notes = null, [Description("Target manuscript length in words.")] int? targetWordCount = null) => api.PostAsync("/api/novels", new { title, author, genre, logline, synopsis, notes, targetWordCount }, ct); [McpServerTool(Name = "update_novel_brief")] [Description("Revise a novel's top-level fields. Only the fields you supply change; " + "pass an empty string to clear one.")] public static Task UpdateNovel( NovelApiClient api, [Description("The novel's id.")] Guid novelId, CancellationToken ct, [Description("New title.")] string? title = null, [Description("Author name.")] string? author = null, [Description("Genre or category.")] string? genre = null, [Description("One-sentence pitch.")] string? logline = null, [Description("Paragraph-length summary of the whole book.")] string? synopsis = null, [Description("Free-form notes on theme, tone, comparable titles.")] string? notes = null, [Description("Target manuscript length in words.")] int? targetWordCount = null) => api.PatchAsync($"/api/novels/{novelId}", new { title, author, genre, logline, synopsis, notes, targetWordCount }, ct); }