Skip to content
screenjson

Licensable

screenjson-server

The licensable ScreenJSON platform for collaborative agent editing. A REST API and an MCP server over a library of screenplays stored as JSON in MongoDB, Elasticsearch, PostgreSQL, Chroma, Weaviate or Pinecone, with S3 and Azure for files. Every scene and line is addressable; edits are ordered, validated and conflict-safe; work is shared out across many agents; every change streams live.

screenjson-server hero image
Repository private
Container ghcr.io/screenjson/screenjson-server

What it is

screenjson-server is a platform for editing and managing screenplays as data, at scale. It keeps a library of scripts as ScreenJSON in your own database, puts a REST API and an MCP server in front of it, and lets any number of people, programs and AI agents work on the same scripts at the same time without stepping on each other.

Think of it as collaborative editing for agents. Point ten Claude sessions, a translation service and two writers at the same library: each one reads and writes individual scenes and lines, every change is checked against the schema and against what the others did, and everyone sees every change as it lands.

Built for agents

The server speaks the Model Context Protocol at /mcp. One command gives Claude (or Cursor, or your own agent) the library as a set of tools:

claude mcp add --transport http screenjson http://127.0.0.1:8080/mcp \
  --header "Authorization: Bearer $TOKEN"
ToolWhat the agent can do
list_documents, searchFind scripts, scenes and lines by title, text or vector.
get_outline, read_sceneRead a script’s structure, then just the scenes it needs.
edit_element, insert_element, delete_nodeChange, add and remove individual lines.
insert_scene, edit_scene_heading, move_nodeRestructure: new scenes, new sluglines, reordering.
checkout, releaseHold a scene while working on it so no one else changes it.
import_screenjson, export_screenjson, run_export_jobBring scripts in; get them out as JSON, PDF, Final Draft, Fade In or Fountain.
get_script_settings, update_script_settingsWire up Git, S3 mirrors, webhooks and automatic exports.
api_requestAnything else the REST API does.

Agents work under the same rules as every other client: their own token, revision checks, schema validation. An agent can’t silently overwrite a writer’s change, and a writer watching the script sees the agent’s edits appear live.

An API for every line

Every part of every script has its own URL, and reading or writing it touches just that part:

/documents/{doc}                                        the whole script
/documents/{doc}/scenes/{scene}                         one scene
/documents/{doc}/scenes/{scene}/heading                 its slugline
/documents/{doc}/scenes/{scene}/elements/{type}/{el}    one line
/documents/{doc}/scenes/{scene}/elements/{type}/{el}/text/fr   that line in French
# Read a line and its revision
curl -si $S/documents/$DOC/scenes/$SCENE/elements/dialogue/$EL | grep -i etag
# ETag: "3"

# Change it, only if nobody else has since
curl -X PATCH $S/documents/$DOC/scenes/$SCENE/elements/dialogue/$EL \
     -H "Authorization: Bearer $T" -H 'If-Match: "3"' \
     -d '{"text": {"fr": "On a quatre-vingt-dix secondes."}}'

Characters, authors, notes, bookmarks, revisions, tags, embeddings and the title page all have routes too: around 130 in all, documented in a built-in API explorer at /swagger/ and as OpenAPI at /openapi.json.

Mass editing

A pass shares a big job out across many workers. “Translate every line of dialogue in the library”, “tag every scene’s props”, “rewrite every action line in present tense”: each worker asks for a batch, gets lines nobody else holds and nobody has finished, and marks each one done as it writes it back.

curl -X POST $S/documents/-/scenes/-/elements/dialogue/checkout \
     -H "Authorization: Bearer $T" \
     -d '{"limit": 20, "pass": "translate-fr", "has_lang": "en"}'

- means any document and any scene. Run one worker or a hundred: every line is handed out and counted once, GET /passes/translate-fr shows progress, and the pass:translate-fr channel streams it live.

Your database, your bucket

Scripts are stored as JSON records in a database you run, split the way that suits your queries: one record per script, per scene, or per line.

StorageUse it for
MongoDB (or FerretDB)A document store of record.
ElasticsearchFull-text search across every line of dialogue.
PostgreSQL with pgvectorJSON records and vector search in one database.
Chroma, Weaviate, PineconeScenes, lines and characters as vectors for retrieval.
S3, MinIO, Azure BlobEach script mirrored as a ScreenJSON file, exports, and import sources.

Turn on a script’s S3 mirror and its whole ScreenJSON is rewritten to the bucket every time it goes quiet after an edit. The database holds the live, editable copy; S3 holds the file every other system reads.

Everything else

  • Live. Every change is an event on a websocket channel: per script, for the whole library, and per pass.
  • Import anything. ScreenJSON goes straight in. Final Draft, Fade In, Fountain and PDF are converted by Greenlight, one file or a hundred.
  • Export anything. ScreenJSON to a download, S3 or Azure; PDF, Final Draft, Fade In and Fountain through Greenlight.
  • Git, per script. Each script can commit to its own repository on GitHub, GitLab or Bitbucket after every burst of edits.
  • Webhooks. Signed notifications when text changes, with a link to send a computed embedding back.
  • A web app for browsing, reading and importing the library, and a desktop app for Windows, macOS and Linux.

Run it

docker run --rm -p 127.0.0.1:8080:8080 \
  -e SCREENJSON_STORAGE_DRIVER=memory \
  ghcr.io/screenjson/screenjson-server:latest

One container, one port. A Compose file ships with a profile per database, and a Kustomize base for Kubernetes.

How it fits

  • screenjson-db-importer is the free, open-source way to load a back catalogue into the same database the server uses. Same records, same settings.
  • Greenlight does the format conversion: Final Draft, Fade In, Fountain and PDF in; PDF and writer formats out.
  • screenjson-ui renders the scripts in the server’s web app, so they look the same everywhere.

When to use it

Use screenjson-server when screenplays are something you work on as data: a library that agents and people edit together, that you update in bulk, search, translate and annotate, and that other systems read from your database and your buckets. If you only need to convert files or load them into a database once, the CLI and the importer are enough.

How-tos