{"id":48976143,"url":"https://github.com/hannasdev/mcp-writing","last_synced_at":"2026-06-07T12:03:38.171Z","repository":{"id":350869521,"uuid":"1208578313","full_name":"hannasdev/mcp-writing","owner":"hannasdev","description":"MCP service for AI-assisted reasoning and editing on long-form fiction projects","archived":false,"fork":false,"pushed_at":"2026-04-26T09:00:12.000Z","size":622,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-26T09:32:59.159Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hannasdev.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":"MAINTAINERS.md","copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-04-12T13:30:33.000Z","updated_at":"2026-04-26T09:00:16.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/hannasdev/mcp-writing","commit_stats":null,"previous_names":["hannasdev/mcp-writing"],"tags_count":94,"template":false,"template_full_name":null,"purl":"pkg:github/hannasdev/mcp-writing","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hannasdev%2Fmcp-writing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hannasdev%2Fmcp-writing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hannasdev%2Fmcp-writing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hannasdev%2Fmcp-writing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hannasdev","download_url":"https://codeload.github.com/hannasdev/mcp-writing/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hannasdev%2Fmcp-writing/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32560977,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-18T09:06:13.849Z","updated_at":"2026-06-07T12:03:38.140Z","avatar_url":"https://github.com/hannasdev.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mcp-writing\n\n[![CI](https://github.com/hannasdev/mcp-writing/actions/workflows/ci.yml/badge.svg)](https://github.com/hannasdev/mcp-writing/actions/workflows/ci.yml) [![GitHub release](https://img.shields.io/github/v/release/hannasdev/mcp-writing)](https://github.com/hannasdev/mcp-writing/releases) [![npm version](https://img.shields.io/npm/v/%40hanna84%2Fmcp-writing)](https://www.npmjs.com/package/@hanna84/mcp-writing) [![npm downloads](https://img.shields.io/npm/dm/%40hanna84%2Fmcp-writing)](https://www.npmjs.com/package/@hanna84/mcp-writing) [![Node.js](https://img.shields.io/badge/node-%3E%3D22.13.0-339933?logo=node.js\u0026logoColor=white)](https://nodejs.org/) [![License: AGPL v3](https://img.shields.io/badge/License-AGPL--v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)\n\nAn MCP service for AI-assisted reasoning and editing on long-form fiction projects.\n\nDesigned to work with [OpenClaw](https://github.com/openclaw/openclaw) but compatible with any MCP-capable AI gateway.\n\n## Quick launch\n\nFor local stdio MCP clients, run the published package directly:\n\n```sh\nWRITING_SYNC_DIR=/path/to/sync-dir DB_PATH=./writing.db npx -y @hanna84/mcp-writing\n```\n\nThe CLI wrapper defaults to stdio transport and adds the Node 22 SQLite flag automatically when needed.\n\n## VS Code extension\n\nFor VS Code-native setup flows (including prose styleguide setup), use:\n\n- [hannasdev/mcp-writing-vscode](https://github.com/hannasdev/mcp-writing-vscode)\n\n## What it does\n\nInstead of feeding an entire manuscript to an AI and hoping it fits in the context window, `mcp-writing` builds a structured index from your scene files. The AI queries that index first — finding relevant characters, beats, and loglines — then loads only the specific prose it needs.\n\n**Current status:**\n- **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.\n- **Recently completed:** Relationship Metadata Boundary closed the sidecar-first scene relationship mutation path, added SQLite-first paired and one-sided evidence workflows, and preserved legacy sidecar/frontmatter compatibility for sync and import.\n- **Active development:** No initiative is currently selected.\n- **Deferred backlog:** OpenClaw integration, client-agnostic setup, divisions, and embeddings search.\n- **Ideas and open questions:** tracked separately so future exploration does not distort the active roadmap.\n\n## Who it is for\n\n- Novelists and writing teams working on long manuscripts with many scenes, characters, and continuity constraints.\n- AI-assisted editing workflows where you want targeted context retrieval instead of full-manuscript prompting.\n- Projects that need traceable, reversible edits with metadata that stays synchronized as drafts evolve.\n\n## Documentation\n\n| Guide | Description |\n|---|---|\n| [docs/guides/setup.md](docs/guides/setup.md) | Prerequisites, first-time setup, Scrivener import, native sync format |\n| [mcp-writing-vscode](https://github.com/hannasdev/mcp-writing-vscode) | VS Code extension for client-native setup flows |\n| [docs/guides/docker.md](docs/guides/docker.md) | Docker Compose, deployment operations, MCP gateway notes |\n| [docs/guides/backup-recovery.md](docs/guides/backup-recovery.md) | Project backup artifacts, diagnostics, and explicit restore workflow |\n| [docs/guides/sidecar-compatibility.md](docs/guides/sidecar-compatibility.md) | Sidecar compatibility roles, migration posture, and daily-work authority boundaries |\n| [docs/foundations/managed-structure-contract.md](docs/foundations/managed-structure-contract.md) | Design boundaries for structural mutation, generated views, import, and maintenance workflows |\n| [docs/agents/tools.md](docs/agents/tools.md) | Full tool reference — auto-generated from source |\n| [docs/agents/README.md](docs/agents/README.md) | Index of agent-focused guidance, examples, and boot files |\n| [docs/agents/use-cases.md](docs/agents/use-cases.md) | Agent-oriented transcripts and prompt/tooling examples |\n| [docs/guides/development.md](docs/guides/development.md) | Running locally, tests, environment variables, troubleshooting |\n\n## Breaking changes\n\n### `describe_workflows` surface redesign\n\n`describe_workflows` now exposes an outcome-first, discovery-first workflow map. This was a breaking change if your prompts or automation depend on previous workflow IDs or ordering; the newer `recommended_next_actions` tier is additive and appears before the full catalogue.\n\nUpdate integrations using this mapping:\n\n- `manuscript_exploration` -\u003e `question_driven_discovery` (or `targeted_scene_reading` when the task is prose inspection)\n- `prose_editing` -\u003e `safe_scene_revision`\n- `character_management` -\u003e `character_understanding`\n- `place_management` -\u003e `place_understanding`\n- `review_bundle` -\u003e `review_preparation`\n\nNew workflow IDs added:\n\n- `thread_understanding`\n- `parity_recovery`\n\nStyleguide workflows are still available, but no longer positioned as part of the primary daily workflow surface.\n\n### `find_scenes` and `get_arc` response-shape standardization\n\n`find_scenes` and `get_arc` now always return structured envelopes, including non-paginated calls.\n\n- Envelope fields: `results`, `total_count`.\n- Pagination fields are included when paging is active.\n- `warning` / `next_step` are included when relevant.\n\nIf your integration previously handled raw arrays for non-paginated calls, update it to parse envelopes consistently.\n\nSafe parsing pattern:\n\n```js\nconst parsed = JSON.parse(toolText);\nif (parsed.ok === false) throw new Error(parsed.error?.message ?? \"tool error\");\nconst scenes = parsed.results ?? [];\nconst totalCount = parsed.total_count ?? scenes.length;\nconst warning = parsed.warning ?? null;\nconst nextStep = parsed.next_step ?? null;\n```\n\n### `get_character_sheet`, `get_place_sheet`, `list_scene_references`, `get_relationship_arc` response-shape standardization\n\nThese metadata-read tools now return structured envelopes instead of flat objects or raw arrays.\n\n- `get_character_sheet` and `get_place_sheet`: previously returned a flat object of field values; now return `{ results: [row], total_count: 1, next_step }`.\n- `list_scene_references`: previously returned `{ references, scene_id, project_id }`; now returns `{ results, total_count, scene_id, project_id }`.\n- `get_relationship_arc`: previously returned a raw JSON array; now returns `{ results, total_count, from_character, to_character }`.\n\nSafe parsing pattern for sheet tools:\n\n```js\nconst parsed = JSON.parse(toolText);\nif (parsed.ok === false) throw new Error(parsed.error?.message ?? \"tool error\");\nconst sheet = parsed.results?.[0] ?? {};\nconst nextStep = parsed.next_step ?? null;\n```\n\nSafe parsing pattern for list/arc tools:\n\n```js\nconst parsed = JSON.parse(toolText);\nif (parsed.ok === false) throw new Error(parsed.error?.message ?? \"tool error\");\nconst items = parsed.results ?? [];\nconst totalCount = parsed.total_count ?? items.length;\n```\n\n## Usage scenarios\n\n### 1) Continuity pass before sending chapters to beta readers\n\nGoal: catch inconsistencies before sharing pages.\n\n1. Run `sync` after your latest writing session.\n2. Ask `find_scenes` for scenes involving a specific character or tag (for example, all scenes tagged `injury` or `promise`).\n3. Use `get_arc` to review that character's ordered progression across the manuscript.\n4. Load only the suspect scenes with `get_scene_prose`.\n5. Attach follow-up notes with `flag_scene` where continuity needs a fix.\n\nOutcome: you review one narrative thread at a time instead of rereading the entire novel to find contradictions.\n\n### 2) Planning and tracking subplot beats during revisions\n\nGoal: make sure subplot threads progress intentionally and resolve on time.\n\n1. Run `list_threads` for the project.\n2. Use `get_thread_arc` to inspect scene order and beat labels for each thread.\n3. When a beat is missing, call `track_thread_arc` to add or update it on the right scene.\n4. Re-run `get_thread_arc` to confirm pacing and coverage.\n\nOutcome: subplot structure stays visible and auditable, which reduces dropped threads in late drafts.\n\n### 3) Tightening scene metadata after heavy prose edits\n\nGoal: keep indexes accurate without manually re-tagging everything.\n\n1. After rewriting scenes, call `enrich_scene` to re-derive lightweight metadata from current prose.\n2. 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, `connect_scene_character_evidence` for character-only evidence, and `connect_scene_place_evidence` for place-only evidence. Those relationship evidence tools prefer canonical IDs but also accept unambiguous scene titles, character names, place names, and case variants; ambiguous or suggested-only matches fail without mutating state. 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.\n3. Use `search_metadata` for keyword/FTS metadata searches across indexed titles, loglines, tags, characters, places, and versions, and use `find_scenes` to verify scenes are discoverable under structured filters. After identifying likely scenes, use `get_scene_prose` for prose context.\n\nOutcome: your AI assistant can reliably find the right scenes without drifting from the manuscript.\n\n### 4) Safe AI-assisted line edits with rollback\n\nGoal: let AI propose prose edits without losing control of your draft.\n\n1. Ask the AI to call `propose_edit` for a specific scene.\n2. Review the staged diff.\n3. Accept with `commit_edit` or reject with `discard_edit`.\n4. Use `list_snapshots` (and optional `snapshot_scene`) to inspect or preserve revision history.\n\nOutcome: you get AI speed with explicit approval and recoverable history for every applied change.\n\n### 5) Refreshing scene-character links after imports or major rewrites\n\nGoal: rebuild scene-to-character links in a controlled way after imported prose changes or metadata drift.\n\n1. Start with `enrich_scene_characters_batch` using the default `dry_run=true` to preview inferred links for a project, chapter, or explicit scene list.\n2. Poll `get_async_job_status` until the batch job completes, then review `job.result.results` for changed scenes, ambiguous matches, and partial failures.\n3. Spot-check a few affected scenes with `get_scene_prose` if the changes touch important continuity or cast-heavy chapters.\n4. Re-run `enrich_scene_characters_batch` with `dry_run=false` once the preview looks correct.\n5. If you want a destructive overwrite instead of additive merge behavior, use `replace_mode=replace` with `confirm_replace=true` deliberately.\n\nOutcome: character-link maintenance becomes a preview-first relationship repair operation instead of a one-off regex script or manual sidecar cleanup.\n\n### 6) Post-upgrade recovery after legacy migration warnings\n\nGoal: recover index confidence quickly when legacy upgrade warnings indicate ambiguous rows were skipped.\n\n1. Start by checking `get_runtime_config` (or `describe_workflows`) and confirm whether `db_migration_warnings` contains `LEGACY_JOIN_ROWS_SKIPPED`.\n2. If present, run `sync` immediately to rebuild scene relationships from compatibility sidecars and prose metadata.\n3. Continue normal discovery (`find_scenes`, `get_arc`, `get_thread_arc`) and watch for stale-metadata warnings.\n4. When you touch stale scenes, run `enrich_scene(scene_id, project_id)` to recover metadata parity incrementally.\n5. If many scenes remain stale, switch to `enrich_scene_characters_batch` (dry-run first) for broader catch-up.\n\nOutcome: upgrade-related data loss risk becomes an explicit, operator-visible recovery workflow instead of a silent state mismatch.\n\n## License\nAGPL-3.0-only\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhannasdev%2Fmcp-writing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhannasdev%2Fmcp-writing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhannasdev%2Fmcp-writing/lists"}