beat-mcp-bridge
# beat-mcp-bridge
Connects Claude to [Beat](https://www.beat-app.fi), the Fountain screenplay
editor, so Claude can read and rewrite your screenplay directly in the app —
no copy/pasting new versions back and forth.
## How it works
Beat's plugin API is JavaScript running inside the app, with no networking.
So this is two halves talking through two small JSON files on disk:
```
Claude <--> MCP server (this repo) <--> request.json / response.json <--> Beat plugin (inside Beat)
```
1. Claude calls an MCP tool (e.g. `beat_replace_scene`).
2. The MCP server writes `request.json` into a shared "bridge" folder.
3. The **Claude Bridge** Beat plugin (a resident Tools-menu plugin) polls
that folder once a second, runs the operation against the live document,
and writes `response.json`.
4. The MCP server reads the result back to Claude.
Edits land in the open document immediately — you'll see the text change
while Beat is on screen.
## Setup
### 1. Create the bridge folder
Both sides need to agree on one folder. Pick any empty folder, e.g.:
```bash
mkdir -p ~/ClaudeBeatBridge
```
### 2. Install the Beat plugin
Copy `beat-plugin/Claude Bridge.beatPlugin` into Beat's plugin folder:
- In Beat: **Tools → Plugin Library**, click the folder icon at the bottom
to reveal the local plugins folder in Finder.
- Copy `Claude Bridge.beatPlugin` (the whole folder) into it.
- Restart the Plugin Library or Beat so it picks up the new plugin.
- Open a screenplay, then check **Tools → Claude Bridge** to enable it.
The first time it runs it will prompt you for the bridge folder path —
enter the same path from step 1 (e.g. `/Users/you/ClaudeBeatBridge`).
- Leave it checked. It stays resident and keeps polling in the background.
### 3. Install the MCP server
```bash
cd beat_claude_mcp
npm install
```
### 4. Point Claude at it
Add to your MCP client config (e.g. Claude Desktop's `claude_desktop_config.json`,
or `claude mcp add` for Claude Code), setting `BEAT_BRIDGE_DIR` to the folder
from step 1:
```json
{
"mcpServers": {
"beat": {
"command": "node",
"args": ["/absolute/path/to/beat_claude_mcp/index.js"],
"env": {
"BEAT_BRIDGE_DIR": "/Users/you/ClaudeBeatBridge"
}
}
}
}
```
Restart the client. Ask Claude to `beat_ping` — it should report Beat is
reachable and how many documents are open.
## Tools
| Tool | Purpose |
|---|---|
| `beat_ping` | Health check — is Beat/the plugin reachable? |
| `beat_list_documents` | List open screenplays, with the `docIndex` used below |
| `beat_get_text` | Full Fountain text of a document |
| `beat_set_text` | Replace the whole document (full rewrite) |
| `beat_get_outline` | Scenes + sections + synopses, with `sceneIndex` |
| `beat_get_scenes` | Just the scenes |
| `beat_get_scene_text` | Text of one scene |
| `beat_replace_scene` | Rewrite one scene in place, leaving the rest untouched |
| `beat_insert_text` | Insert text at a character offset |
| `beat_append_text` | Append text (e.g. a new scene) at the end |
| `beat_inspect_documents` | Debug: dump raw document fields if titles look wrong |
For most editing sessions, prefer `beat_get_outline` + `beat_replace_scene`
over `beat_set_text` — targeted scene rewrites are faster to apply and much
safer to review than swapping the entire document.
## Notes / limitations
- Every open Beat document is targetable via `docIndex` from
`beat_list_documents`, but Beat's plugin docs don't pin down the exact
property names for a document's file path across versions — if
`beat_list_documents` shows unhelpful titles, run `beat_inspect_documents`
and adjust the `candidates` list in `beat-plugin/Claude Bridge.beatPlugin/plugin.js`
(`describeDocument` function) to match what your Beat version exposes.
- The bridge polls once a second, so there's up to ~1s of latency per call
plus the 250ms the MCP server itself polls at — fine for editing, not
built for high-frequency use.
- No file, network, or shell access beyond the one bridge folder — the
plugin only ever reads/writes `request.json` and `response.json` there.
- Standard undo/redo in Beat still works on Claude's edits, since they go
through the same text-replacement APIs as a human typing.
TDQS
Scored across 11 tools
Most tools have clearly distinct purposes: read vs write, whole-document vs single-scene. The overlap between beat_get_outline and beat_get_scenes (both return sceneIndex) is real but descriptions clarify the difference (outline includes sections/synopses). beat_ping and beat_list_documents both list open documents, but ping is framed as an initial health check.
The beat_ prefix is applied uniformly and the verb_noun pattern dominates (replace_scene, insert_text, get_outline, set_text). Minor deviations: beat_ping lacks a noun, and the get_/list_ mix for retrieval is slightly inconsistent but follows a conventional distinction.
11 tools is well-scoped for a screenplay bridge: 6 read/inspection tools and 5 write/edit tools cover the domain without redundancy or bloat. Each tool earns its place for the stated purpose of interacting with Beat documents.
The surface covers the full text lifecycle: read (full, outline, scenes, single scene) and write (full replace, scene replace, insert, append). Notable gaps are the lack of an explicit scene deletion tool (workable via replace with empty text) and no document lifecycle operations, but these appear outside the bridge's scope.