splicedeck
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@splicedeckinspect the file at media/talk_01.mov and then draft a vertical clip for party acme-corp"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
splicedeck
A video editor an AI agent drives, running on your own machine.
One call dresses a cut in a template: motion graphics, overlays, captions and a beat grid to cut against. One pass over a source gives you both a cleaned long-form master and vertical clips. And it remembers how each client, channel or show likes to be cut, so the next edit starts where the last one ended.
There is no timeline to drag and no account to create. Nothing is uploaded.
Status: the pipeline runs end to end, and memory reaches the cut
A source becomes a delivered file today. Measured on the reference machine (Windows 11, Python 3.13, ffmpeg 8.1.2) against a real 223 MB
.mov:inspect 2.6 s draft 27 ms splice 27 ms verify 42 ms deliver 157 s -> 1920×1080 h264 + aac, -23.0 LUFS, decodes clean
python -m pytestreports 1425 passed, 2 skipped in about four minutes. Thirty-one verbs reach the CLI and eighteen of them reach an MCP server, both generated from one table so they cannot drift apart.One headline feature does not work yet. Cutting by quoting needs a speech binary that no manifest can currently obtain. Read What does not work before you plan around it.
Install
You need Python 3.12 or newer and ffmpeg 8.x on your PATH. splicedeck neither installs
nor bundles ffmpeg, and docs/first-run.md §4 explains why that is
deliberate.
The setup script asks where the workspace goes, offers to install ffmpeg after showing you the exact command, scaffolds everything and writes an MCP config:
curl -fsSLO https://raw.githubusercontent.com/ihuzaifashoukat/splicedeck/main/install.sh
less install.sh && bash install.shirm https://raw.githubusercontent.com/ihuzaifashoukat/splicedeck/main/install.ps1 -OutFile install.ps1
notepad install.ps1; powershell -ExecutionPolicy Bypass -File install.ps1Read it before you run it. A curl | bash one-liner would be a poor advertisement for a
project whose README is largely about a threat model.
If you would rather do it yourself, or want the tests:
uv tool install splicedeck # or: pipx install splicedeck
git clone https://github.com/ihuzaifashoukat/splicedeck.git && cd splicedeck
python -m venv .venv
.venv/Scripts/python -m pip install -e ".[dev]" # Windows
.venv/bin/python -m pip install -e ".[dev]" # macOS, LinuxNot on PyPI yet. There is no release, so uv tool install splicedeck will 404 until
the first tag is pushed. Until then use the script, a clone, or
uv tool install "git+https://github.com/ihuzaifashoukat/splicedeck.git".
docs/install.md has every route, the per-platform ffmpeg commands,
the environment variables, and a prompt you can paste into an AI agent to have it install
and wire up splicedeck for you.
Try it
The workspace root is whichever directory you run in, and spd init scaffolds one:
mkdir my-edit && cd my-edit
spd init # bookmarks/ casebook/ elements/ ledger/ media/ profiles/ templates/
mkdir -p casebook/parties/demo
spd ready # what is present, and what each gap blocksinit never overwrites. Re-running it after you have edited a profile fills in
whatever is missing and leaves your edits alone. The files it writes are byte-identical
to the ones this repository ships, and python -m checks.starter --check enforces that.
Then put your footage under media/ and cut:
spd inspect --path media/your-file.mov # mints a source handle
spd draft --party demo --source s1 --bookmark baseline --profile wide-1080
spd apply --sheet c1 --template clean-master # overlays, motion, beat grid
spd splice --sheet c1 --source a --in_ticks 0 --out_ticks 900000 \
--source_in_ticks 0 --cause manual
spd verify --sheet c1
spd deliver --sheet c1Sources must live inside the workspace. A path with a drive letter in it is refused
PATH_OUTSIDE_WORKSPACE before anything is read.
A party is created by a human, by hand, on purpose. draft refuses UNKNOWN_PARTY
until casebook/parties/<name>/ exists.
To drive it from an MCP-capable assistant, register the server:
{"mcpServers": {"splicedeck": {
"command": "C:\\src\\splicedeck\\.venv\\Scripts\\python.exe",
"args": ["-m", "splicedeck.surface.mcp"],
"cwd": "C:\\src\\splicedeck"}}}cwd must be the workspace, because the workspace root is the working directory and
nothing else discovers it. python -m splicedeck.surface.mcp --tools prints the
generated tool list and exits, which is how you tell a broken server from a broken host
configuration. docs/mcp.md is the full guide.
Templates: the look in one call
apply dresses a cut sheet in a named template. It places the overlays, writes the
beat grid the agent then cuts against, and records on the sheet which template it used.
Four ship today:
Template | What it is |
| A calm talking-head master carrying one lower-third and no beat grid |
| A fast-cut vertical: three beat slots with a pulsing accent on each |
| A promo look: full-bleed intro and outro cards around two beat slots |
| One small mark on screen and nothing else |
A template's overlays animate when the optional motion tier is installed, and fall back
to a still imprint when it is not. Six animated compositions ship in
scenes/, written for this project and licensed with it.
Slots are enforced. verify refuses to pass a sheet with an unfilled slot, and a cut
landing outside a slot's tolerance is refused SLOT_TOO_TIGHT with the nearest legal
edges returned as ready-to-send calls. That is what lets an agent hit a rhythm it
cannot see.
You can write your own. spd compose --kind template validates and writes a
hand-authored template or element card. It is deliberately CLI-only: the MCP server may
not write to templates/, and docs/templates.md §4 explains the
reasoning rather than treating it as an oversight.
Why memory
An edit is a thousand small judgements and almost all of them repeat. How long to hold after a punchline. Whether this speaker's filler is noise or personality. How big captions have to be on a phone at arm's length. A stateless tool makes you re-supply that context every session, which is why "AI editing" so often produces something technically correct and tonally wrong.
Here, a decision you make once is recorded and reused:
subtitle.size_px = 74
when {surface: vertical, frame: 1080x1920}
set by a render you shipped and kept, 2026-08-02
before 66That record lives in your repository as reviewable text. You can read the diff, correct
a bad entry by editing a line, and git revert a change that made the edits worse. It
is a behaviour changelog, kept in the same place as everything else you version.
Two rules keep it trustworthy:
Nothing durable is written by the model. A record describes something a human did: shipped a render and kept it, restored a moment the cut removed. The agent can point at what happened; it cannot compose what gets remembered.
Every write passes a human gate. No preference is learned silently.
That loop runs today. spd set, ship, keep, restore and discard append acts to
a party's hash-chained ledger and stage a proposal from each one; an act cannot be
appended to a chain that does not verify. spd review then asks for the value blind,
showing the bounds and the shipped cut but never the number, and a matching answer
becomes a sealed case and a regenerated findings.lock.txt. The next draft resolves
against it: the bookmark opens the settings, the casebook overrides the ones a human
settled, and the sheet records which lock it read.
Local first, and complete
A fresh clone with no API keys and no cloud account produces a finished, delivered file on your own machine. That is the baseline, not a degraded mode.
Cloud services can be switched on where they genuinely help, such as a hosted speech API for difficult audio or diarisation, but nothing becomes required and no deliverable depends on one. ffmpeg does the work as a child process. It is never vendored and never linked.
The project also refuses to guess about your hardware. Encoder support is proven by
test-encoding rather than by reading a feature list, because feature lists lie. On the
development machine ffmpeg -encoders advertises an NVIDIA encoder that fails at
runtime, while the Intel one that actually works goes unmentioned in every guide.
What works
One analysis pass, two deliverables. Transcription and analysis run once per source. The long-form master and the vertical clips both read the same results.
Frame-accurate cutting with no audio drift. Audio stays PCM until the mux and is encoded once. The delivered samples are byte-identical to a reference assembly built in Python over 45 and 120 joins. Measured, not asserted.
Templates and motion in one call, with a beat grid the agent cuts against and a still fallback when the motion tier is absent.
Captions that stay legible. Size and contrast floors are enforced by the renderer, and text that would land under a platform's own interface is refused rather than drawn. Glyphs are shaped and rasterised by a pure-stdlib TrueType parser, so imprints are byte-reproducible and committed as goldens.
Vertical framing that admits uncertainty. When the subject cannot be tracked confidently it declines to auto-frame and says why. A confidently wrong crop is worse than an honest refusal, because nobody reviews the one that looked fine.
Rights that hold up. Music, effects and stock footage carry a record of where they came from and what the terms permit. A delivery refuses to run if any asset lacks one.
Typed refusals that carry their own correction. A refusal arrives with
retry_with, a list of ready-to-send calls. There are 102 codes, each with a construction site and a test proving it is reachable.
What does not work
Stated plainly, because a status section that omits this is the reason the last one was worthless.
Not working | Why | Blocks |
Cutting by quoting |
|
|
Subject tracking by model | No detector is pinned or shipped ( |
|
Cancelling from an MCP host | The stdio loop is single-threaded, so nothing can arrive during a |
|
CHANGELOG.md carries the same list, and the two are meant to stay in
sync.
Two tiers below the model one do work. subject: "centre" is geometric and needs
nothing. SPD_SIGHT_LOCATOR=reduce selects a weights-free locator that finds the subject
by temporal-median background subtraction in pure stdlib Python, no numpy and no compiled
extension anywhere.
Checked against a face detector on the reference master, that locator's median agreed to
within 0.1% of frame width. On the same footage it then reported certainty 0.26 and fitted
no path at all, because a speaker who barely moves against a static background leaves
nothing for background subtraction to hold onto. Both of those are the right answer: the
arithmetic is sound, and the honest limit of a weights-free tier is a hole rather than a
centred guess (docs/framing.md §7). Footage with a moving subject
tracks fine.
How you drive it
Through an MCP server and Skills, so any MCP-capable assistant can use it, plus a CLI
exposing exactly the same verbs. Both surfaces are generated from
splicedeck/surface/verbs.py, and python -m checks.golden --check fails the build if
they drift apart.
The server speaks five protocol revisions, 2024-11-05 through 2026-07-28, and
answers both the initialize handshake and server/discover.
Failures are typed. A refusal carries its own correction as ready-to-send calls rather than prose an agent has to interpret, so recovery is one turn:
{"ok": false, "verb": "draft", "refused": "BOOKMARK_UNKNOWN",
"plain": "No bookmark by that name is shipped.",
"needs_human": false,
"retry_with": [{"verb": "draft", "args": {"bookmark": "baseline", "party": "demo",
"profile": "wide-1080", "situation": "default", "source": "s1"}}]}Skills
Four skills teach an agent the verb order, the traps between verbs, and how to turn a
refusal into the next correct call. They live in
.claude/skills/, and a clone picks them up with no install at all.
Skill | Fires when |
| Turning a source into a delivered file |
| Carving a 9:16 clip and keeping the subject in frame |
| Any |
| Editing this codebase, or when two documents disagree |
This repository is also a Claude Code plugin and its own marketplace:
claude plugin marketplace add ihuzaifashoukat/splicedeck
claude plugin install splicedeck@splicedeckOr install the skills into any of the agents the skills CLI supports, including
Codex, Cursor, OpenCode, Antigravity, Cline, Gemini CLI, Zed and Windsurf:
npx skills add ihuzaifashoukat/splicedeck # add --list to look firstBoth routes ship the skills only. They do not register the MCP server, because the
server needs an absolute interpreter path and a cwd that neither a plugin nor a skill
installer can know. install.sh writes that for you, and
docs/mcp.md has it by hand.
Every other agent runtime reads AGENTS.md.
Design
The specification is written before the code, deliberately.
Document | What it settles |
The contract every contributor and agent works under | |
The map: runtimes, packages, data flow | |
Clone to delivered file, and the Windows traps | |
Every install route, and a prompt for an AI agent | |
Driving splicedeck from an assistant | |
The core artifact: integer-timed, diffable, human-readable | |
Templates, slots, and what | |
How memory is stored, resolved and gated | |
The threat model, and why memory is an attack surface | |
Styles, and the axes they are points in | |
The verb table and the refusal catalogue | |
The feature areas, and what each has to prove |
Persistent memory in an agent is a security surface, not just a feature. Anything an
attacker can write into it outlives the conversation that planted it. If you read one
document, read docs/security.md.
Non-goals
Assembling a film from many sources. Generating video or music. A timeline GUI. Real-time collaboration. A hosted service. Automatically choosing which moments become clips, since it presents candidates and waits for a person.
Requirements
Python 3.12 or newer, and ffmpeg 8.x on your PATH. No compiled Python extension is
used on any default path, so there is no build step and no platform runtime to install
first. Windows, macOS and Linux; CI covers Ubuntu and Windows, and macOS is untested by
machine.
The motion tier additionally needs Node and an npm install inside scenes/. It is
optional, and a delivery without it falls back to still imprints.
Contributing
Issues and design critique are welcome. CONTRIBUTING.md is the
front door: setup, the checks to run, how to add a verb or a refusal code, and the
things that get a pull request rejected regardless of merit. Read
AGENTS.md first. The twelve hard rules are load-bearing, and a change
that breaks one is rejected on that basis alone.
By taking part you agree to the Code of Conduct.
Security
Please do not open a public issue for a vulnerability. SECURITY.md has
the reporting route and what is in scope.
Licence
Apache-2.0. Copyright 2026 Huzaifa Shoukat.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Agentic video editing on real footage: cut, caption, reframe, score, and export at full quality.
A real timeline video editor for AI agents: journaled edits, FFmpeg/MLT rendering, exports
Make videos and docs with your AI agent — describe what you need, every output stays editable.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ihuzaifashoukat/splicedeck'
If you have feedback or need assistance with the MCP directory API, please join our Discord server