Container Runtime
August 25, 2026 ยท View on GitHub
The container image packages ytdl-rmcp with the host tools needed for download,
fingerprinting, tagging, and transfer workflows:
ffmpegfpcalcfromlibchromaprint-toolsopenssh-clientforhost:/pathtargetsrcloneforremote:pathtargetsrsyncfor resumable local/SSH transfers- CA certificates
The server still runs MCP over stdio by default.
Product-owned TOOTIE deployment
The supported persistent TOOTIE runtime declaration lives at:
ops/compose/tootie/docker-compose.yaml
It deliberately overrides the image entrypoint with sleep infinity, retaining the container as a stable environment containing RYTDL, yt-dlp bootstrap state, ffmpeg, fpcalc, SSH, rclone, rsync, and mounted media. Each MCP session is started independently over stdio with:
ops/compose/tootie/mcp-stdio.sh
The helper runs docker exec -i ytdl-mcp ytdl-rmcp serve; it allocates no TTY and exposes no HTTP port. The current live deployment remains at tootie:/mnt/user/compose/ytdl-mcp until an explicit reviewed deploy/sync copies the product-owned declaration there.
Validate the declaration with:
scripts/check-tootie-compose.sh
Build
docker build -t ytdl-rmcp:local .
Published Image
Every push to main publishes:
ghcr.io/dinglebear-ai/rytdl:main
ghcr.io/dinglebear-ai/rytdl:main-<git-sha>
Pull the latest main image with:
docker pull ghcr.io/dinglebear-ai/rytdl:main
Run As An MCP Server
Mount SSH credentials if youtube_download transfers to a host:/path target.
Keep state and cache directories mounted so yt-dlp, ffmpeg sidecars, the ledger,
and archives survive container restarts.
docker run --rm -i \
-e YTDLP_TARGET_PATH=nashost:/mnt/user/data/media/music/yt-dlp \
-e YTDLP_HISTORY_PATH=/home/ytdl/.local/state/ytdl-rmcp/downloads.jsonl \
-v "$HOME/.ssh:/home/ytdl/.ssh:ro" \
-v ytdl-rmcp-state:/home/ytdl/.local/state/ytdl-rmcp \
-v ytdl-rmcp-cache:/home/ytdl/.cache \
ghcr.io/dinglebear-ai/rytdl:main serve
For MCP clients that expect a command, use
docker run --rm -i ... ghcr.io/dinglebear-ai/rytdl:main serve as the command.
Identify A Mounted Library
youtube_identify reads local paths from inside the container. Mount the library
and pass container paths such as /library/....
docker run --rm -i \
-e YTDLP_ACOUSTID_CLIENT_KEY="$YTDLP_ACOUSTID_CLIENT_KEY" \
-e YTDLP_MUSICBRAINZ_CONTACT="you@example.com" \
-v /mnt/user/data/media/music/yt-dlp:/library \
ghcr.io/dinglebear-ai/rytdl:main serve
Then call:
{
"paths": "/library/Artist/Song [id].mp3",
"write_tags": false,
"response_format": "json"
}
Run with write_tags=false first and save the JSON response as a report. After
reviewing candidates, rerun only accepted files with write_tags=true.
Batch Shape For The Existing yt-dlp Library
The current yt-dlp audio library on nashost is expected at:
/mnt/user/data/media/music/yt-dlp
A safe batch pass should:
- Inventory audio files under the mounted library.
- Call
youtube_identifywithwrite_tags=false. - Save one JSONL row per file with candidates, preview, and errors.
- Write tags only for high-confidence reviewed rows.
This avoids blindly mutating files where AcoustID returns multiple plausible MusicBrainz releases or soundtrack variants.