@hanna84/mcp-writing 3.23.1 → 3.23.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +3 -3
- package/package.json +1 -1
- package/src/tools/metadata.js +10 -10
- package/src/tools/search.js +1 -1
- package/src/workflows/workflow-catalogue.js +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -4,9 +4,16 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v3.23.2](https://github.com/hannasdev/mcp-writing/compare/v3.23.1...v3.23.2)
|
|
8
|
+
|
|
9
|
+
- docs: clarify relationship workflow guidance [`#232`](https://github.com/hannasdev/mcp-writing/pull/232)
|
|
10
|
+
|
|
7
11
|
#### [v3.23.1](https://github.com/hannasdev/mcp-writing/compare/v3.23.0...v3.23.1)
|
|
8
12
|
|
|
13
|
+
> 30 May 2026
|
|
14
|
+
|
|
9
15
|
- fix: align relationship compatibility sync and audit [`#231`](https://github.com/hannasdev/mcp-writing/pull/231)
|
|
16
|
+
- Release 3.23.1 [`f0b643b`](https://github.com/hannasdev/mcp-writing/commit/f0b643bcb7b09adf066380d37718b09001dd3020)
|
|
10
17
|
|
|
11
18
|
#### [v3.23.0](https://github.com/hannasdev/mcp-writing/compare/v3.22.5...v3.23.0)
|
|
12
19
|
|
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ Instead of feeding an entire manuscript to an AI and hoping it fits in the conte
|
|
|
30
30
|
- **Core platform complete:** Metadata-first analysis, SQLite-canonical structural and relationship metadata, compatibility sidecar maintenance, AI-assisted prose editing with confirmation + git history, review bundles, and Scrivener Direct extraction are all implemented.
|
|
31
31
|
- **Recently completed:** Database Backup and Recovery added project backup export, freshness diagnostics, advisory operation history, automatic backup refresh after sanctioned project-scoped canonical mutations, dry-run restore planning, transactional restore application, and backup/restore operations guidance.
|
|
32
32
|
- **Previous milestone:** Docker, CI, and Deployment Workflow made Docker a supported way to build, run, smoke-test, and deploy Writing MCP.
|
|
33
|
-
- **Active development:**
|
|
33
|
+
- **Active development:** Relationship Metadata Boundary M3, aligning workflow and generated documentation around SQLite-canonical relationship authority.
|
|
34
34
|
- **Deferred backlog:** OpenClaw integration, client-agnostic setup, divisions, and embeddings search.
|
|
35
35
|
- **Ideas and open questions:** tracked separately so future exploration does not distort the active roadmap.
|
|
36
36
|
|
|
@@ -153,7 +153,7 @@ Outcome: subplot structure stays visible and auditable, which reduces dropped th
|
|
|
153
153
|
Goal: keep indexes accurate without manually re-tagging everything.
|
|
154
154
|
|
|
155
155
|
1. After rewriting scenes, call `enrich_scene` to re-derive lightweight metadata from current prose.
|
|
156
|
-
2. Use `update_scene_metadata` for intentional editorial fields (for example, beat, POV, status, and tags)
|
|
156
|
+
2. Use `update_scene_metadata` for intentional editorial fields (for example, beat, POV, status, and tags). It rejects scene `characters` and `places`; use `connect_character_place_evidence` when a scene proves paired sheet-backed character/place evidence, and keep one-sided scene links for a deliberately named relationship workflow. Use `audit_relationship_metadata` for retained sidecar/frontmatter relationship fields. Use `list_chapters` plus `assign_scene_to_chapter` or `move_scene` for chapter placement and ordering.
|
|
157
157
|
3. Use `search_metadata` and `find_scenes` to verify scenes are discoverable under the expected filters.
|
|
158
158
|
|
|
159
159
|
Outcome: your AI assistant can reliably find the right scenes without drifting from the manuscript.
|
|
@@ -179,7 +179,7 @@ Goal: rebuild scene-to-character links in a controlled way after imported prose
|
|
|
179
179
|
4. Re-run `enrich_scene_characters_batch` with `dry_run=false` once the preview looks correct.
|
|
180
180
|
5. If you want a destructive overwrite instead of additive merge behavior, use `replace_mode=replace` with `confirm_replace=true` deliberately.
|
|
181
181
|
|
|
182
|
-
Outcome: character-link maintenance becomes a preview-first
|
|
182
|
+
Outcome: character-link maintenance becomes a preview-first relationship repair operation instead of a one-off regex script or manual sidecar cleanup.
|
|
183
183
|
|
|
184
184
|
### 6) Post-upgrade recovery after legacy migration warnings
|
|
185
185
|
|
package/package.json
CHANGED
package/src/tools/metadata.js
CHANGED
|
@@ -121,7 +121,7 @@ function buildRelationshipMetadataBoundaryDetails({ projectId, sceneId, blockedF
|
|
|
121
121
|
boundary: "scene_relationship_metadata",
|
|
122
122
|
relationship_tools: ["connect_character_place_evidence", "audit_relationship_metadata"],
|
|
123
123
|
discovery_workflows: ["describe_workflows", "find_scenes", "list_characters", "list_places"],
|
|
124
|
-
next_step: "Use find_scenes, list_characters, and list_places to identify stable IDs. Use connect_character_place_evidence
|
|
124
|
+
next_step: "Use find_scenes, list_characters, and list_places to identify stable IDs. Use connect_character_place_evidence when the scene proves paired sheet-backed character/place evidence; use audit_relationship_metadata to review legacy sidecar/frontmatter relationship fields. Independent character-only or place-only scene links remain valid, but are not changed through update_scene_metadata.",
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -1120,7 +1120,7 @@ export function registerMetadataTools(s, {
|
|
|
1120
1120
|
project_id: scene.project_id,
|
|
1121
1121
|
compatibility: compatibilityRelationships,
|
|
1122
1122
|
canonical: canonicalRelationships,
|
|
1123
|
-
next_step: "Treat SQLite relationship rows as canonical. Use find_scenes, list_characters, and list_places to inspect stable IDs; use connect_character_place_evidence
|
|
1123
|
+
next_step: "Treat SQLite relationship rows as canonical. Use find_scenes, list_characters, and list_places to inspect stable IDs; use connect_character_place_evidence when evidence is paired, and leave independent character-only/place-only repairs to a deliberately named future workflow.",
|
|
1124
1124
|
});
|
|
1125
1125
|
}
|
|
1126
1126
|
}
|
|
@@ -1213,7 +1213,7 @@ export function registerMetadataTools(s, {
|
|
|
1213
1213
|
compatibility_note_count: diagnostics.filter(diagnostic => diagnostic.severity === "info").length,
|
|
1214
1214
|
},
|
|
1215
1215
|
next_steps: [
|
|
1216
|
-
"Use connect_character_place_evidence
|
|
1216
|
+
"Use connect_character_place_evidence when scene-backed character/place evidence is paired; independent one-sided links remain valid but need a deliberately named workflow.",
|
|
1217
1217
|
"Use record_character_relationship_beat for relationship arcs between characters.",
|
|
1218
1218
|
"Use link_reference_evidence for explicit reference evidence.",
|
|
1219
1219
|
"Use export_project_backup when a fresh recovery snapshot is needed.",
|
|
@@ -1440,7 +1440,7 @@ export function registerMetadataTools(s, {
|
|
|
1440
1440
|
// ---- connect_character_place_evidence ------------------------------------
|
|
1441
1441
|
s.tool(
|
|
1442
1442
|
"connect_character_place_evidence",
|
|
1443
|
-
"Connect a character and place as scene-backed story evidence. This
|
|
1443
|
+
"Connect a character and place as paired scene-backed story evidence. This outcome-level workflow covers sheet-backed character/place associations: SQLite scene relationship indexes commit first, project backups refresh after commit, and scene sidecar characters/places are refreshed only as generated compatibility output. Independent character-only or place-only scene links remain valid, but are not handled by update_scene_metadata and need a deliberately named workflow if promoted later.",
|
|
1444
1444
|
{
|
|
1445
1445
|
project_id: z.string().describe("Project the scene belongs to (e.g. 'the-lamb')."),
|
|
1446
1446
|
scene_id: z.string().describe("Scene that provides the evidence for this character/place association."),
|
|
@@ -1470,7 +1470,7 @@ export function registerMetadataTools(s, {
|
|
|
1470
1470
|
// ---- audit_relationship_metadata -----------------------------------------
|
|
1471
1471
|
s.tool(
|
|
1472
1472
|
"audit_relationship_metadata",
|
|
1473
|
-
"Review relationship metadata authority, stale indexes,
|
|
1473
|
+
"Review relationship metadata authority, stale indexes, retained compatibility notes, and scene character/place sidecar drift without mutating SQLite or files. Use this before repair work when character/place associations, sidecar tags, scene threads, or recovery readiness look stale or ambiguous.",
|
|
1474
1474
|
{
|
|
1475
1475
|
project_id: z.string().optional().describe("Optional project scope for the audit."),
|
|
1476
1476
|
},
|
|
@@ -2344,7 +2344,7 @@ export function registerMetadataTools(s, {
|
|
|
2344
2344
|
// ---- update_scene_metadata -----------------------------------------------
|
|
2345
2345
|
s.tool(
|
|
2346
2346
|
"update_scene_metadata",
|
|
2347
|
-
"Update one or more non-structural, non-relationship metadata fields for a scene. Writes only supplied allowed fields to the .meta.yaml sidecar and preserves existing structural compatibility fields; it never modifies prose, mirrors path-derived structure, or changes scene character/place relationship authority. Structural fields (part, chapter, chapter_id, chapter_title, timeline_position) are rejected here; use list_chapters plus assign_scene_to_chapter, move_scene, rename_chapter, or reorder_chapter for structure changes. Relationship fields (characters, places) are rejected here; use discovery workflows plus connect_character_place_evidence
|
|
2347
|
+
"Update one or more non-structural, non-relationship metadata fields for a scene. Writes only supplied allowed fields to the .meta.yaml sidecar and preserves existing structural compatibility fields; it never modifies prose, mirrors path-derived structure, or changes scene character/place relationship authority. Structural fields (part, chapter, chapter_id, chapter_title, timeline_position) are rejected here; use list_chapters plus assign_scene_to_chapter, move_scene, rename_chapter, or reorder_chapter for structure changes. Relationship fields (characters, places) are rejected here; use discovery workflows plus connect_character_place_evidence when evidence is paired, and audit_relationship_metadata for legacy sidecar/frontmatter relationship review. Independent character-only or place-only scene links remain valid, but are intentionally not changed through this generic metadata tool. Allowed changes are immediately reflected in the index. Only available when the sync dir is writable.",
|
|
2348
2348
|
{
|
|
2349
2349
|
scene_id: z.string().describe("The scene_id to update (e.g. 'sc-011-sebastian')."),
|
|
2350
2350
|
project_id: z.string().describe("Project the scene belongs to (e.g. 'the-lamb')."),
|
|
@@ -2361,8 +2361,8 @@ export function registerMetadataTools(s, {
|
|
|
2361
2361
|
timeline_position: z.number().int().optional().describe("Rejected by update_scene_metadata. Use move_scene for ordering changes."),
|
|
2362
2362
|
story_time: z.string().optional(),
|
|
2363
2363
|
tags: z.array(z.string()).optional(),
|
|
2364
|
-
characters: z.array(z.string()).optional().describe("Rejected by update_scene_metadata. Use find_scenes, list_characters, list_places, connect_character_place_evidence
|
|
2365
|
-
places: z.array(z.string()).optional().describe("Rejected by update_scene_metadata. Use find_scenes, list_characters, list_places, connect_character_place_evidence
|
|
2364
|
+
characters: z.array(z.string()).optional().describe("Rejected by update_scene_metadata. Use find_scenes, list_characters, list_places, connect_character_place_evidence when evidence is paired, and audit_relationship_metadata for compatibility review; independent character-only evidence remains valid but needs a deliberately named workflow."),
|
|
2365
|
+
places: z.array(z.string()).optional().describe("Rejected by update_scene_metadata. Use find_scenes, list_characters, list_places, connect_character_place_evidence when evidence is paired, and audit_relationship_metadata for compatibility review; independent place-only evidence remains valid but needs a deliberately named workflow."),
|
|
2366
2366
|
}).describe("Fields to update. Only supplied keys are changed."),
|
|
2367
2367
|
},
|
|
2368
2368
|
async ({ scene_id, project_id, fields }) => {
|
|
@@ -2607,7 +2607,7 @@ export function registerMetadataTools(s, {
|
|
|
2607
2607
|
// ---- update_place_sheet --------------------------------------------------
|
|
2608
2608
|
s.tool(
|
|
2609
2609
|
"update_place_sheet",
|
|
2610
|
-
"Update canonical place profile fields and retained compatibility notes. The place name commits to SQLite first and refreshes project backups; associated_characters and tags are compatibility/review metadata only.
|
|
2610
|
+
"Update canonical place profile fields and retained compatibility notes. The place name commits to SQLite first and refreshes project backups; associated_characters and tags are compatibility/review metadata only. Use connect_character_place_evidence when scene-backed character/place evidence is paired; independent place-only links remain valid but need a deliberately named workflow.",
|
|
2611
2611
|
{
|
|
2612
2612
|
place_id: z.string().describe("The place_id to update (e.g. 'place-harbor-district'). Use list_places to find valid IDs."),
|
|
2613
2613
|
fields: z.object({
|
|
@@ -2716,7 +2716,7 @@ export function registerMetadataTools(s, {
|
|
|
2716
2716
|
}),
|
|
2717
2717
|
non_canonical_fields: ["associated_characters", "tags"].filter(field => Object.hasOwn(fields, field)),
|
|
2718
2718
|
next_step: Object.hasOwn(fields, "associated_characters")
|
|
2719
|
-
? "Use connect_character_place_evidence
|
|
2719
|
+
? "Use connect_character_place_evidence when paired scene-backed character/place evidence should become authoritative; independent one-sided links remain valid but need a deliberately named workflow."
|
|
2720
2720
|
: undefined,
|
|
2721
2721
|
...backupMutationFields(backupResult),
|
|
2722
2722
|
});
|
package/src/tools/search.js
CHANGED
|
@@ -609,7 +609,7 @@ export function registerSearchTools(s, {
|
|
|
609
609
|
// ---- get_place_sheet -----------------------------------------------------
|
|
610
610
|
s.tool(
|
|
611
611
|
"get_place_sheet",
|
|
612
|
-
"Get full place details, including canonical sheet content plus retained sidecar associated_characters and tags as compatibility/review notes. Use connect_character_place_evidence
|
|
612
|
+
"Get full place details, including canonical sheet content plus retained sidecar associated_characters and tags as compatibility/review notes. Use connect_character_place_evidence when scene-backed character/place evidence is paired; independent place-only links remain valid and need an explicit relationship workflow rather than a place-sheet read. Response shape note: returns a structured envelope (`results`, `total_count`) with one result row.",
|
|
613
613
|
{
|
|
614
614
|
place_id: z.string().describe("The place_id to look up (e.g. 'place-harbor-district'). Use list_places to find valid IDs."),
|
|
615
615
|
},
|
|
@@ -68,12 +68,12 @@ export const WORKFLOW_CATALOGUE = [
|
|
|
68
68
|
label: "Track and repair story relationships",
|
|
69
69
|
use_when: "Use when the user wants to track an arc, link evidence, review stale relationships, repair metadata parity, or prepare generated recovery material for relationship metadata.",
|
|
70
70
|
steps: [
|
|
71
|
-
{ tool: "find_scenes", note: "Identify scene_id and project_id from story context before recording relationships." },
|
|
71
|
+
{ tool: "find_scenes", note: "Identify scene_id and project_id from story context before recording relationships; use list_characters and list_places when stable entity IDs need disambiguation." },
|
|
72
72
|
{ tool: "track_thread_arc", note: "Use when a scene should carry a storyline, subplot, setup, escalation, reveal, reversal, payoff, or other thread beat." },
|
|
73
|
-
{ tool: "connect_character_place_evidence", note: "Use when a scene proves
|
|
73
|
+
{ tool: "connect_character_place_evidence", note: "Use when a scene proves paired sheet-backed character/place evidence; SQLite scene relationship indexes commit first and sidecar characters/places remain generated compatibility output. Independent character-only or place-only scene links remain valid, but need a deliberately named future workflow for daily repair." },
|
|
74
74
|
{ tool: "record_character_relationship_beat", note: "Use when a scene proves a relationship beat between two characters without exposing the character_relationships table." },
|
|
75
75
|
{ tool: "link_reference_evidence", note: "Use when scene, character, place, or reference evidence should point to a reference document; SQLite commits first and compatibility output is generated transparency." },
|
|
76
|
-
{ tool: "audit_relationship_metadata", note: "Use before repair work to review stale relationship indexes
|
|
76
|
+
{ tool: "audit_relationship_metadata", note: "Use before repair work to review stale relationship indexes, retained sidecar/frontmatter characters or places, and compatibility drift without mutating canonical state." },
|
|
77
77
|
{ tool: "suggest_scene_references", note: "Use preview first to review candidate scene-reference links from character/place evidence; use apply only after the relationship outcome is intended." },
|
|
78
78
|
{ tool: "enrich_scene_characters_batch", note: "Use dry_run first when prose-derived character relationship parity needs repair across multiple scenes; apply mode syncs SQLite after compatibility output and refreshes backups for changed scenes." },
|
|
79
79
|
{ tool: "diagnose_project_backups", note: "Relationship mutation tools refresh project backups after canonical commits; run this if backup_warnings were returned or recovery readiness matters." },
|
|
@@ -101,9 +101,9 @@ export const WORKFLOW_CATALOGUE = [
|
|
|
101
101
|
steps: [
|
|
102
102
|
{ tool: "sync", note: "Refresh SQLite indexes from current compatibility inputs, then review warnings instead of patching sidecars as the first repair step." },
|
|
103
103
|
{ tool: "diagnose_structure", note: "Use when sidecar, frontmatter, folder, chapter, epigraph, or generated-export structure appears to disagree with SQLite canonical state." },
|
|
104
|
-
{ tool: "audit_relationship_metadata", note: "Use when sidecar threads, tags, flags, associated_characters, characters, places, or reference aliases need authority classification before repair." },
|
|
104
|
+
{ tool: "audit_relationship_metadata", note: "Use when sidecar threads, tags, flags, associated_characters, characters, places, or reference aliases need authority classification before repair; relationship fields are compatibility input/review evidence, not generic metadata writes." },
|
|
105
105
|
{ tool: "track_thread_arc", note: "Use for current thread authority instead of editing sidecar threads." },
|
|
106
|
-
{ tool: "connect_character_place_evidence", note: "Use for
|
|
106
|
+
{ tool: "connect_character_place_evidence", note: "Use for paired scene-backed character/place evidence instead of editing sidecar relationship lists or sending characters/places through update_scene_metadata; independent one-sided links remain valid but are outside this generic metadata path." },
|
|
107
107
|
{ tool: "link_reference_evidence", note: "Use for current reference-link authority instead of editing sidecar/frontmatter aliases." },
|
|
108
108
|
{ tool: "export_project_backup", note: "Generate a recovery snapshot from SQLite canonical state after meaningful canonical migration or repair work; editing backup artifacts does not mutate current state." },
|
|
109
109
|
],
|