script-timer-mcp
README.md
# script-timer-mcp
[](https://github.com/anshumanofficial2002-cpu/script-timer-mcp/actions/workflows/ci.yml)
[](LICENSE)
[](https://modelcontextprotocol.io)
**Know exactly how long your script runs — before you hit record.**
`script-timer-mcp` is a [Model Context Protocol](https://modelcontextprotocol.io) server for short-form video scripts. It times scripts the way they'll actually be spoken (skipping B-roll notes, adding pauses, handling numbers and URLs), tells you what to cut to hit 15/30/60/90 seconds, scores your hook, checks pacing, trims fillers, and exports teleprompter text, a timed beat sheet for the edit, and draft SRT captions.
Pure TypeScript, no dependencies beyond the MCP SDK, no API keys, no network.
```
You: Will this script fit in 30 seconds? [pastes script]
Claude: It runs 0:38 at 170 wpm — cut ~23 words. The Body is 62% of the runtime;
your hook and CTA are fine. Quick wins: "basically" ×2, "in order to" → "to".
Longest sentence is 26 words (9.1s) — split it.
Hook score 4/10: it opens with "Hey guys, welcome back" — lead with the
"$40,000 camera" line instead.
```
---
## Tools
| Tool | What it does |
| --- | --- |
| `estimate_duration` | Total and per-section read time at your pace, the range across paces, comparison to a target, and **calibration**: give the length of a real take and get your personal WPM. |
| `fit_to_duration` | Word budget for a target length, words to cut/add, per-section budget (lock sections like Hook/CTA), the pace that would fit as-is, and ranked cut candidates with seconds saved. |
| `analyze_hook` | Scores the opening 0–10: flags slow openers (greetings, "welcome back", "in this video", "so today…", name intros, early like/subscribe asks) and credits strong patterns (you-language, questions, numbers, tension, contrast, mid-story starts). Ranks hook **variants**. |
| `analyze_pacing` | Sentence lengths, one-breath problems, Flesch readability, repeated words, fillers, section balance, CTA at the end (and none too early). |
| `trim_fillers` | Removes fillers and tightens wordy phrases, repairs capitalization and punctuation, leaves headers and stage directions alone, lists every change and the time saved. |
| `format_teleprompter` | Short lines broken at natural pauses, blank line between sentences, section markers, optional `[m:ss]` timestamps and ALL CAPS. |
| `beat_sheet` | Every line with estimated start/end plus where each B-roll / SFX / on-screen cue lands. Markdown or CSV. |
| `script_to_srt` | Draft SRT with estimated timing (reels style 1–3 words, or standard ≤42 chars) — a placeholder caption track before the VO exists. |
| `compare_scripts` | 2–10 versions side by side: words, time, hook score, longest sentence, CTA, fits target. |
Every tool takes `text` (paste the script) **or** `path` (a `.txt` / `.md` file).
---
## How scripts are read
Write scripts the way you already do. The parser separates what's **spoken** from what isn't:
```markdown
# Hook
I spent $40,000 on cameras and the cheapest one won.
## Body
[B-ROLL: three cameras on a desk]
Here's why. [pause]
SFX: whoosh
VO: The sensor matters less than the light.
CTA: Comment "LIGHT" and I'll send you my setup.
```
| You write | Treated as |
| --- | --- |
| `# Hook`, `## Body`, `**CTA**` (short bold line) | Section header |
| `Hook:`, `Intro -`, `CTA:`, `Outro:`, `Beat 2:`, `Scene 3:` | Section label (text after it is spoken) |
| `PROBLEM:`, `STEP 2:`, `TIP 3:` (caps), or the label alone on a line | Section label. In normal case ("Problem: nobody watches…") it's spoken. |
| `[B-ROLL: …]`, `{SFX}`, `(cut to wide)`, `(laughs)` | Stage direction, not timed |
| Lines starting `B-ROLL:`, `A-ROLL:`, `SFX:`, `MUSIC:`, `ON SCREEN:`, `VISUAL:`, `SHOT:`, `CUT TO:`, `GRAPHIC:`, `LOWER THIRD:`, `OVERLAY:` | Stage direction |
| `TEXT:`, `NOTE:`, `EDIT:`, `CAMERA:` in caps | Stage direction. In normal case ("Note: this only works on Mac") it's spoken. |
| `VO:`, `HOST:`, `NARRATOR:`, `ALL-CAPS NAME:`, or a name that starts 2+ lines (`Hardik: …`) | Speaker label, dropped |
| `[pause]` / `(pause)` · `[beat]` · `[pause 2s]` · `...` | +1 s · +0.5 s · +2 s · +0.4 s |
Timing adjusts for how long things take to **say**: `2026` ≈ 2 words, `$10K` ≈ 3, `3.5x` ≈ 3, `example.com` ≈ "example dot com", `API` ≈ 2. Chinese/Japanese/Korean text is timed per character. Emojis are ignored.
### Paces
| Preset | WPM | Typical use |
| --- | --- | --- |
| `slow` | 130 | Explainers, VO over visuals, emotional pieces |
| `conversational` | 150 | Talking-head YouTube, podcasts |
| `energetic` (default) | 170 | Typical Reels / TikTok / Shorts delivery |
| `fast` | 190 | Hype edits, rapid-fire lists |
Everyone talks at a different speed. Record one take, then run `estimate_duration` with `actual_seconds` to get **your** WPM and pass `wpm` from then on.
---
## Requirements
- **Node.js 20+**. That's it.
## Install
### Claude Desktop
**Settings → Developer → Edit Config**:
```json
{
"mcpServers": {
"script-timer": {
"command": "npx",
"args": ["-y", "github:anshumanofficial2002-cpu/script-timer-mcp"]
}
}
}
```
### Claude Code
```sh
claude mcp add script-timer -- npx -y github:anshumanofficial2002-cpu/script-timer-mcp
```
### Cursor / Windsurf / VS Code / other clients
```json
{
"script-timer": {
"command": "npx",
"args": ["-y", "github:anshumanofficial2002-cpu/script-timer-mcp"]
}
}
```
### From source
```sh
git clone https://github.com/anshumanofficial2002-cpu/script-timer-mcp.git
cd script-timer-mcp && npm install && npm run build
# point your client at: node /absolute/path/to/script-timer-mcp/dist/index.js
```
---
## Example prompts
- "How long is this script at a normal reel pace?" *(paste it)*
- "I recorded `~/Scripts/ep14.md` and the take was 47 seconds. What's my WPM?"
- "Fit `launch.md` to 30 seconds, but don't touch the Hook or CTA."
- "Score these 5 hooks and tell me which to open with."
- "Remove the fillers from my script but keep 'literally', it's how I talk."
- "Make teleprompter text with timestamps, 5 words per line, all caps, save it to `~/Desktop/prompter.txt`."
- "Give me a beat sheet CSV so my editor knows where the B-roll goes."
- "Make a draft SRT from this script so I can lay out captions before the voiceover."
- "Compare v1, v2 and v3 of this script for a 15-second ad."
---
## Tool reference
Shared params: `text` or `path`; `pace` (`energetic`) or `wpm` (60–320).
| Tool | Extra params |
| --- | --- |
| `estimate_duration` | `target_seconds`, `actual_seconds` |
| `fit_to_duration` | `target_seconds` (required), `keep_sections` |
| `analyze_hook` | `variants` (up to 20 lines), `first_seconds` (3) |
| `analyze_pacing` | `long_sentence_words` (25) |
| `trim_fillers` | `aggressive` (false), `extra_fillers`, `keep`, `output_path`, `overwrite` |
| `format_teleprompter` | `words_per_line` (6), `uppercase`, `timestamps`, `show_sections` (true), `show_directions`, `output_path`, `overwrite` |
| `beat_sheet` | `format` (`markdown` \| `csv`), `output_path`, `overwrite` |
| `script_to_srt` | `style` (`reels` \| `standard`), `max_words`, `max_chars`, `uppercase`, `offset_seconds`, `output_path`, `overwrite` |
| `compare_scripts` | `scripts` (`[{label, text}]`, 2–10), `target_seconds` |
**Fillers removed by `trim_fillers`:** basically, literally, honestly, kind of, sort of, you know, I mean, so yeah, pretty much, needless to say, at the end of the day, to be honest, for what it's worth, and ", like,". With `aggressive`: also actually, really, very, just, totally, simply, definitely, certainly, quite, obviously, absolutely, truly.
**Wordy phrases tightened:** in order to → to · due to the fact that → because · at this point in time → now · in the event that → if · is/are able to → can · each and every → every · first and foremost → first · whether or not → whether · the majority of → most · a large number of → many · in the near future → soon · and filler openers like "it's worth noting that", "the thing is", "what I want to say is".
---
## Honest limits
- Durations are **estimates** from word counts. Real delivery varies with pauses, emphasis and editing — calibrate with `actual_seconds` for best results.
- The hook score and filler lists are **heuristics** to point you at likely problems, not a judgement of the idea. English patterns only; timing works for any language.
- Readability (Flesch) is only computed for English.
- `.docx` / `.pdf` / Pages files aren't read — paste the text or export `.txt` / `.md`.
## Safety
- Files are only written when you pass `output_path`; existing files are never replaced without `overwrite: true`.
- No network access, no telemetry.
## Development
```sh
npm install
npm run build
npm test # parser/analysis unit tests + end-to-end tests over stdio
npm run inspect # MCP Inspector
```
`dist/` is committed so `npx github:…` works without a build; CI verifies it matches `src/`.
## Related servers
- [video-probe-mcp](https://github.com/anshumanofficial2002-cpu/video-probe-mcp) — inspect and conform video for each platform
- [caption-forge-mcp](https://github.com/anshumanofficial2002-cpu/caption-forge-mcp) — SRT/VTT/ASS conversion, timing, linting and reel-style captions
- [loudness-check-mcp](https://github.com/anshumanofficial2002-cpu/loudness-check-mcp) — LUFS, true peak, normalization, silence and clipping
- [frame-grab-mcp](https://github.com/anshumanofficial2002-cpu/frame-grab-mcp) — frames, contact sheets, scene cuts and thumbnails your AI can see
- [script-timer-mcp](https://github.com/anshumanofficial2002-cpu/script-timer-mcp) — time, trim and format scripts for short-form video
## License
[MIT](LICENSE) © 2026 Anshuman
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues