scrivener-mcp
A local MCP server that exposes your Scrivener projects to Claude (or any MCP-compatible client). Create new projects from scratch, navigate the binder, read and write document content, and update metadata — all without opening Scrivener.
Requirements
- Node.js 18 or later
- Scrivener 3 on macOS (
.scrivpackages)
Setup
cd scrivener-mcp
npm install
Environment variables
| Variable | Description |
|---|---|
SCRIV_DIR |
Path to a directory containing .scriv packages. Enables list_projects, open_project, and create_project. |
SCRIV_PATH |
Path to a single .scriv package. Opens it immediately on startup. |
SCRIV_PLATFORM |
mac (default) or windows. Controls the RTF format used when writing document content. |
At least one of SCRIV_DIR or SCRIV_PATH must be set. Both can be set simultaneously.
Running manually
# Multi-project mode (recommended)
SCRIV_DIR="/path/to/ScrivenerProjects" npm start
# Single-project mode
SCRIV_PATH="/path/to/MyProject.scriv" npm start
Configuring Claude Desktop
Edit the Claude Desktop config file:
- Mac:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Mac:
{
"mcpServers": {
"scrivener": {
"command": "node",
"args": ["/absolute/path/to/scrivener-mcp/src/index.js"],
"env": {
"SCRIV_DIR": "/Users/you/Writing/ScrivenerProjects"
}
}
}
}
Windows:
{
"mcpServers": {
"scrivener": {
"command": "node",
"args": ["C:\\path\\to\\scrivener-mcp\\src\\index.js"],
"env": {
"SCRIV_DIR": "C:\\Users\\you\\Documents\\ScrivenerProjects",
"SCRIV_PLATFORM": "windows"
}
}
}
}
Restart Claude Desktop after saving.
Available tools
Project management
| Tool | Description |
|---|---|
list_projects |
Lists all .scriv packages in SCRIV_DIR. |
open_project(name) |
Opens a project by name, making it active for all document tools. |
create_project(name, ...) |
Creates a new project and opens it. See below. |
Document tools (require an open project)
| Tool | Description |
|---|---|
get_outline |
Returns the full binder as a nested tree with synopses, labels, and statuses. The best starting point for understanding and working on a project's structure. |
list_documents |
Returns the binder as a flat list with depth indicators. Useful for getting UUIDs. |
get_document(uuid) |
Returns metadata and plain text content for a single document. |
add_document(...) |
Adds a new document or folder to the binder. |
move_document(uuid, newParentUuid) |
Moves a binder item to a different parent folder. |
write_document(uuid, content) |
Writes new plain text content to a document (stored as RTF). |
update_metadata(uuid, changes) |
Updates title, synopsis, label, status, or compile inclusion. |
search_documents(query) |
Searches titles and synopses across the binder. |
Creating a project
create_project accepts a full binder structure so Claude can scaffold an entire project from an idea in one call.
Parameters
| Parameter | Type | Description |
|---|---|---|
name |
string | Project name (becomes the .scriv package name). |
labels |
array | Label definitions. Each is a string or {name, color}. Colors: red, orange, yellow, green, blue, purple, pink, cyan. |
statuses |
array | Status names. Defaults to: To Do, In Progress, First Draft, Revised Draft, Done. |
manuscript |
array | Binder items in the Draft (Manuscript) folder. |
research |
array | Binder items in the Research folder. |
Binder item structure
{
"title": "Chapter 1",
"type": "Folder",
"synopsis": "Alice finds the letter and confronts Bob.",
"content": "Optional initial body text (Text items only).",
"label": "POV: Alice",
"status": "To Do",
"includeInCompile": true,
"children": [...]
}
type:"Folder"for containers (acts, parts, chapters);"Text"for documents (scenes, notes). Defaults to"Text".synopsis: The virtual index card text — appears in Scrivener's corkboard and outliner views. Write a 1–3 sentence summary of what happens or what this item covers.labelandstatusmust match names defined in the project'slabelsandstatusesarrays.
Example
{
"name": "My Novel",
"labels": [
{ "name": "POV: Alice", "color": "blue" },
{ "name": "POV: Bob", "color": "red" }
],
"statuses": ["To Do", "First Draft", "Revised", "Done"],
"manuscript": [
{
"title": "Act One",
"type": "Folder",
"synopsis": "Alice discovers the conspiracy.",
"children": [
{
"title": "Chapter 1",
"type": "Folder",
"synopsis": "A normal Tuesday turns strange.",
"children": [
{
"title": "The Letter",
"type": "Text",
"synopsis": "Alice finds an unsigned letter in her mailbox.",
"label": "POV: Alice",
"status": "To Do"
}
]
}
]
}
],
"research": [
{
"title": "Characters",
"type": "Folder",
"children": [
{
"title": "Alice",
"type": "Text",
"synopsis": "Protagonist. Mid-30s journalist, sceptical but curious."
}
]
}
]
}
Collaborative workflow
The intended pattern is to work with Claude on the structure and content of a project together, using Scrivener's own organisational features:
- Start with
get_outline— Claude reads the full nested structure with synopses before suggesting or making any changes. This is how it understands the story shape. - Build structure with
add_document— Add scenes, chapters, acts, or research notes at any point in the hierarchy. Always include a synopsis; it is what appears on the index card in Scrivener's corkboard. - Reorganise with
move_document— Move items between parents to restructure the narrative without losing any content or metadata. - Write prose with
write_document— Once structure is agreed, populate scenes with content. - Track progress with
update_metadata— Update labels (e.g. POV, scene type) and statuses (e.g. First Draft, Revised) as work progresses.
Notes
- Close Scrivener before writing.
write_document,update_metadata,add_document, andmove_documentall modify project files directly. If Scrivener has the project open, it will overwrite changes on its next auto-save. - Reload after editing in Scrivener. Call
open_projectagain to reload a project that was modified in Scrivener while the server was running. write_documentgenerates minimal RTF compatible with Scrivener 3. Non-ASCII characters are Unicode-escaped.- Label and status IDs are discoverable via
list_documents—labelId/statusIdare raw IDs,label/statusare the resolved names.