Drop the Scene entity/grouping in favor of chapters carrying prose directly and beats belonging to many characters. Add markdown editor + character multi-select components to the web client. Remove all XML doc and inline comments across the touched C#/TS/CSS files in favor of self-documenting names, and record that convention in CLAUDE.md. Add .mcp.json (local MCP server config, no secrets) and ignore .idea/.
75 lines
3.8 KiB
C#
75 lines
3.8 KiB
C#
using System.ComponentModel;
|
|
using ModelContextProtocol.Protocol;
|
|
using ModelContextProtocol.Server;
|
|
|
|
namespace Novelly.Mcp.Tools;
|
|
|
|
[McpServerToolType]
|
|
public static class ManuscriptTools
|
|
{
|
|
[McpServerTool(Name = "list_chapters")]
|
|
[Description("List a project's chapters in manuscript order, with beat and word counts.")]
|
|
public static Task<CallToolResult> ListChapters(
|
|
NovelApiClient api,
|
|
[Description("The project's id.")] Guid projectId,
|
|
CancellationToken ct) =>
|
|
api.GetAsync($"/api/projects/{projectId}/chapters", ct);
|
|
|
|
[McpServerTool(Name = "get_chapter")]
|
|
[Description("Read one chapter in full: its outline (beats) and its drafted prose.")]
|
|
public static Task<CallToolResult> GetChapter(
|
|
NovelApiClient api,
|
|
[Description("The chapter's id.")] Guid chapterId,
|
|
CancellationToken ct) =>
|
|
api.GetAsync($"/api/chapters/{chapterId}", ct);
|
|
|
|
[McpServerTool(Name = "create_chapter")]
|
|
[Description("Add a chapter to a project. It goes at the end of the manuscript unless you supply a number.")]
|
|
public static Task<CallToolResult> CreateChapter(
|
|
NovelApiClient api,
|
|
[Description("The project's id.")] Guid projectId,
|
|
[Description("Chapter title.")] string title,
|
|
CancellationToken ct,
|
|
[Description("Position in the manuscript, 1-based.")] int? number = null,
|
|
[Description("The chapter's outline summary paragraph.")] string? summary = null,
|
|
[Description("Id of the point-of-view character.")] Guid? povCharacterId = null,
|
|
[Description("Where and when the chapter takes place.")] string? setting = null,
|
|
[Description("Planned, Outlined, Drafted, Revised or Final.")] string? status = null,
|
|
[Description("Target length in words.")] int? targetWordCount = null,
|
|
[Description("The chapter's drafted text, in markdown, if you are writing it now.")] string? prose = null,
|
|
[Description("Tags for cross-referencing. Unknown tags are created.")] string[]? tags = null) =>
|
|
api.PostAsync($"/api/projects/{projectId}/chapters", new
|
|
{
|
|
title,
|
|
number,
|
|
summary,
|
|
povCharacterId,
|
|
setting,
|
|
status = status ?? "Planned",
|
|
targetWordCount,
|
|
prose,
|
|
tags
|
|
}, ct);
|
|
|
|
[McpServerTool(Name = "update_chapter")]
|
|
[Description("Revise a chapter's title, number, summary, POV character, setting, notes, status "
|
|
+ "or drafted prose. Use 'prose' to write or replace the chapter's draft text in "
|
|
+ "markdown; the word count is recomputed automatically.")]
|
|
public static Task<CallToolResult> UpdateChapter(
|
|
NovelApiClient api,
|
|
[Description("The chapter's id.")] Guid chapterId,
|
|
CancellationToken ct,
|
|
[Description("New title.")] string? title = null,
|
|
[Description("Position in the manuscript.")] int? number = null,
|
|
[Description("The chapter's outline summary paragraph.")] string? summary = null,
|
|
[Description("Id of the point-of-view character.")] Guid? povCharacterId = null,
|
|
[Description("Where and when the chapter takes place.")] string? setting = null,
|
|
[Description("Anything else worth recording.")] string? notes = null,
|
|
[Description("Planned, Outlined, Drafted, Revised or Final.")] string? status = null,
|
|
[Description("Target length in words.")] int? targetWordCount = null,
|
|
[Description("The chapter's drafted text, in markdown.")] string? prose = null,
|
|
[Description("Tags for cross-referencing. Replaces the existing tags.")] string[]? tags = null) =>
|
|
api.PatchAsync($"/api/chapters/{chapterId}",
|
|
new { title, number, summary, povCharacterId, setting, notes, status, targetWordCount, prose, tags }, ct);
|
|
}
|